Python multiple inheritance does not display class variables or method of second inherited base class

Hi, amazing community, I studied OOPS concepts using python as part of my curriculum. I have a multiple inheritance problem in python. Below 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 at startup I get the following error

 print a.base2var AttributeError: 'MainClass' object has no attribute 'base2var' 

If I change the order of the inherited classes, the variable name in the error will change accordingly.

Am I using super() incorrectly when I want to call the constructors of two inherited classes?

How can I correctly inherit from several base classes and use variables and methods in the main class without this error?

Thanks.

+5
source share
5 answers

You need to add a super call to Base1 so that Base2 __init__ is called after Base1. You can also add a super call to Base2. It is not necessary, but it will not 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 

By the way, you really should use Python 3. super much better in modern Python. :)

+4
source

If you use super() , you must use it consistently to ensure that methods of all classes are called. The Base1 and Base2 classes must also call super(...).__init__() in their __init__() methods. This ensures that all classes in order of method resolution are ultimately called.

This is a bit complicated when not all __init__() methods have an empty argument list. At some point, super() will call object.__init__() , and this never takes any arguments. The trouble is that you don’t know what classes this can happen in advance. You can fix this by creating a subclass of object that takes any number of arguments in __init__() and follows from this. This class should not call object.__init__() because this method actually does nothing (or, if you are paranoid, which can change, you can call object.__init__() without using super() ).

In the general case, super() requires special attention when processing arguments, because you cannot know which class will be next in order of method resolution, since users of your code can create new classes using base classes in combinations that you do not expect. Therefore, you will need to do some work to make sure that the method signatures in all your classes are compatible.

For more information, see Raymond Hettinger seminal Python Super () reviewed by super .

+3
source

Basically, what happens is that Python looks at the parent classes (and their parents, etc. See the link at the end of this paragraph) for some __init__ method. It reads classes from left to right, so it first sees Base1 . Since Base1.__init__ , this method is called. Read a more detailed explanation in this answer .

I believe that the only way to call all the relevant methods is to do it manually

 class MainClass(Base1, Base2): def __init__(self): Base1.__init__(self) Base2.__init__(self) 

then

 a = MainClass() print(a.base1var) print(a.base2var) 

prints

 this is base1 this is base2 
+2
source

Base1 __init__ overrides Base2 __init__.py , so base2var never created.

You have to use super , see How does super () Python work with multiple inheritance?

+1
source

You can not use super, but not for this purpose. It turned out super I changed your 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(Base2, Base1): def __init__(self): super(MainClass, self).__init__() if __name__ == "__main__": a = MainClass() print (a.base2var) 

Than you

 this is base2 
0
source

Source: https://habr.com/ru/post/1274476/


All Articles