how to use iterator in while loop statement in python

16,697

Solution 1

In Python >= 3.8, you can do the following, using assignment expressions:

i = iter(range(10))
while (x := next(i, None)) is not None and x < 5:
    print(x)

In Python < 3.8 you can use itertools.takewhile:

from itertools import takewhile

i = iter(range(10))
for x in takewhile({some logic}, i):
    # do stuff

"Some logic" here would be a 1-arg callable receciving whatever next(i) yields:

for x in takewhile(lambda e: 5 > e, i):
    print(x)
0
1
2
3
4

Solution 2

There are two problems with while next(i):

  1. Unlike a for loop, the while loop will not catch the StopIteration exception that is raised if there is no next value; you could use next(i, None) to return a "falsey" value in that case, but then the while loop will also stop whenever the iterator returns an actual falsey value
  2. The value returned by next will be consumed and no longer available in the loop's body. (In Python 3.8+, that could be solved with an assignment expression, see other answer.)

Instead, you could use a for loop with itertools.takewhile, testing the current element from the iterable, or just any other condition. This will loop until either the iterable is exhausted, or the condition evaluates to false.

from itertools import takewhile
i = iter(range(10))
r = 0
for x in takewhile(lambda x: r < 10, i):
    print("using", x)
    r += x
print("result", r)

Output:

using 0
...
using 4
result 10

Solution 3

You just need to arrange for your iterator to return a false-like value when it expires. E.g., if we reverse the range so that it counts down to 0:

>>> i = iter(range(5, -1, -1))
>>> while val := next(i):
...     print('doing something here with value', val)
...

This will result in:

doing something here with value 5
doing something here with value 4
doing something here with value 3
doing something here with value 2
doing something here with value 1

Solution 4

a = iter(range(10))

try:
    next(a)
    while True:
        print(next(a))
except StopIteration:
    print("Stop iteration")
Share:
16,697

Related videos on Youtube

Union find
Author by

Union find

Updated on December 06, 2021

Comments

  • Union find
    Union find over 2 years

    Is it possible to use a generator or iterator in a while loop in Python? For example, something like:

    i = iter(range(10))
    while next(i):
        # your code
    

    The point of this would be to build iteration into the while loop statement, making it similar to a for loop, with the difference being that you can now additional logic into the while statement:

    i = iter(range(10))
    while next(i) and {some other logic}:
        # your code
    

    It then becomes a nice for loop/while loop hybrid.

    Does anyone know how to do this?

    • user2390182
      user2390182 over 4 years
      has to be a while-loop? for x in i would be the natural way.
    • RomanPerekhrest
      RomanPerekhrest over 4 years
      I guess you would not try your idea on it = itertools.count(); while next(it):
    • Chris_Rands
      Chris_Rands over 4 years
      can you give more context on your use case?
    • Chris Doyle
      Chris Doyle over 4 years
      how would you access the value the iter returned since you dont store it you just take the item and evaluaate its boolean result so what would you do in the loop since you dont have access to the item returned from the iter?
    • RomanPerekhrest
      RomanPerekhrest over 4 years
      What you need to elaborate is what should be a stopping factor of while loop. How about it = iter([True, False, 1, 0, 1]); while next(it): print('1') ? The answers given are simple, but what's your exact intention?
    • Union find
      Union find over 4 years
      What if we wanted to keep this general though, which is why I didn't indicate a specific additional logic. The stopping factor here can just be assumed to be exceeding the last iteration to where the iterator throws an exception. @RomanPerekhrest
  • tobias_k
    tobias_k over 4 years
    But this consumes next(i), and if you call it again in the loop body you miss one value. Maybe with Python 3.8 assignment expressions, though.
  • Chris_Rands
    Chris_Rands over 4 years
    while True and (True or False):-- is this a joke?
  • larsks
    larsks over 4 years
    Sure, this would be a prefect place to use assignment expressions. It wasn't clear from the question that you care about the value of the iterator.
  • larsks
    larsks over 4 years
    Updated the example to use an assignment expression.
  • Union find
    Union find over 4 years
    Everything's getting downvoted.. this seems like a perfectly valid question/answer.
  • TOTO
    TOTO over 4 years
    @Chris_Rands No it's a substitute for his [some logic]
  • Union find
    Union find over 4 years
    This is exactly what I don't want to do. I want to put the next in the while statement.
  • Chris_Rands
    Chris_Rands over 4 years
    got it (not my dv), you should also use next(a) in py 3
  • gabriel garcia
    gabriel garcia over 3 years
    The None param is important or else it will throw an stopIteration exception
  • xing
    xing almost 3 years
    What if the element in the collection or streams is a None?
  • Admin
    Admin over 2 years
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.