Hello awesome community, I was learning the OOPS concepts with python as a part of my curriculum. I am having a problem with multiple inheritance in python. The following is my code:
#!/usr/bin/env python
class Base1(object):
def __init__(self):
self.base1var = "this is base1"
class Base2(object):
def __init__(self):
self.base2var = "this is base2"
class MainClass(Base1, Base2):
def __init__(self):
super(MainClass, self).__init__()
if __name__ == "__main__":
a = MainClass()
print a.base1var
print a.base2var
and when running, I am getting the following error
print a.base2var
AttributeError: 'MainClass' object has no attribute 'base2var'
If I swap the order of classes inherited, the variable name in the error changes accordingly.
Am I using super()
wrong when I want to call the constructors of the two inherited classes?
How can I correctly inherit from multiple base classes and use the variables and methods in the main class without this error?
Thank you.
Multiple inheritance is useful in many situations as a developer, but it greatly increases the complexity of the language, which makes life harder for both the compiler developers and the programmers. One problem occurs when two parent classes have data members or methods of the same name.
Inheritance is the mechanism to achieve the re-usability of code as one class(child class) can derive the properties of another class(parent class). It also provides transitivity ie. if class C inherits from P then all the sub-classes of C would also inherit from P.
A class can be derived from more than one base class in Python, similar to C++. This is called multiple inheritance. In multiple inheritance, the features of all the base classes are inherited into the derived class.
Python is one of the few modern programming languages that supports multiple inheritance. Multiple inheritance is the ability to derive a class from multiple base classes at the same time.
You need to add a super
call to Base1 so that Base2's __init__
will get called after Base1's. You can also add a super
call to Base2. It's not necessary, but it won't hurt.
class Base1(object):
def __init__(self):
super(Base1, self).__init__()
self.base1var = "this is base1"
class Base2(object):
def __init__(self):
#super(Base2, self).__init__()
self.base2var = "this is base2"
class MainClass(Base1, Base2):
def __init__(self):
super(MainClass, self).__init__()
if __name__ == "__main__":
a = MainClass()
print a.base1var
print a.base2var
output
this is base1
this is base2
BTW, you really should be using Python 3. super
is much nicer in modern Python. :)
If you use super()
, you must use it consistently to ensure all classes' methods are called. Your Base1
and Base2
classes should also call super(...).__init__()
in their __init__()
methods. This will ensure that all classes in the method resolution order are eventually called.
This does get a little tricky when not all __init__()
methods have an empty argument list. At some point, super()
will have you calling object.__init__()
, and that never takes any arguments. The trouble is, you might not know which classes this might happen in ahead of time. You can remedy this by creating an object
subclass that takes any number of arguments in __init__()
, and deriving from that. That class needn't call object.__init__()
because that method doesn't actually do anything (or, if you're paranoid that that might change, you can call object.__init__()
without using super()
).
In general, super()
requires extra care in argument handling because you might not know which class will be next in the method resolution order, since users of your code might make new classes using your base classes in combinations you haven't anticipated. So you'll need to do some work to make sure the method signatures in all your classes are compatible.
For more information, see Raymond Hettinger's seminal Python's Super() Considered Super.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With