Python中通过类A为类B绑定外部模块方法后,调用方法无法为B实例设置属性的问题排查
问题原因分析与解决方案
核心问题根源
你遇到的问题,本质是错误地将模块中的函数绑定成了模块对象的专属方法,导致方法里的self根本不是你期望的B类实例。
具体来说,这段代码是罪魁祸首:
attr = attr.__get__(duvisiopy.model_functions, duvisiopy.model_functions.__class__)
__get__是Python描述符协议的方法,当你调用它并传入duvisiopy.model_functions模块对象时,会生成一个绑定到该模块的方法——也就是说,这个方法里的self被固定成了模块本身,而不是后续调用它的B类实例。
所以当你执行a.compile("test1","test2")时:
- 方法里的
self.loss_function和self.optimizer其实是把属性设置到了duvisiopy.model_functions模块对象上,而不是B类实例a - 这就是为什么访问
a.optimizer会报属性不存在,但更新1里返回self后,c指向模块对象,能正常拿到optimizer的原因
修正方案
只需要去掉那个错误的__get__调用,直接把模块中的函数赋值给B类的属性即可。Python会自动在实例调用方法时,把实例作为第一个参数(也就是self)传入。
修改后的A类__new__方法:
def __new__(self, cls): for attr_name in dir(duvisiopy.model_functions): if attr_name not in dir(cls) and not attr_name.startswith("_"): attr = getattr(duvisiopy.model_functions, attr_name) if not isinstance(attr, types.ModuleType): # 直接赋值,无需手动绑定,Python会自动处理实例方法的self绑定 setattr(cls, attr_name, attr) return cls
验证效果
修改后再执行:
b = B() a = A(b) a.compile("test1","test2") print(a.optimizer) # 输出:test2
此时compile方法里的self就是B类实例a,属性会被正确设置到实例上,访问完全正常。
内容的提问来源于stack exchange,提问作者Wtow
相关产品推荐
相关产品推荐

