2009-06-29 25 views
35

type(obj) ve obj.__class__ arasındaki fark nedir? type(obj) is not obj.__class__ bir olasılık var mı?Tür (obj) ve nesn .__ class__ arasındaki fark

Ürünle birlikte verilen nesnelerde, başka bir parametre ile aynı türde bir varsayılan 1 değeri kullanarak genel olarak çalışan bir işlev yazmak istiyorum. Aşağıdaki varyasyon # 1 veya # 2, doğru olanı yapacak mı?

def f(a, b=None): 
    if b is None: 
    b = type(a)(1) # #1 
    b = a.__class__(1) # #2 

cevap

12

type(obj) ve type.__class__ eski tarz sınıfları için aynı davranmazlar:

>>> class a(object): 
...  pass 
... 
>>> class b(a): 
...  pass 
... 
>>> class c: 
...  pass 
... 
>>> ai=a() 
>>> bi=b() 
>>> ci=c() 
>>> type(ai) is ai.__class__ 
True 
>>> type(bi) is bi.__class__ 
True 
>>> type(ci) is ci.__class__ 
False 
+7

En büyük ironi, yairchu'nun yorumunu şu anda biçimlendirmeyi değiştirdiğinden beri aynı soruna neden oluyor ..: P –

+10

Farklı şekillerde nasıl davrandığını ve belki de neden * * olduğunu * göstermek zarar vermez. Sadece * ne zaman farklı * davrandığını söylerseniz, doğru olsa bile, tembel bir cevap verir. – MestreLion

+1

bundan bahsetmeye değer sadece Python 2'deki sorun. Python 3'te her üç ifade de True olacaktır. – Bob

30

Eski tarzı sınıfları sorun, iç çekiyorum:

>>> class old: pass 
... 
>>> x=old() 
>>> type(x) 
<type 'instance'> 
>>> x.__class__ 
<class __main__.old at 0x6a150> 
>>> 

Değil bir sorun Python 3'teki tüm sınıflar yeni tarzı şimdi olduğundan ;-). o örtük veya açık (object ve dahil olmak üzere çeşitli yerleşik türleri gibi dict, list, set ...) ya da başka bir yeni tarzı sınıfından miras eğer Python 2'de

, bir sınıf yeni tarzı sadece __metaclass__, type için ayarlar.

+3

Python 3 kez, hangi * kullanmalıyız *? –

+2

Kodunuz Alex tarafından açıklandığı gibi en iyi uygulamayı izliyorsa, type() 'tercih edilir. Python 3'te her zaman en iyi uygulamayı takip eder, bu yüzden Python 3'teki type() 'ı kullanın. –

+0

@AaronHall Python yazıyorsam, 'type()' işlevinin '__class__' üzerinden de tercih edildiğini düşünmeme yardımcı olur muyum? Sadece yeni stil sınıflarının örnekleriyle çağrılacağını bildiğim 2 kod? – kasperd

30

Bu eski bir soru ama cevapların hiçbiri söz gibi gözüküyor. Genel durumda, yeni tarzı sınıfı type(instance) ve instance.__class__ için farklı değerler olması için mümkün IS:

class ClassA(object): 
    def display(self): 
     print("ClassA") 

class ClassB(object): 
    __class__ = ClassA 

    def display(self): 
     print("ClassB") 

instance = ClassB() 

print(type(instance)) 
print(instance.__class__) 
instance.display() 

Çıktı: ClassB__class__ kıldı

<class '__main__.ClassB'> 
<class '__main__.ClassA'> 
ClassB 

nedenidir tanımlayıcı, ancak nesne içindeki iç alan değişmez. type(instance) doğrudan bu tür alanından okur, bu nedenle doğru değeri döndürür, oysa instance.__class__, iç tip alanını okuyan Python tarafından sağlanan orijinal tanımlayıcının yerini alan yeni açıklayıcıya başvurur. Bu iç alan alanını okumak yerine, sabit kodlanmış bir değer döndürür.

+10

_Caveat lector_: Bu '__class__' geçersiz kılma neden kaçınmalısınız bir örnek olarak alınmalıdır! Kodun kırılması için '__class__' kullanan satırı neden olabilirsiniz. –

+0

Ayrıca, 'OBJ .__ class__' isteğini engelleyen' __getattribute__' tarafından etkilenir, ancak tür (OBJ) 'için değil. – kdb