Python super()参数:为什么不是super(obj)?

Gab*_*iel 27 python inheritance super

我试图了解何时以及如何正确使用Python中的super()(2.7.x或3.x)

>>> help(super)口译员告诉我如何称呼它:

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
Run Code Online (Sandbox Code Playgroud)

我明白在Python3.x中,现在可以在类定义中使用super(),但我不明白为什么super(obj)不可能.或者super(self)在类定义中.

我知道必须有理由,但我找不到它.对我来说,这些线条相当于super(obj.__class__, obj)或者super(self.__class__, self)那些可以正常工作吗?

我认为super(obj)即使在Python 3.x中输入也是一个很好的捷径.

Bre*_*arn 42

只有在Python 2中才需要双参数形式.原因是它self.__class__始终引用继承树中的"叶子"类 - 也就是对象的最具体的类 - 但是当你打电话时super你需要告诉它它当前正在调用哪个实现,因此它可以调用继承树中的下一个实现.

假设你有:

class A(object):
   def foo(self):
      pass

class B(A):
   def foo(self):
      super(self.__class__, self).foo()

class C(B):
   def foo(self):
      super(self.__class__, self).foo()

c = C()
Run Code Online (Sandbox Code Playgroud)

需要注意的是c.__class__C,始终.现在想想如果你打电话会发生什么c.foo().

当你调用super(self.__class__, self)C的方法时,它就像调用一样super(C, self),这意味着"调用C继承的这个方法的版本".这会打电话B.foo,这很好.但是当你super(self.__class__, self)从B 打电话时,它仍然像打电话一样super(C, self),因为它是一样的self,所以self.__class__仍然如此C.结果是B中的调用将再次调用B.foo并发生无限递归.

当然,你真正想要的是能够调用super(classThatDefinedTheImplementationThatIsCurrentlyExecuting, self),这实际上是Python 3 super()所做的.

在Python 3中,您可以做到super().foo()并且它做正确的事情.我不清楚你super(self)的捷径是什么意思.在Python 2中,由于我上面描述的原因,它不起作用.在Python 3中,它将是一个"longcut",因为你可以只使用plain super().

super(type)super(type1, type2)用途可能仍然偶尔需要在Python 3,但那些总是不正常的情况下,更深奥的用途.

  • 一位同事曾经将一个名为“super”的方法重构为另一个类中的单独方法,因此代码最终显示为“super(SomeOtherClass, some_obj).method(...)”,效果很好,但看起来就像任何阅读代码的人都会遇到的错误一样。尽管这本来可以(并且最终)更好地表达,但“super”的两个参数形式在某些边缘情况下仍然有用。 (2认同)
  • 你的前四行解释让我明白了一切。也谢谢你的例子。这就是我试图理解的缺失部分。 (2认同)

kxr*_*kxr 8

尝试简短的回答:

self.__class__ 始终是对象实例的实际(“最次要”)类——不一定是实现该功能的所需类!

替换 super(self.__class__, self)super(__class__, self),您就在 Python 3 中的方法定义中,因为 Python 3 为__class__实现类提供了魔法单元变量。

并且简单地super()使用零参数已经是super(__class__, self) Python 3 中的快捷方式。请参阅PEP3135

Python 2 既不知道__class__也不知道零参数快捷方式super()