繁体   English   中英

循环中的try-except块会跳过NEXT迭代吗?

[英]try-except block in for loop skips NEXT iteration?

我有试图清除数值的文本数据。 我将其尽可能细分为干净的行,并将这些行分成数据点。 一个例子是

["1.115","","","4.3"]

我的代码应该将其变成

["1.115","4.3"]

这是代码段:

for i in t:
    try:
        print(float(i))
    except ValueError:
        print(i)
        t.remove(i)
        continue

所有的print()语句都可用于调试。 运行代码可以

["1.115","","4.3"]

作为输出。 如果连续没有两个非浮点数,则可以正常运行,但是在通过异常处理删除了一个非浮点数后,它不会打印下一个浮点数。

这看起来像是修改当前正在循环的列表的问题-通过删除元素,您已经更改了固化剂偏移量的含义。 一种解决方法是创建一个新列表,而不是更改原始列表:

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)

但是,请确保您已考虑所有可能的情况并进行了全面测试。

如果要在保留列表迭代器的同时修改列表,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)]

就我个人而言,我认为列表理解方法对于此类问题最易读。

更改要迭代的对象不是一个好主意。 列表迭代是逐个索引完成的,因此,当您擦除一个元素时,右侧的其余元素将向下移动。

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)]

只需在循环中添加.copy()并删除“ continue”语句:

for i in t.copy():
    try:
        print(float(i))
    except ValueError:
        print(i)
        t.remove(i)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM