我想知道为什么导入python(python 3.4)中的变量与导入模块然后引用的结果不同,更多的是为什么要制作深层副本 - 并且有办法绕过副本(而不是通过定义一个只返回它的函数)?
a.py
v = 1
def set():
global v
v = 3
main.py
import a
import b
a.set()
b.foo()
b.py
from a import v
def foo():
print(v)
print(a.v)
print(id(v))
print(id(a.v))
输出
1
3
1585041872
1585041904
答案 0 :(得分:2)
问题在于您正在修改标量值。这不是模块特有的问题,只需将变量传递给函数并在那里进行修改就可以正常工作。
值 1
从a
期间导入。无论你在a
之后做什么都不会修改该值,因为它是一个简单的不可变标量值。
如果a.v
是一个对象,对此对象的更改将传播到任何持有对它的引用的变量。
答案 1 :(得分:2)
我自己问duplicate question,并在别人的帮助下弄清楚它是什么。这是我发现的。使用pydoc
链接:
from a import v
未添加对a.v
的引用。相反,当b
发生时,它会将b.v
的新变量添加为a.v
,值为import
。稍后更改a.v
不会更改b.v
的值。
from表单不绑定模块名称:它遍历标识符列表,在步骤(1)中找到的模块中查找每个标识符,并将本地名称空间中的名称绑定到找到的对象
from表单使用稍微复杂的过程:
- 找到
from
子句中指定的模块,必要时加载并初始化它;- 对于
醇>import
子句中指定的每个标识符:
- 检查导入的模块是否具有该名称的属性
- 如果没有,尝试导入具有该名称的子模块,然后再次检查导入的模块中的该属性
- 如果找不到该属性,则会引发
ImportError
。- 否则,对该值的引用将在中使用as子句中的名称存储在本地名称空间中,否则使用属性名称
此处的关键字是本地命名空间中的 。
答案 2 :(得分:1)
让我们检查一下事件的顺序:
a.v = 1 # a.py: v = 1
b.v = a.v # b.py: from a import v
a.v = 3 # a.set()
print(b.v) # foo(): print(v)
print(a.v) # foo(): print(a.v)
正如您所看到的,from a import v
实际上将b.v
绑定到来自a
的值,之后修改为原始变量不会影响副本。
答案 3 :(得分:0)
当您说import a
时,您正在创建对该模块的引用。 a.v未复制。我在所有模块中注意到改变了一个模块。当您说from a import v
时,您正在导入时复制v。如果更改了其中一个变量,则不会将其反映在其他位置。