如何在python中使用带有一个参数的super()

use*_*758 20 python super

在阅读Python中的super()对象时,我阅读了以下语句:

如果省略第二个参数,则返回的超级对象是未绑定的

这究竟是什么意思,我如何super()在代码中使用一个参数?

Mar*_*ers 23

Python函数对象是描述符,Python使用描述符协议函数绑定到实例.此过程生成绑定方法.

绑定是调用方法时self出现'magic' 参数的原因,以及property当您尝试将该属性用作实例上的属性时,对象会自动调用方法的原因.

super()当您尝试使用它来查找父类的方法时,使用两个参数调用相同的描述符协议; super(Foo, self).bar()将遍历Foo父类,直到bar找到属性,如果这是一个描述符的对象,它将被绑定self.呼叫bar然后调用绑定的方法,后者又调用函数通过在该self参数作为bar(self).

为此,super()对象存储self要绑定的参数的类(第一个参数),以及self作为属性的对象类型:

>>> class Foo:
...     def bar(self):
...         return 'bar on Foo'
... 
>>> class Spam(Foo):
...     def bar(self):
...         return 'bar on Spam'
... 
>>> spam = Spam()
>>> super(Spam, spam)
<super: <class 'Spam'>, <Spam object>>
>>> super(Spam, spam).__thisclass__
<class '__main__.Spam'>
>>> super(Spam, spam).__self__
<__main__.Spam object at 0x107195c10>
>>> super(Spam, spam).__self_class__
<class '__main__.Spam'>
Run Code Online (Sandbox Code Playgroud)

查找属性时,搜索__thisclass__属性的__self__属性,从位置开始经过一个位置__self_class__,并绑定结果.

__mro__只有一个参数将错过__self_class____thisclass__属性,并不能做到查找尚未:

>>> super(Spam)
<super: <class 'Spam'>, NULL>
>>> super(Spam).__self__ is None
True
>>> super(Spam).__self_class__ is None
True
>>> super(Spam).bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'super' object has no attribute 'bar'
Run Code Online (Sandbox Code Playgroud)

该对象确实支持描述符协议,因此您可以像绑定方法一样绑定它:

>>> super(Spam).__get__(spam, Spam)
<super: <class 'Spam'>, <Spam object>>
>>> super(Spam).__get__(spam, Spam).bar()
'bar on Foo'
Run Code Online (Sandbox Code Playgroud)

这意味着您可以将这样的对象存储在类中,并使用它来遍历父方法:

>>> class Eggs(Spam):
...     pass
... 
>>> Eggs.parent = super(Eggs)
>>> eggs = Eggs()
>>> eggs.parent
<super: <class 'Eggs'>, <Eggs object>>
>>> eggs.parent.bar()
'bar on Spam'
Run Code Online (Sandbox Code Playgroud)

  • 非常有用的答案,因为这种行为没有记录,谢谢 Martijn。 (2认同)
  • @ДавидШико 阅读了整个答案,我明确地涵盖了这一点 (2认同)