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

时间:2013-07-07 06:36:15

标签: 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)

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

我知道必须有理由,但我找不到它。对我来说,这些行等同于super(obj.__class__, obj)super(self.__class__, self),这些行可以正常工作吗?

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

2 个答案:

答案 0 :(得分:37)

只有在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()会发生什么。

当你在C的方法中调用super(self.__class__, self)时,它就像调用super(C, self),这意味着“调用C继承的此方法的版本”。这将调用B.foo,这很好。但是,当您从B拨打super(self.__class__, self)时,它仍然会调用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”,因为你只能使用普通的super()

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

答案 1 :(得分:1)

尝试一个简短的回答:

self.__class__始终是对象实例的实际(“sub-most”)类 - 不一定是实现该函数的所需类!

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

只有super()零参数已经是Python 3中super(__class__, self)的快捷方式。请参阅PEP3135

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