Why doesn't eval of generator expression work with locals?
Hendrik van Rooyen
mail at microcorp.co.za
Thu Jan 29 08:14:41 CET 2009
"Gabriel Genellina" <gagsl-py2 at yahoo.com.ar> wrote:
En Wed, 28 Jan 2009 16:00:43 -0200, Scott David Daniels
><Scott.Daniels at acm.org> escribió:
>> The reason is that once your created object has its id taken, you
>> must keep a handle on it, otherwise it may get recycled and reused.
>It doesn't matter in this case, I think. globals() is always the same
>object and is alive during the whole test. So something having the same
>id() than globals() must be the very same object, and something having a
>different id() than globals() cannot be the same object.
>If you like, I can rewrite the example without using id():
>>>> L = list(n for n in [globals(),locals()])
>>>> L is L
>>>> L = list(n() for n in [globals,locals])
>>>> L is L
>(I *think* this has to do with free variables in the "right side" (after
>the "in" keyword) of a generator expression; they appear to be evaluated
>when the expression is *defined*, not when is is *used*. By contrast, free
>variables in the "left side" appear to be evaluated when the expression is
Yikes! this is, IMO, far too complicated a way of looking at it.
I think that if you rewrite the "comprehensions" as loops,
you will see what is happening. - in the one case, the locals()
returned is from the outer scope, while in the other the
locals function is called from inside the loop - a different scope,
because there must be *somewhere* where the state is kept to yield
the next value.
If you nest the thing inside something else, then globals() and locals()
won't be the same, but the two locals() will still differ.
I find it very confusing because locals is always the same
function - but what it returns varies depending on where you
call it from. So if you want to pass it around, it's no good
passing the function - you have to pass the returned result,
*called from the scope of interest*. Subtle stuff.
More information about the Python-list