以下所有内容都在一个文件中:
def inner_foo(in_arg):
global x;
x += 99
return in_arg + 1
def outer_foo(in_arg):
global x;
x = 0
output = inner_foo(in_arg)
return output
result = outer_foo(5)
print("result == ", result)
print("x == ", x)
当它在一个文件中时,它可以正常工作。以下是打印的内容:
result == 6
x == 99
但是,如果我们尝试将程序拆分为多个文件,我们就会遇到问题。
# CONTENTS OF inner_foo.py
def inner_foo(in_arg):
global x;
x += 99
return in_arg + 1
这是另一个文件:
# CONTENTS OF outer_foo.py
from inner_foo import inner_foo
def outer_foo(in_arg):
global x
x = 0
output = inner_foo(in_arg)
return output
result = outer_foo(5)
print("result == ", result)
print("x == ", x)
我们在inner_foo.py
内的NameError: name 'x' is not defined
行上收到错误x += 99
将import语句更改为包含x(from inner_foo import inner_foo, x
)会给我们:
ImportError: cannot import name 'x'
答案 0 :(得分:0)
Python“全局”范围实际上是模块级,正如您在尝试导入时推断的那样。问题是,当您执行x += 1
时,这相当于x = x + 1
,但 x
从未在您的模块中定义过。所以,假设我们有a.py
:
def f():
global x
x += 1
x
中没有a
,只有f
。现在,让我们打开一个REPL:
>>> import a
>>> a.f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/juan/workspace/temp/globals_modules/a.py", line 3, in f
x += 1
NameError: name 'x' is not defined
并且,如上所述,“全局范围”实际上是模块级范围,因此f
的全局范围是模块a
的命名空间,不一定是调用者的全局范围,即:
>>> x = 0
>>> a.f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/juan/workspace/temp/globals_modules/a.py", line 3, in f
x += 1
NameError: name 'x' is not defined
所以,实际上,它正在x
的命名空间中查找a
,所以如果我们执行以下操作:
>>> a.x = 0
>>> a.f()
>>> a.x
1
>>> a.f()
>>> a.x
2
有效!所以尽可能简洁地说:
>>> a.f.__globals__ is globals()
False
现在你掌握了这些知识,不沿着这条设计路径前进。依靠模块之间不断变化的全局状态是一条悲伤的道路。不要这样做,不建议这样做,因为几代编码器发现这很糟糕。重新设计您的方法,您将构建更强大,更容易推理和减少错误的软件。