Can someone explain to me what is going for super() in the child_2 class? I find it a bit counter-intuitive that the super() initiation is picking up the convert_id() function in child_2 instead of child_1. I thought by calling super(), it's suppose to use the function in class_1 to initiate the object.
from abc import ABC, abstractmethod
class base(ABC):
@abstractmethod
def convert_id(self, id):
pass
class child_1(base, ABC):
def __init__(self, id):
self.new_id = self.convert_id(id)
def convert_id(self, id):
return id
class child_2(child_1):
def __init__(self, id):
self.id = id
super().__init__(id=self.id)
def convert_id(self, id):
return id+1
test = child_2(0)
print(test.new_id)
1
This is the normal, expected, and essential way of behaving in Object Oriented programming with inheritance.
The idea is that your specialized classes (the inherited classes), can specialize specific methods. The general pattern is that a method in the superclass can orchestrate the calling of various other methods to perform specific tasks for the instance in question - and, if an specialized subclass cares to refine one of the methods by overriding it, that is the one called.
In runtime terms, what happens is that the self
that child_1.__init__
receives is an instance of child_2
(which also happens to be an instance of child_1
) - but an methods called in that received object will be resolved from child_2.
That is only "counterintuitive" if you are thinking of "self" in child_1.__init__
as an instance of child_1
instead. That "casting" never takes place, and neither is it naturally feasible in Python.
Now, if you have a pattern in your code that requires this behavior: that the __init__
in child_1 calls only the methods as defined in child_1
, and never an overiden method in a subclass, that is feasible through the mechanism of "name mangling": if a method or attribute starts with two underscores (__
), the compiler will bake the class name into that method or attribute name, in a way it won't be overiden by accident (while the hint of the __
makes clear for the programmers that it should not be overiden). In other languages than Python, this behavior is achieved through the use of "private" methods: a method to which the subclasses themselves can't have access (unlike "protected").
In time: this behavior has nothing to do with the fact ou inherit from abc.ABC or from the custom metaclass used by that - this is how the language works.
In other words, the behavior you were expecting will take place if you call your method __convert_id
instead of convert_id
. But keep in mind this is not the natural behavior to have with inheritance, only one possible way that has fewer uses than simply allowing the method to be overiden.