我试图了解何时以及如何在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)
也是一个很好的捷径。
答案 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()
。