lambda trouble

Daniel Yoo dyoo at hkn.eecs.berkeley.edu
Fri Mar 19 18:56:48 EST 2004


Darabos Daniel <cyhawk at sch.bme.hu> wrote:

:>>> def p( x ):
: ...     print x
: ...
:>>> l = []
:>>> for i in range( 5 ):
: ...     l.append( lambda: p( i ) )
: ...
:>>> for k in l:
: ...     k()
: ...
: 4
: 4
: 4
: 4
: 4

: And it surprised me a little. I was expecting to see 0, 1, 2, 3, 4.


Hi Darabos,


Someone should make a FAQ out of this.  *grin*


This keeps popping up every so often on comp.lang.python.  Here's a
link to one of the really heated threads about this:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&th=4bca1bec20119375&rnum=6


It sounds like you may have some experience with some kind of
functional language like Scheme.  If so, then you probably understand
the distinction between DEFINE and SET! in Scheme.


The issue that you're running into is that Python uses a SET!-like
behavior when it reassigns the index variable of loops.  To see this
more easily, let me translate your program into an equivalent Scheme
program:

;;;
guile> (define (p x) (display x) (newline))
guile> (define l '())
guile> (define i 0)
guile> (while (< i 5) 
         (begin
            (set! l (cons (lambda () (p i)) l))
            (set! i (+ i 1))))
guile> (for-each (lambda (x) (x)) l)
5
5
5
5
5
;;;

So here we can see the same problem popping up.



: found a solution like this:
:>>> def mylambda( fn, *args ):
: ...     return lambda: apply( fn, args )
: ...
:>>> l = []
:>>> for i in range( 5 ):
: ...     l.append( mylambda( p, i ) )
: ...


Yup, this works, because we take advantage of the name-binding
behavior of parameter passing.  Another way of saying the same thing
is:

###
>>> def make_p(x):
...     def p():
...         print x
...     return p
... 
>>> l = []
>>> for i in range(5):
...     l.append(make_p(i))
... 
>>> for k in l: 
...     k()
... 
0
1
2
3
4
###


It's the issue of DEFINE vs. SET! --- the first assignment in Python
acts like DEFINE, and subsequence reassignments act like SET!.  So
just one thing to be careful about with assignment.


I hope this helps!



More information about the Python-list mailing list