导入变量初始化

时间:2015-06-10 14:15:07

标签: python python-3.x

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

4 个答案:

答案 0 :(得分:2)

问题在于您正在修改标量值。这不是模块特有的问题,只需将变量传递给函数并在那里进行修改就可以正常工作。

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

如果a.v是一个对象,对此对象的更改将传播到任何持有对它的引用的变量。

答案 1 :(得分:2)

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

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

Python 2

  

from表单不绑定模块名称:它遍历标识符列表,在步骤(1)中找到的模块中查找每个标识符,并将本地名称空间中的名称绑定到找到的对象

Python 3

  

from表单使用稍微复杂的过程:

     
      
  1. 找到from子句中指定的模块,必要时加载并初始化它;
  2.   
  3. 对于import子句中指定的每个标识符:      
        
    1. 检查导入的模块是否具有该名称的属性
    2.   
    3. 如果没有,尝试导入具有该名称的子模块,然后再次检查导入的模块中的该属性
    4.   
    5. 如果找不到该属性,则会引发ImportError
    6.   
    7. 否则,对该值的引用将在中使用as子句中的名称存储在本地名称空间中,否则使用属性名称
    8.   
  4.   

此处的关键字是本地命名空间中的

答案 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。如果更改了其中一个变量,则不会将其反映在其他位置。