Version 1 here is what I started with. Version 2 comes from a colleague, version 3 from another colleague.
Version 4 just makes things a little more succinct.

I enjoyed watching this simple function get cleaner as the days went by.

#!/usr/bin/python
import random
import string

def random_str_1(n):
“””
Generate a pseudorandom string of
length n.
“””
out_str = “”
letters = [‘a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’,’i’,’j’,’k’,
‘l’,’m’,’n’,’o’,’p’,’q’,’r’,’s’,’t’,’u’,’v’,’w’,’x’,’y’,’z’]
for i in xrange(n):
out_str += random.choice(letters)
return out_str

def random_str_2(n):
“””
An improvement, using the fact that Python
strings are iterables that iterate over their
characters.
“””
out_str = “”
letters = ‘abcdefghijklmnopqrstuvwxyz’
for i in xrange(n):
out_str += random.choice(letters)
return out_str

def random_str_3(n):
“””
A further improvement, using an existing
library attribute.
“””
out_str = “”
for i in xrange(n):
out_str += random.choice(string.ascii_lowercase)
return out_str

def random_str_4(n):
“””
“””
return “”.join([random.choice(string.ascii_lowercase)
for x in xrange(n)])

def test_all():
“””
Not really much of a unit test. Just confirms that
each of the generated strings is as long as specified.
Doesn’t test that strings are sufficiently random.
“””
methods = [random_str_1, random_str_2, random_str_3, random_str_4]
for n in xrange(40):
for method in methods:
out_str = method(n)
assert len(out_str) == n