# Generate 10 random 3-letter strings

This is a toy project and I am a beginner in Python.

I need to create 10 random 3-letter strings, where characters are a - z.

This is my implementation:

import random

def random_char():
return random.randint(97, 122)

three_letter_words = []
for i in range(0, 10):
three_letter_words.append(chr(random_char()) + chr(random_char()) + chr(random_char()))


I really do not like the part where I call chr(random_char()) 3 times.

How can I improve this to make it more compact and cleaner?

Python 3.6 introduced random.choices, which allows you to write this even more succinctly than using random.choice:

from random import choices
from string import ascii_lowercase

three_letter_words = ["".join(choices(ascii_lowercase, k=3)) for _ in range(10)]

• I am not sure if this is more succinct or easier to read.. – Koray Tugay Jul 10 '18 at 18:21
• @KorayTugay It is shorter than ["".join(choice(ascii_lowercase) for _ in range(3)) for _ in range(10)]. IMO this makes it also easier to read. Whether or not it is easier to read than writing out the for loop, that depends a bit on how used you are to list comprehensions. I think this one is not yet pushing it so far as to become unreadable. – Graipher Jul 10 '18 at 20:20
• I would not recommend doing from random import choices. choices isn't a comprehensive enough name to stand on its own like that. random.choices(...) seems like a much more readable choice (pun intended). – Alexander Jul 10 '18 at 22:54
1. random.choice(string.ascii_lowercase)

2. To get a string of n characters:

''.join([random.choice(string.ascii_lowercase) for _ in range(n)])


To generate cryptographically secure random strings (since this is a toy project, why not use a CSPRNG? it's a useful thing to learn):

import string

# only needs to be initialized once
import random
csprng = random.SystemRandom()

# alternatively, the "secrets" module is meant for generating strong csprng numbers
import secrets
csprng = secrets.SystemRandom()

# uses @Graipher's suggestion of .choices()
def random_string(len = 3, charsets = string.ascii_lowercase):
return ''.join(csprng.choices(charsets, k = len))

three_letter_strings = [random_string() for _ in range(10)]

print(three_letter_strings)

"""
example output:
['ebi', 'hbg', 'hlm', 'rhp', 'eka', 'uja', 'uhi', 'lju', 'vvf', 'qtj']
"""

"""
alternatively, below is likely faster
if you want to do this a lot more than 10 times

see: https://stackoverflow.com/a/2970789
"""

import itertools

three_letter_strings = [random_string() for _ in itertools.repeat(None, 10)]

print(three_letter_strings)


Tested with Python 3.6.5

• You should probably only be using one SystemRandom instance. Also, if you're extending an empty list with a generator expression you might as well just use a list comprehension. Lastly, your use of itertools.repeat just produces the same string 10 times - this may be random in the XKCD sense but probably isn't what OP was after. – Izaak van Dongen Jul 10 '18 at 9:51
• @IzaakvanDongen thanks for your feedback, I've edited my answer to include your suggestions (and fixed itrertools.repeat, I'd forgotten that it returns the same thing N times, instead of calling it N times). – esote Jul 10 '18 at 11:35
• Wow, it is actually faster: %timeit [0 for _ in range(10000000)]: 325 ms ± 1.38 ms, %timeit [0 for _ in repeat(None, 10000000)]: 184 ms ± 1.72 ms. That's a factor 2! (Of course this is only relevant as long as looping dominates the timing and not the execution of the function itself.) – Graipher Jul 10 '18 at 11:59