如何重定义Python3 MagicMock魔术方法?子类重写为何返回NotImplemented?
这个问题的核心在于MagicMock对魔术方法的特殊处理机制——它并不会像普通类那样直接使用你子类中重写的魔术方法,而是会动态生成一个mock版本的方法,这就是为什么你得到NotImplemented的原因。
MagicMock的设计初衷是自动mock所有属性和方法,包括魔术方法。当你访问t1.__lt__时,它的内部拦截机制会优先创建一个默认返回NotImplemented的mock方法,完全绕过了你在子类中定义的__lt__实现。
而普通类(比如你例子中的B)没有这种动态mock的逻辑,所以子类重写的方法会被正常调用,自然能返回self。
解决方法
你可以通过两种方式让子类的魔术方法按预期工作:
方法1:在__init__中设置魔术方法的side_effect
利用MagicMock的side_effect属性,给__lt__绑定自定义逻辑:
from unittest.mock import MagicMock class MockForTest(MagicMock): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 让__lt__调用时返回自身 self.__lt__.side_effect = lambda: self t1 = MockForTest() print(t1.__lt__()) # 输出类似<__main__.MockForTest object at 0x000001D6EE77B2B0>的实例对象
方法2:覆盖__getattr__拦截魔术方法的获取
通过重写__getattr__,当获取__lt__时返回你自定义的方法,其他属性交给父类处理:
from unittest.mock import MagicMock class MockForTest(MagicMock): def __getattr__(self, name): if name == '__lt__': return lambda: self # 其他属性继续使用MagicMock的默认逻辑 return super().__getattr__(name) t1 = MockForTest() print(t1.__lt__()) # 同样返回实例对象
这两种方法都能绕过MagicMock的默认魔术方法mock逻辑,让你的自定义实现生效。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

