Theoretical question about Lambda

Paul Foley see at below
Mon May 6 07:20:26 EDT 2002


On Mon, 06 May 2002 07:10:14 GMT, Alex Martelli wrote:

>>>> funs=[lambda:x for x in range(5)]
>>>> [f() for f in funs]
> [4, 4, 4, 4, 4]
>>>> funs=[lambda x=x:x for x in range(5)]
>>>> [f() for f in funs]
> [0, 1, 2, 3, 4]

> But actually with the first form you get 5 functions that all return 
> *whatever value name x is currently bound to*, NOT functions that return 
> the last value in seq:

Oh, right, I knew that...just temporarily forgot that the x introduced
by the listcomp "leaks" out.  But you can write it as

  from __future__ import nested_scopes

  def getfns(seq):
     return [(lambda: x) for x in seq]

  funs = getfns([1,2,3,4,5])

so that the x in the listcomp doesn't leak into the global
environment, and the lambda does form a closure.  You still get a list
of functions that all return 5.

> The 'closure' alternative which I also posted and you snipped is superior
> to either lambda alternative because it 'snapshots' state like the second
> of these lambda variations but doesn't squirrel it away in the fragile spot
> of "a default value for an argument" (risking somebody mistakenly supplying
> an argument and thus overriding the default...:-).

Well, I assumed you were using nested_scopes, so this wasn't an issue.

>> [The usual binding-vs-assignment misunderstanding that I keep trying
>> to explain to people who say Python's assignment is really "binding"]

> I'm one of those people to which you "keep trying to explain" and I'm
> deeply unconvinced by your explanations.  Assignment rebinds names

OK; question: what's the difference, if any, between

     x = n
     do_something

and

     def foo(x):
        do_something

     foo(n)

as far as x is concerned?

Given that (lambda: x) /does/ close over x with nested scopes enabled,
can you explain why

  fns = getfns(seq)

produces a list of functions that all return seq[-1]?  And why, as you 
point out,

  def getfns2(seq):
     return [(lambda x=x: x) for x in seq]

produces functions that return all the elements of seq?
[Assume you call them with no arguments!]

-- 
Nonono, while we're making wild conjectures about the behavior of
completely irrelevant tasks, we must not also make serious mistakes,
or the data might suddenly become statistically valid.
                                                           -- Erik Naggum
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(#\@) "actrix.gen.nz>"))



More information about the Python-list mailing list