En Python 2, tipo y clase no son la misma cosa, en concreto, para las clases de estilo antiguo, type(obj)
is not the same object como obj.__class__
. Por lo que es posible debido a que las instancias de clases de estilo antiguo en realidad son de un tipo diferente (instance
) de su clase:
>>> 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>
Esto se resuelve en las clases de nuevo estilo:
>>> 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'>
-viejo estilo clase no es un tipo, la clase de nuevo estilo es:
>>> isinstance(A, type)
False
>>> isinstance(NA, type)
True
Las clases de estilo antiguo se declaran obsoletas. En Python 3, solo hay clases de estilo nuevo; class A()
es equivalente a class A(object)
y su código arrojará True
en ambos controles.
Echa un vistazo a esta pregunta para algunos más discusión: What is the difference between old style and new style classes in Python?
+1: Esta es una descripción muy clara, y un muy buen punto. ¡Gracias! – EOL
Para cualquier persona que se pregunte, 'isinstance' es [special-cased] (https://github.com/python/cpython/blob/e6a0b5982973e64b9fa28e5e3e54eb8c47882780/Objects/abstract.c#L2898) para instancias y clases antiguas (es decir,' PyClass_Check (cls) && PyInstance_Check (inst) 'en C). Como no hay una relación basada en tipo, obtiene el '__class__' de la instancia para una comprobación' issubclass', que también es [special-cased] (https://github.com/python/cpython/blob/e6a0b5982973e64b9fa28e5e3e54eb8c47882780/Objects /classobject.c#L486) para clases antiguas. – eryksun