3 回答
TA贡献1848条经验 获得超10个赞
正确。除非指定上下文,否则不能在具有子功能的函数中使用exec。从文档:
如果在函数中使用了exec并且该函数包含带有自由变量的嵌套块,则除非exec显式指定exec的本地名称空间,否则编译器将引发SyntaxError。(换句话说,“ exec obj”将是非法的,但“ ns中的exec obj”将是合法的。)
有充分的理由,如果不是星期天晚上,我可能会明白。现在,下一个问题:为什么要使用exec?很少需要。你说你有充分的理由。我对此表示怀疑。;)如果您有充分的理由,我会告诉您解决方法。:-P
哦,好了,这仍然是:
def test2():
"""Test with a subfunction."""
exec 'print "hi from test2"' in globals(), locals()
def subfunction():
return True
TA贡献1875条经验 获得超5个赞
尽管在Python中看起来好像局部变量存储在字典中locals()
,但通常不是。相反,它们通常存储在堆栈中,并通过索引进行访问。这使得局部变量查找的速度比每次必须进行字典查找的速度都要快。如果使用该locals()
函数,则得到的是从所有局部变量创建的新字典,这就是为什么分配给locals()
通常不起作用的原因。
此方案有两个例外:
当您exec
在函数内部使用非限定条件时,Python会关闭优化,并使用真正的字典作为局部变量。这意味着您可以从中创建或更新变量exec
,但这也意味着该函数中所有本地变量访问将运行得更慢。
另一个例外是,当您嵌套函数时,内部函数可以访问外部函数范围内的局部变量。执行此操作时,变量将存储在“单元”对象中,而不是存储在堆栈中。无论是从内部函数还是外部函数访问范围变量,额外的间接级别都会使作用域变量的使用变慢。
您遇到的问题是,通常如何存储局部变量的这两个例外是不兼容的。您不能将变量存储在字典中并同时通过单元格引用进行访问。Python 2.x通过禁止exec来解决此问题,即使在这种情况下,您也不想使用任何作用域变量。
TA贡献1780条经验 获得超1个赞
这是一个很有趣的情况:
>>> def func():
... exec('print "hi from func"')
... def subfunction():
... return True
...
File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'func' because
it contains a nested function with free variables
确实不起作用的原因是它subfunction包含一个自由变量,并且由于在Python 2中,exec理论上可以修改包含范围中的局部变量,因此无法决定该变量是应与全局变量还是与父变量绑定功能范围。Python Zen中的其中一句诗是“面对模棱两可,拒绝猜测的诱惑”。这就是Python 2所做的。
现在的问题是:这个自由(未绑定)变量是什么?好吧,是True!
实际上,它可以通过None以下方式重现:
>>> def func():
... exec('print "hi from func"')
... def subfunction():
... return None
...
File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'test2' because it contains a nested
function with free variables
即使None无法分配给它,并且在字节码中将其视为常量,但越野车解析器仍认为这是一个未绑定变量。
但是,如果您将其替换为1并且可以正常使用,则可以:
>>> def test2():
... exec('print "hi from func"')
... def subfunction():
... return 1
...
>>>
为避免此错误,请明确指定要使用的全局变量和可能的局部变量exec,例如:
>>> def test2():
... exec 'print "hi from test2"' in {}
... def subfunction():
... return None
...
>>>
在Python 3中,exec这只是一个简单的函数,没有由解析器或字节码编译器专门处理。在Python 3 exec中无法重新绑定函数本地名称,因此此SyntaxError和歧义不存在。
Python 2 vs 3兼容性的一种特殊情况是,尽管Python 2.7文档指出:
形式exec(expr, globals)等同于exec expr in globals,而形式exec(expr, globals, locals)等同于exec expr in globals, locals。元组形式exec提供了与Python 3的兼容性,Python 3 exec是函数而不是语句。
元组形式并不总是100%兼容的,因为在处理exec带有嵌套函数的in函数中存在一个错误(issue 21591);在Python 2.7.8之前,以下代码可能引发了异常:
def func():
exec('print "hi from test2"', {})
def subfunction():
return None
这已在Python 2.7.9中修复,并且不再抛出。
添加回答
举报