super(cls, instance) 和 super(cls, subclass) 有什么区别? [英] What is the difference between super(cls, instance) and super(cls, subclass)?
问题描述
super(cls, instance)
和 super(cls, subclass)
不会都返回 cls
的超类吗?
差别很大;super()
使用类型(类)第二个参数而不是对象(实例)为您提供未绑定的方法,而不是绑定的方法(就像在类上访问这些方法一样).
我将首先解释 super()
如何与实例第二个参数一起工作.
super()
检查 self
的 MRO,找到第一个参数(type
或 supertype
)MRO,然后找到下一个具有请求属性的对象.
演示:
<预><代码>>>>类基类(对象):... def foo(self): 返回 'BaseClass foo'...>>>类中介(BaseClass):... def foo(self): 返回'中介 foo'...>>>派生类(中介):... def foo(self): return 'Derived foo'...>>>d = 派生()>>>d.foo()'派生的 foo'>>>super(Derived, d).foo<0x10ef4de90处<__main__.Derived对象>的绑定方法Intermediary.foo>>>>超级(派生的,d). foo()'中介foo'>>>超级(中介,d).foo()'基类 foo'>>>派生.__mro__(<class '__main__.Derived'>, <class '__main__.Intermediary'>, <class '__main__.BaseClass'>, <type 'object'>)Derived
的 MRO 为 (Derived, Intermediary, BaseClass)
;super()
通过使用 type(d).__mro__
查看第二个参数来找到这个 MRO.foo
的搜索从给出的第一个参数之后的 next 类开始.
foo()
方法绑定在这里,调用即可.
如果您给 super()
一个 type 作为第二个参数,那么它将使用该类型的 MRO,例如而不是使用 type(instance).__mro__
它只是用于 type.__mro__
.然而,它没有实例来绑定方法.super(supertype, type).foo
是只是(未绑定的)函数对象:
要调用 .foo()
我必须显式传入一个 self
参数.
(在 Python 2 中,上面会返回一个 foo
unbound method 对象而不是函数,但原理是一样的).
返回的方法同样来自 MRO 链中的下一个类;BaseClass.foo
在那里返回.
这取决于 function.__get__
方法(即 描述符协议,负责绑定),因为它在传递要绑定到的类时返回自身(或者,在 Python 2 中,一个未绑定的方法).(对于classmethod
对象,__get__
在类中传递时确实返回一个绑定对象).
所以,TL;DR,对于方法 super(type, object)
返回一个 bound 方法,super(supertype, type)
返回未绑定的方法.目标是可以将此对象存储为类私有属性以避免必须继续查找类对象,请参阅 如何将 super() 与一个参数一起使用?.它的用例已在 Python 3 中完全过时,因此它是 预定弃用.
Won’t super(cls, instance)
and super(cls, subclass)
both return the superclass of cls
?
The difference is huge; super()
with a type (class) second argument instead of an object (instance) gives you unbound methods, not bound methods (just like accessing those methods on a class would).
I'll explain first how super()
works with an instance second argument.
super()
inspects the MRO of self
, finds the first argument (type
or supertype
) in the MRO, then finds the next object that has the requested attribute.
Demo:
>>> 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'>)
The MRO of Derived
is (Derived, Intermediary, BaseClass)
; super()
finds this MRO by looking at the second argument, using type(d).__mro__
. The search for foo
starts at the next class after the first argument given.
The foo()
method is bound here, you can just call it.
If you give super()
a type as the second argument, then it'll use the MRO of that type, e.g. instead of using type(instance).__mro__
it just goes for type.__mro__
. However it then has no instance to bind the methods to. super(supertype, type).foo
is just the (unbound) function 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'
To call .foo()
I have to explicitly pass in a self
argument.
(In Python 2, the above would return a foo
unbound method object instead of a function, but the principle is the same).
The method returned is also, again, from the next class in the MRO chain; BaseClass.foo
was returned there.
This is down to the function.__get__
method (i.e. the descriptor protocol, responsible for binding), as it returns itself (or, in Python 2, an unbound method) when passed a class to bind to. (For classmethod
objects, __get__
does return a bound object when passed in a class).
So, TL;DR, for methods super(type, object)
returns a bound method, super(supertype, type)
returns unbound methods. The goal was to make it possible to store this object as a class-private attribute to avoid having to keep looking up the class object, see How to use super() with one argument?. It's use-case has been obsoleted entirely in Python 3 so it is slated for deprecation.
这篇关于super(cls, instance) 和 super(cls, subclass) 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!