Most elegant way to generate 3-char sequence

John Machin sjmachin at lexicon.net
Sat Jun 10 07:37:55 EDT 2006


On 10/06/2006 7:01 PM, Rob Cowie wrote:
> John Machin wrote:
>> On 10/06/2006 7:49 AM, Rob Cowie wrote:
>>> Hi all,
>>>
>>> I wish to generate a sequence of the form 'aaa', 'aab', aac'.... 'aba',
>>> 'abb', 'abc' etc. all the way to 'zzz'.
>>>
>>> How would you construct a generator to acheive this?
>>>
>>> A simple, working but somewhat inelegant solution is...
>> You're not wrong.
>>
>>> alpha = ['a','b','c','d'] #shortened for brevity
>> Hope you remember the alphabet correctly.
> Not sure I understand your point. Why would I forget the alphabet?

... or mistype it? If you use string.ascii_lowercase, your readers know 
what is intended without checking that it is in fact that.

> 
>> Why type all that punctuation?
> What punctuation?

Refer to the effbot's post.

> 
>> Any reason this cruft is global (i.e. not local to the generator)?
> No

The point being that gizmoids should not be given a wider visibility 
than is required. A handy side effect is that it is more efficient to 
reference a local than a global (global names have to be looked up in a 
dictionary).

> 
>>> alpha2 = ['a','b','c','d']
>>> alpha3 = ['a','b','c','d']
>> Hope you get the redundant copy/paste right.
> Again, I don't understand what you mean

You need only one alpha, not 3. Otherwise your readers have to compare 
alpha to alpha2 and alpha2 to alpha3 to ascertain that you haven't typoed.

> 
>>> def generator():
>>>   for char in alpha:
>> Why stop at two spaces? One-space indentation is syntactically correct :-)
> As are 3, 4 and 5 space indentation. Yet again, what is your point?

4-space indentation is more or less standard. 2-space indentation is 
definitely not an aid to swift comprehension of Python code.

> 
>>>     for char2 in alpha2:
>>>       for char3 in alpha3:
>>>         yield char + char2 + char3
>>>
>>> x = generate()
>> Did you meant "generator"?
> Yes, made a mistake
>>> x.next() # etc, etc, etc,
>>>
>> |>> def generator():
>> ...     import string
>> ...     alpha = string.ascii_lowercase
>> ...     for char in alpha:
>> ...         for char2 in alpha:
>> ...             for char3 in alpha:
>> ...                 yield char + char2 + char3
>> ...
>> |>> x = generator()
>> |>> the_lot = list(x)
>> |>> len(the_lot) == 26 ** 3
>> True
>> |>> [the_lot[i] for i in (0, 1, 25, 26, -27, -26, -1)]
>> ['aaa', 'aab', 'aaz', 'aba', 'zyz', 'zza', 'zzz']
>>
>> Cheers,
>> John
> 
> I'm aware the code I posted is not great - it isn't code I would
> consider using.

If you wouldn't consider using it, don't drag it out in public. Some 
n00b might think it the epitome of good style :-)

> It was only intended to serve as an illustration of the
> task at hand in case my explanation wasn't sufficient.
> 
> I'm grateful to you for using list(generator) in your example. I was
> not aware this could be done (I haven't yet fully read the generator
> documentation).

A generator is an iterable. list(), sum(), max(), min(), enumerate(), 
zip() etc work on iterables. It's that simple, and that powerful.

You might be interested in the itertools standard module as well.

Cheers,
John



More information about the Python-list mailing list