[Tutor] lambda problem
Corran Webster
cwebster@nevada.edu
Thu, 6 Apr 2000 09:23:23 -0700
> Dear Tutors,
>
> Isn't it possible to use a lambda inside a lamda?
The short answer is yes - see below.
> 2. With a "lambda in lambda" shortcut:
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >>> li=map(lambda y:map(lambda x:x+y, [30,40]),[1,2,3])
> Traceback (innermost last):
> File "<pyshell#18>", line 1, in ?
> li=map(lambda y:map(lambda x:x+y, [30,40]),[1,2,3])
> File "<pyshell#18>", line 1, in <lambda>
> li=map(lambda y:map(lambda x:x+y, [30,40]),[1,2,3])
> File "<pyshell#18>", line 1, in <lambda>
> li=map(lambda y:map(lambda x:x+y, [30,40]),[1,2,3])
> NameError: y
>
> The inner lambda seems not to recognize the variable y defined by the
> outer lambda. Do I want something impossible or do I misunderstand how
> lambda is functionning?
The problem is that the inner lambda has no knowledge of the variable y
(this is indicated by the NameError
This is not a problem particular to lambdas, but to any python function.
What you are doing is effectively:
def f(y):
def g(x):
# can't see y in here!
return x+y
map(g, [30,40])
map(f, [1, 2, 3])
and this won't work either. The problem is how Python scopes variables -
there is no nesting of scopes, so there is no way (without severe hackish
wizardry) for g to get any information about f's variables. This is
probably because functions in Python are first-class objects, and so it's
unclear whether the 'y' you want is the one from f, or perhaps one from
some other function which has managed to get ahold of g (perhaps because f
returned g) and is calling it.
There is a work-around, which is standard to the point of being idiomatic
for lambdas in Python. By passing y in as a default argument to the second
lambda, you get the result you want:
>>> li = map(lambda y: map(lambda x, y=y: x+y, [30,40]),[1,2,3])
>>> li
[[31, 41], [32, 42], [33, 43]]
This isn't entirely foolproof (you can get weird results if y is mutable
and the lambda mutates it somehow), and is definitely hackish, but it works.
Regards,
Corran