-2

I am investigating the source code of a package, and noticed that classes are able to call certain methods that aren't defined within the class.

For example:

inst = ClassA()
meth = inst.meth1()
"some stuff printing to console"

However, meth1() is not defined within ClassA. In the ClassA definition, there is an input that references another class:

from package.sub.file import ClassB
class ClassA(ClassB):
    ...normal class stuff...

From another file:

class ClassB:
   ...normal class stuff...
    def meth1(self):
        ...stuff...

My main question is how is this possible? How does meth1 become a method for ClassA? I am confused as to why passing ClassB as an input transfers all the methods associated with ClassB to ClassA

swabhard
  • 39
  • 1
  • 5

1 Answers1

3

This is inheritance, a common concept in object-oriented programming.

When one class (the child) inherits from another (the parent), an instance of the child is treated exactly the same as an instance of the parent. That means that if a parent defines a method, it is available to instance of its child as well.


As to how Python implements inheritance, buckle up :)

When ClassA is created, it has an attribute called the method-resolution order (MRO) added to it.

>>> ClassA.__mro__
(<class '__main__.ClassA'>, <class '__main__.ClassB'>, <class 'object'>)

This is built using ClassA, its parent classes, and their parent classes, all the way up to object, the ultimate base class; and it is used for all sorts of attribute lookups.

A somewhat abridged account:

When you try to call inst.meth1, Python goes through the following steps (some steps omitted for clarity and brevity):

  1. Does inst.meth1 exist? No. Start checking the classes in the MRO
  2. Does ClassA.meth1 exist? No, check the next class.
  3. Does ClassB.meth1 exist? Yes.
  4. What is ClassB.meth1? It's a function; call it with inst as the first argument.

Thus (without going into the descriptor protocol in detail), inst.meth1() is equivalent to ClassB.meth1(inst).

chepner
  • 497,756
  • 71
  • 530
  • 681