473,804 Members | 2,126 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

lambda trouble

Hi!

I was doing something like this:
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.
After some brainwork I now kind of understand what happens and I even
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 ) )
.... for k in l:

.... k()
....
0
1
2
3
4

But I still feel a bit unsatisfied. Do you have some advice for me?

Cheers,

Daniel
Jul 18 '05 #1
9 1637

Darabos Daniel wrote:
And it surprised me a little. I was expecting to see 0, 1, 2, 3, 4.
After some brainwork I now kind of understand what happens and I even
found a solution like this:

Well, it is not suprising. In a lambda expression, everything after the
: is symbolic. It is compiled,
not evaluated. You can use a named function instead of an unnamed one:

[GCC 3.3.3 [FreeBSD] 20031106] on freebsd5
Type "help", "copyright" , "credits" or "license" for more information.
def p(x): .... print x
.... l = []
for i in range( 5 ): .... def func():
.... p(i)
.... l.append( func )
.... for k in l: .... k()
.... l [<function func at 0x81a4f0c>, <function func at 0x81a4f44>, <function
func at 0x81a4f7c>, <function func at 0x81a4fb4>, <function func at
0x81ae02c>]


You have different functions. However, in every function, the name 'i'
is not a local name. (Python has only two levels: local and global.)
Here is another solution. However, it uses eval. Probably, it is not the
fastest one.

def p(x):
print x

l = []
for i in range( 5 ):
l.append(eval(" lambda: p( %s )"%i))

for k in l:
k()
Udv,

Laci
Jul 18 '05 #2
Gandalf wrote:

Darabos Daniel wrote:
And it surprised me a little. I was expecting to see 0, 1, 2, 3, 4.
After some brainwork I now kind of understand what happens and I even
found a solution like this:

Well, it is not suprising. In a lambda expression, everything after the
: is symbolic. It is compiled,
not evaluated. You can use a named function instead of an unnamed one:

[GCC 3.3.3 [FreeBSD] 20031106] on freebsd5
Type "help", "copyright" , "credits" or "license" for more information.
>>> def p(x): ... print x
... >>> l = []
>>> for i in range( 5 ): ... def func():
... p(i)
... l.append( func )
... >>> for k in l: ... k()
... >>> l [<function func at 0x81a4f0c>, <function func at 0x81a4f44>, <function
func at 0x81a4f7c>, <function func at 0x81a4fb4>, <function func at
0x81ae02c>] >>>
You have different functions. However, in every function, the name 'i'
is not a local name. (Python has only two levels: local and global.)
Here is another solution. However, it uses eval. Probably, it is not the
fastest one.

def p(x):
print x

l = []
for i in range( 5 ):
l.append(eval(" lambda: p( %s )"%i))

for k in l:
k()
Udv,

Laci

It is really even simpler:
def p(x): print x
l=[lambda i=i: p(i) for i in range(5)]
for k in l: k()

0
1
2
3
4


Jul 18 '05 #3

"Darabos Daniel" <cy****@sch.bme .hu> wrote in message
news:Pine.GSO.4 .58L0.040319173 6410.14978@balu ...
Hi!

I was doing something like this:
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.
If you had written

for i in range(5):
def f(): return p(i)
l.append(f)

would you have still been surprised? Or given that f is constant, how
about the exactly equivalent

def f(): return p(i)
for i in range(5):
l.append(f)

or even the equivalent

def f(): return p(j)
for i in range(5):
l.append(f)
j=i
def p(z): print z
<etc>

After some brainwork I now kind of understand what happens and I even
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 ) )
... for k in l:

... k()
...
0
1
2
3
4

But I still feel a bit unsatisfied. Do you have some advice for me?


Remember that 1) 'lambda args: expr' basically abbreviates 'def f(args):
return expr'; and 2) function code bodies only execute when the function
is called, and in particular, do not dereference or access globals until
called. While a function is being constructed, it is irrelevant that a
global even exist, let along that it be in use as a loop var.

Terry J. Reedy


Jul 18 '05 #4
On 19 Mar 2004, Darabos Daniel <- cy****@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.
The `i' in your code is bound to the global value of `i' which is 4.
After some brainwork I now kind of understand what happens and I even
found a solution like this:
def mylambda( fn, *args ): ... return lambda: apply( fn, args )

[...]
But I still feel a bit unsatisfied. Do you have some advice for me?


You have to bind the value of `i' in the lambda form; you did that with
your function definition but it can be done a bit simpler:
funs = [lambda i=i: sys.stdout.writ e(str(i)+"\n") for i in range(4)]
for f in funs: .... f()
....
0
1
2
3


With the `i=i' the `i' in the lambda got bound.
KP

--
And has thou slain the Jabberwock?
Come to my arms, my beamish boy!
O frabjous day! Callooh! Callay!'
He chortled in his joy. "Lewis Carroll" "Jabberwock y"
Jul 18 '05 #5
Darabos Daniel <cy****@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.pytho n. Here's a
link to one of the really heated threads about this:

http://groups.google.com/groups?hl=e...0119375&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!
Jul 18 '05 #6
Daniel Yoo <dy**@hkn.eecs. berkeley.edu> wrote in message news:<c3******* ***@agate.berke ley.edu>...

Someone should make a FAQ out of this. *grin*
Just to know, how does it work? If I write a FAQ entry, who is in
charge
of putting it in the official FAQ? (I don't have the time to write
down
this specific FAQ now, but I may be willing to write down a FAQ in the
future).
This keeps popping up every so often on comp.lang.pytho n. Here's a
link to one of the really heated threads about this:

http://groups.google.com/groups?hl=e...0119375&rnum=6


