【问题标题】:Passing "local" variables in Python by changing and importing modules?通过更改和导入模块在 Python 中传递“本地”变量?
【发布时间】:2014-07-01 10:49:21
【问题描述】:

我今天不得不阅读并修复一些非常糟糕的脚本,我很困惑,因为我根本不明白它们为什么会起作用。需要明确的是,我永远不会做这样的事情。我的问题是在这种情况下命名空间如何工作,而不是为什么这是一个坏主意或如何做得更好。

无论如何,最简单的情况可以用两个文件重现。

test.py:

import math
math.myvar = "Is this a local variable?"
math.pi = 1.2345
import u

u.py:

import math
print(math.myvar)
print(math.pi)

现在,令我惊讶的是,运行 python test.py 将打印 myvar 和错误的 pi 值。当然,如果没有u.py 中的import math,它将不会打印myvar。这是怎么发生的?我虽然导入的模块在范围内完全是本地的。

【问题讨论】:

    标签: python import module namespaces scope


    【解决方案1】:

    模块是全局单例。它们存储在sys.modules 映射中,以防止每次在某个地方使用每个模块时都必须加载它。

    模块中的所有全局变量都作为模块对象的属性公开; math.pi 就是这样一个全球性的。你可以通过赋值来改变这些全局变量,因为模块是单例对象,每个对模块对象的引用都会看到变化。

    记住,Python 名称是引用math 这个名字对于你的模块来说确实是“本地的”,但它仍然是对全局 <module 'math' from '/usr/lib/python2.7/lib-dynload/math.so'> 对象的引用。

    【讨论】:

    • 是的,我现在明白了。一些研究表明,文档在描述导入内部时实际上提到了这一点:docs.python.org/2/library/imp.html#imp.load_module
    • 所以我想我可以通过执行sys.modules.pop('math') 并再次导入来清除之前的更改。
    • @Karol: 或使用reload() function,尽管这将保留 math.myvar 名称。这是reload() 的显式特征。
    猜你喜欢
    • 2012-07-14
    • 2016-12-28
    • 2012-08-27
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2012-11-11
    相关资源
    最近更新 更多