Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么';t exec在具有子函数的函数中工作?_Python_Exec - Fatal编程技术网

Python 为什么';t exec在具有子函数的函数中工作?

Python 为什么';t exec在具有子函数的函数中工作?,python,exec,Python,Exec,看起来您不能在具有子函数的函数中使用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('pr

看起来您不能在具有子函数的函数中使用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()

编辑:我把错误缩小到在子函数中有一个函数。这与raise关键字无关。

我觉得这个错误相当明显:

SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables

有关更多信息,请参见pep 227:

在修改print语句以使用print函数后,它在Python 3.1.3中运行良好


在Python2.6中,它生成了语法错误:函数“test2”中不允许使用非限定exec。它包含一个带有自由变量的嵌套函数,我认为这不是一个bug。

正确。除非指定上下文,否则不能在具有子函数的函数中使用exec。从文档中:

如果函数中使用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

尽管在Python中,局部变量似乎存储在字典
locals()
中,但它们通常不是。相反,它们主要存储在堆栈上,并通过索引进行访问。这使得局部变量查找比每次必须进行字典查找更快。如果您使用
locals()
函数,那么您得到的是一个从所有局部变量创建的新字典,这就是为什么分配给
locals()
通常不起作用的原因

此场景有几个例外情况:

当在函数中使用非限定的
exec
时,Python会关闭优化,并对局部变量使用真正的字典。这意味着您可以从
exec
内部创建或更新变量,但也意味着该函数中的所有局部变量访问将运行得更慢

另一个例外是,嵌套函数时,内部函数可以访问外部函数作用域中的局部变量。执行此操作时,变量存储在“cell”对象中,而不是存储在堆栈上。额外的间接级别使得所有作用域变量的使用都变慢,无论您是从内部还是外部函数访问它们


您遇到的问题是,这两个局部变量通常存储方式的例外是不兼容的。不能将变量存储在字典中并同时通过单元格引用访问。Python2.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
即使
None
不能被赋值,并且它被认为是字节码中的一个常量,但bug解析器认为它在这里是一个未绑定的变量

但是如果您将其替换为
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
...
>>>

在Python3中,
exec
只是一个简单的函数,并不由解析器或字节码编译器专门处理。在Python3中,exec不能重新绑定函数本地名称,因此不存在这种语法错误和歧义


Python2与Python3兼容性中的一个特殊情况是

表单
exec(expr,globals)
相当于全局中的
exec expr
,而表单
exec(expr,globals,locals)
相当于全局中的
exec expr,locals
exec
的元组形式提供了与Python3的兼容性,其中
exec
是一个函数而不是一个语句

元组形式并不总是100%兼容的,就像以前一样;在Python 2.7.8之前,以下代码可能引发了异常:

def func():
    exec('print "hi from test2"', {})
    def subfunction():
        return None

这在Python2.7.9中得到了修复,不再抛出。

dict
list
理解也可以被视为Python2.7.5上的子函数

例如,这在Python 2.7.5上失败,但在Python 2.7.12上有效:

def func():
    exec('print("a")')
    (str(e) for e in range(10))
与:

可能是内部编译成字节码中的函数

TODO查找修复提交。这超出了我的git日志--grepfoo

类似于
dict
理解:

def func():
    exec('print("a")', {e:str(e) for e in range(10)})
这特别糟糕,因为它是
global
参数的常用参数


在:

中还提出了一个例子:为一个深奥的NoSQL数据库实现一个人性化的面向对象API,该数据库只与Python有非常低级的绑定。不过,您还有一个问题:是否有一种方法可以将“exec”ed代码注入到特定的类中?如果是,如何执行?@AndreiKucharavy No,
exec
执行代码,因此没有“exec”之类的代码可以注入。已执行代码是已执行的代码。您可以编译代码并将其注入,也许这就是您的意思?但是通常你不需要编译它,你只需要注入它。没有明显的理由仅仅因为想要一个面向对象的API到NoSQL数据库就必须执行任何操作。对不起,我的错:不是注入代码,而是插入代码,所以它可以作为特定类的一部分调用。其思想是解析用户创建的配置文件,并从定义中生成一系列对象,这些对象可以作为简单的python对象调用,但在后台实现一个buff
  File "./a.py", line 4
    exec('print("a")')
SyntaxError: unqualified exec is not allowed in function 'func' it contains a nested function with free variables
def func():
    exec('print("a")', {e:str(e) for e in range(10)})