Theoretical question about Lambda

Alex Martelli aleax at aleax.it
Mon May 6 03:10:14 EDT 2002


Paul Foley wrote:
        ...
>> I originally thought this kind of situation might count as 'substantial':
> 
>> funs = [ (lambda : x) for x in seq ]
> 
> I'd expect that to return a list of as many functions as there are
> items in seq, that all return the last value in seq.  I.e., if seq is

Right!  No need to "expect" when one can just check:

>>> 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:

>>> funs=[lambda:x for x in range(5)]
>>> x=23
>>> [f() for f in funs]
[23, 23, 23, 23, 23]

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...:-).

> [1, 2, 3, 4, 5], you'd get 5 functions that all return 5, not

Or 23, or whatever x has last been re-bound to:-).

> functions that return 1, 2, 3, 4, and 5 respectively, as I think
> you're expecting (and the second version, with the "funize" function,
> does work that way)

Clearly I didn't do a good job of explaining what I meant -- why what "I
originally thought" was not acceptable, and avoiding lambda turned out to
be preferable in this case too.


> [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
('binds' if the names weren't previously bound).  In a function's default
argument value, or even better in a closure-idiom, you bind in such a way 
as to impede successive rebinding (almost totally for a closure; barring
accidental argument passing only, for a default argument), so the object
to which the name refers stays the same (you can complete a 'snapshot'
effect, if you're dealing with _mutable_ values which isn't the case in
these examples, by explicitly taking a copy).


Alex





More information about the Python-list mailing list