2015-06-10 56 views
2

我想知道为什么在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

所以你想改变从调用代码导入模块的状态。为什么? –

+0

配置 - 我想要读取配置,然后再访问它。 –

+0

通过调用代码更改动态配置? –

回答

2

的问题是,你正在修改一个标量值。这不是特定于模块的问题,只需将该变量传递给函数并在其中进行修改即可。

1a,期间导入。无论你在a之后做什么都不会修改该值,因为它是一个简单的不可变的标量值。

如果a.v是一个对象,改变该对象会传播到任何变量保持它的一个引用。

+2

只是为了阐明:对象的更改会传播,但将变量重新绑定到另一个对象则不会。 – bereal

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.va,和原来的变量之后修改不会影响副本。

0

当您说import a时,您正在创建对模块的引用。 a.v不会被复制。我在所有模块中都注意到在一个模块中进行更改。当您说from a import v时,您正在导入时制作v的副本。如果其中任何一个变量被改变,它都不会反映在别处。

1

自己问了一个duplicate question,并且在别人的帮助下,我弄清楚它是什么。这是我发现的。 With pydoc链接:

from a import v未添加对a.v的引用。相反,当import发生时,它将b添加为b.v的新变量,其值为a.v。稍后更改a.v不会更改b.v的值。

Python 2

的从形式不结合模块名称:它通过标识符的列表,看起来它们中的每一个向上在步骤(1)中发现的模块中,并且在结合的名称找到对象的本地名称空间。

Python 3

的形式从使用一个稍微复杂的过程:

  1. 发现在from子句,装载指定,并且如果需要的话对其进行初始化的模块;
  2. 每个在import子句指定的标识符:
    1. 检查,如果导入的模块有这个名字的属性
    2. 如果没有,尝试导入一个子模块具有该名称,然后检查导入的模块再次针对该属性
    3. 如果未找到该属性,则会引发ImportError
    4. 否则,以该值的引用存储在本地名称空间中,在使用名称的,就好像它是本,以其他方式使用的属性名称

关键字这里子句在本地命名空间中为