撤销'global <var>'语句
我正在学习Python,刚好有个问题想问。这个问题可能没有什么实际意义,我只是出于好奇想了解一下。
我有一个函数:
def f():
x = 12 #this is a local variable
global x #this is a global I declared before
x = 14 #changes global x
<How can I return the local x?>
我知道这样写很糟糕,而且会收到语法警告。我只是想知道怎么才能“找回”我的局部变量。
谢谢大家。
3 个回答
不能撤销global
语句的效果。
global
语句在它出现的整个函数运行期间都有效,不管它在函数中的位置,也不管它是否被执行。因此,在下面这个函数的赋值中:
def f():
x = 3
if False:
global x
x
依然被视为全局变量。
所以在后面再加一个语句来撤销它的效果是没有意义的,因为global
语句并不是在函数执行的某个时刻被执行的,而是对整个函数行为的一种声明。
我非常怀疑这件事能做到。
>>> x = 1
>>> def f():
... x = 12
... global x
... print x
...
<stdin>:3: SyntaxWarning: name 'x' is assigned to before global declaration
>>> f()
12
>>> x
12
如你所见,即使在global
关键字后没有明确给x
赋值,python还是会把这两个值同步起来。要理解原因,你需要对它进行拆解。
>>> dis.dis(f) # different f with print statement removed for clarity
2 0 LOAD_CONST 1 (12)
3 STORE_GLOBAL 0 (x)
3 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
>>>
这里根本没有显示global
关键字,但赋值语句被编译成了STORE_GLOBAL
。一旦你执行了这个操作,就完成了。使用全局变量要小心,使用global
关键字更要谨慎。
你的代码并没有按照你想的那样运行,而且也没有办法让它按照你描述的那样去做。你不能“恢复”globals
的功能,因为它在运行时没有任何效果。
global
这个关键词是在编译时被解释的,所以在f()
的第一行你设置x = 12
时,这实际上是在修改全局的x
。因为编译器已经决定了,x
在整个函数中都指的是全局命名空间里的x
,而不仅仅是在global
语句之后。
你可以很简单地测试这一点:
>>> def g():
... x = 12
... y = 13
... global x
... print "locals:",locals()
...
<stdin>:4: SyntaxWarning: name 'x' is assigned to before global declaration
>>> g()
locals: {'y': 13}
locals()
函数可以让我们查看局部命名空间,我们可以看到里面没有x
这个变量。
在
global
语句中列出的名字,不能在同一个代码块中出现在这个global
语句之前。在
global
语句中列出的名字,不能被定义为正式参数,或者在for
循环控制目标、class
定义、函数定义或import
语句中使用。当前的实现并没有强制执行后面两个限制,但程序不应该滥用这种自由,因为未来的实现可能会强制执行这些限制,或者默默地改变程序的含义。
只需给局部变量起个不同的名字就可以了。