lambda in list comprehension acting funny
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sat Jul 14 03:46:45 EDT 2012
On Fri, 13 Jul 2012 21:53:10 -0700, rusi wrote:
> On Jul 14, 8:43 am, Steven D'Aprano <steve
> +comp.lang.pyt... at pearwood.info> wrote:
>> On Fri, 13 Jul 2012 19:31:24 -0700, rusi wrote:
>> > Consider the following
>>
>> > def foo(x):
>> > i = 100
>> > if x:
>> > j = [i for i in range(10)]
>> > return i
>> > else:
>> > return i
>>
>> A simpler example:
>>
>> def foo():
>> i = 100
>> j = [i for i in range(10)]
>> return i
>>
>> In Python 3, foo() returns 100; in Python 2, it returns 9.
>
> You did not get the point.
I got the point. I just thought it was unnecessarily complex and that it
doesn't demonstrate what you think it does.
> Converting my example to your format:
>
> def foo_steven(n):
> i = 100
> j = [i for i in range(n)]
> return i
>
> $ python3
> Python 3.2.3 (default, Jun 26 2012, 00:38:09) [GCC 4.7.1] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> def foo_steven(n):
> ... i = 100
> ... j = [i for i in range(n)]
> ... return i
> ...
>>>> foo_steven(0)
> 100
>>>> foo_steven(4)
> 100
Yes, we know that in Python 3, list comprehensions create their own
scope, and the loop variable does not leak.
> $ python
> Python 2.7.3rc2 (default, Apr 22 2012, 22:35:38) [GCC 4.6.3] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> def foo_steven(n):
> ... i = 100
> ... j = [i for i in range(n)]
> ... return i
> ...
>>>> foo_steven(0)
> 100
>>>> foo_steven(3)
> 2
Yes, we know that in Python 2, list comprehensions don't create their own
scope, and consequently the list variable does leak.
> Python 2:
> When n>0 comprehension scope i is returned
> When n=0 function scope i is returned
Incorrect.
In Python 2, *there is no comprehension scope*. There is only local
scope. In Python 2, regardless of the value of n, the local variable i is
ALWAYS returned. It just happens that sometimes the local variable i is
modified by the list comprehension, and sometimes it isn't. In Python 2,
this is no more mysterious than this piece of code:
def example(n):
i = 100
for i in range(n):
pass
return i
py> example(0)
100
py> example(4)
3
If the loop doesn't execute, the loop variable isn't modified. In Python
2, it doesn't matter whether you use a for-loop or a list comprehension,
the loop variable is local to the function.
> Python 3: The return statement is lexically outside the comprehension
> and so that outside-scope's i is returned in all cases.
Correct. In Python 3, list comprehensions now match generator expressions
and introduce their own scope which does not effect the local function
scope.
Some history:
http://bugs.python.org/issue510384
http://bugs.python.org/issue1110705
--
Steven
More information about the Python-list
mailing list