Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python supports a limited form of multiple inheritance. In what way limited?

Tags:

In the python tutorial it's said that "Python supports a limited form of multiple inheritance".

What are the limitations?

like image 958
ElenaT Avatar asked May 20 '12 14:05

ElenaT


People also ask

Does Python support multiple inheritance in Python?

Yes, Python supports multiple inheritance. Like C++, a class can be derived from more than one base classes in Python. This is called Multiple Inheritance.

What is multiple inheritance does Python support multiple inheritance?

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.


2 Answers

I'm not sure to what limitations the author of the python tutorial was referring, but I would guess it has in part to do with the way that method / attribute lookup is implemented in python (the "method resolution order" or MRO). Python uses the C3 superclass linearization mechanism; this is to deal with what is termed to be "The Diamond Problem".

Once you've introduced multiple inheritance into your class hierarchy, any given class doesn't have a single potential class that it inherits from, it only has "the next class in the MRO", even for classes that expect that they inherit from some class in particular.

For example, if class A(object), class B(A), class C(A), and class D(B, C), then the MRO for class D is D->B->C->A. Class B might have been written, probably was, thinking that it descends from A, and when it calls super() on itself, it will get a method on A. But this is no longer true; when B calls super(), it will get a method on C instead, if it exists.

If you change method signatures in overridden methods this can be a problem. Class B, expecting the signature of a method from class A when it calls super, instead gets a method from C, which might not have that signature (and might or might not not implement the desired behavior, from class B's point of view).

class A(object):     def __init__(self, foo):         print "A!"  class B(A):     def __init__(self, foo, bar):         print "B!"         super(B, self).__init__(foo)  class C(A):     def __init__(self, foo, baaz):         print "C!"         super(C, self).__init__(foo)  class D(B, C):     def __init__(self, foo, bar):         print "D!"         super(D, self).__init__(foo, bar)  print D.mro() D("foo", "bar") 

In this code sample, classes B and C have reasonably extended A, and changed their __init__ signatures, but call their expected superclass signature correctly. But when you make D like that, the effective "superclass" of B becomes C instead of A. When it calls super, things blow up:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>] D! B! Traceback (most recent call last):   File "/tmp/multi_inherit.py", line 22, in <module>     D("foo", "bar")   File "/tmp/multi_inherit.py", line 19, in __init__     super(D, self).__init__(foo, bar)   File "/tmp/multi_inherit.py", line 9, in __init__     super(B, self).__init__(foo) TypeError: __init__() takes exactly 3 arguments (2 given) 

This same sort of thing could happen for other methods as well (if they call super()), and the "diamond" doesn't have to only appear at the root of the class hierarchy.

like image 159
Matt Anderson Avatar answered Oct 01 '22 01:10

Matt Anderson


Apart from @Matt Anderson's answer I think that the limitations is in fact for the old style classes (which the tutorial for Python 2.6 still addresses).

In the Python 3 tutorial the text is now: Python supports a form of multiple inheritance as well.

like image 41
JohnDoDo Avatar answered Oct 01 '22 00:10

JohnDoDo