如何让Python模块每次导入时都生成新对象?
解决每次调用
call_foo()都输出6的问题 这问题我太熟悉了!Python里模块默认是单例模式的——第一次导入后,模块对象会被缓存到sys.modules字典里,后续所有的import操作都会直接复用这个缓存好的对象。所以你现在每次调用call_foo(),都是在修改同一个foo模块实例里的a值,自然会越来越大。
要实现每次调用都让import foo像创建新对象一样,有两种实用的方法:
方法一:用importlib.reload()重载模块
直接在每次调用时重新加载foo模块,重置它的内部状态:
# bar.py import importlib import foo # 先导入一次基础模块 def call_foo(): importlib.reload(foo) # 关键:每次调用都重新加载foo foo.a += 1 print(foo.a) call_foo() # 输出6 call_foo() # 输出6
reload()会重新执行foo.py的代码,把模块内的变量重置为初始值,这样每次调用时foo.a都会回到5,加1后自然就是6。
方法二:删除sys.modules中的模块缓存
先把缓存的foo模块从sys.modules里删掉,这样下次import就会重新创建全新的模块对象:
# bar.py import sys def call_foo(): # 移除已缓存的foo模块(如果存在) if 'foo' in sys.modules: del sys.modules['foo'] import foo # 此时会重新导入,生成新的模块实例 foo.a += 1 print(foo.a) call_foo() # 输出6 call_foo() # 输出6
sys.modules是Python用来存储所有已导入模块的缓存字典,删除对应的键后,import foo会重新执行模块代码,相当于每次都创建了一个新的foo模块对象,a的初始值始终是5。
注意事项
- 这两种方法都适合简单场景,如果你的
foo模块有复杂的初始化逻辑(比如打开文件、建立数据库连接),频繁重载/重新导入可能会引发副作用,需要谨慎使用。 - 生产环境中尽量避免频繁操作模块缓存,除非确实有明确的需求,否则可能影响性能和代码的可维护性。
内容的提问来源于stack exchange,提问作者Herel Adrastel




