I know that using side effects in Python list comprehensions is not good practice. But I can't understand why something like the following happens:

In [66]: tmp = [1,2,3,4,5]; [tmp.remove(elem) for elem in tmp]
Out[66]: [None, None, None]

In [67]: tmp
Out[67]: [2, 4]

Whether or not this is good practice, shouldn't the interior of the list comprehension do something predictable? If the above is predictable, can someone explain why only three remove operations occurred, and why the even entries are the ones that remain?

有帮助吗?

解决方案

This isn't about listcomps, it's about removing from lists you're iterating over:

>>> tmp = [1,2,3,4,5]
>>> for elem in tmp:
...     tmp.remove(elem)
... 
>>> tmp
[2, 4]

It goes something like this:

>>> tmp = [1,2,3,4,5]
>>> for elem in tmp:
...     print elem, tmp
...     tmp.remove(elem)
...     print elem, tmp
... 
1 [1, 2, 3, 4, 5]
1 [2, 3, 4, 5]
3 [2, 3, 4, 5]
3 [2, 4, 5]
5 [2, 4, 5]
5 [2, 4]

First it's looking at the 0th element, and 1 is removed. So on the next iteration, it wants to remove the 1st element, which is now the 3, etc.

其他提示

It's never a good idea to remove from a list as you're iterating over it directly. Edit: whoops, I was confusing lists with dictionaries. Dictionaries have an iteritems() and iterkeys() method which is what you would use when you're iterating over a dictionary and removing items from it.

For a list, you would probably want to copy the list if you want to do this inside a list comp. Or, alternately:

[None and tmp.pop(0) for i in xrange(len(tmp))]
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top