Looping from 1 to infinity in Python

前端 未结 6 2083
日久生厌
日久生厌 2020-11-27 18:41

In C, I would do this:

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

How can I achieve something similar in Python?

相关标签:
6条回答
  • 2020-11-27 19:09
    def to_infinity():
        index = 0
        while True:
            yield index
            index += 1
    
    for i in to_infinity():
        if i > 10:
            break
    
    0 讨论(0)
  • 2020-11-27 19:10

    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.

    0 讨论(0)
  • 2020-11-27 19:18

    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.

    0 讨论(0)
  • 2020-11-27 19:27
    def infinity():
        i=0
        while True:
            i+=1
            yield i
    
    
    for i in infinity():
        if there_is_a_reason_to_break(i):
            break
    
    0 讨论(0)
  • 2020-11-27 19:30

    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.

    0 讨论(0)
  • 2020-11-27 19:32

    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().

    0 讨论(0)
提交回复
热议问题