我有以下代码:
class A:
pass
class B(A):
def foo(self, a):
if a:
return 'B'
return super(B, self).foo(a)
class C:
def foo(self, a):
return 'C'
class D(B, C):
def foo(self, a):
return super().foo(a)
d = D()
print(d.foo(0))
当我d.foo(0)
基于 MRO 调用时,它首先调用类的foo
方法B
并在其中调用,如果条件错误,它将返回super(B, self).foo(0)
但类A
没有 foo 方法,我预计会出现此错误:
AttributeError: 'super' object has no attribute 'foo'
但它'C'
从 class返回C
。为什么?
super()
在 MRO 中搜索具有该属性的下一个类;即A
没有实现它并不重要,C
仍然被认为是。
对于D
,MRO 是D
, B
, A
, C
:
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>)
所以super().foo
在D
会发现B.foo
,距离B.foo
,A
被跳过,C.foo
被发现; 您可以从交互式解释器中自行测试:
>>> super(D, d).foo
<bound method B.foo of <__main__.D object at 0x1079edb38>>
>>> super(B, d).foo
<bound method C.foo of <__main__.D object at 0x1079edb38>>
这是属性搜索算法的 Python 实现的样子:
def find_attribute(type_, obj, name):
starttype = type(obj)
mro = iter(starttype.__mro__)
# skip past the start type in the MRO
for tp in mro:
if tp == type_:
break
# Search for the attribute on the remainder of the MRO
for tp in mro:
attrs = vars(tp)
if name in attrs:
res = attrs[name]
# if it is a descriptor object, bind it
descr = getattr(type(res), '__get__', None)
if descr is not None:
res = descr(
res,
None if obj is starttype else obj,
starttype)
return res
wheretype_
是super()
(定义方法的类)的第一个参数,obj
是实例(所以type(d)
在这里),name
是你正在寻找的属性。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句