Basically, it simplifies any loop that uses a boolean flag like this:
found = False # <-- initialize boolean
for divisor in range(2, n):
if n % divisor == 0:
found = True # <-- update boolean
break # optional, but continuing would be a waste of time
if found: # <-- check boolean
print n, "is composite"
else:
print n, "is prime"
and allows you to skip the management of the flag:
for divisor in range(2, n):
if n % divisor == 0:
print n, "is composite"
break
else:
print n, "is prime"
Note that there is already a natural place for code to execute when you do find a divisor - right before the break
. The only new feature here is a place for code to execute when you tried all divisor and did not find any.
This helps only in conjuction with break
. You still need booleans if you can't break (e.g. because you looking for the last match, or have to track several conditions in parallel).
Oh, and BTW, this works for while loops just as well.
any/all
Nowdays, if the only purpose of the loop is a yes-or-no answer, you might be able to write it much shorter with the any()
/all()
functions with a generator or generator expression that yields booleans:
if any(n % divisor == 0
for divisor in range(2, n)):
print n, "is composite"
else:
print n, "is prime"
Note the elegancy! The code is 1:1 what you want to say!
[This is as effecient as a loop with a break
, because the any()
function is short-circuiting, only running the generator expression until it yeilds True
. In fact it's usually even faster than a loop. Simpler Python code tends to have less overhear.]
This is less workable if you have other side effects - for example if you want to find the divisor. You can still do it (ab)using the fact that non-0 value are true in Python:
divisor = any(d for d in range(2, n) if n % d == 0)
if divisor:
print n, "is divisible by", divisor
else:
print n, "is prime"
but as you see this is getting shaky - wouldn't work if 0 was a possible divisor value...