Re: lambda in list comprehension acting funny

Discussion in 'Python' started by Daniel Fetchinson, Jul 11, 2012.

  1. > 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
    Daniel Fetchinson, Jul 11, 2012
    #1
    1. Advertising

  2. In article <>,
    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?


    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
    Franck Ditter, Jul 12, 2012
    #2
    1. Advertising

  3. Daniel Fetchinson

    Alister Guest

    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!
    Alister, Jul 12, 2012
    #3
  4. 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
    Steven D'Aprano, Jul 12, 2012
    #4
  5. 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'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
    > &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.
    88888 Dihedral, Jul 14, 2012
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. philoso
    Replies:
    5
    Views:
    456
    Sudsy
    Nov 21, 2003
  2. Vedran Furac(
    Replies:
    4
    Views:
    318
    Marc 'BlackJack' Rintsch
    Dec 19, 2008
  3. Daniel Fetchinson

    lambda in list comprehension acting funny

    Daniel Fetchinson, Jul 11, 2012, in forum: Python
    Replies:
    45
    Views:
    665
    Robert Miles
    Aug 16, 2012
  4. Jurko Gospodnetić

    Re: lambda in list comprehension acting funny

    Jurko Gospodnetić, Jul 11, 2012, in forum: Python
    Replies:
    0
    Views:
    192
    Jurko Gospodnetić
    Jul 11, 2012
  5. Daniel Fetchinson

    Re: lambda in list comprehension acting funny

    Daniel Fetchinson, Jul 11, 2012, in forum: Python
    Replies:
    0
    Views:
    176
    Daniel Fetchinson
    Jul 11, 2012
Loading...

Share This Page