iterools module offers many powerful, high-performance building blocks to build or manipulate iterator objects. Manipulating iterators is often better than manipulating lists thanks to iterators’ intrinsic “lazy evaluation” approach: items of an iterator are produced one at a time, as needed, while all the items of a list (or other sequence) must exist in memory at the same time (this “lazy” approach even makes it feasible to build and manipulate unbounded iterators, while all lists must always have finite numbers of items).
This section documents the most frequently used attributes of module
itertools; each of them is an iterator type, which you can call to get an instance of the type in question.
Builds and returns an iterator whose items are all those from the first iterable passed, followed by all those from the second iterable passed, and so on until the end of the last iterable passed, just like the generator expression:
(item for iterable in iterables for item in iterable)
Builds and returns an unbounded iterator whose items are consecutive integers starting from
def count(firstval=0): while True: yield firstval firstval += 1
Builds and returns an unbounded iterator whose items are the items of
def cycle(iterable): buffer =  for item ...