在eval中修改Python全局变量
我有这样的代码:在eval中修改Python全局变量,python,eval,Python,Eval,我有这样的代码: globals_defined = {'add': my_add_fn, 'divide': my_divide_fn} eval_result = eval(<some code>, {data: {'name_1': 'NAME1', 'name_2': 'NAME2'}, globals_defined) 编辑:我应该先添加这个。是的,我需要使用eval。此评估最初来自用户输入,但已解析为一个抽象语法树,该树拒绝除少数数学运算以外的所有运算。然后,AST是通
globals_defined = {'add': my_add_fn, 'divide': my_divide_fn}
eval_result = eval(<some code>, {data: {'name_1': 'NAME1', 'name_2': 'NAME2'}, globals_defined)
编辑:我应该先添加这个。是的,我需要使用eval。此评估最初来自用户输入,但已解析为一个抽象语法树,该树拒绝除少数数学运算以外的所有运算。然后,AST是通过定义一些自定义函数定义来评估的
不过,听起来我不能这样做。您不应该首先使用eval。 但是,由于您没有显示您在其中运行的代码,因此没有办法建议替代方案 事实上,Python的
eval
只执行表达式——Python中的赋值是语句
——通常情况下,在eval中不能有赋值
解决这个问题的方法就是使用exec
而不是eval。默认情况下,exec
将使用运行它的模块的全局变量,因此,执行代码中的任何赋值都将影响全局命名空间
如果您将字典作为第二个参数传递给exec
,它将使用该字典作为其全局字典,然后您可以让它使用赋值修改该dict中的值
这是关于eval和exec的一般性陈述-您的具体问题是(可能)试图调用eval内部的函数-add()
-该函数在globals\u定义的
字典中公开。问题是您的add函数是在模块中定义的,超出了eval(或exec)范围。my\u add\u fn
函数的全局变量不是传递给eval的globals
,而是模块globals本身。因此,它访问的变量count\u iterations
在模块范围内,而不是在globals\u定义的
字典内
当然有办法解决这个问题。最好的方法是:不要使用eval(或exec)。
最后一行的print习惯用法表明您是Python新手,否则您将了解现有的强大的字符串格式化方法。
也就是说:您可以调用存储在字典中的函数,就像访问字典中的任何元素一样,即:
globals\u defined[“add”]()
将使用您的所有my\u add\u fn
功能-这是一个如何避免使用“eval”的提示
最后,回到您的问题所在——解决问题的一种方法是让您的函数不依赖于其全局名称空间,而是接收和返回参数——然后在exec字符串范围外对函数返回的值进行赋值——因此:
def my_add_fn(count):
return 'blah!', count+1
global_dict = {"add": my_add_fn, "count_iterations": 0}
exec("result, count_iterations = add()", global_dict)
print "Count = {}".format(global_dict["count_iterations"])
为什么要尝试使用全局名称空间?为什么不构造一个特定的本地名称空间来将函数传递给
eval
?将globals()?你想解决什么问题?我也不能这样做,因为会有多个评估正在运行?将多个eval更改为多个exec。相反,将代码更改为不使用eval动态调用所需函数。:-)他/她实际上并没有这样做——他/她正在传递一本自定义词典。相反,问题在于调用一个试图更改全局变量的函数——但函数的全局变量不是传递给eval的全局变量。
def my_add_fn():
global count_iterations
count_terations += 1
return 'blah!'
def my_add_fn(count):
return 'blah!', count+1
global_dict = {"add": my_add_fn, "count_iterations": 0}
exec("result, count_iterations = add()", global_dict)
print "Count = {}".format(global_dict["count_iterations"])