List comprehension in if clause of another list comprehension

Peter Otten __peter__ at web.de
Fri Dec 19 06:45:56 EST 2008


Vedran Furac( wrote:

> Hi!
> 
> In [69]: a = 'a b c'
> In [70]: b = 'a b, c d'
> 
> In [74]: [i for i in a.split() if i not in b.split()]
> Out[74]: ['b']
> 
> Everything ok.
> 
> In [77]: b.split() == [i for i in b.split()]
> Out[77]: True
> 
> As expected. Now, put this in the first list comprehension:
> 
> In [80]: [i for i in a.split() if i not in [i for i in b.split()] ]
> Out[80]: ['d']
> 
> Hmmmm... why is that?

>>> a = "abc"
>>> b = "a b, c d".split()
>>> b
['a', 'b,', 'c', 'd']
>>> [i for i in a if i not in b]
['b']

As expected, so far, but now comes the critical step:

>>> [i for i in a if i not in [i for i in b]]
['d']

The problem is that list comprehensions do not introduce a new namespace. So
the inner and the outer list comp share the same i. You can either rename
the inner i

>>> [i for i in a if i not in [k for k in b]]
['b']

or use a generator expression which does give a new namespace:

>>> list(x for x in "abc")
['a', 'b', 'c']
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

>>> [i for i in a if i not in (i for i in b)]
['b']

Peter




More information about the Python-list mailing list