How to write this iterator?

George Sakkis gsakkis at
Tue Sep 20 03:16:37 CEST 2005

<severa at> wrote in message
news:mailman.597.1127133504.509.python-list at
> Sorry, my description was not very good, I meant something behaving as:
> >>>example=Liter("abc","12345","XY")
> >>>for x in example: print x,
> a 1 X b 2 Y c 3 4 5
> or for that append() method,
> >>>example=Liter("abc", "12345")
> >>>for i in range(3): print,
> a 1 b
> >>>example.append("XY")
> >>>for x in example: print x,
> 2 c X 3 Y 4 5
> Hope this clarifies what I mean
> Best regards
> Pavol

Check the module I posted on append() makes things more
complicated -- mainly because generators don't accept attributes, so it
has to be wrapped in a class -- but the simple generator (without
append) is more manageable:

def cycleiter(*iterables):
    """Return an iterator that cycles over one or more iterables,
    yielding one item from each iterable at a time. Once an iterable
    is exhausted, it is removed from the cycle. This iterator is
    exhausted when all participating iterables are exhausted.

    >>> it = cycleiter("abc","12345","XY")
    >>> list(it)
    ['a', '1', 'X', 'b', '2', 'Y', 'c', '3', '4', '5']
    >>> list(it)
    start = 0
    iterators = map(iter, iterables)
    while iterators:
        # cycle through the existing iterators, starting from start
        for i,current in cyclefrom(enumerate(iterators), start):
            except StopIteration: # the current iterator is exhausted
                # remove it and set the cycle to restart from the next
                del iterators[i]
                start = i

def cyclefrom(iterable, start=0):
    """Cycle over the elements of the iterable starting at the given

    >>> from itertools import islice
    >>> list(islice(cyclefrom('abcde', 3), 9))
    ['d', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b']
    >>> list(islice(cyclefrom('abcde', 5), 9))
    ['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd']
    # chain the last part with the first one and cycle over it. Needs
    # to replicate the iterable for consuming each part
    it1,it2 = tee(iterable)
    return cycle(chain(islice(it1, start, None), islice(it2, start)))

By the way, these generators seem general enough to make it to
itertools. Actually cyclefrom can be accomodated by adding the optional
start argument to itertools.cycle. What do you think ?


More information about the Python-list mailing list