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

Steve Holden steve at holdenweb.com
Tue Jan 27 22:36:57 EST 2009


Gabriel Genellina wrote:
> 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
> 
No, locals is different, not locals(). You are looking at two different
functions that return the same object when called in the given context,
that's all.

> 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]
> 
Same thing: two different functions, same result.

> 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*...
> 
regards
 Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC              http://www.holdenweb.com/




More information about the Python-list mailing list