2009-06-29 19 views
35

Jaka jest różnica między type(obj) i obj.__class__? Czy istnieje możliwość uzyskania type(obj) is not obj.__class__?Różnica między typem (obj) i obj .__ klasa__

Chcę napisać funkcję działającą generalnie na dostarczonych obiektach, używając wartości domyślnej 1 w tym samym typie co inny parametr. Która z odmian, nr 1 lub nr 2, zrobi to, co trzeba?

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

Odpowiedz

12

type(obj) i type.__class__ nie zachowują się tak samo dla klas starym stylu:

>>> 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

Największą ironią jest komentarz yairchu teraz ma ten sam problem, ponieważ zmienili formatowanie: P –

+10

Nie zaszkodzi pokazać * jak * zachowują się inaczej, a może także * dlaczego *. Powiedzenie * kiedy * zachowują się inaczej, brzmi leniwie, nawet jeśli jest poprawna. – MestreLion

+1

Warto wspomnieć, że jest to tylko problem w Pythonie 2. W Pythonie 3 wszystkie trzy wyrażenia będą prawdziwe. – Bob

30

klas starym stylu są problemem, wzdychają:

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

nie problem w Pythonie 3, ponieważ wszystkie zajęcia są teraz nowy styl ;-).

W Pythonie 2, klasa jest tylko nowy styl czy dziedziczy z innej klasy nowego stylu (w tym object i różnych typów wbudowanych, takich jak dict, list, set ...) lub jawnie lub niejawnie ustawia __metaclass__ na type.

+3

To jest Python 3 raz, który * powinni * używamy? –

+2

Jeśli Twój kod jest zgodny z najlepszą praktyką opisaną przez Alex, preferowane byłoby "type()". W Pythonie 3 zawsze podąża za najlepszą praktyką, więc użyj type() w Pythonie 3. –

+0

@AaronHall Byłbym poprawny, zakładając, że używanie 'type()' jest również preferowane w stosunku do '__class__' jeśli piszę Python 2 kod, w którym wiem, że będzie on wywoływany tylko z instancjami klas w nowym stylu? – kasperd

30

To stara sprawa, ale żadna z odpowiedzi wydaje się wspomnieć, że. w ogólnym przypadku, JEST możliwe dla klasy nowy styl mieć różne wartości dla type(instance) i instance.__class__:

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() 

wyjściowa:

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

Powodem jest to, że ClassB jest przesłanianie __class__ deskryptor, jednak pole typu wewnętrznego w obiekcie nie zostanie zmienione. type(instance) czyta bezpośrednio z tego typu pola, więc zwraca poprawną wartość, natomiast instance.__class__ odnosi się do nowego deskryptora zastępującego pierwotny deskryptor dostarczony przez Python, który odczytuje pole typu wewnętrznego. Zamiast odczytywać to pole typu wewnętrznego, zwraca wartość zakodowaną na stałe.

+10

_Caveat lector_: należy to traktować jako przykład, dlaczego powinieneś unikać nadpisywania '__class__'! Możesz przerwać kod w linii, która używa '__class__' do zerwania. –

+0

Wpływa również na '__getattribute__', który przechwytuje żądanie dla' OBJ .__ class__', ale nie dla 'type (OBJ)'. – kdb

Powiązane problemy