python - ast 执行在函数与模块范围内产生不同的结果
问题描述
编辑:问题与ast
模块无关。
只需使用即可复制它exec
:
y = None
exec("y = 5.0")
print(y) # prints 5.0
对比
def foo():
y = None
exec("y = 5.0")
print(y)
foo() # prints None
原始问题:
我正在使用ast
模块以编程方式生成代码。我有以下代码,有效:
import ast
num = ast.Num(n=5.)
y = None
assign = ast.Assign(targets=[ast.Name(id='y', ctx=ast.Store())], value=num)
tree = ast.Module(body=[assign], type_ignores=[])
ast.fix_missing_locations(tree)
c = compile(tree, filename="", mode="exec")
exec(c) # replaces the value of 'y' with 5.0
print(y) # prints 5.0
但是,一旦我将此代码包装在一个函数中,它就会停止工作:
import ast
def foo():
num = ast.Num(n=5.)
y = None
assign = ast.Assign(targets=[ast.Name(id='y', ctx=ast.Store())], value=num)
tree = ast.Module(body=[assign], type_ignores=[])
ast.fix_missing_locations(tree)
c = compile(tree, filename="", mode="exec")
exec(c)
print(y)
foo() # prints None
这是我第一次看到 python 代码在被移动到函数内部后表现不同。我已经检查并且分配也没有放入y
模块(本地人):
print(y) # NameError: name 'y' is not defined
解决方案
在函数中,您可以将分配捕获到任何字典中,该字典将用作已执行语句的范围:
def foo():
scope = {}
exec("y = 5.0", scope)
print(scope['y'])
foo() # prints 5.0
推荐阅读
- c# - 如何在 EF Core 中使用联合运算符执行原始查询?
- java - 有什么方法可以在 Android 的操作栏中应用过滤器
- python - 我在 np.random.seed(2) 中收到“IndentationError: expected an indented block”。如何解决这个问题?
- firebase - 如何在颤动中将日期存储在firebase的数组中?
- html - html中的div标签有什么作用
- numpy - 具有类矩阵输出的一维数组的成对计算
- python - 在烧瓶和 pytest 中使用 500 状态码模拟响应
- excel - 剪切和粘贴行,为什么这么慢,试图加快性能
- python - 如何生成包含字典的列表?
- jenkins - 如何使用输入构建参数设置超时?我正在使用声明性管道