Why doesn't eval of generator expression work with locals?

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Wed Jan 28 03:06:17 CET 2009


En Tue, 27 Jan 2009 22:17:16 -0200, Robert Kern <robert.kern at gmail.com>  
escribió:
> On 2009-01-27 17:56, Fabio Zadrozny wrote:

> Making locals and globals different emulates a function, where the code  
> will fail:
>
>    >>> del y, ar
>    >>> def f():
>    ...     y = 'bar'
>    ...     ar = ['foo', 'bar']
>    ...     print 'Raw genexp:', all((x==y) for x in ar)
>    ...     print 'Evaled:', eval('all((x==y) for x in ar)')
>    ...
>    >>> f()
>    Raw genexp: False
>    Evaled:
>    Traceback (most recent call last):
>      File "<stdin>", line 1, in <module>
>      File "<stdin>", line 5, in f
>      File "<string>", line 1, in <module>
>      File "<string>", line 1, in <genexpr>
>    NameError: global name 'y' is not defined
>
> Now, the reason that the raw generator expression works inside the  
> function but not in the eval() is because the raw generator expression  
> gets lexical scopes rather than just the two locals and globals dicts.  
> Lexical scoping is not available to the eval() function.

I *thought* I did understand this until I came to this example:

1)
>>> id(globals()), id(locals())
(11239760, 11239760)

# ok, globals and locals are the same at the module level

2)
>>> s = "(id(n) for n in [globals(),locals()])"
>>> list(eval(s))
[11239760, 11239760]  # still the same results

3)
>>> s = "(id(n()) for n in [globals,locals])"
>>> list(eval(s))
[11239760, 12583248]  # locals() is different

Why do I get a different locals() here? Both expressions define the same  
scopes, ok? That is, I'd say that both 2) and 3) define the same, nested  
scopes -- why the different results?

Seems that this is unrelated to eval, we can take it out of the question  
and still get the same values:

>>> list(id(n) for n in [globals(),locals()])
[11239760, 11239760]
>>> list(id(n()) for n in [globals,locals])
[11239760, 12583248]

Worse, it isn't the new, inner scope of generator expressions. A list  
comprehension gives the same results:

>>> [id(n) for n in [globals(),locals()]]
[11239760, 11239760]
>>> [id(n()) for n in [globals,locals]]
[11239760, 12583248]

Seems that it is important *when* those functions are evaluated, but I  
don't understand *why*...

-- 
Gabriel Genellina




More information about the Python-list mailing list