On 8/27/2011 11:45 PM, 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)



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: either make a factory function:

def f(): return n
is a CONSTANT value. It is not a closure.

Your code above is the same as
def f(): return n
funcs = [f,f,f]
n = 2
[i() for i in funcs]

def mkfnc(n):
     def fnc():
         return n
     return fnc

fnc is a closure and n in a nonlocal name. Since you only read it, no nonlocal declaration is needed.

funcs=[]
for n in range(3):
     funcs.append(mkfnc(n))

which seems roundabout, or take advantage of the "default values set at definition 
time" behaviour:

funcs=[]
for n in range(3):
     def f(n=n):
         return n
     funcs.append(f)

which seems obscure, and a side-effect.

It was the standard idiom until nested functions were upgraded to enclose or capture the values of nonlocals.

My question is, is this an inescapable consequence of using closures,

I cannot answer since I am not sure what you mean by 'this'.
Closures are nested functions that access the locals of enclosing functions. To ensure that the access remains possible even after the enclosing function returns, the last value of such accessed names is preserved even after the enclosing function returns. (That is the tricky part.)

--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to