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

为何Python Mock仅在特定模块导入方式下生效?

为什么两种导入方式下Mock utils.get_id的效果不同?

这本质是Python导入语句的命名空间绑定逻辑差异,和传值/传引用无关,下面拆解两种情况的运行机制:

1. 第一种导入:from utils import get_id

当car.py用这种写法时,Python会执行以下操作:

  • 加载utils模块(未加载过的话)
  • 在car模块的独立命名空间里,创建一个名为get_id的变量,直接指向原utils.get_id函数对象
  • 后续Car.setup里调用的get_id(),实际是调用car模块命名空间里的这个变量指向的对象

你在测试代码里修改的是utils.get_id——也就是把utils模块命名空间里的get_id变量换成了Mock对象,但car模块里的get_id变量仍然指向原来的函数。这就像:

a = [1,2,3]
b = a
a = [4,5,6]
# b还是[1,2,3],因为a和b是两个独立变量,只是最初指向同一对象

car.get_id和utils.get_id就是例子里的b和a,修改其中一个的指向不会影响另一个。

2. 第二种导入:from . import utils

改成这种写法后,Python的逻辑变成:

  • 加载utils模块(未加载过的话)
  • 在car模块的命名空间里创建一个名为utils的变量,指向整个utils模块对象
  • 后续Car.setup里调用的utils.get_id(),是先通过car.utils找到模块对象,再从模块对象的命名空间里取出get_id属性

此时你在测试里修改utils.get_id,是直接修改了模块对象本身的属性,而car模块里的utils变量一直指向这个模块对象,所以setup调用时会拿到替换后的Mock对象。

验证方式

可以在测试代码里加两行打印验证:

# 第一种导入方式下,两者地址不同
print(id(utils.get_id))
print(id(car.get_id))

# 第二种导入方式下,两者地址会同步变化
print(id(utils.get_id))
print(id(car.utils.get_id))

内容的提问来源于stack exchange,提问作者ningelsohn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:55:04