【发布时间】:2016-02-27 12:37:29
【问题描述】:
我最近遇到了一些不寻常的行为。
foo.py
a = 0
def bar():
print (a)
控制台:
>>> import foo
>>> foo.bar()
0
>>> foo.a = 10
>>> foo.bar()
10
控制台:
>>> from foo import *
>>> bar()
0
>>> a
0
>>> a = 10
>>> a
10
>>> bar()
0
我推断import * 实际上是在创建a 的两个副本——一个在全局命名空间中,一个在foo 模块中,无法访问。这种行为是否在任何地方进行了解释/记录?我不知道要搜索什么。
这似乎是import * 的一个显着且出乎意料的后果,但出于某种原因,我以前从未见过它。
【问题讨论】:
-
这是一个定义明确的行为,没有隐藏的命名空间,只是每个函数都知道其模块的全局变量。当前模块中的全局变量不会影响导入模块的全局变量。 Each module has its own private symbol table, which is used as the global symbol table by all functions defined in the module. Thus, the author of a module can use global variables in the module without worrying about accidental clashes with a user’s global variables.
-
Python 中基本上没有用户定义的全局变量。有一个讨厌的 hack 来创建真正的全局变量,你基本上不应该使用它,但是你定义的任何东西,比如
a = 10最多是模块级别的。 -
来自
foo的原始a是该函数闭包的一部分 -
@user65 没错,但这并不意味着如果您在当前模块中覆盖
a,bar的输出也会发生变化。bar()仍然会从bar.__globals__获得a的值。 -
谢谢,我现在对 Python 中作用域和导入的工作原理有了更深入的了解。