2014-04-04 18 views
51

Bu kod ...Python3 değişken adlarında basit bir fark, kodun çalışma şeklini değiştirebilir mi?

class Person: 
    num_of_people = 0 

    def __init__(self, name): 
     self.name = name 
     Person.num_of_people += 1 

    def __del__(self): 
     Person.num_of_people -= 1 

    def __str__(self): 
     return 'Hello, my name is ' + self.name 

cb = Person('Corey') 
kb = Person('Katie') 
v = Person('Val') 

aşağıdaki hatayı ...

Exception AttributeError: "'NoneType' object has no attribute 'num_of_people'" in <bound method Person.__del__ of <__main__.Person object at 0x7f5593632590>> ignored 

üretir Ama bu kod yok.

class Person: 
    num_of_people = 0 

    def __init__(self, name): 
     self.name = name 
     Person.num_of_people += 1 

    def __del__(self): 
     Person.num_of_people -= 1 

    def __str__(self): 
     return 'Hello, my name is ' + self.name 

cb = Person('Corey') 
kb = Person('Katie') 
vb = Person('Val') 

Gördüğüm tek fark, son değişken adı "vb" vs. "v" şeklindedir.

Python'a yaslanıyorum ve şimdi OOP şeyleri üzerinde çalışıyorum.

+2

@StevenRumbalski: Kısaca, evet. Ama sadece tercüman çıkışında. –

+6

İlk kod bu istisnayı üretmiyor. Tam izinizi göster. (Düzeltme: Python 3.3 veya daha yüksek bir sürümde bu istisnayı üretmiyor. 3.2'de.) – geoffspear

+0

@Wooble Nah! Eksik olan şey buydu .. – aIKid

cevap

59

Evet, buna neden olan değişken adın çok fazla olmamasına rağmen, doğrudan değil.

Python çıkarıldığında, tüm modüller de silinir. Modüllerin temizlenme şekli, bir modüldeki tüm globals'ları None'a ayarlayarak (böylece bu referanslar artık orijinal nesnelere değinmeyecektir). Bu globals, bir sözlük nesnesindeki anahtarlardır ve sözlükler isteğe bağlı olarak sipariş edildiğinden, bir değişkeni yeniden adlandırmak, değişkenlerin temizlendiği sırayı değiştirebilir.

v, vb olarak yeniden adlandırdığınızda, değişkenlerin temizlendiği sırayı değiştirdiniz ve şimdi en son Person temizlendi. PersonNone ayarlı değilse örneği her zaman hareketsiz sınıfına başvuru veya sınav verecektir çünkü

def __del__(self): 
    type(self).num_of_people -= 1 

:

Bir iş çevresinde yerine __del__ yöntemde type(self).num_of_people -= 1 kullanmaktır

def __del__(self): 
    if Person is not None: 
     Person.num_of_people -= 1 

İki not:

  • CPython 3.4, Safe Object Finalization uyarınca None (çoğu durumda) için globals ayarlamamaktadır; PEP 442.

  • CPython 3.3, globals sözlüğünde kullanılan str anahtarlarına otomatik olarak randomized hash salt uygular; Bu, gözlemlediğiniz davranışı daha da rasgele hale getirir, sadece kodunuzu birkaç kez tekrar çalıştırmanız hata mesajını tetikleyebilir veya tetiklemeyebilir.

+2

Ugh .. Cevap çok parlak, ama bunu gerçekten anlamıyorum. 'Yorumlayıcı çıkışında' ile ne demek istiyorsun? Açıklayabilir misin? – aIKid

+3

@aIKid: Python çıktığı zaman, (veya modülü sys.modules'den tüm referansları kaldırarak ve silmeden değiştirdiyseniz, ancak bu genellikle yapılmaz), '__del__' adlı modül çağrılır ve ardından İlk önce, modül içindeki tüm globals'ları isimlerini 'None' olarak isimlendirerek temizleyin. –

+0

Yani istisna sadece tercümandan çıktığımızda ortaya çıkıyor .. <- Bu yanlış, değil mi? – aIKid

İlgili konular