我正在尝试学习 Python 中的 super() 函数。
我以为我已经掌握了它,直到我看到这个例子(2.6)并发现自己卡住了。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 9, in do_something
do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>
当我在示例之前阅读此行时,这不是我所期望的:
If we're using a class method, we don't have an instance to call super with. Fortunately for us, super works even with a type as the second argument. --- The type can be passed directly to super as shown below.
这正是 Python 告诉我的,通过说应该使用 B 的实例调用 do_something() 是不可能的。
最佳答案
有时必须阅读更多文本以了解想法的味道而不是细节。这是其中一种情况。
在 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
被绑定(bind)到返回的方法。换句话说,cls
作为第一个参数传递给类 A 的方法 do_your_stuff()
。
重申:super(B, cls).do_your_stuff()
导致 A
的 do_your_stuff
方法为
使用作为第一个参数传递的 cls
调用。为了让它工作,A
的
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: 调用 Python 对象时超出最大递归深度
。
如果 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 会从上下文中找出 super()
在class B
的定义应该等价于super(B, cls)
。
但在任何情况下,super(cls, cls)
(或出于类似原因,super(type(self), self)
)都不会正确。
关于python - 将 super 与类方法一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1817183/