Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #54477 > unrolled thread
| Started by | Kasper Guldmann <gmane@kalleguld.dk> |
|---|---|
| First post | 2013-09-20 15:21 +0000 |
| Last post | 2013-09-20 19:30 +0300 |
| Articles | 4 — 4 participants |
Back to article view | Back to comp.lang.python
lambda - strange behavior Kasper Guldmann <gmane@kalleguld.dk> - 2013-09-20 15:21 +0000
Re: lambda - strange behavior Rotwang <sg552@hotmail.co.uk> - 2013-09-20 16:52 +0100
Re: lambda - strange behavior rusi <rustompmody@gmail.com> - 2013-09-20 09:25 -0700
Re: lambda - strange behavior Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2013-09-20 19:30 +0300
| From | Kasper Guldmann <gmane@kalleguld.dk> |
|---|---|
| Date | 2013-09-20 15:21 +0000 |
| Subject | lambda - strange behavior |
| Message-ID | <mailman.185.1379690708.18130.python-list@python.org> |
I was playing around with lambda functions, but I cannot seem to fully grasp
them. I was running the script below in Python 2.7.5, and it doesn't do what
I want it to. Are lambda functions really supposed to work that way. How do
I make it work as I intend?
f = []
for n in range(5):
f.append( lambda x: x*n )
assert( f[4](2) == 8 )
assert( f[3](3) == 9 )
assert( f[2](2) == 4 )
assert( f[1](8) == 8 )
assert( f[0](2) == 0 )
[toc] | [next] | [standalone]
| From | Rotwang <sg552@hotmail.co.uk> |
|---|---|
| Date | 2013-09-20 16:52 +0100 |
| Message-ID | <l1hqv8$8k9$1@dont-email.me> |
| In reply to | #54477 |
On 20/09/2013 16:21, Kasper Guldmann wrote:
> I was playing around with lambda functions, but I cannot seem to fully grasp
> them. I was running the script below in Python 2.7.5, and it doesn't do what
> I want it to. Are lambda functions really supposed to work that way. How do
> I make it work as I intend?
>
> f = []
> for n in range(5):
> f.append( lambda x: x*n )
>
> assert( f[4](2) == 8 )
> assert( f[3](3) == 9 )
> assert( f[2](2) == 4 )
> assert( f[1](8) == 8 )
> assert( f[0](2) == 0 )
This is a common gotcha. In the function "lambda x: x*n" n is a global
variable, which means that when the function is called it searches
globals() for the current value of n, which is 4 (since that was its
value when the for loop ended). There are several ways to define
functions that depend on the values bound to names at creation time,
like you're trying to do. One is to use the fact that default function
arguments are evaluated when the function is created. So this will work:
f = []
for n in range(5):
f.append(lambda x, n = n: x*n)
Another is to use the fact that arguments passed in function calls are
evaluated when the function is called. That means that you can define a
function which takes a parameter as an argument and returns a function
which depends on that parameter to get the desired behaviour, like this:
f = []
for n in range(5):
f.append((lambda n: lambda x: x*n)(n))
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2013-09-20 09:25 -0700 |
| Message-ID | <57ea049c-8b78-43ff-a14c-b9b4b3e5e2a4@googlegroups.com> |
| In reply to | #54477 |
On Friday, September 20, 2013 8:51:20 PM UTC+5:30, Kasper Guldmann wrote: > I was playing around with lambda functions, but I cannot seem to fully grasp > them. I was running the script below in Python 2.7.5, and it doesn't do what > I want it to. Are lambda functions really supposed to work that way. How do > I make it work as I intend? > > f = [] > for n in range(5): > f.append( lambda x: x*n ) > > assert( f[4](2) == 8 ) > assert( f[3](3) == 9 ) > assert( f[2](2) == 4 ) > assert( f[1](8) == 8 ) > assert( f[0](2) == 0 ) You are not wrong in being surprised. Here's the python rewritten in a more functional style And then the same in haskell. $ python3 Python 3.3.2+ (default, Jun 13 2013, 13:47:13) [GCC 4.8.1] on linux Type "help", "copyright", "credits" or "license" for more information. >>> fl= [lambda x: x + n for n in range(5)] >>> [f(1) for f in fl] [5, 5, 5, 5, 5] >>> -------haskell----- $ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Prelude> let fl = [\x-> x+n | n <- [0..4]] Prelude> [f 1 | f <- fl] [1,2,3,4,5] Prelude>
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2013-09-20 19:30 +0300 |
| Message-ID | <qot7gebcv76.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #54477 |
Kasper Guldmann writes: > I was playing around with lambda functions, but I cannot seem to > fully grasp them. I was running the script below in Python 2.7.5, > and it doesn't do what I want it to. Are lambda functions really > supposed to work that way. How do I make it work as I intend? > > f = [] > for n in range(5): > f.append( lambda x: x*n ) > > assert( f[4](2) == 8 ) > assert( f[3](3) == 9 ) > assert( f[2](2) == 4 ) > assert( f[1](8) == 8 ) > assert( f[0](2) == 0 ) It's not the lambda, it's the for. All five functions share the one n, whose value the for changes in each iteration so that the last value remains in force after the loop. There's a trick: f.append( lambda x, n=n: x*n ). Now the lambda gets to remember the value of the n of the for as the default value of its own local n.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web