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'