2016-10-12 14 views
5

Python dizeleri, 'is' operatörünün hazır bilgi üzerinde çalışacak şekilde nasıl depolar? tek adresi olarak düşük tamsayılar sakladığı için python'da

>>> a = 5 
>>> a is 5 
True 

ama

>>> a = 500 
>>> a is 500 
False 

budur. Ancak sayılar karmaşık olmaya başladığında, her int kendi benzersiz adres alanını alır. Bu bana mantıklı geliyor.

Geçerli uygulama, bu aralıkta bir int oluşturduğunuzda, aslında var olan nesneye bir başvuru aldığınızda, -5 ile 256 arasındaki tüm tamsayılar için bir dizi tamsayı nesnesi tutar.

Şimdi, neden bu dizeler için geçerli değil? Dizeler, büyük tamsayılar kadar karmaşık değiller (eğer moreso değilse)?

>>> a = '1234567' 
>>> a is '1234567' 
True 

Python, tüm dize değişmezleri için aynı adresi nasıl verimli kullanır? Sayılar için olduğu gibi olası her diziyi tutamaz.

cevap

0

Tüm olası dizelerden oluşan bir diziyi saklamıyor, bunun yerine, dizenin karması tarafından dizine eklenmiş olan tüm bildirilen dizelerin bellek adreslerini gösteren bir karma tablosu var. Eğer a = 'foo' derken zaten bir giriş karma tabloda varsa örnek

için

, ilk dize foo ve kontrolleri sağlamalarının. Evet ise, a değişken şimdi adrese başvurur.

Tabloda herhangi bir giriş bulunmuyorsa, python dizeyi saklamak için bellek ayırır,sağlamalarını ve tabloya ayrılmış belleğin adresini içeren bir girdi ekler.

Bkz:

  1. How is the 'is' keyword implemented in Python?
  2. https://en.wikipedia.org/wiki/String_interning
+0

',' id's –

+0

nesnesini karşılaştırır Hafıza adreslerini de karşılaştırır. CPython IIRC'de http://stackoverflow.com/questions/2987958/how-is-the-is-keyword-implemented-in-python –

+1

id == bellek adresine bakın. –

3

Bu, interning adı verilen bir optimizasyon tekniğidir. CPython, equal values of string constants'u tanır ve yeni örnekler için fazladan bellek ayırmaz ancak aynı id() değerini vererek, aynı olanı işaret eder (staj).

Bir tek sabitleri davranılmasını bu şekilde (b gibi basit işlemler tanınan) onaylamak için etrafında oynayabilir: manuel bir dize zorlayabilir Ancak

# Two string constants 
a = "aaaa" 
b = "aa" + "aa" 

# Prevent interpreter from figuring out string constant 
c = "aaa" 
c += "a" 

print id(a)   # 4509752320 
print id(b)   # 4509752320 
print id(c)   # 4509752176 !! 

zaten intern() kullanarak mevcut bir eşlenmesi :

c = intern(c) 

print id(a)   # 4509752320 
print id(b)   # 4509752320 
print id(c)   # 4509752320 !! 

Diğer tercümanlar bunu farklı yapabilir. Dizeler değişmez olduğundan, ikisinden biri diğerini değiştirmeyecektir.

+0

Öyle -5 +256 önceden tanımlanmış tamsayılar aralığında benziyor. Diğerlerinin hepsi, gerçeklerden yaratılmış gibi gözüküyorlar, bu yüzden "yanlış" ifadesini döndürür. –

+0

Yanıt olarak işaretlemediniz, çünkü "optimizasyonu" diyorsunuz ama nasıl depolandığını açıklamıyorsunuz. Veya diğer kelimelerde NASIL optimizasyon yapıyorlar. –