[Tutor] Would somebody kindly...
Steven D'Aprano
steve at pearwood.info
Fri Oct 31 01:09:08 CET 2014
On Wed, Oct 29, 2014 at 10:39:53PM -0700, Clayton Kirkwood wrote:
> When you have
> [item for item in [list] if item[0] == key], after the iteration
> completes does item equal the matched entities or does it have the
> original item?
Why don't you try it for yourself and find out? At the interactive
interpreter -- do you know how to run the interactive interpreter? if
not, you should ask -- simply try it:
py> key = 23
py> result = [item for item in [(20, 1), (21, 2), (23, 4)] if item[0] == key]
py> print(item)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'item' is not defined
So in Python 3, the list comprehension variable `item` is *not* visible
outside of the list comprehension. If we set a variable `item` ahead of
time, then try it again, we'll see that it is not changed.
py> item = "something"
py> result = [item for item in [(20, 1), (21, 2), (23, 4)] if item[0] == key]
py> print(item)
something
[Note: this is different from Python 2, where the list comprehension
variable "leaks" outside of the comprehension. That was considered an
accident, if not a bug, and fixed in Python 3.]
What is happening here? This may not be *exactly* what Python does, but
it will give you a reasonable idea of how list comprehensions work. When
you write something like:
result = [2*x + 1 for x in sequence if condition(x)]
the Python compiler builds a hidden function:
def _list_comp():
tmp = []
for x in sequence:
if condition(x):
tmp.append(2*x + 1)
return tmp
then executes it:
result = _list_comp()
(except that the hidden function is completely invisible to Python code,
only the compiler can access it).
So you can see that the list comp variable x is a local variable,
localised to the list comprehension, and doesn't change any existing x
outside of the list comprehension.
> This is from a previous email--
> When I run:
> values = [ ('a', 1), ('b', 2), ('a', 5), ('c', 7)]
> key = 'a'
> pair=[]
> [pair for pair in values if key == pair[0]]
> print(pair)
>
> I get [].
Correct. The result of the list comprehension [pair for ...] is built,
then thrown away because you don't do anything with it. The existing
variable `pair` is unchanged, since the `pair` inside the list comp
lives inside it's own scope, separate from the outside `pair`. This is
no different from this situation:
pair = 'something' # global scope
def f():
pair = 23 # local to function f
def g():
pair = 42 # local to function g
[pair for pair in sequence] # local to list comp
In this case, there are four *different* `pair` variables, different
because they live in different scopes.
> When I run:
> values = [ ('a', 1), ('b', 2), ('a', 5), ('c', 7)]
> key = 'a'
> pair=[]
> x=[pair for pair in values if key == pair[0]]
> print(x)
>
> I get [('a', 1), ('a', 5)]
That's because you build the list, and instead of throwing it away, you
assign it to the variable `x`, then print `x`. The variable `pair`
remains unchanged.
--
Steven
More information about the Tutor
mailing list