I have a program that runs an operation either a fixed number of times, or "forever" until some condition is reached. The implementation was fine, but I was having trouble getting a code structure I was happy with.
My initial logic boiled down to:
max_iterations = 5 # Either an integer or None (the number actually comes from user input)
stop_flag = False
i = 0
while not stop_flag:
do_some_operation(i)
i += 1
stop_flag = (i == max_iterations) or test_some_stop_condition()
But I wasn't very happy with this, I don't like that there's both an i
variable and a stop
flag.
The stop flag can be eliminated by moving the logic to the while:
i = 0
while not ((i == max_iterations) or test_some_stop_condition()):
do_some_operation(i)
i += 1
but this seems even less readable to me. That conditional is not particularly understandable now it's moved to the while
.
So, I used itertools.count
to do the iteration:
import itertools
max_iterations = 5 # Either an integer or None (the number actually comes from user input)
for i in itertools.count():
do_some_operation(i)
if (i == max_iterations) or test_some_stop_condition():
break
I'm not very happy with this either, but I think it's reasonably clean and readable. Ideally I think the termination condition should be entirely in the for
or while
, leaving the body of the loop entirely for the actual work, but I can't think of a way to do it cleanly.
Is there a better solution?
Some notes:
i
variable is required, since do_some_operation
makes use of it.test_some_stop_condition()
can still return True
regardless of whether i
is None
or an int
. This is fine.(This question might be better suited to https://codereview.stackexchange.com/, I'm honestly not sure...)
max_iterations could be handled with
for i in islice(count(), max_iterations):
or
for i in count() if max_iterations is None else range(max_iterations):
or if int values are always positive:
for i in range(max_iterations) if max_iterations else count():