python multiple inheritance, calling base class function
I am getting confused as to how calling of super(ParentOne, self).foo() is evaluated in this case. As per my understanding ParentOne class does not have any idea of the methods and attributes of ParentTwo class. How does super works in case of multiple inheritance
3 Answers 3
Python constructs a method resolution order (MRO) when it builds a class. The MRO is always linear. If python cannot create a linear MRO, then a ValueError will be raised. In this case, your MRO probably looks like:
Child -> ParentOne -> ParentTwo -> object
Now when python see’s a super(cls, self) , it basically looks at self and figures out the MRO. It then uses cls to determine where we are currently at in the MRO and finally it returns an object which delegates to the next class in the MRO. So, in this case, a super(Child, self) call would return an object that delegates to ParentOne . A super(ParentOne, self) class would return an object that delegates to ParentTwo . Finally a super(ParentTwo, self) call would delegate to object . In other words, you can think of super as a fancier version of the following code:
def kinda_super(cls, self): mro = inspect.getmro(type(self)) idx = mro.index(cls) return Delegate(mro[idx + 1]) # for a suitably defined `Delegate`
Note that since super(ParentTwo, self) returns a «Delegate» to object , we can see why you’re getting an AttributeError when you try super(ParentTwo, self).foo() — Specifically the reason is because object has no foo method.
How do I call a parent class’s method from a child class in Python?
When creating a simple object hierarchy in Python, I’d like to be able to invoke methods of the parent class from a derived class. In Perl and Java, there is a keyword for this ( super ). In Perl, I might do this:
package Foo; sub frotz < return "Bamf"; >package Bar; @ISA = qw(Foo); sub frotz
In Python, it appears that I have to name the parent class explicitly from the child. In the example above, I’d have to do something like Foo::frotz() . This doesn’t seem right since this behavior makes it hard to make deep hierarchies. If children need to know what class defined an inherited method, then all sorts of information pain is created. Is this an actual limitation in python, a gap in my understanding or both?
I think the naming of the parent class isn’t such a bad idea. It can help when the child class inherits from more than one parent, since you explicitly name the parent class.
Be aware of the changes in super handling between Python 2 and Python 3 https://www.python.org/dev/peps/pep-3135/. Naming the class is no longer required (although may still be a god idea, at least sometimes).
16 Answers 16
class Foo(Bar): def baz(self, **kwargs): return super().baz(**kwargs)
class Foo(Bar): def baz(self, arg): return super(Foo, self).baz(arg)
Yes, you can, but the OP was asking how to do it without explicitly naming the superclass at the call site (Bar, in this case).
super() is weird with multiple inheritance. It calls to the «next» class. That might be the parent class, or might be some completely unrelated class which appears elsewhere in the hierarchy.
The syntax super(Foo, self) is for Python 2.x correct? In Python 3.x, the super() is preferred correct?
super(type[, object-or-type])
Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.
class A(object): # deriving from 'object' declares A as a 'new-style-class' def foo(self): print "foo" class B(A): def foo(self): super(B, self).foo() # calls 'A.foo()' myB = B() myB.foo()
Better example than Adam’s because you demonstrated using a new-style class with the object base class. Just missing the link to new-style classes.
Adam’s has the benefit of showing both Python2 and Python3 forms. While this example works with both versions, the «new-style class» business and the arguments to super() are artifacts of Python2 — see Adam’s Python 3 version for cleaner code example (in Python3, all classes are now new-style classes, so there is no need to explicitly inherit from object , and super() does not require the class and self arguments, it’s just super() ).
Is there any difference between calling just super().foo() instead of super(B, self).foo()? Both seem be working.
@RavindraS The super function without arguments only works from within a method, while the two-argument version can be used in free functions as well. See the end of the doc.
ImmediateParentClass.frotz(self)
will be just fine, whether the immediate parent class defined frotz itself or inherited it. super is only needed for proper support of multiple inheritance (and then it only works if every class uses it properly). In general, AnyClass.whatever is going to look up whatever in AnyClass ‘s ancestors if AnyClass doesn’t define/override it, and this holds true for «child class calling parent’s method» as for any other occurrence!
This mandates that the ImmediateParentClass be also present in scope for this statement to be executed. Just having the object imported from a module will not help.
@TusharVazirani if the parent class is an immediate parent , it is in the scope of the whole class, isn’t that?
@TusharVazirani now I understand, thank you. I was thinking about calling from the current class’s method (as was stated by the OP).
Python 3 has a different and simpler syntax for calling parent method.
If Foo class inherits from Bar , then from Bar.__init__ can be invoked from Foo via super().__init__() :
class Foo(Bar): def __init__(self, *args, **kwargs): # invoke Bar.__init__ super().__init__(*args, **kwargs)
Many answers have explained how to call a method from the parent which has been overridden in the child.
«how do you call a parent class’s method from child class?»
«how do you call inherited methods?»
You can call methods inherited from a parent class just as if they were methods of the child class, as long as they haven’t been overwritten.
class A(): def bar(self, string): print("Hi, I'm bar, inherited from A"+string) class B(A): def baz(self): self.bar(" - called by baz in B") B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B"
yes, this may be fairly obvious, but I feel that without pointing this out people may leave this thread with the impression you have to jump through ridiculous hoops just to access inherited methods in python. Especially as this question rates highly in searches for «how to access a parent class’s method in Python», and the OP is written from the perspective of someone new to python.
Calling function from the base class
I’m new to Python. I have a class which has some common definitions which will be used across several other classes in a module. This is the current structure of my program.
class A(object): def __init__(self, x, y): """Initialization method""" super(A, self).__init__() self.x = x self.y = y def function_1(self, ftype): >> return abc def function_2(self, stype): >> return xyz class B(A): def __init__(self, x, y, e_type): A.__init__(self, x, y) self.e_type = enablement_type def function_3(self, mtype): >> **HERE I need to call the function1 and function2 of class A**
A.function1(self, ftype='new') A.function2(self, stype='new')
is the correct way? Pylint says all good when I did so. 2: Also, can you elaborate super in easy terms please
2 Answers 2
For ur 1st question: What you are doing is code reusability with inheritance concept.
Once u said ‘class B(A)’, all the members and functions of A are available in B for usage. Hence, u can directly call B function like below
self.function1(ftype='new') self.function2(stype='new')
This is the typical way of accessing any function of a instance in Python. Whatever you mentioned in question is just access a static function in any other file. That is going to work anyway. But it has nothing to do with inheritance.
For your 2nd question: In case of inheritance, you can choose to completely redefine a generic reusable function from base class or extend some feature for a special case or just use as it is. In the case of extension of existing function, what you need to do is override the function you want to extend and it’s body should call all base class function, then additional code. Here calling a base class function is done with super.function()
def function1(self, ftype): super.function1(self, ftype) # the new code specific to this class goes here
init() are special functions, called as constructor. The are called while instantiating the class like ‘objInstance = B()’ . Other functions are treated as explained above.
Hope it clarifies your doubts.
How to call Base Class’s __init__ method from the child class? [duplicate]
If the init function of the base class takes some arguments that I am taking them as arguments of the child class’s init function, how do I pass these arguments to the base class? The code that I have written is:
class Car(object): condition = "new" def __init__(self, model, color, mpg): self.model = model self.color = color self.mpg = mpg class ElectricCar(Car): def __init__(self, battery_type, model, color, mpg): self.battery_type=battery_type super(ElectricCar, self).__init__(model, color, mpg)
4 Answers 4
You could use super(ChildClass, self).__init__()
class BaseClass(object): def __init__(self, *args, **kwargs): pass class ChildClass(BaseClass): def __init__(self, *args, **kwargs): super(ChildClass, self).__init__(*args, **kwargs)
Your indentation is incorrect, here’s the modified code:
class Car(object): condition = "new" def __init__(self, model, color, mpg): self.model = model self.color = color self.mpg = mpg class ElectricCar(Car): def __init__(self, battery_type, model, color, mpg): self.battery_type=battery_type super(ElectricCar, self).__init__(model, color, mpg) car = ElectricCar('battery', 'ford', 'golden', 10) print car.__dict__
If you pass BaseClass to super , it’ll skip over BaseClass and call object.__init__ , which is almost certainly not what you want.
Meanwhile, the only thing wrong with the OP’s code is his indentation, explaining super (even if you explained it correctly, which you didn’t) doesn’t help, especially given that he already used it exactly the same way; in fact, it’s character-for-character identical.
Thanks, @abarnert. Initially, he did not post his code and the question he asked is the one in the title.
Your answer is the most highly voted. You should really reference how to not use the derived class name by doing super().__init__(args)
As Mingyu pointed out, there is a problem in formatting. Other than that, I would strongly recommend not using the Derived class’s name while calling super() since it makes your code inflexible (code maintenance and inheritance issues). In Python 3, Use super().__init__ instead. Here is the code after incorporating these changes :
class Car(object): condition = "new" def __init__(self, model, color, mpg): self.model = model self.color = color self.mpg = mpg class ElectricCar(Car): def __init__(self, battery_type, model, color, mpg): self.battery_type=battery_type super().__init__(model, color, mpg)
Thanks to Erwin Mayer for pointing out the issue in using __class__ with super()