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

Sim*_*wsi 47 python super python-2.7

我最近发现(通过StackOverflow)调用基类中的方法我应该调用:

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

没关系,它有效.但是,当我进行更改时,我发现自己经常在类之间复制和粘贴,而且我经常忘记将派生类参数修复为super()函数.

我想避免记得更改派生类参数.我可以改为使用self.__class__super()函数的第一个参数吗?

它似乎有用,但有充分的理由我不应该这样做吗?

Mar*_*ers 79

你不能.该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()
Run Code Online (Sandbox Code Playgroud)

演示:

>>> 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
Run Code Online (Sandbox Code Playgroud)

因为type(self)Subclass,不是 Derived,在Derived.method().

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

  • 优秀,非常清楚,解释,谢谢. (5认同)

Ign*_*ams 12

self.__class__可能不是一个子类,而是一个孙子或更年轻的类,导致一个堆栈破坏循环.