Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #25167 > unrolled thread

Re: lambda in list comprehension acting funny

Started byDaniel Fetchinson <fetchinson@googlemail.com>
First post2012-07-11 08:43 +0200
Last post2012-07-14 03:31 -0700
Articles 5 — 5 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: lambda in list comprehension acting funny Daniel Fetchinson <fetchinson@googlemail.com> - 2012-07-11 08:43 +0200
    Re: lambda in list comprehension acting funny Franck Ditter <franck@ditter.org> - 2012-07-12 08:49 +0200
    Re: lambda in list comprehension acting funny Alister <alister.ware@ntlworld.com> - 2012-07-12 09:44 +0000
      Re: lambda in list comprehension acting funny Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-07-12 11:29 +0000
      Re: lambda in list comprehension acting funny 88888 Dihedral <dihedral88888@googlemail.com> - 2012-07-14 03:31 -0700

#25167 — Re: lambda in list comprehension acting funny

FromDaniel Fetchinson <fetchinson@googlemail.com>
Date2012-07-11 08:43 +0200
SubjectRe: lambda in list comprehension acting funny
Message-ID<mailman.2007.1341988993.4697.python-list@python.org>
> funcs = [ lambda x: x**i for i in range( 5 ) ]
> print funcs[0]( 2 )
> print funcs[1]( 2 )
> print funcs[2]( 2 )
>
> This gives me
>
> 16
> 16
> 16
>
> When I was excepting
>
> 1
> 2
> 4
>
> Does anyone know why?

And more importantly, what's the simplest way to achieve the latter? :)


-- 
Psss, psss, put it down! - http://www.cafepress.com/putitdown

[toc] | [next] | [standalone]


#25203

FromFranck Ditter <franck@ditter.org>
Date2012-07-12 08:49 +0200
Message-ID<franck-EA5E88.08495812072012@news.free.fr>
In reply to#25167
In article <mailman.2007.1341988993.4697.python-list@python.org>,
 Daniel Fetchinson <fetchinson@googlemail.com> wrote:

> > funcs = [ lambda x: x**i for i in range( 5 ) ]
> > print funcs[0]( 2 )
> > print funcs[1]( 2 )
> > print funcs[2]( 2 )
> >
> > This gives me
> >
> > 16
> > 16
> > 16
> >
> > When I was excepting
> >
> > 1
> > 2
> > 4
> >
> > Does anyone know why?

In Python 3.x :

funcs = [lambda x: x**i for i in range(5)]
list(map(lambda f: f(2),funcs)) --> [16, 16, 16, 16, 16]

Ooops, cool semantics :-)

In Racket Scheme (http://racket-lang.org), they seem to know lambdas :

#lang racket

;;; quick and dirty list comprehension syntax as a macro, for fun :

(define-syntax-rule (list-of expr for x in L)     
  (map (lambda (x) expr) L))

(list-of (sqr x) for x in (range 5)) --> (0 1 4 9 16)

(define funcs (list-of (lambda (x) (expt x i)) for i in (range 5)))
(map (lambda (f) (f 2)) funcs) --> (1 2 4 8 16)

    franck

[toc] | [prev] | [next] | [standalone]


#25207

FromAlister <alister.ware@ntlworld.com>
Date2012-07-12 09:44 +0000
Message-ID<P%wLr.743666$N53.119162@fx20.am4>
In reply to#25167
On Wed, 11 Jul 2012 08:43:11 +0200, Daniel Fetchinson wrote:

>> funcs = [ lambda x: x**i for i in range( 5 ) ]
>> print funcs[0]( 2 )
>> print funcs[1]( 2 )
>> print funcs[2]( 2 )
>>
>> This gives me
>>
>> 16 16 16
>>
>> When I was excepting
>>
>> 1
>> 2
>> 4
>>
>> Does anyone know why?
> 
> And more importantly, what's the simplest way to achieve the latter? :)

Having read Steve's explanation in the other thread (which I think has 
finally flipped the light switch on lambda for me) it only requires a 
minor change

funcs=[ lambda x,y=i:x**y for i in range(5) ]

although I cant actually think why this construct would be needed in 
practice, how are you actually using it


-- 
* Simunye is so happy she has her mothers gene's
<Dellaran> you better give them back before she misses them!

[toc] | [prev] | [next] | [standalone]


#25209

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-07-12 11:29 +0000
Message-ID<4ffeb52c$0$29965$c3e8da3$5496439d@news.astraweb.com>
In reply to#25207
On Thu, 12 Jul 2012 09:44:15 +0000, Alister wrote:

> On Wed, 11 Jul 2012 08:43:11 +0200, Daniel Fetchinson wrote:
> 
>>> funcs = [ lambda x: x**i for i in range( 5 ) ] 
[...]
> Having read Steve's explanation in the other thread (which I think has
> finally flipped the light switch on lambda for me) it only requires a
> minor change
> 
> funcs=[ lambda x,y=i:x**y for i in range(5) ]
> 
> although I cant actually think why this construct would be needed in
> practice, how are you actually using it

I would expect that the example given is just sample code demonstrating 
the problem. A slightly more realistic case might be something like 
defining a bunch of callbacks for, say, a GUI application.

For example, the good ol' calculator app, where you have ten buttons for 
digits 0-9. So you might give each button a callback function that 
inserts its own digit into the text field:

buttons = [make_button(name=str(i)) for i in range(10)]


That works fine. So now you go to add a callback to each one:

buttons = [make_button(name=str(i), callback=lambda: FIELD.insert(i))
           for i in range(10)]


and lo and behold, the ten buttons named "0" through "9" all insert 9. 
The reason is that the callback functions aren't given the value of i, 
but only the name[1] "i". By the time the callbacks are actually used, 
i == 9 and all the buttons share the same value.



[1] Technically closures may not store values by name, but the principle 
is sound: the function, when called later, looks up the current value of 
variable i, which is not necessarily the same as it was when the closure 
was originally defined.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#25309

From88888 Dihedral <dihedral88888@googlemail.com>
Date2012-07-14 03:31 -0700
Message-ID<34872b84-3724-41d0-92ca-b7fec60b0efc@googlegroups.com>
In reply to#25207
Alister於 2012年7月12日星期四UTC+8下午5時44分15秒寫道:
> On Wed, 11 Jul 2012 08:43:11 +0200, Daniel Fetchinson wrote:
> 
> &gt;&gt; funcs = [ lambda x: x**i for i in range( 5 ) ]
> &gt;&gt; print funcs[0]( 2 )
> &gt;&gt; print funcs[1]( 2 )
> &gt;&gt; print funcs[2]( 2 )
> &gt;&gt;
> &gt;&gt; This gives me
> &gt;&gt;
> &gt;&gt; 16 16 16
> &gt;&gt;
> &gt;&gt; When I was excepting
> &gt;&gt;
> &gt;&gt; 1
> &gt;&gt; 2
> &gt;&gt; 4
> &gt;&gt;
> &gt;&gt; Does anyone know why?
> &gt; 
> &gt; And more importantly, what&#39;s the simplest way to achieve the latter? :)
> 
> Having read Steve&#39;s explanation in the other thread (which I think has 
> finally flipped the light switch on lambda for me) it only requires a 
> minor change
> 
> funcs=[ lambda x,y=i:x**y for i in range(5) ]
> 
> although I cant actually think why this construct would be needed in 
> practice, how are you actually using it
> 
> 
> -- 
> * Simunye is so happy she has her mothers gene&#39;s
> &lt;Dellaran&gt; you better give them back before she misses them!

Uhn, there are 5 objects in the list if not factored well to be executed in 
the run time.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web