Why do closures do this?

Carl Banks pavlovevidence at gmail.com
Sun Aug 28 23:16:30 CEST 2011


On Saturday, August 27, 2011 8:45:05 PM UTC-7, John O'Hagan wrote:
> Somewhat apropos of the recent "function principle" thread, I was recently surprised by this:
> 
> funcs=[]
> for n in range(3):
>     def f():
>         return n
>     funcs.append(f)
> 
> [i() for i in funcs]
> 
> The last expression, IMO surprisingly, is [2,2,2], not [0,1,2]. Google tells me I'm not the only one surprised, but explains that it's because "n" in the function "f" refers to whatever "n" is currently bound to, not what it was bound to at definition time (if I've got that right), and that there are at least two ways around it: ....
> My question is, is this an inescapable consequence of using closures, or is it by design, and if so, what are some examples of where this would be the preferred behaviour?


It is the preferred behavior for the following case.

def foo():
    def printlocals():
        print a,b,c,d
    a = 1; b = 4; c = 5; d = 0.1
    printlocals()
    a = 2
    printlocals()

When seeing a nested function, there are strong expectations by most people that it will behave this way (not to mention it's a lot more useful).  It's only for the less common and much more advanced case of creating a closure in a loop that the other behavior would be preferred.


Carl Banks



More information about the Python-list mailing list