简体   繁体   中英

Better way to access super class method in multiple inheritance

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.

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 .

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.

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

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM