[Python-porting] Strange behavior of eval() in Python 3.1

Georg Brandl g.brandl at gmx.net
Sun Aug 29 15:48:12 CEST 2010


Am 29.08.2010 15:42, schrieb Bo Peng:

> However, the last statement fails under Python 3.1
> 
> Python 3.1.2 (r312:79149, Mar 21 2010, 00:41:52) [MSC v.1500 32 bit
> (Intel)] on win32
> Type "help", "copyright", "credits" or "license" for more information.
>>>> dd = {'a': {1: 0.1, 2: 0.2}}
>>>> print(eval('a[1]', {}, dd))
> 0.1
>>>> print(eval("[x for x in a.keys()]", {}, dd))
> [1, 2]
>>>> print(eval("[a[x] for x in a.keys()]", dd, dd))
> [0.1, 0.2]
>>>> print(eval("[a[x] for x in a.keys()]", {}, dd))
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "<string>", line 1, in <module>
>   File "<string>", line 1, in <listcomp>
> NameError: global name 'a' is not defined
>>>>
> 
> Because a is in clearly accessible from the passed dictionary, I have
> no idea why it has to be defined in the global dictionary. Does anyone
> know what is going on here? How can I change make it work with Python
> 3?

In Python 3, all comprehensions are executed in their own function scope,
like generator expressions in Python 2.  (If you used ``list(a[x] for x
in a.keys())``, it would fail in Python 2 too.)

Therefore, and because the compilation of the expression to eval() can
not generate closures (because it does not know in advance what locals
are available), it has to look up "a" as a global.

Georg

-- 
Thus spake the Lord: Thou shalt indent with four spaces. No more, no less.
Four shall be the number of spaces thou shalt indent, and the number of thy
indenting shall be four. Eight shalt thou not indent, nor either indent thou
two, excepting that thou then proceed to four. Tabs are right out.



More information about the Python-porting mailing list