1

I am getting error in multiple inheritance. As I am new in python so I did not getting why I am unable to do so.

class A(object):
    def say_hello(self):
        print 'A says hello'


class B(A):
    def say_hello(self):
        super(B, self).say_hello()
        print 'B says hello'

class C(A):
    def say_hello(self):
        super(C, self).say_hello()
        print 'C says hello'

class D(A, B):
    def say_hello(self):
        super(D, self).say_hello()
        print 'D says hello'

DD = D()
DD.say_hello() 

I am getting Error:- Cannot create a consistent method resolution.. Why?

Mahendra Garg
  • 516
  • 1
  • 9
  • 27

1 Answers1

5

D inherits A and B and both have a function say_hello. And B inherits from A.

You can't multiply inherit from a base class followed by a derived class
It's impossible to define a consistent MRO that satisfies the usual MRO constraints/guarantees. As described here

You now call super(D, self).say_hello() and python does not know which say_hello to pick.
A or B?!

This as example would work:

class D(A): #D only inherits A not A and B
    def say_hello(self):
        super(D, self).say_hello()
        print 'D says hello'


DD = D()
DD.say_hello()

#output
>>>A says hello
>>>D says hello


#There are 2 connections to As say_hello
    A-----
   / \   |
  B   C  |
  |     /
  \    / 
    D

PS: Please use "self" as name for the first parameter

Update: It would pick As say_hello if the inheritance would look something like this

class A(object):
    def say_hello(cls):
        print 'A says hello'


class B():
     def say_hello(cls):
        print 'B says hello'


class C(B):
    def say_hello(cls):
        super(C, cls).say_hello()
        print 'C says hello'


class D(A, C):
    def say_hello(self):
        super(D, self).say_hello()
        print 'D says hello'


DD = D()
DD.say_hello()

Inheritance-tree:

    A
  /
  |   B
  |   |
  |   C
  \   / 
    D

Python now picks the say_hello with the least specialization e.g. A.

JDurstberger
  • 4,127
  • 8
  • 31
  • 68
  • 1
    Wouldn't it pick A because it is the earlier base with the method? – JL Peyret Dec 03 '15 at 08:25
  • @JLPeyret i am sorry, I do not understand your question. Of course he will call As `say_hello` – JDurstberger Dec 03 '15 at 08:31
  • But you did not answer his question you just removed multiple inheritance. My question was in regards to your 'python does not know' sentence. I think it would pick A as per OPs question, except I suspect B calling A itself might confuse it. – JL Peyret Dec 03 '15 at 08:35
  • I think same.. JL Peyret – Mahendra Garg Dec 03 '15 at 10:35
  • Have you read through the link I provided? There is a very detailed explanation on how inheritance-trees are build and when this fails. – JDurstberger Dec 03 '15 at 10:46
  • It shouldn't pick it because it's the least specialized. It should pick it because it's the first in the left to right order of inheritance of `D(A,C)` – Cobertos Mar 03 '18 at 17:34
  • @Cobertos: I think the point being made is *if* this was allowed, it would be picking the least specialized version; the *reason* is, as you say, because it's listed first, but the problem there is that, reasonably, when `C` asks to invoke a `super()` method, it expects that 1) `A`'s method has not yet been called, and 2) `A`s method will eventually be called (as long as all other classes in the chain cooperatively delegate via `super()` as well). If `A`'s method is invoked *first*, even if it call's `super()` to invoke the others, it's too late; the order of invocation invariants are broken. – ShadowRanger Oct 27 '22 at 14:09