2012-10-16 76 views
1

我知道在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操作發生,爲什麼偶數條目仍然存在?

+0

http://stackoverflow.com/questions/2442651/how-to-delete-an-element-from-a -list-while-iterating-it-in-python?rq = 1 –

+0

@JoshLee我不需要刪除元素,本身,我只是想明白爲什麼'None或...'的東西不是加工。事實證明,它正在工作,我沒有意識到索引正在改變。 – ely

+0

另外,在這個例子中,我將'None'放在哪個部分實際上是一個昂貴的計算,可能會導致返回'None',在這種情況下,從'tmp'刪除項目* may * be對我來說是一個可行的選擇。但無論如何,在列表理解結束時加入一個「if」子句也不好,因爲它需要再次評估這個昂貴的函數才能知道要保留什麼。 – ely

回答

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。因此,在下一次迭代中,它要刪除第一個元素,即現在的第三個元素,等等。

+0

哎呀,所以如果我把它做成[[無或tmp.remove(elem)for elem in list(tmp)]'或'[None或tmp.remove(elem)for elem in tmp [:]]'那麼它應該「按預期工作」(仍然是糟糕的風格和所有)。 – ely

-1

當您直接對它進行迭代時,從列表中刪除並不是一個好主意。 編輯:哎呀,我很困惑名單與字典。字典有一個iteritems()和iterkeys()方法,這是您在迭代字典並從中刪除項目時要使用的方法。

對於一個列表,如果您想在列表comp中執行此操作,您可能需要複製該列表。或者,交替:

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