当 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 C
的 wave
方法,尽管不是通过更常见的函数定义,而是使用 setattr
代替。然后我们有 class B
继承 A
,B
试图用它自己的方法覆盖 wave
方法,但是,这是不可能的,这是怎么回事?我该如何解决?
我想尽可能保留classA
的setattr
样式定义,请指教。
我从来没有系统地学习过 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 更详细地解释了属性查找的工作原理。
我创建的一个 '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 C
的 wave
方法,尽管不是通过更常见的函数定义,而是使用 setattr
代替。然后我们有 class B
继承 A
,B
试图用它自己的方法覆盖 wave
方法,但是,这是不可能的,这是怎么回事?我该如何解决?
我想尽可能保留classA
的setattr
样式定义,请指教。
我从来没有系统地学习过 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 更详细地解释了属性查找的工作原理。