如何在实例级别用属性重写Python类方法?以Dog类为例
解决方案
要实现需求,你不能直接把woof属性赋值给bark(这会让bark变成字符串类型,无法调用),得把返回woof的逻辑包装成绑定到实例的方法,下面提供两种可行方式:
方式1:用Lambda快速包装
直接给foo.bark赋值带绑定逻辑的lambda,简单快捷:
class Dog: woof = 'woof' def woofwoof(self): return 'woof woof' def woOof(self): return 'woOof' def bark(self): return self.woofwoof() def test(foo): print(type(foo.bark)) print(foo.bark()) foo = Dog() test(foo) foo.bark = foo.woOof test(foo) # 关键修改:用lambda包装,实时获取实例的woof属性 foo.bark = lambda self=foo: self.woof test(foo) # 测试修改woof后的效果 foo.woof = 'new woof!' test(foo)
运行结果:
<class 'method'> woof woof <class 'method'> woOof <class 'function'> woof <class 'function'> new woof!
注:这种方式下bark类型是function,但依然可以正常调用,若下游代码仅要求可调用而非严格method类型,完全可用。
方式2:用types.MethodType绑定标准方法
如果严格要求bark的类型必须是method,可以先定义普通函数,再绑定到实例:
import types class Dog: woof = 'woof' def woofwoof(self): return 'woof woof' def woOof(self): return 'woOof' def bark(self): return self.woofwoof() def test(foo): print(type(foo.bark)) print(foo.bark()) # 定义新的bark逻辑函数 def new_bark(self): return self.woof foo = Dog() test(foo) foo.bark = foo.woOof test(foo) # 关键修改:用MethodType把函数绑定到实例 foo.bark = types.MethodType(new_bark, foo) test(foo) # 测试修改woof后的效果 foo.woof = 'new woof!' test(foo)
运行结果:
<class 'method'> woof woof <class 'method'> woOof <class 'method'> woof <class 'method'> new woof!
原理说明
- 直接赋值
foo.woof时,bark被设置为字符串类型,自然无法调用; - 赋值
foo.woOof时,woOof是已经绑定到实例的method类型对象,所以能正常调用; - 用lambda或
MethodType包装后,我们把返回woof的逻辑变成了可调用的方法,且能实时获取woof的最新值,完全满足下游代码的调用要求。
内容的提问来源于stack exchange,提问作者Daneel Olivaw
相关产品推荐
相关产品推荐

