2

Hello i was searching about class inheritance in python and i saw that it supports Multiple Inheritance as well but somehow seems problematic :o I ve found an example:

class ParentOne:
    def __init__(self):
        print "Parent One says: Hello my child!"
        self.i = 1

    def methodOne(self):
        print self.i

class ParentTwo:
    def __init__(self):
        print "Parent Two says: Hello my child"

class Child(ParentOne, ParentTwo):
    def __init__(self):
        print "Child Says: hello"
A=Child()

Output

Child Says: hello

So when child inherits ParentOne and ParentTwo why arent those classes initialised? Should we manually initialize them within the inherit class Child? Whats the correct example so we can see all messages printed using only inheritage?

In fact, it is slightly more complex than that; the method resolution order changes dynamically to support cooperative calls to super(). This approach is known in some other multiple-inheritance languages as call-next-method and is more powerful than the super call found in single-inheritance languages.

How can it be more powerful when it need to be initialized manually? Sorry for all these questions. Thanks in advance.

1
  • 4
    Remember from the Zen: explicit is better than implicit. Commented Oct 5, 2012 at 20:06

5 Answers 5

7

This is what super is for:

class ParentOne():
    def __init__(self):
        super().__init__()        
        print("Parent One says: Hello my child!")
        self.i = 1

    def methodOne(self):
        print(self.i)

class ParentTwo():
    def __init__(self):
        super().__init__() 
        print("Parent Two says: Hello my child")

class Child(ParentOne, ParentTwo):
    def __init__(self):
        super().__init__()
        print("Child Says: hello")

A=Child()

prints

Parent Two says: Hello my child
Parent One says: Hello my child!
Child Says: hello
Sign up to request clarification or add additional context in comments.

6 Comments

Not quite: this is tagged python-3, so super has a different format - just super().__init__.
@DanielRoseman It works this way too. But yeah, the short form is better if you know you're on 3.x (unfortunately, not all of us are).
@unutbu Nice answer. If you please, could you somehow explain what method resolution order changes dynamically to support cooperative calls to super() means? Thanks :)
I think the word dynamic here is referring to the fact that you do not know what method super().__init__() is going to run until run-time because it depends on self's MRO. super().__init__ looks in self.__class__.mro() for the next class after the current class and calls that class's __init__.
Mnyaaaahhhhh.... super() is really mostly for when you don't know what your parent classes are, like when you are using mixins. In this case you can just call the classes directly. But you need to know which case you have and when to use which, as you can't mix them. :-) But sure, in this case, super() works, as the whole hierarchy has the same parameters (only self) to __init__().
|
4

The base class methods are not called because you are not calling them. You always have to do this explicitly, no matter if there is a single base or multiple bases. In this simple case, add super().__init__() to all three classes. For more general advice, read Python’s super() considered super! .

Comments

2

It's very simple:

class ParentOne:
    def __init__(self):
        print "Parent One says: Hello my child!"
        self.i = 1

    def methodOne(self):
        print self.i

class ParentTwo:
    def __init__(self):
        print "Parent Two says: Hello my child"

class Child(ParentOne, ParentTwo):
    def __init__(self):
        ParentOne.__init__(self)
        ParentTwo.__init__(self)
        print "Child Says: hello"

A=Child()

Problem solved. You can also use super() but in this case you do not need to. Note that you can't mix the two methods, you either need to call super() in all the classes in the hierarchy, or none of them.

Comments

2

In your example, you are specifically overriding the inherited __init__ method with the child classes __init__ method. If you want all of them to be run, you can explicitly invoke the parents' init methods with super().

If you had not overridden the __init__ method, then the one from ParentOne would be used in this example.

Comments

1

The correct example is something along (Python3):

class BaseClass:
    def __init__(self):
        print("Initializing base")

class ParentOne(BaseClass):
    def __init__(self):
        super().__init__()
        print("Initializing parent 1")

class ParentTwo(BaseClass):
    def __init__(self):
        super().__init__()
        print("Initializing parent 1")

class Child(ParentOne, ParentTwo):
    def __init__(self):
        super().__init__()
        print("Initializing child")

c = Child()

Python defines the "super" built-in that correctly resolves the next-to-be-called method, using a well described method resolution order - so, it is not "problematic" at all, - to the contrary, it works quite well on corner cases other languages do have problem - it is described here: http://www.python.org/download/releases/2.3/mro/

1 Comment

Note that in this specific case, BaseClass is not needed, as object also accepts .__init__() and it's implicitly the base class of the Parent* classes. It becomes necessary (and recommended) once the method does not exist "further up" or has a incompatible signature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.