【问题标题】:Why does accessing globals work via import module, but not from module import var?为什么通过导入模块访问全局变量,而不是从模块导入变量?
【发布时间】:2017-08-28 03:39:33
【问题描述】:

我一直在阅读和学习大量关于 python 的知识,但是所有具有不同结果的导入变体有点令人困惑。

我遇到了一个问题,即我导入的全局变量始终是默认值,即使我在该模块中调用了一个方法来操作它。我是这样导入的:

from fona import connect, disconnect, CON

前两个是函数,最后一个是 var。前两个打开或关闭连接,我可以通过 var CON 访问该连接。当我这样做时,CON 将保持无,即使 connect 成功初始化它(我有很多详细的输出来验证这一点)。我越来越乱七八糟,无法弄清楚。在我有了更多想法之前,写了一篇与这篇非常不同的帖子。

import fona

然后我通过 fona.connect/disco/CON 访问所有内容。然后它工作。我正在努力理解为什么并且找不到任何资源。是什么让这些进口产品与众不同?我很喜欢from x import y as z,但在这种情况下我似乎不能使用它。

【问题讨论】:

    标签: python import module globals


    【解决方案1】:

    在 Python 中,“全局”表示“模块级”(实际上在运行时“全局”变量是 module 对象实例的属性)。

    现在这个声明:

    from fona import CON
    

    是语法糖:

    import fona
    CON = fona.CON 
    del fona
    

    所以此时我们有两个名称指向同一个对象 - fon.CON<yourothermodule>.CON

    现在如果在fona 中我们有一个重新绑定fona.CON 的函数,即:

    def foo():
        global CON
        con = "XXX"
    

    调用此函数只会重新绑定fona.CON,而不是<yourothermodule> 中的CON 变量。

    如果改为导入整个fona 模块并使用fona.CON,您确实会在调用fona.foo() 后看到重新绑定的效果,因为您实际上是在访问fona 模块的属性,而不是您的本地(本地到) 属性。

    实际上,在同一个模块中使用两个 dicts 时,您会遇到完全相同的情况:

    d1 = {"a":1}
    d2 = {}
    d2["a"] = d1["a"]
    d1["a"] = 42 # this won't change d2["a"]
    print d1, d2
    

    其实你甚至不需要字典,只要在同一个命名空间中的两个名字就足够了:

    Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
    >>> a = 1
    >>> b = a
    >>> print a
    1
    >>> print b
    1
    >>> b is a
    True
    

    如您所见,此时b 不是a 的“副本”,它实际上只是绑定到同一个对象的另一个名称。现在如果我们重新绑定a:

    >>> a = 2
    >>> print a
    2
    >>> print b
    1
    >>> b is a
    False
    >>> 
    

    我们可以看到它不会影响b,它只会让a指向另一个对象。

    【讨论】:

    • 谢谢你。我错误地认为它将是对该变量的引用,而不是另一个实例/副本。
    • 一个参考 - Python 从不复制任何东西,除非明确要求。但是,当您 重新绑定 fona.CON 时,它不会将其他绑定更改为 fona.CON 之前绑定的内容 - 参见我回答中的 dict 示例。如果您改用可变对象并对其进行变异而不是将名称重新绑定到另一个对象,您会发现两个名称都指向同一个对象(当然,直到其中一个名称被重新绑定)。
    • 好的,现在更有意义了。我错误地假设执行“from fona import CON”会给我对 CON 的引用,因此当在 fona 模块中更改 CON(通过连接/迪斯科)时,CON 在我的模块中将是最新的。然而,创建了一个“本地”,它是对导入时 CON 的引用,并且随着 CON(fona) 被重新分配,它没有。然而,调用 fona.CON 会检查 fona 模块。谢谢。
    【解决方案2】:
    from fona import CON
    

    与*几乎相同:

    import fona
    CON = fona.CON
    

    现在,如果 fona 在内部发生变化,fona.CON 被替换为新值,这对您自己的变量没有影响。就像你说:

    y = 1
    x = y
    y = 2
    

    x 仍然是 1,尽管 y 现在是 2。


    *除了后者留下名字fona,前者没有。

    【讨论】:

      猜你喜欢
      • 2020-11-02
      • 2013-04-02
      • 2018-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-27
      • 2021-12-14
      • 2010-11-05
      相关资源
      最近更新 更多