You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中监视类的实例化及方法调用?

我明白你的问题了——你想在运行原始类代码的同时,既跟踪类的实例化过程,又监控实例方法的调用,但用wraps=A时方法调用没被记录,用autospec=True又没法执行原始方法。

问题根源

当你用mock.patch('__main__.A', wraps=A)时,mock类m在被实例化时会调用原始的A.__init__,返回的是原始A的实例,而不是mock实例。这个原始实例的方法没有被mock包装,所以m.method_calls自然不会记录这些方法的调用。

而autospec=True会生成一个模仿原始类结构的mock,但默认情况下,这些mock方法不会调用原始实现,只会记录调用行为。

解决方案:包装实例并关联到类mock

我们可以自定义mock类的side_effect,让它在创建原始实例后,用一个mock包装这个实例。这样既会执行原始代码,又能跟踪实例方法的调用,同时这些调用会被关联到类mock的method_calls中。

下面是完整的实现代码:

import mock

class A:
    def __init__(self, some_arg):
        print("constructor")
    def f(self, some_var):
        print(some_var)

def spied_instance_creator(*args, **kwargs):
    # 创建原始类的实例,保证实际代码执行
    original_instance = A(*args, **kwargs)
    # 用mock包装原始实例,跟踪方法调用
    spied_instance = mock.Mock(wraps=original_instance, spec=A)
    return spied_instance

# 打补丁,使用自定义的实例创建逻辑
patch = mock.patch('__main__.A', side_effect=spied_instance_creator)
mocked_class = patch.start()

# 执行你的业务代码
a = A('something')
a.f('my_arg')

# 验证实例化和方法调用都被跟踪
assert mock.call('something') in mocked_class.mock_calls
# 注意:实例方法调用在类mock的method_calls中会以call().f(...)的形式存在
assert mock.call().f('my_arg') in mocked_class.method_calls

# 结束补丁(可选,在测试框架中通常会自动处理)
patch.stop()

为什么这样有效?

  1. spied_instance_creator函数负责创建原始实例,确保__init__和f的实际代码被执行。
  2. 用mock.Mock(wraps=original_instance, spec=A)包装原始实例,既保留了原始方法的功能,又能跟踪所有方法调用。
  3. 类mock的side_effect返回这个包装后的实例,所以实例的方法调用会被记录到类mock的method_calls中。

这样你就能同时满足“运行实际代码”和“监视实例化、方法调用”两个需求了。

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:08:29