0

I've created the following emulator function for itertools.cycle in python.

def cycle1(s) :
   while True :
       for i in s :  
           yield i

However, I am not sure why the following produces a syntax error:

def cycle2(s) :
   return (i for i in s while True)

Why cannot I use while in list comprehension? How can I have an infinite loop within list comprehension?

Thank you.

Farrousa
  • 149
  • 1
  • 11
  • Possible duplicate of [Using while in list comprehension or generator expressions](https://stackoverflow.com/questions/5505891/using-while-in-list-comprehension-or-generator-expressions) – wjandrea Oct 18 '19 at 00:24

2 Answers2

1

Why cannot I use while in [the syntax for comprehensions and generator expressions]?

It just isn't defined to work that way. Maybe a future version might support it, if there is a clear proposal (PEP) and enough demand.

How can I have an infinite loop within list comprehension?

with a for clause that loops over some unbounded generator. itertools provides a couple of those: count (produces increasing numbers endlessly) and repeat (keeps yielding the same value, unless an explicit count is provided). Alternately, you can build it yourself from the built-in iter:

>>> help(iter)
Help on built-in function iter in module builtins:

iter(...)
    iter(iterable) -> iterator
    iter(callable, sentinel) -> iterator

    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.

The first version clearly doesn't help, but for the second, all we need is a callable that returns some value, and a sentinel value that is a different value. E.g. iter(lambda: True, False).

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
0

It raises error because that syntax is not defined in Python! You can try:

class MyGenerator:
    def __init__(self,s):
        self.s = s
        self._ix = None

    def __iter__(self):
        return self

    def __next__(self):
        if self._ix is None:
            self._ix = 0

        self._ix = (self._ix + 1) % self.s
        return self._ix

g = MyGenerator(5)

for i in range(20):
    print(next(g))
aminrd
  • 4,300
  • 4
  • 23
  • 45