对于子类,isinstance 在 python 中是如何工作的?

问题描述

玩弄isinstance,我想知道它如何用于子类检查。

class A:
    pass

class B(A):
    pass

class C(B):
    pass

print(isinstance(C(),C)) # True,I understand this fine
print(isinstance(C(),B)) # True,Ok,but how is this `True`?
print(isinstance(C(),A)) # True,this too?

What are the differences between type() and isinstance()? 解释了 isinstance 确实适用于我的第二个和第三个 print 语句中所见的子类。我的问题不是那个,但是,它是如何工作的?当定义类 A 时,它没有关于类 B 或类 C 存在的信息,同样,B 没有关于 C 的信息。>

根据 How does isinstance work for List? __instancecheck__ 是为 isinstance 调用的,所以如果我的类 A 是在 BC 之前创建的,这是怎么回事Python 知道 C() 确实是子类(BA 的子类)或 AC,是 B 的子类,而 A 本身是 float emulated_step(float a,float x){ return 1.0/(1+pow(1000,-(x-a)*8192)); } ) 的子类?

当我在 Python 中继承一个类使得基类知道子类存在时会发生什么事情吗?如果是这种情况,谁能告诉我这是如何工作的?

PS:如果需要任何说明,请告诉我。非常感谢。

解决方法

C() 持有对其类型 C 的引用,而 C 具有其所有祖先(包括其自身)的元组 C.__mro__。默认 type.__instancecheck__ 查看该元组以查看对象是否是特定类的实例。

如果您从 type.__instancecheck__ 开始执行函数调用,您最终会到达 this loop

for (i = 0; i < n; i++) {
    if (PyTuple_GET_ITEM(mro,i) == (PyObject *)b)
        return 1;

Python 中的类 do 也有关于它们的子类的信息 - C 级 PyType_Ready 函数 informs 在准备子类时关于子类的基类。但是,对于 isinstance 的第二个参数有很多后代的情况,从基类向下搜索继承图会产生病态缓慢的行为。

,

基类不需要知道任何关于它被其他类继承的信息。 当您在 isinstance() 上调用 C() 时,它是 B 的子类(A 的子类),它创建了从 C 向上的继承树(一直到对象,它是 B 的基类)每节课)。 然后它“知道”A 和B 在那里。 您定义 A、B、C 的顺序没有任何意义。