In Python 2, tipo e classe non sono la stessa cosa, in particolare, per le classi di vecchio stile, type(obj)
is not the same object come obj.__class__
. Così è possibile, perché le istanze di classi in stile antico sono in realtà di tipo diverso (instance
) che la loro classe:
>>> class A(): pass
>>> class B(A): pass
>>> b = B()
>>> assert b.__class__ is B
>>> issubclass(b.__class__, A) # same as issubclass(B, A)
True
>>> issubclass(type(b), A)
False
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.B at 0x10043aa10>
Questo si risolve in classi di nuovo stile:
>>> class NA(object): pass
>>> class NB(NA): pass
>>> nb = NB()
>>> issubclass(type(nb), NA)
True
>>> type(nb)
<class '__main__.NB'>
>>> nb.__class__
<class '__main__.NB'>
Old-style la classe non è un tipo, la classe new-style è:
>>> isinstance(A, type)
False
>>> isinstance(NA, type)
True
Le classi di vecchio stile sono dichiarate deprecate. In Python 3, ci sono solo classi di nuovo stile; class A()
equivale a class A(object)
e il tuo codice produrrà True
in entrambi i controlli.
Date un'occhiata a questa domanda per un po 'di discussione: What is the difference between old style and new style classes in Python?
+1: questa è una descrizione molto chiara e un ottimo punto. Grazie! – EOL
Per chiunque si domandi, 'isinstance' è [special-cased] (https://github.com/python/cpython/blob/e6a0b5982973e64b9fa28e5e3e54eb8c47882780/Objects/abstract.c#L2898) per le istanze e le classi vecchio stile (ad esempio' PyClass_Check (cls) && PyInstance_Check (inst) 'in C). Poiché non esiste una relazione di tipo, ottiene il '__class__' dell'istanza per un controllo' issubclass', che è anche [speciale-cased] (https://github.com/python/cpython/blob/e6a0b5982973e64b9fa28e5e3e54eb8c47882780/Objects /classobject.c#L486) per le classi vecchio stile. – eryksun