[Tutor] Odd behavior with eval, list comps, and name lookup
Peter Otten
__peter__ at web.de
Fri Feb 18 11:16:52 CET 2011
John wrote:
> I noticed some odd behavior relating to eval(). First, a baseline case for
> behavior:
>
>>>> def test():
> ... x = 5
> ... return [a for a in range(10) if a == x]
> ...
>>>> test()
> [5]
>
> So far so good. Now let's try eval:
>
>>>> c = compile('[a for a in range(10) if a == x]', '', 'single')
>>>> eval(c, globals(), {'x': 5})
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "", line 1, in <module>
> File "", line 1, in <listcomp>
> NameError: global name 'x' is not defined
>
> Looks like 'x' is searched for only among the globals, bypassing the
> locals. The same behavior is seen between exec and eval, with and without
> compile, and between 3.1.3 and 3.2rc2. Given simpler code without a list
> comp, the locals are used just fine:
>
>>>> c = compile('a=5; a==x', '', 'single')
>>>> eval(c, {}, {'x': 5})
> True
>
> Could anyone help me understand these scoping rules? Thanks.
Except for class definitions the compiler statically determines whether a
variable is global or local (or a closure).
List comprehensions and generator expressions are realized as functions;
therefore they have their own local scope that you cannot provide via
eval/exec.
You could argue that in the following example
>>> exec("x = 2; print([a for a in range(3) if a == x])", {}, {})
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 'x' is not defined
the assignment x = 2 should give the compiler a clue that x is supposed to
be a local name, just like in
def f():
x = 2
print([a for a in range(3) if a == x])
My *guess* is that this is an implementation restriction rather than a
conscious decision. It works for the common case of module-level code
because there local and global namespace are identical:
>>> exec("x = 2; print([a for a in range(3) if a == x])", {})
[2]
Peter
More information about the Tutor
mailing list