0

This works fine:

>>> def my_range(stop):
    i = 0
    while i < stop:
        yield i
        i += 1

>>> [k for k in my_range(10) if k < 5]
[0, 1, 2, 3, 4]

Now I modify my generator:

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

>>> result = []
>>> for k in my_range():
    if k < 5:
        result.append(k)
    else:
        break


>>> print(result)
[0, 1, 2, 3, 4]

Now, why is this trapped in an infinite loop? Even though I have k < 5. Aren't generators supposed to iterate only when next is called?

>>> [k for k in my_range() if k < 5]
jurgenreza
  • 5,856
  • 2
  • 25
  • 37

2 Answers2

7

The condition in an LC doesn't imply a break when it returns false; if you want that behavior then look into itertools, specifically takewhile().

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
6

This answer explains it well:

Keep in mind the following:

[ expression for item in list if conditional ]

Is equivalent to:

for item in list:
    if conditional:
        expression

which means that your list comprehension:

[k for k in my_range() if k < 5]

is equivalent to:

for k in my_range():
    if k < 5:
        k

Now it should be clear why this never terminates: there's nothing to actually break the infinite loop.

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710