简体   繁体   English

在多重继承中访问超类方法的更好方法

[英]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.我正在python中学习多重继承,我想使用super方法从派生类访问AnimalC方法eat

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. super内部的默认调用调用C类方法eat ,但要调用Animal类方法,我使用了Animal.eat(self)我的问题是如何使用super方法调用Animal类方法。

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.如果你想进行合理的多重继承,你需要每个人都调用super除了一个基类,基类有责任不调用 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.使用相同的方法拥有两个完全独立的基类并不是使用 OOP 理论有意义的事情,也不是 Python 有工具可以很好处理的事情。

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 .您可能会在许多示例中看​​到两个明显独立的基类,但在这些情况下,示例方法通常是__init__ ,而它的单个非超级调用基类是object

You can't call Animal.eat using super .您不能使用super调用Animal.eat super uses Python's Method Resolution Order (MRO) to figure out which class to call, and C is overshadowing Animal in that MRO. super使用Python 的方法解析顺序 (MRO)来确定要调用哪个类,而C在该 MRO 中盖过了Animal

In your example, super(Wolf, self).eat() has the same effect as C.eat(self) .在您的示例中, super(Wolf, self).eat()C.eat(self)具有相同的效果。 Calling Animal.eat(self) works, but only as long as the inheritance graph stays the way it currently is.调用Animal.eat(self)有效的,但Animal.eat(self)是继承图保持当前的状态。

Having to call a method that's not available due to the MRO is an indication that the class modelling needs to be improved.由于 MRO 而不得不调用一个不可用的方法表明类建模需要改进。

super is used for look-up in parent classes. super用于在父类中查找。 In your case, because you set the inheritance in the order C, Animal , the order of preference for method finding is the following:在您的情况下,因为您按照C, Animal的顺序设置继承,方法查找的优先顺序如下:

  • first parent class第一个父类
  • second parent class第二个父类

So super will return the closest parent's method.所以super将返回最近的父方法。

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. super()使用方法解析顺序 (MRO)来确定调用哪个超类方法。

The best way to control which class method in the case of multiple inheritance is to call it explicitly, without using super() .在多重继承的情况下控制哪个类方法的最好方法是显式调用它,而不使用super()

Or you can reorder the superclasses in the subclass definition to change the MRO.或者,您可以对子类定义中的超类重新排序以更改 MRO。 This allows you to continue using super() but sacrifices some readability, IMO.这允许您继续使用super()但牺牲了一些可读性,IMO。

Example using super() :使用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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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