为了账号安全,请及时绑定邮箱和手机立即绑定

exec为什么不能在具有子功能的功能中工作?

exec为什么不能在具有子功能的功能中工作?

繁华开满天机 2019-12-02 12:52:29
看起来您不能在具有子功能的函数中使用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 Truetest2()编辑:我将错误缩小为在子功能中具有功能。它与raise关键字无关
查看完整描述

3 回答

?
慕桂英546537

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


查看完整回答
反对 回复 2019-12-02
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

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

此方案有两个例外:

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

另一个例外是,当您嵌套函数时,内部函数可以访问外部函数范围内的局部变量。执行此操作时,变量将存储在“单元”对象中,而不是存储在堆栈中。无论是从内部函数还是外部函数访问范围变量,额外的间接级别都会使作用域变量的使用变慢。

您遇到的问题是,通常如何存储局部变量的这两个例外是不兼容的。您不能将变量存储在字典中并同时通过单元格引用进行访问。Python 2.x通过禁止exec来解决此问题,即使在这种情况下,您也不想使用任何作用域变量。


查看完整回答
反对 回复 2019-12-02
?
慕神8447489

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中修复,并且不再抛出。


查看完整回答
反对 回复 2019-12-02
  • 3 回答
  • 0 关注
  • 976 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信