我正在尝试学习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.
通过说do_something()应该用B的实例调用,这正是Python告诉我的不可能。
有时,文字必须更多地阅读,而不是细节。这是其中一个案例。
在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
返回一个绑定方法(参见footnote 2)。由于cls
作为super()
的第二个参数传递,因此cls
被绑定到返回的方法。换句话说,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)
是制作课堂方法的老方法。新的(呃)方法是使用@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将从上下文中找出super()
定义中的class B
应该等同于super(B, cls)
。
但在任何情况下,super(cls, cls)
(或类似的原因,super(type(self), self)
)都不会纠正。
在Python 3中,您可以跳过为super
指定参数,
class A:
@classmethod
def f(cls):
return "A's f was called."
class B(A):
@classmethod
def f(cls):
return super().f()
assert B.f() == "A's f was called."
我已经更新了这篇文章,使其更加清晰:Python Attributes and Methods # Super
上面使用classmethod的示例显示了一个类方法 - 它将类本身而不是实例作为第一个参数传递。但是你甚至不需要一个实例来调用这个方法,例如:
>>> class A(object):
... @classmethod
... def foo(cls):
... print cls
...
>>> A.foo() # note this is called directly on the class
<class '__main__.A'>
网页上的示例似乎已发布。您是否为超类创建了do_something
方法,但没有将其变成类方法?像这样的东西会给你这个错误:
>>> class A(object):
... def do_something(cls):
... print cls
... # do_something = classmethod(do_something)
...
>>> class B(A):
... def do_something(cls):
... super(B, cls).do_something()
... do_something = classmethod(do_something)
...
>>> B().do_something()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in do_something
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
由于这个美丽的景色和可爱的社区,我想我现在明白了这一点。
如果你不介意的话请纠正我,如果我在课堂方法上错了(我现在试图完全理解):
# EXAMPLE #1
>>> class A(object):
... def foo(cls):
... print cls
... foo = classmethod(foo)
...
>>> a = A()
>>> a.foo()
# THIS IS THE CLASS ITSELF (__class__)
class '__main__.A'
# EXAMPLE #2
# SAME AS ABOVE (With new @decorator)
>>> class A(object):
... @classmethod
... def foo(cls):
... print cls
...
>>> a = A()
>>> a.foo()
class '__main__.A'
# EXAMPLE #3
>>> class B(object):
... def foo(self):
... print self
...
>>> b = B()
>>> b.foo()
# THIS IS THE INSTANCE WITH ADDRESS (self)
__main__.B object at 0xb747a8ec
>>>
我希望这个插图显示..