我写了一个简单的Python程序
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
我在代码的第if l[i]==0:
行遇到了“索引超出范围”的错误。
通过调试,我发现i
在增加并且列表在减少。然而,我的循环终止条件是i < len(l)
。那么为什么会出现这样的错误?
l
时减少其长度,因此当你接近范围语句中的索引结尾时,一些索引不再有效。l = [x for x in l if x != 0]
if x
,因为非零数会被视为True
。i < len(l)
这样的循环终止条件,因为len(l)
是在循环之前预先计算的,而不是在每次迭代时重新计算。不过,您确实可以以这样的方式编写它:i = 0
while i < len(l):
if l[i] == 0:
l.pop(i)
else:
i += 1
len(l)
表达式只会在range()
内置函数被调用时计算一次。那时构建的范围对象不会改变, 它无法了解关于对象l
的任何信息。
附注:l
是一个糟糕的值名称!它看起来像数字1或大写字母I。
Mark Rushakoff所说的是正确的,但是如果你在for循环中按相反的顺序迭代,也可以从列表中删除元素。例如:
x = [1,2,3,0,0,1]
for i in range(len(x)-1, -1, -1):
if x[i] == 0:
x.pop(i)
这就像一座高楼从顶部倒塌到底部:即使它正在崩溃的过程中,你仍然可以“进入”并访问尚未倒塌的楼层。
>>> l = [1,2,3,0,0,1]
>>> filter(lambda x: x > 0, l)
[1, 2, 3]
活到老,学到老。 简单就是美,除非你需要复杂的东西。
filter(None, l)
- Steve Loshfilter
仍然是工具箱中重要的一部分,当你需要更高级的评估时就会用到它。 - jathanisml = [1, 2, 3, 0, 0, 1]
while 0 in l:
l.remove(0)
不要迭代列表,而是删除0
,直到列表中没有任何0
列表推导式将帮助您找到解决方案。
但在Python中复制对象的正确方法是使用Python模块copy——浅层复制和深层复制操作。
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
import copy
l=[1,2,3,0,0,1]
duplicate_l = copy.copy(l)
for i in range(0,len(l)):
if l[i]==0:
m.remove(i)
l = m
那么,你自己的代码本来可以工作。 但为了优化,列表推导式是一个不错的解决方案。
len()
的循环内修改引用的列表。当您从列表中删除项目时,下一个循环将计算新的len()
。
例如,在第一次运行后,当您使用l.pop(i)
移除(i)
时,这是成功的,但在下一个循环中,列表的长度已经改变,因此所有索引号都已经被移动。到某个点时,循环尝试在缩短的列表上运行并抛出错误。
在循环外部执行此操作可以工作,但最好在循环之前首先声明一个空列表,并在循环内部将要保留的所有内容追加到新列表中。
对于那些可能遇到同样问题的人们。
len(l)
之后放置print(i)
,仍会出现错误。我在命令行(shell)中运行相同的代码,它可以正常运行而不出错。我的做法是,在主程序中计算len(l)
并将其作为参数传递。这样就可以正常工作了。有时候,Python确实很奇怪。我觉得这里大多数的解决方案都是关于列表推导式,但如果你想进行原地删除并且将空间复杂度保持在O(1)的话;解决方案是:
i = 0
for j in range(len(arr)):
if (arr[j] != 0):
arr[i] = arr[j]
i +=1
arr = arr[:i]
代码:
while True:
n += 1
try:
DATA[n]['message']['text']
except:
key = DATA[n-1]['message']['text']
break
控制台:
Traceback (most recent call last):
File "botnet.py", line 82, in <module>
key =DATA[n-1]['message']['text']
IndexError: list index out of range
range(len(l))
,因为默认起始值是0。 - abyxl
(小写字母 el)、O
(大写字母 oh)或I
(大写字母 eye)作为单个字符变量名。 http://www.python.org/dev/peps/pep-0008/ - Stephan202range(0,len(l))
的结果会随着l
的改变而变化?你为什么这样认为?你在哪里读到的? - S.Lott