1

How does isinstance work in python for subclasses?

Playing around with isinstance, I would like to know how it works for a subclass check.

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()? explains that isinstance does work for a subclass as seen in my second and third print statement. My question is not that, but, how does it work? When class A was defined it had no information but about the existence of class B or class C, likewise B had no information about C.

According to How does isinstance work for List? __instancecheck__ is called for isinstance, so if my class A was created before B and C how does this Python know that C() is indeed an instance of one of the subclass (B, subclass of A) or subclass of subclass of A (C, which is a subclass of B which itself is a subclass of A)?

Does something happen when I inherit a class in Python such that the base class knows that a child class exists? If that is the case can anyone let me know how this works?

PS : Do let me know if any clarification is needed. Many Thanks.

Submitted May 02nd 2021 by Admin

Answers
0

The base class doesn't need to know anything about it's inheritance by other classes. When you call the isinstance() on C(), which is a subclass of B (which is a subclass of A) it creates the inheritance tree from C upwards (all the way to object which is the base class of every class). It then "knows" that A and B are there. The order in which you defined A,B,C doesn't have any meaning.

Admin | 4 months ago


0

C() holds a reference to its type, C, and C has a tuple C.__mro__ of all its ancestors (including itself). The default type.__instancecheck__ looks through that tuple to see whether an object is an instance of a particular class.

If you follow the function calls down from type.__instancecheck__, you eventually end up in this loop:

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

Classes in Python do also have information about their subclasses - the C-level PyType_Ready function informs the base classes about a subclass while readying the subclass. However, searching the inheritance graph downward from the base class would produce pathologically slow behavior for cases where the second argument to isinstance has a lot of descendants.

Admin | 4 months ago



Relevant Questions


Missing arguement

January 05th 2021