Is this a bug of the lambda function

Carsten Haese carsten at uniqsys.com
Fri Oct 12 07:54:21 EDT 2007


On Fri, 12 Oct 2007 01:00:47 -0400, Zhu Wayne wrote 
> Hi, 
> I have a short code which gives me strange results, the code is as follows: 
> 
> f = [lambda x: None]*5 
> for j in range(0, 5): 
>      f[j] = lambda x: float(j)*x 
> [...]
> It seems only when I use the index j (which is declear with the lambda
> function), I can get expected answer [...]

'j' is not declared with the lambda function. Inside the lambda, 'j' is a
global name. Global names inside a function body are looked up when the
function is called, not when the function is defined.

You are actually defining five identical functions that look up the global
name j, take its float value, and multiply that times the argument x.
If the name 'j' is deleted, the functions won't run anymore. Observe:

>>> f = [lambda x: None]*5
>>> for j in range(0, 5):
...   f[j] = lambda x: float(j)*x
...
>>> del j
>>> f[0](1)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in <lambda>
NameError: global name 'j' is not defined

To get the behavior you expect, you're going to have to cause the name 'j' to
be looked up (and frozen, so to speak) at the time the lambda is defined. One
way to do that is to use a default function argument:

>>> for j in range(0, 5):
...   f[j] = lambda x, inner_j=j: float(inner_j)*x
...
>>> del j
>>> f[0](1.)
0.0

Hope this helps,

--
Carsten Haese
http://informixdb.sourceforge.net




More information about the Python-list mailing list