Python无法修改父类时如何让继承方法读取子类重写的类变量
问题本质
父类的print_a方法硬编码了Parent.A的取值路径,不会动态识别实例所属的子类,因此子类重写类变量A后,调用继承的print_a方法依然会返回父类的A值。
可行解决方案
方案1:运行时给父类方法打猴子补丁(无需修改源码文件,全局生效,兼容性好)
仅在运行时动态修改父类print_a的实现,把硬编码的取值改为动态读取实例所属类的类变量,原有逻辑完全保留:
import inspect # 读取原有print_a的源码,替换硬编码的Parent.A为动态取值 original_source = inspect.getsource(Parent.print_a) modified_source = original_source.replace("Parent.A", "self.__class__.A") # 执行修改后的代码生成新方法 exec(modified_source) # 替换父类的原有方法 Parent.print_a = print_a
修改完成后执行原有调用代码,就会输出子类的A值2,父类自身的调用逻辑也不受影响。
方案2:子类内包装父类方法(不修改父类任何属性,单线程场景可用)
如果不想改动父类的任何运行时属性,可以在子类内对print_a做包装,临时替换父类A的取值,调用完成后自动恢复:
class Child(Parent): A = 2 def print_a(self): original_a = Parent.A Parent.A = self.A try: super().print_a() finally: Parent.A = original_a
该方案的缺点是多线程场景下,若同时有父类实例调用print_a可能出现取值错乱,适合单线程使用。
方案3:子类内独立执行方法逻辑(无副作用,多线程安全)
通过复制原方法的代码对象,用临时全局命名空间执行,完全不影响父类和其他实例:
class Child(Parent): A = 2 def print_a(self): # 复制原方法的全局命名空间,临时把Parent指向当前子类 temp_globals = Parent.print_a.__globals__.copy() temp_globals["Parent"] = self.__class__ # 执行原方法的代码逻辑 exec(Parent.print_a.__code__, temp_globals, {"self": self})
该方案完全没有副作用,兼容多线程场景,仅性能略低于前两种方案,普通业务场景无感知。
内容的提问来源于stack exchange,提问作者igorbggg
相关产品推荐
相关产品推荐

