for 循环中的 try-except 块跳过 NEXT 迭代?
Posted
技术标签:
【中文标题】for 循环中的 try-except 块跳过 NEXT 迭代?【英文标题】:try-except block in for loop skips NEXT iteration? 【发布时间】:2017-09-10 01:55:28 【问题描述】:我有一些文本数据,我正在尝试清理数值。我尽可能将其分成干净的行,并将这些行分成数据点。一个例子是
["1.115","","","4.3"]
我的代码应该把它变成
["1.115","4.3"]
这里是sn-p:
for i in t:
try:
print(float(i))
except ValueError:
print(i)
t.remove(i)
continue
所有的 print() 语句都用于调试。运行代码给出了
["1.115","","4.3"]
作为输出。如果连续没有两个非浮点数,它运行正常,但通过异常处理删除一个非浮点数后,它不会打印下一个浮点值。
【问题讨论】:
您正在修改列表。要么复制它,要么从一个空列表开始 【参考方案1】:这看起来像是修改您当前正在循环的列表的问题——通过删除一个元素,您改变了当前偏移量的含义。一种解决方法是创建一个新列表而不是更改原始列表:
t = ["1.115", "", "", "4.3"]
s = []
for i in t:
try:
s.append(float(i))
except ValueError:
pass
print(s)
如果你真的想循环修改原始列表,你可以试试这样:
t = ["1.115", "", "", "4.3"]
i = 0
while i < len(t):
try:
float(t[i])
i += 1
except ValueError:
del t[i]
print(t)
但请确保您已经考虑了所有可能的情况并进行了彻底的测试。
【讨论】:
【参考方案2】:如果您在修改列表的同时将迭代器保存到列表中,那么 Python(和大多数语言)很可能会感到困惑。
这段代码是该问题的牺牲品,因为您正在修改您正在迭代的同一个列表。构造一个作为输出的新列表更为常见。这是一个例子:
def yield_only_floats(l):
for s in l:
try:
float(s)
yield s
except ValueError:
pass
x = list(yield_only_floats(["1.115","","","4.3"]))
print x
得到 ['1.115', '4.3'] 的结果
如果您想修改原始列表,您仍然可以这样做:
x = ["1.115","","","4.3"]
x[:] = list(yield_only_floats(x))
但是,如果你真的想在迭代时修改你正在迭代的同一个列表,最好的办法是反向迭代:
def leave_only_floats(l):
for i in xrange(len(l) - 1, -1, -1):
try:
float(l[i])
except ValueError:
del l[i]
x = ["1.115","","","4.3"]
leave_only_floats(x)
请注意,我还使用了位置删除,而不是值删除,这使得它更快(不必再次搜索列表)
顺便说一句,您也可以考虑使用列表推导:
def is_float(s):
try:
float(s)
return True
except ValueError:
return False
x = ["1.115","","","4.3"]
y = [s for s in x if is_float(s)]
对于这类问题,我个人认为列表推导式是最易读的。
【讨论】:
【参考方案3】:只需将 .copy() 添加到您的循环中并删除“继续”语句:
for i in t.copy():
try:
print(float(i))
except ValueError:
print(i)
t.remove(i)
【讨论】:
【参考方案4】:更改您正在迭代的对象不是一个好主意。列表迭代是逐个索引完成的,因此当您删除一个元素时,右侧的剩余元素会向下移动。
t = ["1.115", "", "", "4.3"]
for i in t:
try:
print(float(i))
except ValueError:
print(i)
t.remove(i)
# First run of loop:
idx = 0
i = "1.115"
t = ["1.115", "", "", "4.3"]
# Second run of loop
idx = 1
i = ""
t = ["1.115", "", "4.3"]
# Third, last run of loop
idx = 2
i = "4.3"
t = ["1.115", "", "4.3"]
正确的做法:
t = ["1.115","","","4.3"]
def is_float(number):
try:
float(number)
return True
except ValueError:
return False
res = [x for x in t if is_float(x)]
【讨论】:
以上是关于for 循环中的 try-except 块跳过 NEXT 迭代?的主要内容,如果未能解决你的问题,请参考以下文章
是否有一种 Pythonic 的方式来跳过 for 循环中的 if 语句以使我的代码运行得更快?
像 while 循环一样,我怎样才能跳过 for 循环中的一个步骤?