为什么exec在内部断开? [英] Why are closures broken within exec?

查看:119
本文介绍了为什么exec在内部断开?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python 2.6中,

 >>> execprint(lambda:a)()in dict(a = 2),{} 
2
>> trace(最近最后调用):
文件< stdin>,第1行, in< module>
< module>中的文件< string>,第1行
在< lambda>中的文件< string>,第1行。
NameError:全局名称'a'未定义
>>>全局(),{'a':2}中的execprint(lambda:a).__ closure__

我希望它打印两次 2 ,然后打印一个带有单个单元格的元组 。在3.1中也是同样的情况。发生了什么?

解决方案

当你传递一个字符串到 exec eval ,它会将该字符串编译为代码对象,然后再考虑全局变量或局部变量。所以当你说:

  eval('lambda:a',...)

这意味着:

  ('lambda:a','< stdin&';'eval'),...)

没有办法编译知道 a 是一个freevar,因此将其编译为全局引用:

 >>> c = compile('lambda:a','< stdin>','eval')
>>> c.co_consts [0]
< code object< lambda>在0x7f36577330a8,文件< stdin>,第1行>
>>>> dis.dis(c.co_consts [0])
1 0 LOAD_GLOBAL 0(a)
3 RETURN_VALUE

因此,为了使它工作,你必须在全局变量而不是本地变量中加入 a



是的,这有点狡猾。但是,这是 exec eval 为你我想...他们不应该是好的。 p>

In Python 2.6,

>>> exec "print (lambda: a)()" in dict(a=2), {}
2
>>> exec "print (lambda: a)()" in globals(), {'a': 2}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
  File "<string>", line 1, in <lambda>
NameError: global name 'a' is not defined
>>> exec "print (lambda: a).__closure__" in globals(), {'a': 2}
None

I expected it to print 2 twice, and then print a tuple with a single cell. It is the same situation in 3.1. What's going on?

解决方案

When you pass a string to exec or eval, it compiles that string to a code object before considering globals or locals. So when you say:

eval('lambda: a', ...)

it means:

eval(compile('lambda: a', '<stdin>', 'eval'), ...)

There's no way for compile to know that a is a freevar, so it compiles it to a global reference:

>>> c= compile('lambda: a', '<stdin>', 'eval')
>>> c.co_consts[0]
<code object <lambda> at 0x7f36577330a8, file "<stdin>", line 1>
>>> dis.dis(c.co_consts[0])
  1           0 LOAD_GLOBAL              0 (a)
              3 RETURN_VALUE        

Therefore to make it work you have to put a in the globals and not the locals.

Yeah, it's a bit dodgy. But then that's exec and eval for you I suppose... they're not supposed to be nice.

这篇关于为什么exec在内部断开?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