F
Fernando Perez
Hi all,
consider the following small example:
"""
Small test to try to understand a strange subtlety with closures
"""
def outer(nmax):
aa = []
for n in range(nmax):
def a(y):
return (y,n)
print 'Closure and cell id:',id(a.func_closure),\
id(a.func_closure[0])
aa.append(a)
return aa
print 'Closure creation.'
nmax = 3
aa = outer(nmax)
print
print 'Closure use.'
for n in range(nmax):
print '%s:%s' % (n,aa[n]('hello'))
################## EOF #################
If I run this, I get:
planck[test]> python debug_closures.py
Closure creation.
Closure and cell id: 1075998828 1075618940
Closure and cell id: 1075999052 1075618940
Closure and cell id: 1075999084 1075618940
Closure use.
0'hello', 2)
1'hello', 2)
2'hello', 2)
My confusion arises from the printout after 'closure use'. I was expecting that
each new function 'a' created inside the loop in 'outer' would capture the
value of n, therefore my expectation was to see a printout like:
0'hello', 0)
1'hello', 1)... etc.
However, what happens is a bit different. As can be seen from the printouts
of 'Closure and cell id', in each pass of the loop a new closure is created,
but it reuses the *same* cell object every time. For this reason, all the
closures end up sharing the scope with the values determined by the *last*
iteration of the loop.
This struck me as counterintuitive, but I couldn't find anything in the
official docs indicating what the expected behavior should be. Any
feedback/enlightenment would be welcome. This problem appeared deep inside a
complicated code and it took me almost two days to track down what was going
on...
Cheers,
f
consider the following small example:
"""
Small test to try to understand a strange subtlety with closures
"""
def outer(nmax):
aa = []
for n in range(nmax):
def a(y):
return (y,n)
print 'Closure and cell id:',id(a.func_closure),\
id(a.func_closure[0])
aa.append(a)
return aa
print 'Closure creation.'
nmax = 3
aa = outer(nmax)
print 'Closure use.'
for n in range(nmax):
print '%s:%s' % (n,aa[n]('hello'))
################## EOF #################
If I run this, I get:
planck[test]> python debug_closures.py
Closure creation.
Closure and cell id: 1075998828 1075618940
Closure and cell id: 1075999052 1075618940
Closure and cell id: 1075999084 1075618940
Closure use.
0'hello', 2)
1'hello', 2)
2'hello', 2)
My confusion arises from the printout after 'closure use'. I was expecting that
each new function 'a' created inside the loop in 'outer' would capture the
value of n, therefore my expectation was to see a printout like:
0'hello', 0)
1'hello', 1)... etc.
However, what happens is a bit different. As can be seen from the printouts
of 'Closure and cell id', in each pass of the loop a new closure is created,
but it reuses the *same* cell object every time. For this reason, all the
closures end up sharing the scope with the values determined by the *last*
iteration of the loop.
This struck me as counterintuitive, but I couldn't find anything in the
official docs indicating what the expected behavior should be. Any
feedback/enlightenment would be welcome. This problem appeared deep inside a
complicated code and it took me almost two days to track down what was going
on...
Cheers,
f