有时必须阅读更多文本以了解想法的味道而不是细节。这是其中一种情况。
在linked page 中,示例 2.5、2.6 和 2.7 都应该使用一种方法,do_your_stuff。 (即do_something要改成do_your_stuff。)
另外,作为Ned Deily pointed out,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
返回一个 bound 方法(参见footnote 2)。由于cls 作为第二个参数传递给super(),因此绑定到返回方法的是cls。换句话说,cls 作为第一个参数传递给类 A 的方法 do_your_stuff()。
重申:super(B, cls).do_your_stuff() 导致 A 的 do_your_stuff 方法为
调用 cls 作为第一个参数传递。为了让它工作,A's
do_your_stuff 必须是类方法。链接页面没有提到,
但事实确实如此。
附言。 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() 在B.do_your_stuff 内部被调用,你最终会在无限循环中调用B.do_your_stuff。
在 Python3 中,添加了 0-argument form of super,因此 super(B, cls) 可以替换为 super(),并且 Python3 将根据上下文确定 class B 定义中的 super() 应该等同于 super(B, cls)。
但在任何情况下,super(cls, cls)(或出于类似原因,super(type(self), self))都不正确。