一尘不染

在派生类中调用super()时,可以传递self .__ class__吗?

python

我最近发现,在我应该调用的基类中调用方法:

super([[derived class]], self).[[base class method]]()

很好,可以。但是,我发现自己经常在类之间进行复制和粘贴,而常常忘记将派生类参数固定为super()函数。

我想避免必须记住要更改派生类参数。我是否可以仅将其self.__class__用作super()函数的第一个参数?

它似乎可行,但是有充分的理由为什么我不应该这样做?


阅读 169

收藏
2020-12-20

共1个答案

一尘不染

你不能。该super()调用需要知道该方法属于哪个类,以在基类中搜索被覆盖的方法。

如果您在传递self.__class__(或更好,type(self))则super()给出 错误的 出发点,以寻找方法,并最终调用_再次它自己的方法_ 。

在构成方法解析顺序序列的类列表中,将其视为指针。如果传入,type(self)则指针将引用任何子类,而不是原始起点。

以下代码导致无限递归错误:

class Base(object):
    def method(self):
        print 'original'

class Derived(Base):
    def method(self):
        print 'derived'
        super(type(self), self).method()

class Subclass(Derived):
    def method(self):
        print 'subclass of derived'
        super(Subclass, self).method()

演示:

>>> Subclass().method()
subclass of derived
derived
derived
derived

<... *many* lines removed ...>

  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
RuntimeError: maximum recursion depth exceeded while calling a Python object

因为type(self)Subclass没有 DerivedDerived.method()

在这个例子中,MRO为Subclass[Subclass, Derived, Base],而super()需要知道从哪里开始寻找任何替代的方法。通过使用type(self)它告诉它从开始Subclass,所以它将Derived.method()在我们开始的地方找到下一个。

2020-12-20