Is there an elegant way in Python to detect whether a break condition was engaged at the last iteration or never at all?
C++ example:
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 example:
n = 10
for k in range(n):
if condition: break
if k == n: print("Never broke")
else: print("Broke at", k)
In Python, we don't know whether condition
was true at the last iteration since k is 9 in both cases.
Why not just use range(n + 1)
instead? Because on some contexts, we might get an "index out of range" error when k is n.
One possible workaround is to use a sentinel value as shown below, but is there a better way?
n, flag = 10, True
for k in range(n):
if condition:
flag = False
break
if flag: print("Never broke")
else: print("Broke at", k)
Use for
/else
. That's specifically what it's for.
for k in range(n):
if condition:
print("Broke at", k)
break
else:
print("Never broke")
Not necessarily better, but often you can condense the loop into a use of any
or all
(for when you only care if a value was found) or next
(for when you care about the value found).
For example, to find the first item satisfying some test, or None
if no such item exists, you can use two-arg next
plus a generator expression:
needle = next((x for x in haystack if isneedle(x)), None)
if needle is not None:
... do stuff with needle ...
else:
... no needle ...
or roughly equivalently with one-arg next
and exception handling:
try:
needle = next(x for x in haystack if isneedle(x))
except StopIteration:
... no needle ...
else:
... do stuff with needle ...
A realistic use case might be identifying a prime number via trial division. In that case, you don't care what factor you found, you just care that there was a factor, so you could write a testing function as:
num = ...
isnumprime = num >= 2 and all(num % f != 0 for f in range(2, int(num ** 0.5) + 1))
for
/else
is a perfectly adequate way to do this (see other answers), but any
/all
/next
(usually with generator expressions) can be cleaner in specific contexts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With