看起来你不能在具有子功能的函数中使用exec ...
任何人都知道为什么这个Python代码不起作用?我在test2的exec上遇到错误.另外,我知道exec的风格并不好,但相信我,我正在使用exec是出于正当的理由.否则我不会用它.
#!/usr/bin/env python
#
def test1():
exec('print "hi from test1"')
test1()
def test2():
"""Test with a subfunction."""
exec('print "hi from test2"')
def subfunction():
return True
test2()
Run Code Online (Sandbox Code Playgroud)
编辑:我把bug缩小到在子功能中有一个功能.它与raise关键字无关.
Len*_*bro 65
正确.除非指定上下文,否则不能在具有子函数的函数中使用exec.来自文档:
如果在函数中使用exec并且函数包含带有自由变量的嵌套块,则编译器将引发SyntaxError,除非exec显式指定了exec的本地名称空间.(换句话说,"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
Run Code Online (Sandbox Code Playgroud)
Dun*_*can 28
虽然在Python中看起来有点像局部变量存储在字典中locals(),但它们通常不是.相反,它们主要存储在堆栈中并通过索引访问.这使得局部变量查找比每次都必须进行字典查找更快.如果你使用该locals()函数,那么你得到的是一个从所有局部变量创建的新字典,这就是为什么分配locals()通常不起作用的原因.
这种情况有几个例外:
当你exec在函数内部使用不合格时,Python会关闭优化并使用真正的字典作为局部变量.这意味着您可以从内部创建或更新变量exec,但这也意味着该函数中的所有本地变量访问都将运行得更慢.
另一个例外是当您嵌套函数时,内部函数可以访问外部函数作用域中的局部变量.当它执行此操作时,变量存储在"单元"对象中,而不是存储在堆栈中.除了从内部或外部函数访问它们之外,额外的间接级别使得所有范围变量的使用都变慢.
您遇到的问题是,通常存储局部变量的这两个例外是不兼容的.您不能将变量存储在字典中并同时通过单元格引用进行访问.Python 2.x通过禁止exec来修复此问题,即使在这样的情况下,您也不会尝试使用任何作用域变量.
这是一个相当有趣的案例:
>>> 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
Run Code Online (Sandbox Code Playgroud)
这不起作用的原因是subfunction包含一个自由变量,并且因为在Python 2中,exec理论上可以修改包含范围中的局部变量,所以无法确定变量是否应该从全局变量或父变量绑定功能范围."禅宗禅"中的一句经文是"面对模棱两可,拒绝猜测的诱惑." 这就是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
Run Code Online (Sandbox Code Playgroud)
即使None无法分配,并且它被视为字节码中的常量,但是错误的解析器认为它是一个未绑定的变量.
但如果你用它替换它1并且它没有问题:
>>> def test2():
... exec('print "hi from func"')
... def subfunction():
... return 1
...
>>>
Run Code Online (Sandbox Code Playgroud)
要避免此错误,请明确指定要使用的全局变量和可能的本地变量exec,例如:
>>> def test2():
... exec 'print "hi from test2"' in {}
... def subfunction():
... return None
...
>>>
Run Code Online (Sandbox Code Playgroud)
在Python 3中,exec它只是一个简单的函数,并不是由解析器或字节码编译器专门处理的.在Python 3 exec中无法重新绑定函数本地名称,因此不存在此SyntaxError和歧义.
Python 2与3兼容性的一个特殊情况是,虽然Python 2.7文档说明了这一点
表格
exec(expr, globals)相当于exec expr in globals,而形式exec(expr, globals, locals)相当于exec expr in globals, locals.元组形式exec提供与Python 3的兼容性,其中exec是函数而不是语句.
元组表单并不总是100%兼容,因为在处理exec具有嵌套函数的函数时存在错误(issue 21591) ; 直到Python 2.7.8,以下代码可能抛出异常:
def func():
exec('print "hi from test2"', {})
def subfunction():
return None
Run Code Online (Sandbox Code Playgroud)
这是在Python 2.7.9中修复的,它不再抛出.