为什么奇怪的列表理解行为有副作用?

时间:2012-10-16 23:16:44

标签: python lambda list-comprehension side-effects

我知道在Python列表推导中使用副作用并不是一种好的做法。但我无法理解为什么会发生以下情况:

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]

这是否是一种好的做法,列表理解的内部是否应该做一些可预测的事情?如果上面的 可预测,有人可以解释为什么只发生了三次remove操作,以及为什么偶数条目仍然存在?

2 个答案:

答案 0 :(得分:6)

这不是关于listcomps,而是关于从你正在迭代的列表中删除:

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

它是这样的:

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

首先它正在查看第0个元素,并删除1。所以在下一次迭代中,它想要删除第一个元素,现在是3,等等。

答案 1 :(得分:-1)

当您直接迭代列表时,从列表中删除绝不是一个好主意。 编辑:哎呀,我用词典混淆了列表。字典有一个iteritems()和iterkeys()方法,当你迭代字典并从中删除项目时,你会使用它。

对于列表,如果要在列表comp中执行此操作,则可能需要复制列表。或者,或者:

[None and tmp.pop(0) for i in xrange(len(tmp))]