【问题标题】:When calling super() in a derived class, can I pass in self.__class__? [duplicate]在派生类中调用 super() 时,可以传入 self.__class__ 吗? [复制]
【发布时间】:2013-08-15 01:04:51
【问题描述】:

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

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

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

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

这似乎行得通,但我有充分的理由不应该这样做吗?

【问题讨论】:

    标签: python python-2.7 super


    【解决方案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不是 Derived,在Derived.method()

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

    【讨论】:

    • 很好,很清楚,解释,谢谢。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2013-11-15
      • 2013-02-11
      • 1970-01-01
      • 2014-08-10
      • 1970-01-01
      • 2015-05-30
      • 2014-04-30
      • 2012-05-10
      相关资源
      最近更新 更多