首页 > 解决方案 > 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

标签: pythonabstract-syntax-tree

解决方案


在函数中,您可以将分配捕获到任何字典中,该字典将用作已执行语句的范围:

def foo():
    scope = {}
    exec("y = 5.0", scope)
    print(scope['y'])

foo()  # prints 5.0

推荐阅读