使用方法引用调用时,Python继承中的重写机制失效问题
解决Python继承场景下字典动态调用方法不触发重写的问题
问题重现
你通过字典实现方法动态调用,但子类重写的方法无法被正确触发,示例代码如下:
class A(): def sum(self, id: int): return 1 def multiply(self, id: int): return 2 def process(self, type: str, id: int): callable_method = self.__dispatcher.get(type) return callable_method(self, id) __dispatcher = { "+": sum, "*": multiply } class B(A): def process(self, type: str, id: int): return super(B, self).process(type, id) def multiply(self, id: int): return 3 # 调用后返回2而非预期的3 ob = B() print(ob.process("*", 0))
可行解决方案
方案1:通过方法名字符串动态获取实例方法
将字典存储的改为方法名而非直接的方法引用,在process中用getattr从实例获取方法,这样会遵循Python的方法解析顺序(MRO),优先调用子类重写的方法:
class A(): def sum(self, id: int): return 1 def multiply(self, id: int): return 2 def process(self, type: str, id: int): method_name = self.__dispatcher.get(type) if not method_name: raise ValueError(f"Unsupported type: {type}") callable_method = getattr(self, method_name) return callable_method(id) __dispatcher = { "+": "sum", "*": "multiply" } class B(A): def process(self, type: str, id: int): return super(B, self).process(type, id) def multiply(self, id: int): return 3 # 调用返回3,符合预期 ob = B() print(ob.process("*", 0))
方案2:在实例初始化时构建绑定方法的字典
将__dispatcher改为实例属性,在__init__中绑定当前实例的方法,这样子类实例化时会自动绑定子类重写后的方法:
class A(): def __init__(self): # 初始化时绑定实例的方法 self.__dispatcher = { "+": self.sum, "*": self.multiply } def sum(self, id: int): return 1 def multiply(self, id: int): return 2 def process(self, type: str, id: int): callable_method = self.__dispatcher.get(type) if not callable_method: raise ValueError(f"Unsupported type: {type}") return callable_method(id) class B(A): def process(self, type: str, id: int): return super(B, self).process(type, id) def multiply(self, id: int): return 3 # 调用返回3,符合预期 ob = B() print(ob.process("*", 0))
问题原因分析
原代码中__dispatcher是类级别的属性,存储的是父类A的sum和multiply函数对象(未绑定方法)。当你调用callable_method(self, id)时,直接执行的是A类中定义的方法逻辑,不会触发子类的重写——因为它绕过了Python实例的方法查找链,直接调用了父类的原始函数。
而上述两种方案都通过不同方式遵循了Python的方法解析规则:方案1通过getattr从实例动态查找方法,方案2在实例初始化时绑定了已经经过MRO解析的实例方法,因此都能正确调用子类重写后的方法。
内容的提问来源于stack exchange,提问作者pxm
相关产品推荐
相关产品推荐

