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

Andrew Clover and-dev at doxdesk.com
Fri Oct 3 21:42:24 CEST 2008

Greg Ewing wrote:

 > 1. If the loop variable is referenced by such a nested
 >    function, a new local scope is effectively created
 >    to hold each successive value of the loop variable.

Why only the loop variable? What about:

     >>> for i in range(3):
     ...     j= str(i)
     ...     funs.append(lambda: j)
     >>> funs[0]()

It seems an odd sort of scope that lets rebindings inside it fall 
through outwards.

> Also, most other languages which have lexical scoping
> and first-class functions don't seem to suffer from
> problems like this.

That's not always because of anything to do with introducing scopes 
though. Some of those languages can bind the variable value early, so if 
you were to write the equivalent of:

     >>> i= 3
     >>> f= lambda: i
     >>> i= 4

f() would give you 3. I would love to see an early-value-binding 
language with similar syntax to Python, but I can't see how to get there 
from here.

There are other languages with lexical scope and late value binding, 
such as JavaScript; their for loops behave the same as Python.

> 0. There is no change if the loop variable is not
>    referenced by a nested function defined in the loop
>    body.

You mean:

     >>> i= 0
     >>> geti= lambda: i

     >>> for i in [1]:
     ...     print i is geti()

     >>> for i in [1]:
     ...     dummy= lambda: i
     ...     print i is geti()

This seems unconscionably spooky to me.

Explicit is better than yadda yadda. How about explicitly requesting to 
be given a new scope each time around the loop? This would clear up the 
compatibility problems.

     >>> for local i in range(3):
     ...     funs.append(lambda: i)
     ...     q= 3
     >>> funs[0]()
     >>> q

Or similar syntax as preferred.

And Clover
mailto:and at doxdesk.com

More information about the Python-ideas mailing list