15
class Animal(object):
    def eat(self):
        print("I eat all")

class C(object):
    def eat(self):
        print("I too eat")

class Wolf(C, Animal):
    def eat(self):
        print("I am Non Veg")
        super(Wolf, self).eat()
        Animal.eat(self)

w = Wolf()
w.eat()

I am learning multiple inheritance in python, I want to access Animal and C method eat from derived class using super method.

Default call of super inside calls C class method eat, but to call Animal class method I used Animal.eat(self) .My question is how can I call Animal class method using super method.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
Kracekumar
  • 19,457
  • 10
  • 47
  • 56
  • possible duplicate of [How does Python's super() work with multiple inheritance?](http://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance) – Eli Bendersky Sep 14 '11 at 12:06

4 Answers4

8

If you want to do sane multiple inheritance, you need everyone to be calling super except exactly one base class, which has as its duty not to call super. Having two completely-independent base classes with the same method isn't something that makes sense using OOP theory and is not something that Python has the tooling to handle well.

You might see two apparently-independent base classes used in a lot of examples, but in those cases the example method is usually __init__, and the single non-super-calling base class for it is object.

Mike Graham
  • 73,987
  • 14
  • 101
  • 130
  • 4
    `Having two completely-independent base classes with the same method isn't something that makes sense using OOP theory and is not something that Python has the tooling to handle well.` What about mixins trying to decorate behavior? – Bharat Khatri Mar 21 '18 at 14:19
2

You can't call Animal.eat using super. super uses Python's Method Resolution Order (MRO) to figure out which class to call, and C is overshadowing Animal in that MRO.

In your example, super(Wolf, self).eat() has the same effect as C.eat(self). Calling Animal.eat(self) works, but only as long as the inheritance graph stays the way it currently is.

Having to call a method that's not available due to the MRO is an indication that the class modelling needs to be improved.

phihag
  • 278,196
  • 72
  • 453
  • 469
  • 10
    *`super(Wolf, self).eat()` is just syntactic sugar for `Wolf.eat(self).`* No it's not—it's just normal syntax. These two calls are semantically different, as the first walks the MRO and may do different things for different instances of `Wolf` (depending on more specialized classes subclassing it), whereas the second just calls `Wolf.eat`, which in this case will lead to infinite recursion. (The former actually happens to call `C.eat` in this code.) *Calling `Animal.eat(self)` is perfectly fine* Unless you want arbitrary inheritance to allow calling all parent methods exactly once. – Mike Graham Sep 14 '11 at 12:13
  • @Mike Graham is correct. super(Wolf, self.).eat() isn't sugar for Wolf.eat(self), which would be a recursive call to the subclass. super(Wolf, self).eat() calls the eat() method of the parent class. – Alex Smith Sep 14 '11 at 12:25
  • @Mike Graham Yes, *syntactic sugar* is the wrong term here. Fixed the unrolling of super to `C.eat`, and clarified the rest. Thanks! – phihag Sep 14 '11 at 12:30
  • @phihag, Your edit makes some good improvements, but I still think you're offering somewhat shaky advice. Calling `C.eat` with `super` and `Animal.eat` directly cannot ensure that both of them get called exactly once, since the MRO of a further subclass of Wolf may not be what you expect. – Mike Graham Sep 14 '11 at 12:32
  • @Mike Graham Can you give an example for a subclass whose `super(Subclass, self).eat()` ends up not calling `Animal.eat` and `Wolf.eat` exactly once, assuming the subclasses don't do any non-MRO superclass calling shenanigans of themselves? I was under the impression that one of the criteria for an MRO is precisely that `C` always comes before `Wolf` in any linearization of any subclass of `Wolf`. – phihag Sep 14 '11 at 12:40
1

super is used for look-up in parent classes. In your case, because you set the inheritance in the order C, Animal, the order of preference for method finding is the following:

  • first parent class
  • second parent class

So super will return the closest parent's method.

A remark though, is that search is done as depth-first:

>>> class A(object):
...      def t(self):
...          print 'from A'
>>> class B(object):
...      def t(self):
...          print 'from B'
>>> class C(A):
...      pass
>>> class D(C, B):
...      pass
>>> d = D()
>>> d.t()
from A
Joël
  • 2,723
  • 18
  • 36
  • Try same thing after replacing `class D(C, B)` to `class D(B, C):`, find the difference – Kracekumar Sep 14 '11 at 12:16
  • Yes the result is different, as Python will search first in class `B`, and will find method `t` that returns `from B`. In my example, it searches in `C`, then in its parents, *before* searching in `B`. – Joël Sep 14 '11 at 14:00
  • I don't see super being used here. How can that be used in this example to achive the same results? – Arindam Roychowdhury Feb 08 '17 at 05:49
1

super() uses the Method Resolution Order (MRO) to determine which superclass method is called.

The best way to control which class method in the case of multiple inheritance is to call it explicitly, without using super().

Or you can reorder the superclasses in the subclass definition to change the MRO. This allows you to continue using super() but sacrifices some readability, IMO.

Example using super():

class Wolf(C, Animal):
    def eat(self):
        # C.eat() comes first in the MRO
        super(Wolf, self).eat()

Versus:

class Wolf(Animal, C):
    def eat(self):
        # Animal.eat() comes first in the MRO
        super(Wolf, self).eat()
Alex Smith
  • 1,495
  • 12
  • 13
  • This also does not work in general, because subclasses of `Wolf` can have MROs that look different than you expect. – Mike Graham Sep 14 '11 at 12:24
  • @Mike Graham: This example demonstrates how to control the MRO for only for the `Wolf` class, not for possible subclasses of `Wolf`, but you raise an excellent point. – Alex Smith Sep 14 '11 at 12:31
  • Right, but `super` exists to solve the problem of calling every superclass method exactly once in the presence of arbitrary inheritance. If we weren't worried about additional inheritance, we wouldn't have required `super` in the first place. – Mike Graham Sep 14 '11 at 12:35
  • `super()` calls only one superclass method, not each of them. Even without `super()`, this can be done by calling the superclass method explicitly, but `super()` is nice because it provides a layer of abstraction over the inheritance hierarchy. – Alex Smith Sep 14 '11 at 12:55
  • `super` calls exactly one superclass method. When *everyone* uses super except for the base class that exists not to, all of them get called exactly once, and this is what `super` is for. `super` exists because you **cannot** get this same behavior by just calling base class methods explicitly. – Mike Graham Sep 14 '11 at 14:11