我写了一个简单的python程序
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
Run Code Online (Sandbox Code Playgroud)
这给了我错误'列表索引超出范围'在线 if l[i]==0:
经过调试后,我可以发现i它正在增加并且列表正在减少.
但是,我有循环终止条件i < len(l).那我为什么会收到这样的错误呢?
Mar*_*off 51
l当您迭代它时,您正在减少列表的长度,因此当您在范围语句中接近索引的末尾时,其中一些索引不再有效.
它看起来像你想要做的是:
l = [x for x in l if x != 0]
Run Code Online (Sandbox Code Playgroud)
这将返回一个l没有任何零元素的副本(顺便说一下,该操作被称为列表理解).您甚至可以缩短最后一部分if x,因为非零数字评估为True.
在i < len(l)你编写代码的方式中,没有循环终止条件,因为它len(l)是在循环之前预先计算的,而不是在每次迭代时重新计算.但是你可以用这种方式编写它:
i = 0
while i < len(l):
if l[i] == 0:
l.pop(i)
else:
i += 1
Run Code Online (Sandbox Code Playgroud)
Jon*_*erg 17
在len(l)评估range()内置函数时,表达式仅进行一次计算.此时构建的范围对象不会改变; 它不可能知道关于这个对象的任何信息l.
PS l是价值的糟糕名称!它看起来像数字1,或大写字母I.
什么马克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)
Run Code Online (Sandbox Code Playgroud)
它就像一座从上到下倒塌的高楼:即使它在倒塌的中间,你仍然可以“进入”它并参观尚未倒塌的楼层。
你正在迭代它时改变列表的大小,这可能不是你想要的,是你的错误的原因.
编辑:正如其他人已经回答和评论的那样,列表推导更好地作为首选,尤其是回答这个问题.出于这个原因,我提出这个替代方案,虽然不是最好的答案,但它仍然解决了问题.
所以在那个注释中,你也可以使用filter,它允许你调用一个函数来评估你不想要的列表中的项目.
例:
>>> l = [1,2,3,0,0,1]
>>> filter(lambda x: x > 0, l)
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
活到老,学到老.简单就是更好,除非你需要复杂的东西.
| 归档时间: |
|
| 查看次数: |
640589 次 |
| 最近记录: |