我创建了一个 Python 模块,它只有一个函数,它只打印“a!”。我打开了 Python 解释器并以 2 种不同的语法导入了模块
>>> import a
>>> from a import func
>>> func()
a!
>>> a.func()
a!
此时我改变了 func 来打印其他东西,然后再次计算
>>> func()
a!
>>> a.func()
a!
这当然是预料之中的,因为模块没有重新加载。然后我重新加载了模块并期望两个函数都更新,但是:
>>> reload(a)
<module 'a' from 'a.py'>
>>> a.func()
aasd!
>>> func()
a!
似乎只有 a.func 更新了。我一直认为 Python 只保留同一个模块的单个实例,但现在似乎有两个。我做了进一步的测试以验证我的说法,并在模块的顶层添加了一个打印语句,然后重新启动解释器并再次导入:
>>> import a
module imported
>>> import a
>>> from a import func
这让我更加困惑,因为我预计会看到两次“模块导入”。我做的第三个实验是全局变量实验:
>>> import a
module imported
>>> from a import GLOBAL_VAR
>>> GLOBAL_VAR = 5
>>> a.GLOBAL_VAR
1
>>> GLOBAL_VAR
5
>>> GLOBAL_VAR is a.GLOBAL_VAR
False
所以模块只有一个实例,但内部对象有不同的实例?如何实现 Gevent's monkey patching有这样的行为?
最佳答案
模块一旦被导入,就只是另一个 python 对象。所以看到下面的例子,你的结果应该不会让你吃惊:
x = SomeObject()
x.y = 1
a = x.y
x.y = 2
print(a) #a is still 1, not 2
当您执行 from module import name
时,会在当前命名空间中创建一个变量 name
,它包含对导入内容的引用(无论是包/模块/类/任何)。它是以下内容的语法糖:
import module
name = module.name
现在,当您重新加载 module
时,您显然不会更新引用 name
的内容。
关于你的第二个实验,一个模块在导入后缓存在 sys.modules
中;后续导入将利用缓存。因此,所有直接在模块级别的代码,如您的 print
,只会在第一次导入时执行。
关于python - 同一个 Python 模块的两个实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20605799/