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

时间:2013-08-13 12:06:49

标签: python python-2.7 super

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

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

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

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

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

2 个答案:

答案 0 :(得分:78)

不,你不能。 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) SubclassDerived不是 Derived.method()Subclass

在示例中,[Subclass, Derived, Base]的MRO为super()type(self)需要知道从哪里开始搜索任何被覆盖的方法。使用Subclass,您可以告诉它Derived.method()开始,接下来会找到{{1}},这就是我们开始的地方。

答案 1 :(得分:11)

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