itertools.cycle(iterable) vs while True
itertools.cycle(iterable) vs while True
I was recently asked to do this task (school) :
Write a loop generator, which takes as parameter a finite iterable, and generates in infinite loop the iterable
So I did :
import itertools
def loop(l):
for element in itertools.cycle(l):
yield element
and one of my classmate did :
def loop(l):
while True:
for element in l:
yield element
I'd like to know what are the main differences between the two and if there is a more "pythonic" way to write something simple as this.
3 Answers
3
I'd like to know what are the main differences between the two ...
The main difference is that these code snippets are not entirely equivalent in behaviour. Using cycle, you can accept and repeat an exhaustible iterator, whereas the while loop can not.
cycle
while
>>> def gen():
... yield 1
... yield 2
...
>>> def loop_it(it):
... for element in itertools.cycle(it):
... yield element
...
>>> g = loop_it(gen())
>>> next(g)
1
>>> next(g)
2
>>> next(g)
1
Contrast:
>>> def loop_while(it):
... while True:
... for element in it:
... yield element
...
>>> g = loop_while(gen())
>>> next(g)
1
>>> next(g)
2
>>> next(g)
# ... hangs forever
... and if there is a more "pythonic" way to write something simple as this
My recommendation is for the while loop, exactly as written. If you are asked in a school task to write the generator, it will likely be frowned upon to use "one prepared earlier" from itertools. The while loop is also more Pythonic. An "itertoolsthonic" approach would instead be using the cycle directly, like this:
while
while
items = itertools.cycle(l)
# do something with `items`
There is no point to write the extra scaffolding of a generator function and for loop yielding from an itertools.cycle - since the cycle is already an iterator, you would just use it directly.
itertools.cycle
gen
@chepner I would say the return value of a generator function is both an iterator and an iterable. I would go so far as to say that every iterator is an iterable.
– wim
Sep 6 '18 at 20:32
Well, there is no problem with using some libs, we are in the last year but we didn't have a python module yet. So using libs is not an issue. However our teacher do a lot of code golfing :)
– L. Faros
Sep 6 '18 at 20:40
You're right, itertools.cycle isn't of great interest here over the classical while True loop.
itertools.cycle
while True
On the other hand, it's of great help in infinite generator comprehensions, where you cannot create an infinite loop because it only allows for, tests and function calls. Example to generate squared value of a list indefinitely:
for
generator = (x*x for x in itertools.cycle(l))
Of course you could always shorten your current code with:
def loop(l):
yield from itertools.cycle(l)
or even:
loop = itertools.cycle
As I see it, the purpose of itertools.cycle is that you wouldn't have to write it yourself at all :)
itertools.cycle
The most pythonic way would be to simply write loop = itertools.cycle.
loop = itertools.cycle
If you truly need to write it as a generator for your school assignment, the second form would probably perform faster, because the first form basically does the same but also has additional overhead from re-yielding the values from cycle in your generator.
cycle
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Technically,
gen(or even more technically, its return value) is an iterator, not an iterable.– chepner
Sep 6 '18 at 20:26