python中super(type,object)和super(超类型,类型)有什么区别?

时间:2014-03-14 11:38:11

标签: python class inheritance super

赢了super(type, object)super(supertype, type)都返回了type(supertype)超类的对象?有什么区别?

2 个答案:

答案 0 :(得分:5)

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

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

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

演示:

>>> 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).attrsuper(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'