В Python 2, типа и класса не то же самое, в частности, для классов старого стиля, type(obj)
is not the same object как obj.__class__
. Таким образом, это возможно потому, что экземпляры классов старого стиля на самом деле другого типа (instance
), чем их класс:
>>> 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>
Это решается в новых классов:
>>> 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'>
Старый стиле класс не является типом, класс нового типа:
>>> isinstance(A, type)
False
>>> isinstance(NA, type)
True
Классы старого стиля объявлены устаревшими. В Python 3 есть только классы нового стиля; class A()
эквивалентен class A(object)
, и ваш код даст True
в обеих проверках.
Взгляните на этот вопрос для более некоторого обсуждения: What is the difference between old style and new style classes in Python?
+1: Это очень четкое описание и очень хороший момент. Благодаря! – EOL
Для тех, кто задается вопросом, 'isinstance' является [специальным обложением] (https://github.com/python/cpython/blob/e6a0b5982973e64b9fa28e5e3e54eb8c47882780/Objects/abstract.c#L2898) для экземпляров и классов старого стиля (т.е.' PyClass_Check (cls) && PyInstance_Check (inst) 'в C). Поскольку нет отношения типа к типу, он получает экземпляр '__class__' экземпляра для проверки' issubclass', который также [с особым обложением] (https://github.com/python/cpython/blob/e6a0b5982973e64b9fa28e5e3e54eb8c47882780/Objects /classobject.c#L486) для классов старого стиля. – eryksun