Generators are essentially dynamic sequences, making their official debut in Python 2.5.

That got me to thinking: can we make a circular list with them?

Why yes, we can...

Comments
well done
# generic circular sequence.  See test suite below for usage.
def circular_sequence1(seq=""):
    i = 0
    while True:
        yield seq[i]
        i = (i + 1)%len(seq)

# circular sequence with ability to reset the index.  See test suite below.
def circular_sequence2(seq=""):
    i = 0
    while True:
        comp = seq[i]
        item = (yield seq[i])  # yield is a two-way gate
        if item != None:       # .send(item) passes item back; 
                               # None returned by yield otherwise
            # look from current point onwards
            try:
                j = seq.index(item, i)
            # look from beginning up to current point
            except:
                try:
                    j = seq.index(item, 0, i)
                # OOPS! bad item
                except:
                    raise
            i = j
        else:
            i = (i+1) % len(seq)


# Test suite -- Demo code
print "\n" + "-"*30 + "\ncircular_sequence1"
print "-"*30
a = circular_sequence1(["Do","Re","Mi","Fa","Sol","La","Ti"])
for i in range(20):
    print a.next()

print "\n" + "-"*30 + "\ncircular_sequence2"
print "-"*30
b = circular_sequence2(["Do","Re","Mi","Fa","Sol","La","Ti"])
for i in range(20):
    print b.next()

print "Mi -->", 
b.send("Mi")
print b.next()

print "Ti -->",
b.send("Ti")
print b.next()

print "Do -->",
b.send("Do")
print b.next()

print "Fi -->",
try:
    b.send("Fi")
except ValueError, e:
    print e

print "\n" + "-"*30 + "\ncircular_sequence2"
print "-"*30
c = circular_sequence2(["Larry", "Curly", "Moe", "Larry"])
for i in range(10):
    print c.next()

print "Larry -->",
c.send("Larry")
print c.next()

print "Larry -->",
c.send("Larry")
print c.next()

Another approach to a circular list ...

'''' ringbuffer_function_deque1.py
using the Python deque module as a ringbuffer
as the buffer fills up first entries are dropped
tested wth Python27 and Python33
'''

import collections

def ringbuffer_10(mylist, dq=collections.deque(maxlen=10)):
    '''
    mimics a ringbuffer of default length 10
    you can change that to your needs
    '''
    for n in mylist:
        dq.append(n)
    return list(dq)

# testing ...
mylist = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
ringbuffer = ringbuffer_10(mylist)
print(ringbuffer)
print('-'*40)

# send more data
mylist = [22, 23, 24, 25]
ringbuffer = ringbuffer_10(mylist)
print(ringbuffer)

''' result ...
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
----------------------------------------
[16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
'''

Edited 4 Years Ago by vegaseat