42

我试图了解何时以及如何在 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)

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

我知道这一定是有原因的,但我找不到。对我来说,这些行相当于super(obj.__class__, obj)orsuper(self.__class__, self)并且那些行得通吗?

我认为super(obj)即使在 Python 3.x 中,仅键入也是一个不错的捷径。

4

2 回答 2

61

双参数形式只有在 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()

请注意,c.__class__总是C。现在想想如果你调用c.foo().

当你调用super(self.__class__, self)C 的一个方法时,它就像 call 一样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 3super()所做的。

在 Python 3 中,你可以做super().foo()并且它做正确的事。我不清楚你所说super(self)的捷径是什么意思。在 Python 2 中,由于我上面描述的原因,它不起作用。在 Python 3 中,这将是一个“longcut”,因为您可以使用 plainsuper()代替。

在 Python 3 中偶尔可能仍需要super(type)and的用法,但对于不寻常的情况,这些用法总是更深奥的。super(type1, type2)

于 2013-07-07T06:53:17.490 回答
10

尝试一个简短的答案:

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()

于 2017-04-03T11:39:07.097 回答