
python 导入模块时仅执行一次模块体,因此模块级创建的类实例是全局唯一的;但更推荐按需实例化,以提升可测试性、避免隐式状态依赖。
python 导入模块时仅执行一次模块体,因此模块级创建的类实例是全局唯一的;但更推荐按需实例化,以提升可测试性、避免隐式状态依赖。
在 Python 中,import 并非简单地“复制代码”,而是一套受 sys.modules 缓存机制严格管理的运行时过程。当你在 foo.py 中定义类并直接实例化:
# foo.py
class Foo:
def __init__(self):
print("Foo instance created") # 仅首次导入时打印
foo = Foo() # 模块级实例化
该实例 foo 的创建行为只发生一次——即该模块首次被导入时。后续所有 import foo 或 from foo import Foo 均直接复用 sys.modules["foo"] 中已加载的模块对象,其中 foo.foo 引用的是同一个实例。
✅ 正确理解:
- from foo import Foo 导入的是类(可复用的蓝图),不触发实例化;
- import foo 导入的是整个模块对象,其顶层语句(含 foo = Foo())仅执行一次;
- 所有模块共享同一份模块命名空间,因此 foo.foo 在任意位置访问都指向同一实例。
⚠️ 但模块级实例化存在明显隐患:
- 隐式单例:行为不可控,难以 mock 或重置,严重阻碍单元测试;
- 初始化副作用:若 __init__ 含 I/O、网络调用或依赖未就绪的全局状态,可能导致导入失败或竞态;
- 参数僵化:无法为不同使用场景传入差异化参数(如配置、连接池大小等)。
? 推荐实践:导出类,由使用者按需实例化
# foo.py —— 仅定义,不实例化
class Foo:
def __init__(self, name="default"):
self.name = name
print(f"Foo({name}) created")
# bar.py
from foo import Foo
instance_a = Foo(name="alpha") # 显式、可控、可测试
# baz.py
from foo import Foo
instance_b = Foo(name="beta") # 独立生命周期,互不影响
? 总结:
Python 的模块缓存机制确保了类定义和模块级对象的唯一性,但这不意味着应滥用模块级实例。将实例化职责交还给调用方,是符合 Python 哲学(显式优于隐式)、利于解耦与测试的稳健设计。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











