我试图理解Python的exec()函数

2024-09-29 19:24:12 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我有一个字符串,它是一个函数

code = """def somefn(x):
    return x + x
    y = somefn(z)"""

我试着在另一个函数中运行它,比如

def otherfn(codestr):
    z = 2
    exec(codestr)
    return y

otherfn(code)

但它给了我一个错误:

Traceback (most recent call last): File "C:/Users/Admin/Desktop/heh.py", line 11, in otherfn(code) File "C:/Users/Admin/Desktop/heh.py", line 9, in otherfn return y NameError: name 'y' is not defined

它在函数之外工作得很好,比如

z=2 exec(codestr) print(y)

它发现y很好,但不确定它在函数中时为什么会出错

我怎样才能解决这个问题?这与globals()和locals()有关吗?使用Python3.6 btw


Tags: 函数pyreturnadmindeflinecodeusers
1条回答
网友
1楼 · 发布于 2024-09-29 19:24:12

你的代码有几个问题。首先,您有一个缩进问题ysomefn()函数中得到“defined”,在return之后,所以它实际上从来没有机会进入堆栈。您需要将code重新定义为:

code = """def somefn(x):
    return x + x
y = somefn(z)"""

但这只是冰山一角。更大的问题是exec()不能修改函数的局部作用域。这是因为Python不使用dict来查找本地范围中的变量,因此exec()中的所有更改不会反射回堆栈以启用查找。这导致了一个奇怪的问题,exec()似乎改变了locals()字典,但Python仍然抛出一个NameError

def otherfn(codestr):
    z = 2
    exec(codestr)
    print(locals()["y"])  # prints 4
    return y  # NameError

otherfn(code)

issue4831所述,这是一种预期行为,在official docs中进一步强调:

Note: The default locals act as described for function locals() below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns.

但是,如果必须反映这些更改,则只需执行post exec local scope更新:

def otherfn(codestr):
    z = 2
    locals_ = locals()
    exec(codestr, globals(), locals_)
    y = locals_["y"]
    return y

otherfn(code)

相关问题 更多 >

    热门问题