【问题标题】:Import variable initialization导入变量初始化
【发布时间】:2015-06-10 14:15:07
【问题描述】:

我想知道为什么在 python (python 3.4) 中导入变量与导入模块然后引用的结果不同,更重要的是为什么要进行深层复制 - 有没有办法绕过复制(而不是通过定义一个简单地返回它的函数)?

a.py

v = 1

def set():
    global v
    v = 3

ma​​in.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

【问题讨论】:

  • 因此您想从调用代码中更改导入模块的状态。为什么?
  • 配置 - 我想读取配置,然后再访问它。
  • 调用代码改变动态配置?

标签: python python-3.x


【解决方案1】:

问题在于您正在修改标量值。这不是特定于模块的问题,只需将变量传递给函数并在那里修改它,它的工作原理是一样的。

1 是从 a 导入的,句号。之后在a 中所做的任何事情都不会修改该值,因为它是一个简单的不可变标量值。

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

【讨论】:

  • 只是澄清一下:对对象的更改会传播,但将变量重新绑定到另一个对象不会。
【解决方案2】:

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

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

Python 2

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

Python 3

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

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

这里的关键字是在本地命名空间中

【讨论】:

    【解决方案3】:

    让我们检查一下事件的顺序:

    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,以后对原始变量的修改不会影响副本。

    【讨论】:

      【解决方案4】:

      当您说import a 时,您正在创建对模块的引用。 a.v 没有被复制。我在所有模块中都注意到一个模块的变化。当您说from a import v 时,您是在导入时制作 v 的副本。如果任一变量发生更改,则不会在其他地方反映出来。

      【讨论】:

        猜你喜欢
        • 2011-02-19
        • 2019-05-17
        • 2021-07-08
        • 2012-06-15
        • 2012-10-19
        • 2016-11-03
        • 2017-03-20
        • 2016-07-31
        相关资源
        最近更新 更多