我有这段代码:
numbers = [0,1,2,3,4]
for i in range(0,len(numbers),1):
print 'i = {} , len(numbers) = {}'.format(i,len(numbers))
numbers.remove(i)
输出结果为:
i = 0 , len(numbers) = 5
i = 1 , len(numbers) = 4
i = 2 , len(numbers) = 3
i = 3 , len(numbers) = 2
i = 4 , len(numbers) = 1
我的问题是,为什么循环停止运行一次' i'比那更大(数字)'? (第4行)
谢谢
答案 0 :(得分:1)
列表的长度与此无关。要了解原因,请继续阅读。
首先,您误解了range
函数的作用。来自文档:
范围(开始,停止[,步骤])这是一个多功能的创建功能 包含算术进度的列表。它最常用于 环路。
range
做的是创建一个(有些)数字列表( python2 ),然后迭代它。
>>> range(0, 5, 1)
[0, 1, 2, 3, 4]
这可能看起来一样,但事实上,它是一个完全不同的列表。您可以通过将返回值分配给变量,然后打印出id()
,然后numbers
来确认。
您要做的是迭代实际列表,而不是range
函数生成的列表。您可以通过稍微更改循环定义来执行此操作:
numbers = [0, 1, 2, 3, 4]
ctr = 0
for i in numbers:
print('i = {} , len(numbers) = {}'.format(ctr, len(numbers)))
numbers.remove(i)
ctr += 1
输出:
i = 0 , len(numbers) = 5
i = 1 , len(numbers) = 4
i = 2 , len(numbers) = 3
现在,您会看到,在每次迭代后,列表会变短,直到列表在i
命中之前耗尽。
要明白原因,就会发生这样的事情:
Iteration 0
0 1 2 3 4 (numbers)
ctr
Iteration 1 (0 deleted)
1 2 3 4 (numbers)
ctr
Iteration 2 (1 deleted)
2 3 4 (numbers)
ctr
End (2 deleted)
这里,ctr
就像一个指针,指向列表中的当前元素。循环的每次迭代ctr
都会向前推进一步到下一个元素。
现在,每次删除元素时,不仅列表大小缩小,而且迭代器前进一个步骤,因此您实际上向前移动两次。
我们如何防止这种情况?你已经发现了解决方案。使用range
。
numbers = [0, 1, 2, 3, 4]
ctr = 0
for i in range(0, len(numbers), 1):
print('i = {} , len(numbers) = {}'.format(ctr, len(numbers)))
numbers.remove(i)
ctr += 1
这就是:
Iteration 0
0 1 2 3 4 (numbers)
0 1 2 3 4 (range)
ctr
Iteration 1 (0 deleted)
1 2 3 4 (numbers)
0 1 2 3 4 (range)
ctr
Iteration 2 (1 deleted)
2 3 4 (numbers)
0 1 2 3 4 (range)
ctr
Iteration 3 (2 deleted)
3 4 (numbers)
0 1 2 3 4 (range)
ctr
Iteration 4 (3 deleted)
4 (numbers)
0 1 2 3 4 (range)
ctr
End (4 deleted)
所以,你得到:
i = 0 , len(numbers) = 5
i = 1 , len(numbers) = 4
i = 2 , len(numbers) = 3
i = 3 , len(numbers) = 2
i = 4 , len(numbers) = 1
总而言之,当您遍历副本时,原始列表将缩小,这意味着长度也会减少,但是因为您正在迭代range
对象,该对象返回0到4之间的数字序列(包括0和4)并且不受后续删除的影响,循环将运行5次迭代(等于range
返回的元素数)。