如何通过编程方式确定Python运算符实际调用的方法
验证Python运算符对应底层魔术方法的简便实现
你原来的遍历patch方案本质是反向枚举排查,逻辑冗余还需要处理内置类属性只读的问题,完全可以用更轻量的正向打桩方案实现,不需要复杂的mock逻辑,代码量少且通用。
注意Python的运算符重载有特殊查找规则:执行运算符操作时,解释器会直接从对象所属类的层面检索对应的魔术方法,不会读取实例上的同名属性,所以我们只需要给测试类的所有魔术方法统一加上调用记录,执行目标操作后直接读取被触发的方法名即可:
def build_trace_class(): called = set() class TraceProbe: pass # 为所有内置魔术方法注入调用记录逻辑 for method_name in dir(object): if not (method_name.startswith("__") and method_name.endswith("__")): continue def wrap(name): def _wrapper(*args, **kwargs): called.add(name) raise NotImplementedError("仅做调用追踪,无实际逻辑") return _wrapper setattr(TraceProbe, method_name, wrap(method_name)) return TraceProbe, called # 测试[]运算符 ProbeCls, called = build_trace_class() probe = ProbeCls() try: _ = probe[0] except Exception: # 桩方法无实际逻辑会抛异常,不影响调用记录 pass print(called) # 输出: {'__getitem__'},直接确认[]运算符对应的底层方法
这个方案通用性极强,要验证其他运算符或内置函数对应的魔术方法,只需要修改测试时的操作语句即可:
- 测试
+运算符:执行probe + 1,会捕获到__add__ - 测试
len()调用:执行len(probe),会捕获到__len__ - 测试
in成员判断:执行1 in probe,会捕获到__contains__ - 测试
[]赋值操作:执行probe[0] = 1,会捕获到__setitem__
不需要提前遍历目标类型的属性,不需要处理mock的路径问题,纯原生Python即可运行,没有额外依赖。
内容的提问来源于stack exchange,提问作者zwithouta
相关产品推荐
相关产品推荐

