检查是否触发了中断条件

时间:2017-12-13 01:31:01

标签: python loops break sentinel

在Python中是否有一种优雅的方法来检测是否在最后次迭代或从不中使用了中断条件?

C ++示例:

int k, n = 10;
for (k = 0; k < n; k++)
    if (condition) break;

if (k == n) cout << "Never broke\n";
else        cout << "Broke at " << k << '\n';

Python示例:

n = 10
for k in range(n):
    if condition: break

if k == n: print("Never broke")
else:      print("Broke at", k)

在Python中,我们不知道condition在最后一次迭代中是否为真,因为在这两种情况下k都是9。

为什么不直接使用range(n + 1)?因为在某些情况下,当k为n时,我们可能会得到“索引超出范围”错误。

一种可能的解决方法是使用如下所示的标记值,但有更好的方法吗?

n, flag = 10, True
for k in range(n):
    if condition:
        flag = False
        break

if flag: print("Never broke")
else:    print("Broke at", k)

2 个答案:

答案 0 :(得分:4)

使用for / else。这具体是它的用途。

for k in range(n):
    if condition:
       print("Broke at", k)
       break
else:
    print("Never broke")

答案 1 :(得分:1)

不一定更好,但通常您可以将循环压缩为使用anyall(当您只关心找到值时)或next(适用于何时)你关心找到的价值。)

例如,要查找满足某些测试的第一个项目,或者None如果不存在此类项目,则可以使用两个arg next加上一个生成器表达式:

needle = next((x for x in haystack if isneedle(x)), None)
if needle is not None:
    ... do stuff with needle ...
else:
    ... no needle ...

或大致相当于one-arg next和异常处理:

try:
    needle = next(x for x in haystack if isneedle(x))
except StopIteration:
    ... no needle ...
else:
    ... do stuff with needle ...

一个现实的用例可能是通过试验部门确定一个素数。在这种情况下,你不关心你找到了什么因素,你只关心有一个因素,所以你可以写一个测试函数:

num = ...
isnumprime = num >= 2 and all(num % f != 0 for f in range(2, int(num ** 0.5) + 1))

for / else是完全适合的方法(请参阅其他答案),但是any / all / next(通常带有生成器)表达式)在特定情况下可以更清洁。