Here is a non-trollish thread on the subject, which may also
be interesting if you know some Lisp/Scheme:

http://groups.google.it/groups?hl=it....lang.python.*

HTH,

Michele Simionato
Jul 18 '05 #7
The problem, they say, is that a variable in a FOR clause can't bind a variable
inside a lambda abstraction. Fortunately the lambda operator itself doesn't
share this limitation, so you can make the variable visible to the binder in the
FOR clause by binding with a lambda and then evaluating the resulting
abstraction at the variable in question, like so:
def p(x): print x
list=[]
for i in range(5): list.append((la mbda j: lambda: p(j))(i))
x=map(lambda f: f(),list) 0
1
2
3
4

Or, more concisely,
def p(x): print x
list=[(lambda j: lambda: p(j))(i) for i in range(5)]
x=map(lambda f: f(),list)

0
1
2
3
4
Jul 18 '05 #8
"Elaine Jackson" <el************ ***@home.com> wrote in message news:<b397c.868 228$X%5.57128@p d7tw2no>...
The problem, they say, is that a variable in a FOR clause can't bind a variable
inside a lambda abstraction.


I find this explanation confusing. It is just a matter of times:
the lambda uses the value of the bound name at *calling* time, not at
*definition* time:
i=1
f=lambda : i # definition time, i=1
i=2
f() # calling time, i has been rebound to 2 2
def p(x): print x
list=[(lambda j: lambda: p(j))(i) for i in range(5)]
x=map(lambda f: f(),list)


This works since the inner lambda uses the value of j at the calling time
of the outer lambda.

Just to clarifify the point for the OP, since I am sure you understand
the all story ;)
Michele Simionato
Jul 18 '05 #9
Darabos Daniel <cy****@sch.bme .hu> writes:
Do you have some advice for me?


I'll write the concise outline in words here. If you want a more
detailed explanation, then you could do worse than reading the thread
suggested by Michele. Therein he and I go into quite some
(excruciating and graphic :-) detail of what is going on.

The original problem is that there is a single binding of "i" which is
shared by all the lambdas you shove into "l". You want each lambda to
have its own, separate, binding of "i". To do this, you need to create
a new scope which binds "i" (originally, all the lambdas find "i" in
an outer scope). In Python, the only way to create a new nested scope
is with functions (which includes lambdas); any local variables in a
function are bound in a new inner scope. You sholuld create an i which
is local to your function (lambda), and bind it to the value you want.

For example:

lambda i=i: p(i)

Notes:

"i=i" means "i is a parameter (hence also a local variable) whose
default value is 'i at the time of function creation'" ...

.... therefore, the lambda now has its own "i", which is bound to the
value of the outer "i" at the time that the lambda form is being
evaluated.
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
2630
by: Ian McMeans | last post by:
I was bitten by a bug today that depended on how lambda works. It took me quite a while to realize what was going on. First, I made multiple lambda functions inside a loop, each of which depended on the current loop variable. >>> a = >>> for index in range(5): a.append(lambda: index)
53
3708
by: Oliver Fromme | last post by:
Hi, I'm trying to write a Python function that parses an expression and builds a function tree from it (recursively). During parsing, lambda functions for the the terms and sub-expressions are constructed on the fly. Now my problem is lazy evaluation. Or at least I think it is. :-)
26
3510
by: Steven Bethard | last post by:
I thought it might be useful to put the recent lambda threads into perspective a bit. I was wondering what lambda gets used for in "real" code, so I grepped my Python Lib directory. Here are some of the ones I looked, classified by how I would rewrite them (if I could): * Rewritable as def statements (<name> = lambda <args>: <expr> usage) These are lambdas used when a lambda wasn't needed -- an anonymous function was created with...
4
1635
by: markscottwright | last post by:
Just for the hell of it, I've been going through the old Scheme-based textbook "Structure and Interpretation of Computer Programs" and seeing what I can and can't do with python. I'm trying to create a function that returns the function (not the results of the function, but a function object) that results from applying function f to it's (single) argument N times. For example, if you have "def sq(x): return x*x", then repeated(sq, 2)(2)...
181
8932
by: Tom Anderson | last post by:
Comrades, During our current discussion of the fate of functional constructs in python, someone brought up Guido's bull on the matter: http://www.artima.com/weblogs/viewpost.jsp?thread=98196 He says he's going to dispose of map, filter, reduce and lambda. He's going to give us product, any and all, though, which is nice of him.
5
2523
by: Max Rybinsky | last post by:
Hello! Please take a look at the example. >>> a = # Just a list of tuples >>> a Now i want to get a list of functions x*y/n, for each (x, y) in a:
267
10870
by: Xah Lee | last post by:
Python, Lambda, and Guido van Rossum Xah Lee, 2006-05-05 In this post, i'd like to deconstruct one of Guido's recent blog about lambda in Python. In Guido's blog written in 2006-02-10 at http://www.artima.com/weblogs/viewpost.jsp?thread=147358
5
2165
by: Octal | last post by:
How does the lambda library actually works. How does it know how to evaluate _1, how does it recognize _1 as a placeholder, how does it then calculate _1+_2, or _1+2 etc. The source files seem a bit complicated so any explanation would be appreciated. Thanks
1
2633
by: Tim H | last post by:
Compiling with g++ 4: This line: if_then_else_return(_1 == 0, 64, _1) When called with a bignum class as an argument yields: /usr/include/boost/lambda/if.hpp: In member function 'RET boost::lambda::lambda_ functor_base<boost::lambda::other_action<boost::lambda::ifthenelsereturn_action>
0
9711
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10595
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10343
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10088
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9169
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6862
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5529
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3831
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3001
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.