Moving to Freedom, .Org(on)

Python Sequence Generator

Here’s some code to generate an arbitrary unique sequence of any combination of numbers, letters, or any character other than whitespace.

I turned this into a class that implements the iterator protocol, and added a unit test module. I may have went overboard with the unit testing, but I looked at it as a learning exercise, and it’s kind of rewarding in a deep and meaningful way to be able to press a button and put a module through its paces. Final code counts: 180 lines 317 lines

The code is now released with the GNU GPL license v3:

sequence_generator.tgz (16K)

It’s written for Python 2.6, but I ran the files through the 2to3 tool with an eye to an easy conversion to Python 3.

The constructor takes two parameters. The first is stoplen. The sequence will stop generating new values when the length of the next value equals stoplen. The second is the sequence “alphabet.” The default is an alphanumeric sequence. You can also specify a rollover len where it will reset to “zero” (the first character in the sequence’s alphabet) when the next value equals rollover_len.

So, you might use it in an iteration context:

>>> from sequence_generator import SeqGen
>>> for i in SeqGen(3, 'ABC'):
...     print i.rjust(2, 'A')

Or you might try:

>>> s = SeqGen()
>>> s.seqchars
>>> next(s)
>>> next(s)
>>> s.rollover_len = 5
>>> s.value = 'zzzy'
>>> next(s)
>>> next(s)

Or you may revel in the beauty of a (hopefully!) comprehensive set of unit tests:

$ ./ -v
ALPHANUM_26 sequence ... ok
ALPHANUM_36 sequence ... ok
ALPHANUM_62 sequence ... ok
binary sequence ... ok
default (ALPHANUM_36) sequence ... ok
HEX sequence ... ok
LETTERS sequence ... ok
base numbers and letters ... ok
NUMBERS sequence ... ok
__init__ input parameter validation ... ok
iteration / stop iteration ... ok
main with bad input ... ok
main with good input ... ok
rollover ... ok
seqchars ... ok
get_value ... ok
set_value ... ok
validate ... ok

Ran 18 tests in 0.227s



I was looking for Python “sequence generator” code earlier today. By that, I’m thinking of a method to increment an arbitrary string of letters and numbers in an orderly way.

I figured there should be code samples out there to make quick work of it, but it was more challenging to find something than expected. Part of it might be my weak conceptual grasp of the subject. Maybe I just lacked the necessary search terms. With the words I did have — sequence and generator — I got a lot of static since these terms describe basic Python concepts.

I finally resorted to crafting my own sequence generator. To you, Future Searcher, I hope it will be useful. It is easy enough to convert this into a function, which I did for my script. (Or maybe you’ll want an actual generator!) I won’t elaborate on it more. If you’re looking for this, you probably know everything you need to know.


import sys

if len(sys.argv) < 2:
    last_value = ' '
    last_value = ' ' + sys.argv[1].strip()

next_value = ''

# alphabet: first character must repeat at end so we can detect digit rollover

# hex = '0123456789abcdef0'
# 36 chars = '0123456789abcdefghijklmnopqrstuvwxyz0'
# 62 chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0'
# 28 chars = '23456789BCDFGHJKMNPQRSTVWXYZ2'
#            (dropping 0, 1, and vowels to avoid confusion and actual words)

alphabet = '0123456789abcdefghijklmnopqrstuvwxyz0'

increment = True
for x in reversed(last_value):  # walk backwards, incrementing as necessary
    if x == ' ':                # reached the beginning
        if increment:           # all chars rolled over: grow a digit
            x = alphabet[0]     # create new leftmost "zero" to count from
            break               # we're done

    if increment:
        next_alphabet_idx = alphabet.find(x) + 1
        this_char = alphabet[next_alphabet_idx]
        if next_alphabet_idx + 1 < len(alphabet):
            increment = False   # we're done "rolling"
        this_char = x

    next_value = this_char + next_value  # building new value right to left
    # print(next_value.strip())

print('last value = ' + last_value.strip())
print('next value = ' + next_value)

Previously More Still...