请注意:这是不有关如何更改函数体内全局变量的问题。我了解global
关键字。
我的脚本有一堆全局配置变量。我想编写一个函数来隐藏本地命名空间中的一个全局变量(下面称为modified_procedure()
)并调用另一个引用配置变量的函数。即,
PARAMETER = 1
def procedure():
return PARAMETER * 3
def modified_procedure():
PARAMETER += 1
return procedure()
这会失败,因为PARAMETER
的主体中出现modified_procedure()
,因此解释器将其视为局部变量,并且不会在全局命名空间中查找它。我不是要改变全局变量PARAMETER
;我试图在modified_procedure()
的命名空间中隐藏它。
我可以想到几个不方便的解决方案:
procedure()
global
中的modified_procedure()
修改PARAMETER
,然后在退回procedure()
我可以通过遮蔽PARAMETER
来实现吗?如果是这样,怎么样?
答案 0 :(得分:4)
略微hackish,但你可以使用下面的方法使事情有效。
首先,定义初始方法如下:
PARAMETER = 1
def procedure(PARAMETER = PARAMETER):
return PARAMETER * 3
现在,在第二种方法中,您可以使用globals()
method并使用修改后的PARAMETER
调用它:
def modified_procedure_v1():
PARAMETER = globals()["PARAMETER"] + 1
return procedure()
您甚至可以使用更新的PARAMETER值以下列方式从修改后的方法中调用第一个方法:
def modified_procedure_v2():
PARAMETER = globals()["PARAMETER"] + 1
return procedure(PARAMETER)
因此,最终结果变为:
>>> modified_procedure_v1() #uses global PARAMETER
3
>>> modified_procedure_v2() #uses PARAMETER value local to this method
6
答案 1 :(得分:1)
你要求的动态范围是多少。 Python,就像今天仍在使用的大多数语言一样(Perl和Emacs Lisp都是值得注意的例外)根本不支持动态范围,选择词法范围。
您可以更改procedure
函数对象以替换其__globals__
。但这会更加黑客,还有更多代码可以启动。如果您可以更改procedure
以接受参数,请执行此操作。如果它必须涉及全球,那么暂时改变全球将是最不痛苦和令人惊讶的方法。
答案 2 :(得分:1)
你可以(ab)使用mock
库暂时更改PARAMETER
全局范围内记录的procedure
的值:
import mock
def modified_procedure():
with mock.patch.dict(procedure.func_globals, PARAMETER=PARAMETER+1):
return procedure()
在Python 3中,mock
是unittest
包而不是第三方库的一部分,它将是
from unittest import mock
def modified_procedure():
with mock.patch.dict(procedure.__globals__, PARAMETER=PARAMETER+1):
return procedure()
不使用mock
,您可以尝试类似
def modified_procedure():
# Support Python 2 and 3.
try:
d = procedure.__globals__
except AttributeError:
d = procedure.func_globals
# Ensure that procedure()'s globals are restored
# even if it raises an exception.
try:
d['PARAMETER'] += 1
return procedure()
finally:
d['PARAMETER' -= 1