赢了super(type, object)
和super(supertype, type)
都返回了type(supertype)
超类的对象?有什么区别?
答案 0 :(得分:5)
差异很大;带有类型(类)第二个参数而不是对象(实例)的super()
为您提供了未绑定的方法,而不是绑定的方法(就像在类上访问这些方法一样)。
我将首先解释super()
如何使用实例第二个参数。
super()
检查self
的MRO,在MRO中找到第一个参数(type
或supertype
),然后找到具有所请求属性的下一个对象。
演示:
>>> 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 Derived.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。在给出第一个参数后,在 next 类中搜索foo
。
foo()
方法绑定在此处,您可以调用它。
如果您将super()
类型作为第二个参数,那么它将使用该类型的MRO,例如而不是使用type(instance).__mro__
,它只适用于type.__mro__
。但是它没有将方法绑定到的实例。 super(supertype, type).foo
未绑定:
>>> super(Intermediary, Derived).foo
<unbound method Derived.foo>
>>> super(Intermediary, Derived).foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Derived instance as first argument (got nothing instead)
>>> super(Intermediary, Derived).foo(d)
'BaseClass foo'
要调用.foo()
,我必须明确传入self
参数。
(在Python 3中,上面将返回foo
函数对象而不是未绑定方法,但原理是相同的。)
返回的方法也是来自MRO链中的下一个类; BaseClass.foo
被归还。
这取决于function.__get__
方法(即负责绑定的descriptor protocol),因为它返回一个未绑定的对象(Python 2中的未绑定方法,Python 3中的函数本身)传递了一个类来绑定。 (对于classmethod
objects,__get__
在类中传递时会返回绑定对象。
因此,TL; DR,方法super(type, object)
返回绑定方法,super(supertype, type)
返回未绑定方法。
答案 1 :(得分:0)
super(cls, instance).attr
检查 M.R.O. instance
的类(即 instance.__class__.__mro__
),在 M.R.O. 中查找 cls
之后的 next 类。具有属性 attr
,如果有 attr.__get__(instance, instance.__class__)
方法,则返回 __get__
的结果,如果没有 attr
方法,则返回 __get__
。这种情况用于函数:
>>> 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
检查 M.R.O. subclass
(即subclass.__mro__
),在具有属性cls
的MRO中查找attr
之后的next类,并返回结果attr.__get__(None, subclass)
如果它有 __get__
方法或返回 attr
如果它没有 __get__
方法。这种情况用于classmethod
:
>>> 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
返回函数:
>>> 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).attr
和super(cls, subclass).attr
分别返回instance.__class__
和subclass
的绑定方法:
>>> 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'