# List comprehension in if clause of another list comprehension

Discussion in 'Python' started by Vedran Furac(, Dec 19, 2008.

1. ### Vedran Furac(Guest

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?

Regards!

Vedran Furac(, Dec 19, 2008

2. ### Peter OttenGuest

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

Peter Otten, Dec 19, 2008

3. ### Vedran Furac(Guest

Peter Otten wrote:

> 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']

Thanks!

Vedran Furac(, Dec 19, 2008
4. ### Guest

Peter Otten:
> The problem is that list comprehensions do not introduce a new namespace.

I think Python3 fixes this bug.

Bye,
bearophile

, Dec 19, 2008
5. ### Marc 'BlackJack' RintschGuest

On Fri, 19 Dec 2008 04:26:16 -0800, bearophileHUGS wrote:

> Peter Otten:
>> The problem is that list comprehensions do not introduce a new
>> namespace.

>
> I think Python3 fixes this bug.

Or removes that feature. ;-)

Marc 'BlackJack' Rintsch, Dec 19, 2008