Python pop()和pop(0)的区别

21

所以下面的内容让我感到困惑。

#!/usr/bin/python

test = [0, 0, 0, 1, 2, 3, 4, 5, 6]
test1 = [0, 0, 0, 1, 2, 3, 4, 5, 6]

for _dummy in test:
    if(_dummy == 0):
        test.pop()
for _dummy in test1:
    if(_dummy == 0):
        test1.pop(0)

print test
print test1

结果

ubuntu-vm:~/sandbox$ ./test.py 
[0, 0, 0, 1, 2, 3]
[0, 1, 2, 3, 4, 5, 6]

也许我基本上误解了pop的实现方式。但我的理解是,它会删除列表中给定索引处的项目,并返回该项目。如果没有指定索引,它将默认删除最后一个项目。因此,在第一次循环中,它应该从列表左侧删除3个项目,在第二次循环中,它应该从列表末尾删除3个项目。


这在我的电脑上完美运行。我正在使用Python 2.7.6。 - XrXr
在迭代列表时,您不能对其进行突变。 - univerio
我已经在两个不同的系统上尝试过这个。一个是由大学提供的运行Python 2.6的IDE,另一个是在我的VM Ubuntu上运行2.7.4。嗯。 - PerryDaPlatypus
我也在Python.org上尝试了一下(3.3.2),结果相同。 - PerryDaPlatypus
4个回答

29

第一个测试结果并不令人惊讶;三个元素从末尾删除。

第二个测试有点出乎意料。只删除了两个元素。为什么?

在Python中,列表迭代基本上是通过对列表进行递增索引来实现的。当您删除一个元素时,您会将右侧所有元素向左移动。这可能会导致索引指向不同的元素。

举例说明:

start of loop
[0,0,0,1,2,3,4,5,6]
 ^   <-- position of index

delete first element (since current element = 0)
[0,0,1,2,3,4,5,6]
 ^

next iteration
[0,0,1,2,3,4,5,6]
   ^

delete first element (since current element = 0)
[0,1,2,3,4,5,6]
   ^

从现在开始不再遇到零,因此不再删除任何元素。


为了避免将来的混淆,请尽量避免在迭代列表时修改它们。尽管Python不会报错(与无法在迭代过程中修改的字典不同),但会导致奇怪而通常是反直觉的情况,就像这个例子一样。


10

由于列表或堆栈的工作方式是后进先出[LIFO],因此使用pop()会删除列表中的最后一个元素。

pop(0)表示它将删除列表中第一个元素的索引位置上的元素。

根据文档

list.pop([i]):

从列表中删除给定位置的项,并返回该项。如果未指定索引,则 a.pop() 删除并返回列表中的最后一项。(在方法签名中方括号中的 i 表示该参数是可选的,而不是您应在该位置键入方括号。您将经常在 Python 库参考文档中看到这种符号表示法。)


6
你在迭代列表时修改了它们,导致混乱。如果你查看第一个元素,删除它,然后继续查看第二个元素,那么你会错过一个元素。因为它"改变了位置",所以原来在第二个位置的元素永远不会被检查。

0
当你在Python中使用'for item in ITEMS:'命令时,你仍然是通过索引进行迭代,item仍然被隐式设置为item = ITEMS[index]。每个pop(0)将项目向左移动,下一个item被引用为item = ITEMS[index++],所以,在test1中的第三个零永远不会被循环处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接