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

2

22

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

What are the limitations?

Rhomboid answered 20/5, 2012 at 14:50 Comment(0)
R
5

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.

Ranchod answered 21/5, 2012 at 12:44 Comment(0)
L
12

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.

Linder answered 20/5, 2012 at 16:21 Comment(1)
All this is true, but any language with multiple inheritance has to deal with these issues. If we assume your answer is correct, then what language (with MI) wouldn't have a limited form of multiple inheritance?Ceremonial
R
5

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.

Ranchod answered 21/5, 2012 at 12:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.