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