python - 将 super 与类方法一起使用

标签 python class object super class-method

我正在尝试学习 Python 中的 super() 函数。

我以为我已经掌握了它,直到我看到这个例子(2.6)并发现自己卡住了。

http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#super-with-classmethod-example

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() 导致 Ado_your_stuff 方法为 使用作为第一个参数传递的 cls 调用。为了让它工作,Ado_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 对象时超出最大递归深度

如果 clsC,则 super(cls, cls) 搜索 C.mro() C 之后的类。

In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]

由于那个类是B,当clsC时,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/

相关文章:

javascript - 显示多个 div 的输入内容

Java:如何 "instanceof argument"

javascript - 将 javascript 对象值添加到全局变量

c++ - 如何初始化数组指针对象

python - 尝试使用 pip : SyntaxError; confused between python2 and python3? 将 Python 2.7.0 升级到 Python 2.7.3

python - 我如何使用 mongodb 在 Pyramid 中创建单元测试?

c# - 从类实例将消息返回到表单的最佳方法?

java - 获取 JSON 中的重复响应

python - DJango 休息框架中的员工休假类型条件

Python 谷歌翻译