【问题标题】:ast execution produces different result in a function vs module scopeast 执行在函数与模块范围内产生不同的结果
【发布时间】:2019-09-12 05:23:32
【问题描述】:

编辑:问题与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

【问题讨论】:

    标签: python abstract-syntax-tree


    【解决方案1】:

    在函数中,您可以将赋值捕获到任何字典中,作为执行语句的作用域:

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

    【讨论】:

    • 谢谢,它有效。一个问题仍然存在 - 当我们未指定范围时,分配去了哪里?它不是模块全局变量。
    【解决方案2】:

    变量 Y 是在函数范围内声明的,并且在函数范围之外不可用。如果您希望 Y 在函数调用后可用,请将其返回或使用全局变量。

    更新: 请参阅我关于 exec 和范围的评论:exec() and variable scope

    【讨论】:

    猜你喜欢
    • 2021-12-25
    • 2021-09-21
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多