[Python-ideas] For-loop variable scope: simultaneous possession and ingestion of cake

Arnaud Delobelle arnodel at googlemail.com
Mon Oct 6 14:31:11 CEST 2008

2008/10/6 Jan Kanis <jan.kanis at phil.uu.nl>:
>> There is a very simple and efficient way to implement
>> this in current CPython: If the loop variable is referenced
>> by a nested function, it will be in a cell. Instead of
>> rebinding the existing cell, each time around the loop
>> a new cell is created, replacing the previous cell.
>> Immediately before exiting the loop, one more new cell
>> is created and the final value of the loop variable
>> copied into it.
> [skip]
>> The benefit would be that almost all code involving
>> loops and nested functions would behave intuitively,
> +1 from me too.
> Neil Toronto wrote:
>> Spanking good point. To hack this "properly" all cell variables closed over within the loop would have to go into the per-iteration scope.
> Agreed. And to preserve current semantics these values would need to
> be copied to the new scope of every next iteration (if it's closed
> over).
>>> It seems an odd sort of scope that lets rebindings inside it fall through outwards.
>> True, but a lot of Python programs would depend on this - even new ones because of social inertia.
> It'll unfortunately have to wait til python 4000 :).
> I like finally fixing this problem, which I've also run into. But I
> don't like the idea of introducing a new keyword to create new scopes.
> I think all variable that are assigned to in a loop body and closed
> over should be put into a cell as Greg proposes, not just the index
> variable. (In both for and while loops.) At the end of each loop
> iteration all such variables would need to be copied to the 'next'
> scope, which could be the parent scope or the next iteration.
> I'm trying really hard to think about cases that would break if this
> new behaviour was introduced, but I can't think about anything. The
> only thing that would 'break' is if you would want the standard
> example of
>  lst = []
>  for i in range(10):
>   lst.append(lambda: i)
>  for f in lst:
>   print f()
> to actually print 9 times 10. But if you want your bunch of lambda
> functions that you create in the loop body to all refer to the last
> value of i, why on earth would you even attempt to create a whole
> bunch of lambdas in this way?? (except to show that for loops are
> broken)

How do you want this to behave?

lst = []
a = [0]
for i in range(10):
    a[0] = i
    lst.append(lambda: a[0])
for f in lst:

How about this?

for a[0] in range(10):
    lst.append(lambda: a[0])
for f in lst:

ATM, I think this proposal will only make things more complicated from
every point of view.


More information about the Python-ideas mailing list