有时,必须更多地阅读文本以获得想法的味道,而不是细节。这是其中一种情况。
在链接页面中,示例 2.5、2.6 和 2.7 都应该使用一种方法,do_your_stuff
。(即do_something
应改为do_your_stuff
。)
此外,正如Ned Deily 所指出的,A.do_your_stuff
必须是类方法。
class A(object):
@classmethod
def do_your_stuff(cls):
print 'This is A'
class B(A):
@classmethod
def do_your_stuff(cls):
super(B, cls).do_your_stuff()
B.do_your_stuff()
super(B, cls).do_your_stuff
返回一个绑定的方法(见脚注 2)。由于 cls
作为第二个参数传递给super()
,它cls
被绑定到返回的方法。换句话说,cls
作为第一个参数传递给do_your_stuff()
类 A的方法。
重申一下:super(B, cls).do_your_stuff()
导致A
' 的do_your_stuff
方法被调用,cls
并作为第一个参数传递。为了使它起作用,A
's
do_your_stuff
必须是一个类方法。链接页面没有提到这一点,但确实如此。
PS。do_something = classmethod(do_something)
是制作类方法的旧方法。新的(er)方法是使用 @classmethod 装饰器。
注意super(B, cls)
不能代替super(cls, cls)
。这样做可能会导致无限循环。例如,
class A(object):
@classmethod
def do_your_stuff(cls):
print('This is A')
class B(A):
@classmethod
def do_your_stuff(cls):
print('This is B')
# super(B, cls).do_your_stuff() # CORRECT
super(cls, cls).do_your_stuff() # WRONG
class C(B):
@classmethod
def do_your_stuff(cls):
print('This is C')
# super(C, cls).do_your_stuff() # CORRECT
super(cls, cls).do_your_stuff() # WRONG
C.do_your_stuff()
会提高RuntimeError: maximum recursion depth exceeded while calling a Python object
。
如果cls
是C
,则super(cls, cls)
搜索C.mro()
后面的类C
。
In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]
既然那个类是B
,什么时候cls
是C
,super(cls, cls).do_your_stuff()
总是调用B.do_your_stuff
。由于super(cls, cls).do_your_stuff()
被调用 inside B.do_your_stuff
,你最终会B.do_your_stuff
在一个无限循环中调用。
在 Python3 中,添加了0 参数形式,super
因此super(B, cls)
可以替换为super()
,并且 Python3 会从上下文中找出super()
定义中的class B
应该等价于super(B, cls)
。
但在任何情况下super(cls, cls)
(或出于类似原因super(type(self), self)
)都不正确。