首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >超级(cls,实例)和超级(cls,子类)之间有什么区别?

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

Stack Overflow用户
提问于 2014-03-14 11:38:11
回答 2查看 1.2K关注 0票数 3

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-14 11:42:54

差别很大;带有类型(类)第二个参数而不是对象(实例)的super()给出了未绑定方法,而不是绑定方法(就像访问类上的那些方法一样)。

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

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

演示:

代码语言:javascript
复制
>>> 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'>)

Derived的MRO是(Derived, Intermediary, BaseClass)super()通过查看第二个参数(使用type(d).__mro__ )找到这个MRO。在给出的第一个参数之后,对foo的搜索将从下一个类开始。

foo()方法在这里绑定,您只需调用它。

如果您给super()一个类型作为第二个参数,那么它将使用该类型的MRO,例如,它不使用type(instance).__mro__,而是只用于type.__mro__。但是,这样它就没有要绑定方法的实例了。super(supertype, type).foo,只是(未绑定的)函数对象

代码语言:javascript
复制
>>> 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'

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

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

返回的方法也是从MRO链中的下一个类返回的;在那里返回了BaseClass.foo

这可以归结为function.__get__方法(即负责绑定的描述符协议 ),因为它在传递要绑定的类时返回自身(或者在Python2中返回一个未绑定的方法)。(对于对象__get__在类中传递时确实返回绑定对象)。

因此,TL;DR,对于方法super(type, object)返回绑定方法,super(supertype, type)返回未绑定方法。其目的是使将该对象存储为类私有属性成为可能,以避免继续查找类对象(请参阅如何用一个参数来使用超级()? )。它的用例在Python3中完全过时了,所以它就是排定反对意见

票数 10
EN

Stack Overflow用户

发布于 2021-05-07 23:44:51

super(cls, instance).attr检查instance类(即instance.__class__.__mro__)的M.R.O.,查找具有属性attr的M.R.O.中的cls之后的下一个类,如果有__get__方法,则返回attr.__get__(instance, instance.__class__)的结果;如果没有__get__方法,则返回attr。此情况用于函数。

代码语言:javascript
复制
>>> class A:
...     def f(self): return 'A.f'
... 
>>> class B(A):
...     def f(self): return 'B.f ' + super(B, self).f()
... 
>>> B().f()
'B.f A.f'

super(cls, subclass).attr检查subclass的M.R.O. (即subclass.__mro__),查找具有属性attr的M.R.O.中的cls后面的下一个类,如果有__get__方法返回attr.__get__(None, subclass)的结果,如果没有__get__方法则返回attr。本例用于classmethod

代码语言:javascript
复制
>>> class A:
...     @classmethod
...     def f(cls): return 'A.f'
... 
>>> class B(A):
...     @classmethod
...     def f(cls): return 'B.f ' + super(B, cls).f()
... 
>>> B.f()
'B.f A.f'

对于函数属性,super(cls, instance).attr返回instance的绑定方法,而super(cls, subclass).attr返回函数

代码语言:javascript
复制
>>> class A:
...     def f(self): return 'A.f'
... 
>>> class B(A):
...     def f(self): return 'B.f'
... 
>>> b = B()
>>> b.f
<bound method B.f of <__main__.B object at 0x10e7d3fa0>>
>>> B.f
<function B.f at 0x10e7ea790>
>>> b.f()
'B.f'
>>> B.f(b)
'B.f'
>>> super(B, b).f
<bound method A.f of <__main__.B object at 0x10e7d3fa0>>
>>> super(B, B).f
<function A.f at 0x10e7ea700>
>>> super(B, b).f()
'A.f'
>>> super(B, B).f(b)
'A.f'

对于classmethod属性,super(cls, instance).attrsuper(cls, subclass).attr分别返回instance.__class__subclass的绑定方法。

代码语言:javascript
复制
>>> class A:
...     @classmethod
...     def f(cls): return 'A.f'
... 
>>> class B(A):
...     @classmethod
...     def f(cls): return 'B.f'
... 
>>> b = B()
>>> b.f
<bound method B.f of <class '__main__.B'>>
>>> B.f
<bound method B.f of <class '__main__.B'>>
>>> b.f()
'B.f'
>>> B.f()
'B.f'
>>> super(B, b).f
<bound method A.f of <class '__main__.B'>>
>>> super(B, B).f
<bound method A.f of <class '__main__.B'>>
>>> super(B, b).f()
'A.f'
>>> super(B, B).f()
'A.f'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22403937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档