Python 超级(cls,实例)和超级(cls,子类)之间有什么区别?

Python 超级(cls,实例)和超级(cls,子类)之间有什么区别?,python,class,inheritance,super,Python,Class,Inheritance,Super,super(cls,instance)和super(cls,subclass)都返回cls的超类吗?差别很大super()使用类型(类)第二个参数而不是对象(实例)为您提供未绑定的方法,而不是绑定的方法(就像在类上访问这些方法一样) 我将首先解释super()如何使用实例第二个参数 super()检查self的MRO,在MRO中找到第一个参数(type或supertype),然后找到具有请求属性的下一个对象 演示: 要调用.foo()我必须显式地传入一个self参数 (在Python2中,上面将

super(cls,instance)
super(cls,subclass)
都返回
cls的超类吗?

差别很大
super()
使用类型(类)第二个参数而不是对象(实例)为您提供未绑定的方法,而不是绑定的方法(就像在类上访问这些方法一样)

我将首先解释
super()
如何使用实例第二个参数

super()
检查
self
的MRO,在MRO中找到第一个参数(
type
supertype
),然后找到具有请求属性的下一个对象

演示:

要调用
.foo()
我必须显式地传入一个
self
参数

(在Python2中,上面将返回一个
foo
unbound方法对象,而不是函数,但原理相同)

返回的方法同样来自MRO链中的下一个类
BaseClass.foo
在那里返回

这取决于
函数。\uuuu get\uuuu
方法(即,负责绑定的方法),因为它在传递要绑定的类时返回自身(或者在Python 2中返回未绑定的方法)。(例如,
\uuuuu get\uuuu
在类中传递时返回绑定对象)

因此,TL;DR,对于方法
super(类型,对象)
返回绑定方法,
super(类型,类型)
返回未绑定方法。其目的是使此对象可以存储为类私有属性,以避免不停地查找类对象,请参阅。它的用例在Python3中已经完全过时了,所以它是。

super(cls,instance)。attr
检查
实例类的M.R.O.(即
实例.\uu class.\uu mro.\uuuuu
),在M.R.O中查找
cls
之后具有属性的下一个类,并返回
attr.\uuuuu get.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法的
attr结果,如果没有
方法,则返回
attr
。此案例用于以下函数:

>>A类:
...     def f(自身):返回“A.f”
... 
>>>B(A)类:
...     def f(self):返回'B.f'+超级(B,self).f()
... 
>>>B().f()
“B.f A.f”
super(cls,subclass).attr
检查
子类的M.R.O.(即
subclass.\uuuu mro\uuuuu
),在mro中查找
cls
之后具有属性
attr
的下一个类,并返回
attr.\uu get\uuu的结果(无,subclass)
如果它有
\uuuuu get\uuu
方法,或者如果它没有
\uu get\uuu
方法,则返回
attr
。本案例用于:

>>A类:
...     @类方法
...     def f(cls):返回“A.f”
... 
>>>B(A)类:
...     @类方法
...     def f(cls):返回'B.f'+super(B,cls).f()
... 
>>>B.f()
“B.f A.f”
对于函数属性,
super(cls,instance).attr
返回
instance
的绑定方法,而
super(cls,subclass).attr
返回函数:

>>A类:
...     def f(自身):返回“A.f”
... 
>>>B(A)类:
...     def f(自身):返回“B.f”
... 
>>>b=b()
>>>b.f
>>>B.f
>>>b.f()
“B.f”
>>>B.f(B)
“B.f”
>>>超级(B,B).f
>>>超级(B,B).f
>>>super(B,B).f()
“A.f”
>>>超级(B,B).f(B)
“A.f”
对于属性,
super(cls,instance).attr
super(cls,subclass).attr
分别返回
实例的绑定方法

>>A类:
...     @类方法
...     def f(cls):返回“A.f”
... 
>>>B(A)类:
...     @类方法
...     def f(cls):返回“B.f”
... 
>>>b=b()
>>>b.f
>>>B.f
>>>b.f()
“B.f”
>>>B.f()
“B.f”
>>>超级(B,B).f
>>>超级(B,B).f
>>>super(B,B).f()
“A.f”
>>>super(B,B).f()
“A.f”

我相信您的意见,但我在官方文件中没有找到任何有关这方面的信息。有官方的解释吗?@KramerLi:这都包含在文档中。@KramerLi:我最近将实现“移植”到Python以回答另一个问题:。这有助于理解吗?谢谢,你的回答已经很清楚了。从您的回答中,我得到的最重要的信息是“带有类型(类)第二个参数而不是对象(实例)的super()为您提供了未绑定的方法”。我认为这是python官方文档应该提到的一个非常重要的信息。但我真的没有在官方文件中找到此类信息(我也阅读了您提供的链接)。因此,我只是想知道我是否错过了官方文档中的任何内容?@KramerLi:我可能比需要更强调这一点,但我确实看到文档中没有明确说明,相同的绑定规则适用于正常的实例和类属性访问。
>>> class BaseClass(object):
...     def foo(self): return 'BaseClass foo'
... 
>>> class Intermediary(BaseClass):
...     def foo(self): return 'Intermediary foo'
... 
>>> class Derived(Intermediary):
...     def foo(self): return 'Derived foo'
... 
>>> d = Derived()
>>> d.foo()
'Derived foo'
>>> super(Derived, d).foo
<bound method Intermediary.foo of <__main__.Derived object at 0x10ef4de90>>
>>> super(Derived, d).foo()
'Intermediary foo'
>>> super(Intermediary, d).foo()
'BaseClass foo'
>>> Derived.__mro__
(<class '__main__.Derived'>, <class '__main__.Intermediary'>, <class '__main__.BaseClass'>, <type 'object'>)
>>> super(Intermediary, Derived).foo
<function BaseClass.foo at 0x106dd6040>
>>> super(Intermediary, Derived).foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'self'
>>> super(Intermediary, Derived).foo(d)
'BaseClass foo'