当 Parent 已经明确地`setattr`相同的函数时如何覆盖函数?

How to override a function when Parent already explicitly `setattr` the same function?

我创建的一个 'minimal' 示例:

class C:
    def wave(self):
        print("C waves")

class A:
    def __init__(self):
        c = C()
        setattr(self, 'wave', getattr(c, 'wave'))

class B(A):
    def wave(self):
        print("B waves")

>>> a = A()
>>> a.wave()
C waves # as expected
>>> b = B()
>>> b.wave()
C waves # why not 'B waves'?
>>> 

在示例中,class A 明确定义其方法 wave 为 class Cwave 方法,尽管不是通过更常见的函数定义,而是使用 setattr 代替。然后我们有 class B 继承 AB 试图用它自己的方法覆盖 wave 方法,但是,这是不可能的,这是怎么回事?我该如何解决?

我想尽可能保留classAsetattr样式定义,请指教。

我从来没有系统地学习过 Python,所以我想我对 Python 的继承和 setattr 的工作原理缺少一些理解。

Class A 将 wave() 方法设置为它在 __init__() 中的 instance 属性。这可以通过检查实例的字典看到:

>>> b.__dict__
{'wave': <bound method C.wave of <__main__.C object at 0x7ff0b32c63c8>>}

您可以通过从 b

中删除实例成员来解决这个问题
>>> del b.__dict__['wave']
>>> b.wave()
B waves

删除实例属性后,wave() 函数将从 class 字典中获取:

>>> B.__dict__
mappingproxy({'__module__': '__main__',
              'wave': <function __main__.B.wave(self)>,
              '__doc__': None})

这里要注意的是,当Python查找属性时,实例属性优先于class属性(除非class属性是一个数据descriptor,但这里不是这种情况)。

我当时还写了一篇 blog post 更详细地解释了属性查找的工作原理。