gpt4 book ai didi

python - 在 exec 中用空局部变量列表理解 : NameError

转载 作者:太空狗 更新时间:2023-10-29 17:26:25 24 4
gpt4 key购买 nike

考虑以下片段:

def bar():
return 1
print([bar() for _ in range(5)])

它给出了预期的输出 [1, 1, 1, 1, 1]

但是,如果我尝试在空环境中exec 相同的片段(localsglobals 都设置为 {} ), 它给出了 NameError:

if 'bar' in globals() or 'bar' in locals():
del bar
# make sure we reset settings

exec("""
def bar():
return 1
print([bar() for _ in range(5)])
""", {}, {})

NameError: name 'bar' is not defined

如果我像 exec(…, {})exec(…) 那样调用 exec,它会按预期执行。

为什么?

编辑:

还请考虑以下代码段:

def foo():
def bar():
return 1
print('bar' in globals()) # False
print('bar' in locals()) # True
print(['bar' in locals() for _ in [1]]) # [False]
print([bar() for _ in [1, 2]]) # [1, 1]

就像在我的第一个 exec 中一样,我们在本地列表理解中没有障碍。但是,如果我们尝试调用它,它就会起作用!

最佳答案

您的问题的解决方案就在这里:

In all cases, if the optional parts are omitted, the code is executed in the current scope. If only globals is provided, it must be a dictionary, which will be used for both the global and the local variables. If globals and locals are given, they are used for the global and local variables, respectively. If provided, locals can be any mapping object. Remember that at module level, globals and locals are the same dictionary. If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.

https://docs.python.org/3/library/functions.html#exec

基本上,您的问题是 bar 是在 locals 范围内定义的,并且仅在 locals 中定义。因此,这个 exec() 语句有效:

exec("""
def bar():
return 1
print(bar())
""", {}, {})

然而,列表理解创建了一个新的本地范围,其中 bar 未定义,因此无法查找。

此行为可以用以下方式说明:

exec("""
def bar():
return 1
print(bar())
print(locals())
print([locals() for _ in range(1)])
""", {}, {})

返回

1
{'bar': <function bar at 0x108efde18>}
[{'_': 0, '.0': <range_iterator object at 0x108fa8780>}]

编辑

在您的原始示例中, bar 的定义位于(模块级别)全局范围内。这对应于

Remember that at module level, globals and locals are the same dictionary.

exec 示例中,您通过传递两个不同的字典在全局变量和局部变量之间引入了人为的范围划分。如果您传递了相同的一个或仅传递了一个全局变量(这反过来意味着这个变量将同时用于 globalslocals),您的示例也可以工作。

至于编辑中介绍的示例,这归结为 python 中的作用域规则。详细解释请阅读:https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces

简而言之,虽然 bar 不在列表理解的局部范围内,也不在全局范围内,但它在 foo 的范围内。并且给定 Python 作用域规则,如果在局部作用域中找不到变量,它将在封闭作用域中搜索,直到到达全局作用域。在您的示例中,foo 的作用域位于本地作用域和全局作用域之间,因此将在搜索结束之前找到 bar。

然而,这仍然与 exec 示例不同,在 exec 示例中,您传入的 locals 范围并未包含列表推导的范围,而是与其完全分开。

可以在此处找到包括插图在内的范围规则的另一个很好的解释:http://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html

关于python - 在 exec 中用空局部变量列表理解 : NameError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45132645/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com