我有以下代码:
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))
当我根据MRO调用d.foo(0)
时,它首先调用foo
类的B
方法,并在其中,如果条件错误,它将返回super(B, self).foo(0)
但是class A
没有foo方法,我期待这个错误:
AttributeError: 'super' object has no attribute 'foo'
但它会从班级'C'
返回C
。为什么呢?
答案 0 :(得分:1)
super()
在MRO中搜索具有该属性的 next class ; <{1}}未实现它并不重要,因为仍然会考虑A
。
对于C
,MRO为D
,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
这是属性搜索算法的Python实现:
>>> 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>>
其中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
是type_
的第一个参数(方法定义的类),super()
是实例(因此obj
)和{{ 1}}是您要查找的属性。