Python 3中的4种super()调用方式该如何使用?

24

我想知道什么时候使用哪个版本的Python 3 super()。

Help on class super in module builtins:

class super(object)
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)

到目前为止,我只使用过没有参数的super(),它按照我的期望工作(对于Java开发人员来说)。

问题:

  • 在这个上下文中,“bound”是什么意思?
  • “绑定的(super)对象”和“未绑定的(super)对象”有什么区别?
  • 什么时候使用super(type, obj),什么时候使用super(type, type2)
  • Mother.__init__(...)这样命名超类会更好吗?
2个回答

21

让我们使用以下类进行演示:

class A(object):
    def m(self):
        print('m')

class B(A): pass

未绑定的 super 对象没有将属性访问分派到类,您必须使用描述符协议:

>>> super(B).m
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'super' object has no attribute 'm'
>>> super(B).__get__(B(), B)
<super: <class 'B'>, <B object>>

super对象绑定到实例会生成绑定方法:

>>> super(B, B()).m
<bound method B.m of <__main__.B object at 0xb765dacc>>
>>> super(B, B()).m()
m

super对象绑定到类会产生函数(Python 2中未绑定方法):

>>> super(B, B).m
<function m at 0xb761482c>
>>> super(B, B).m()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: m() takes exactly 1 positional argument (0 given)
>>> super(B, B).m(B())
m

请查看Michele Simionato的"关于Python Super的知识要点"博客系列文章(123)以获取更多信息。


1
这个问题特别针对Python3,但是Simionato的博客系列是关于Python2的,并且提到了 优点在于你避免了在调用语法中重复类名,因为该名称被隐藏在私有名称的缩编机制中。。 然而在Python3中,这已经不再是真的,所以至少这一点优势已经过时了。 - gerrit
这回答了OP的“每个是做什么的?”但它并没有回答“你什么时候会使用每一个?”而且它实际上也没有解释“未绑定”与“绑定”的区别;如果B是一个类名,b = B()是一个实例,那么B是一个未绑定的对象,而b是一个绑定的对象。 - smci

9

快速提醒,super 的新用法在 PEP3135 新超类 中有详细说明,这是在 Python 3.0 中实现的。特别值得注意的是:

super().foo(1, 2)

替换旧的:

super(Foo, self).foo(1, 2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接