it looks strange
Peter Otten
__peter__ at web.de
Tue Sep 27 04:32:31 EDT 2016
cpxuvs at gmail.com wrote:
>>>> li=[lambda :x for x in range(10)]
>>>> res=li[0]()
>>>> print res
> 9
>
> why?
Look what happens if you look up x manually:
>>> li = [lambda :x for x in range(10)]
>>> x
9
So at this point x is 9 and a function written to return the value bound to
the name x will return 9
>>> li[0]()
9
>>> x = 42
>>> li[0]()
42
This is called late binding and neither the lambda behaves like any other
function
>>> def f(): return x
...
>>> f()
42
>>> x = "whatever"
>>> f()
'whatever'
To get the desired results you can either use default values which are bound
when the function is created
>>> li = [lambda x=x: x for x in range(9)]
>>> li[0]()
0
>>> li[5]()
5
or a closure:
>>> li = [(lambda x: lambda: x)(x) for x in range(9)]
>>> li[0]()
0
>>> li[5]()
5
This looks less messy when you use a function:
>>> def make_const_func(value):
... return lambda: value
...
>>> li = [make_const_func(x) for x in range(9)]
>>> li[7]()
7
In both cases the value is bound inside a function and not affected by the
current binding of the global x.
In Python 3 the situation is almost the same, except that the x from the
list comprehension is no longer exposed to the enclosing namespace.
More information about the Python-list
mailing list