A gotcha: Python pain point?

Jean-Paul Calderone exarkun at divmod.com
Mon Jun 11 20:58:01 EDT 2007


On Mon, 11 Jun 2007 16:54:10 -0700, James Stroud <jstroud at mbi.ucla.edu> wrote:
>Beorn wrote:
>> Consider this example:
>>
>>   >>> def funcs(x):
>>   ...     for i in range(5):
>>   ...         def g(): return x + i
>>   ...         yield g
>>
> [snip]
>
>If this isn't classified as a bug, then someone has some serious
>explaining to do. Why would it be desirable for a generator to behave
>differently in two different contexts. Should I import this to see how
>many principles this behavior violates?

It follows logically from first principals. ;)  You might disagree with
those, but given them, it's hard to disagree with the conclusion.

The first form forces the generator to run to completion before the list
comprehension evaluates any iteration, and so the loop variable inside
the generator is already 4, and so all functions yielded will return 5
when called.

The second form lets the generator run lazily, so it has only reached the
iteration which yielded a particular function by the time that function
is called by the list comprehension, so each function yields a different
value, because it is the continuing iteration of the generator which changes
the values returned by the yielded functions.

As far as explanations go, perhaps that's not a very good one (all I've done
is describe the behavior, after all, and less concisely than the original
Python did!) but maybe the translation into english will somehow help reveal
how this behavior is consistent.

For what it's worth, I agree that scoping in Python is not ideal and this
is a good example of an area where that shortcoming causes surprises.

Jean-Paul



More information about the Python-list mailing list