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
___
Tutor maillist - Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor