Looping from 1 to infinity in Python

PythonLoops

Python Problem Overview


In C, I would do this:

int i;
for (i = 0;; i++)
  if (thereIsAReasonToBreak(i))
    break;

How can I achieve something similar in Python?

Python Solutions


Solution 1 - Python

Using itertools.count:

import itertools
for i in itertools.count(start=1):
    if there_is_a_reason_to_break(i):
        break

In Python 2, range() and xrange() were limited to sys.maxsize. In Python 3 range() can go much higher, though not to infinity:

import sys
for i in range(sys.maxsize**10):  # you could go even higher if you really want
    if there_is_a_reason_to_break(i):
        break

So it's probably best to use count().

Solution 2 - Python

def to_infinity():
    index = 0
    while True:
        yield index
        index += 1

for i in to_infinity():
    if i > 10:
        break

Solution 3 - Python

Simplest and best:

i = 0
while not there_is_reason_to_break(i):
    # some code here
    i += 1

It may be tempting to choose the closest analogy to the C code possible in Python:

from itertools import count

for i in count():
    if thereIsAReasonToBreak(i):
        break

But beware, modifying i will not affect the flow of the loop as it would in C. Therefore, using a while loop is actually a more appropriate choice for porting that C code to Python.

Solution 4 - Python

Reiterating thg435's comment:

from itertools import takewhile, count

def thereIsAReasonToContinue(i):
    return not thereIsAReasonToBreak(i)

for i in takewhile(thereIsAReasonToContinue, count()):
    pass # or something else

Or perhaps more concisely:

from itertools import takewhile, count

for i in takewhile(lambda x : not thereIsAReasonToBreak(x), count()):
    pass # or something else

takewhile imitates a "well-behaved" C for loop: you have a continuation condition, but you have a generator instead of an arbitrary expression. There are things you can do in a C for loop that are "badly behaved", such as modifying i in the loop body. It's possible to imitate those too using takewhile, if the generator is a closure over some local variable i that you then mess with. In a way, defining that closure makes it especially obvious that you're doing something potentially confusing with your control structure.

Solution 5 - Python

If you want to use a for loop, it's possible to combine built-in functions iter (see also this answer) and enumerate for an infinite for loop which has a counter. We're using iter to create an infinite iterator and enumerate provides the counting loop variable. The start value is zero by default, but you can set a different start value with the start argument.

for i, _ in enumerate(iter(bool, True), start=1):
    input(i)

Which prints:

1
2
3
4
5
...

Solution 6 - Python

If you're doing that in C, then your judgement there is as cloudy as it would be in Python :-)

For a loop that exits on a simple condition check at the start of each iteration, it's more usual (and clearer, in my opinion) to just do that in the looping construct itself. In other words, something like (if you need i after loop end):

int i = 0;
while (! thereIsAReasonToBreak(i)) {
    // do something
    i++;
}

or (if i can be scoped to just the loop):

for (int i = 0; ! thereIsAReasonToBreak(i); ++i) {
    // do something
}

That would translate to the Python equivalent:

i = 0
while not there_is_a_reason_to_break(i):
    # do something
    i += 1

Only if you need to exit in the middle of the loop somewhere (or if your condition is complex enough that it would render your looping statement far less readable) would you need to worry about breaking.

When your potential exit is a simple one at the start of the loop (as it appears to be here), it's usually better to encode the exit into the loop itself.

Solution 7 - Python

def infinity():
    i=0
    while True:
        i+=1
        yield i


for i in infinity():
    if there_is_a_reason_to_break(i):
        break

Solution 8 - Python

def natural_numbers():
  yield from map(sum, enumerate(iter(int,1)))

for i in natural_numbers():
  if there_is_a_reason_to_break(i):
      break;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2058002View Question on Stackoverflow
Solution 1 - PythonJohn La RooyView Answer on Stackoverflow
Solution 2 - PythonspicavigoView Answer on Stackoverflow
Solution 3 - PythonwimView Answer on Stackoverflow
Solution 4 - PythonSteve JessopView Answer on Stackoverflow
Solution 5 - PythonfinefootView Answer on Stackoverflow
Solution 6 - PythonpaxdiabloView Answer on Stackoverflow
Solution 7 - PythonrekinyzView Answer on Stackoverflow
Solution 8 - PythonfirejoxView Answer on Stackoverflow