lambda in list comprehension acting funny

rusi rustompmody at gmail.com
Fri Jul 13 15:44:59 CEST 2012


On Jul 13, 11:36 am, Steven D'Aprano <steve
+comp.lang.pyt... at pearwood.info> wrote:
> On Thu, 12 Jul 2012 21:33:40 -0700, rusi wrote:
> > On Jul 11, 11:41 am, Daniel Fetchinson <fetchin... at 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?
>
> >> Cheers,
> >> Daniel
>
> > Your expectations are reasonable.
>
> You forget to finish that sentence.
>
> "Your expectations are reasonable, for languages that don't have
> variables which can actually vary."
>
> *wink*
>
> For purely functional languages like Haskell, the behaviour you show
> below makes sense. Since Haskell doesn't allow variables to change their
> value, once a closure sees i=1 (say), then it must *always* see i=1.
>
> But that's not the case in Python, where the Haskell behaviour would be
> unfortunate. Imagine if you did this:
>
> VERBOSE = True
>
> def function(arg):
>     if VERBOSE:
>         print("calling function with arg %r" % arg)
>     process(arg)
>
> You would expect the function to honour changes to the variable VERBOSE,
> would you not? Using Python's scoping rules for closures, it does. Using
> Haskell's rules, it wouldn't.

Heres a more appropriate analog

------------------------------------------
VERBOSE = True

def function(arg):
    if VERBOSE:
       print("calling function with arg %r" % arg)
    process(arg)

def caller():
    VERBOSE = False
    function(1)

---------------------------------------------
Python semantics: function sees VERBOSE False
Haskell semantics: function sees VERBOSE True



More information about the Python-list mailing list