为什么isinstance(nonnewstyle,object)在Python 2.X中返回true?

Why does isinstance(nonnewstyle, object) return true in Python 2.X?

我正在读一本关于Python的教科书,它涵盖了新的课堂差异。在使用经典类的解释器中,观察python 2.x中的以下代码:

1
2
3
4
class C: pass
X = C()
isinstance(X, object) #returns true
isinstance(C, object) #returns true

(要使用新样式的类,必须从2.x中的对象类显式派生)

那么,一个不从对象类派生(就像经典类那样)的对象怎么可能是对象的实例呢?在3.x和2.x的情况下,幕后发生了什么?

至于这是否是一个重复的问题:我已经知道技术上一切都是一个对象,我想知道在Python本身的设计中如何显式地处理这种差异,而不是想当然地认为IsInstance的结果。


x是旧样式类c的旧样式实例,它不是object的子类。

但是,所有对象,甚至是旧样式实例,都是某种类型的实例(也就是新样式类)。所有旧样式实例的类型都是types.InstanceType;与types.ClassType(旧样式类的类型)一起,这两种类型负责旧样式类系统的实现。

types.InstanceTypeobject的一个子类,所有的新型类也是如此。isinstance(x, object)返回true不是因为x的旧样式类继承了object的,而是因为它的新样式类继承了。


python中的一切都是object的一个实例,包括object本身:

1
2
>>> isinstance(object, object)
True

这是因为当type.__instancecheck__钩子为self传入object时,True钩子返回EDOCX1,不管另一个论点是什么(记住,特殊方法是在type(something)上查找的,而不是在something上查找的,并且是手动传入的)。

如果要测试旧样式的类,一个更有用的测试是如果该类是type的实例或object的子类:

1
2
3
4
>>> isinstance(C, type)
False
>>> issubclass(C, object)
False

对于新样式的类,这些测试中的任何一个都是正确的:

1
2
3
4
5
6
>>> class Newstyle(object): pass
...
>>> isinstance(Newstyle, type)
True
>>> issubclass(Newstyle, object)
True

例如,测试它们是否是types.InstanceType的实例:

1
2
>>> isinstance(X, InstanceType)
True


你可能把isinstanceissubclass混淆了。旧样式类不是从object派生的,这意味着issubclass(C, object)的结果将是False。另一方面,新的样式类总是(直接或间接)包含object作为基类。

一切都是object的一个例子。这样做,isinstance(C, object)isinstance(x, object)将永远是True