>>> [i(4) for i in [(lambda n: i + n) for i in range(10)]]
and i got this:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for +: 'function' and 'int'
Apparently the outer and inter "i"s got confused. when i change the outer 'i' to 'f':
[f(4) for f in [(lambda n: i + n) for i in range(10)]]
i get this:
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
With generator expressions it worked as expected:
>>> [i(4) for i in ((lambda n: i + n) for i in range(10))]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Meanwhile:
[i(4) for i in map(lambda i: lambda n:i+n, range(10))]
Also works as expected.
This obviously has nothing to do with the lambda in python and everything to do with the way loops work.
Python has a few quirks of this kind, this one i didn't know about. I didn't know that list comprehensions and generator expressions differ in any other way than the thing they return. I should have known better, they are very different things.
edit: looks like this also works:
[i(4) for i in [(lambda i: lambda n:i+n)(i) for i in range(10)]]
List comprehensions also "leak" their loop variable into the surrounding scope. This will also change in Python 3.0, so that the semantic definition of a list comprehension in Python 3.0 will be equivalent to list(<generator expression>). Python 2.4 and beyond should issue a deprecation warning if a list comprehension's loop variable has the same name as a variable used in the immediately surrounding scope.
and
After exploring many possibilities, a consensus emerged that binding issues were hard to understand and that users should be strongly encouraged to use generator expressions inside functions that consume their arguments immediately. For more complex applications, full generator definitions are always superior in terms of being obvious about scope, lifetime, and binding.
Thanks for the clarification. I didn't know that until i started messing with them just now for my post.
Heres a a clearer example(you could deduce this from my previous post):
>>> x=((lambda n: i + n) for i in range(10))
>>> y=((lambda i: lambda n: i + n)(i) for i in range(10))
>>> [f for f in x]==[i for i in y]
True
this is with generators.
with list comprehensions it becomes:
>>> x=[(lambda n: i + n) for i in range(10)]
>>> y=[(lambda i: lambda n: i + n)(i) for i in range(10)]
>>> [f for f in x]==[i for i in y]
False
This obviously has nothing to do with the lambda in python and everything to do with the way loops work.
Python has a few quirks of this kind, this one i didn't know about. I didn't know that list comprehensions and generator expressions differ in any other way than the thing they return. I should have known better, they are very different things.
edit: looks like this also works:
Its all about scope I guess.