For single-inheritance,
super(SimpleRoomsEnv, self).__init__() essentially does exactly the same thing as
Environment.__init__(self).
However, for multiple inheritance it provides an interesting way of handling the
"Dreaded Diamond" problem by ensuring that the
__init__ methods for all superclasses are each called exactly once by eliminating duplicates, but also ensures that the order in which they're called is consistent too
The inheritance heirarchy is essentially a graph of classes - obviously there are multiple __init__ methods which need to be called, and they need to be called in a specific order known as the
Method Resolution Order (
MRO). Python defines an algorithm for this which is basically a depth-first search.
This solution to the diamond problem is known as 'cooperative' multiple inheritance. There are other solutions, but this one is (IMO) a much better one than you get from languages like C++
Firstly, look at what happens when you attempt to implement the dreaded diamond without using
super():
https://repl.it/repls/UrbanKindheartedWorkspaceLook carefully at the
child class __init__() method - Two things:
- Firstly, the need to call '
right.__init__(self)' and '
left.__init__(self)' -- this is problematic on its own because a programmer must remember to call those in the correct order to be consistent with the order in which
right and
left are inherited by
child. (i.e. base->right->left->child)
- Secondly, the output shows that the
base.__init__() method is called
twice - probably
not what a programmer wants to happen because it's duplication,
One thing I'd point out is that there's nothing technically "wrong" here - this is the classic way of solving the multiple inheritance diamond problem, and this is the way that C++ does things. It sucks though - you end up with the base class being inherited twice and needing to care about the inheritance order in two different places - this is is one of the reasons why multiple inheritance is a bit dirty in C++ and it just makes the code harder to work with.
Python has a far more elegant solution to this called 'cooperative multiple inheritance' which uses the built-in
super() function to avoid making any direct references to the superclass, adding an extra level of indirection instead to let
super() call the correct parent or sibling according to Python's "
Method Resolution Order" rules (basically a depth-first algorithm which steps through the multiple inheritance 'graph').
https://repl.it/repls/EdibleLinearCgiTwo things here:
- Firstly, super() figures out the Method Resolution Order (all nicely take care of, no need to over-think it!)
- Secondly, super() eliminates the extra (usually unwanted) call out to the class called "
base".
Maybe some interesting reading related to this:
https://www.python.org/download/releases/2.3/mro/https://docs.python.org/3/library/functions.html#super