11
\$\begingroup\$

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?

asked Jul 9, 2018 at 23:51
\$\endgroup\$
0

3 Answers 3

18
\$\begingroup\$

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)]
answered Jul 10, 2018 at 8:37
\$\endgroup\$
2
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Commented Jul 10, 2018 at 20:20
  • 2
    \$\begingroup\$ 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). \$\endgroup\$ Commented Jul 10, 2018 at 22:54
11
\$\begingroup\$
  1. a much more readable way of specifying that character range:

    random.choice(string.ascii_lowercase)
    
  2. To get a string of n characters:

    ''.join([random.choice(string.ascii_lowercase) for _ in range(n)])
    
answered Jul 10, 2018 at 1:27
\$\endgroup\$
3
\$\begingroup\$

In addition to @l0b0's answer:

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

answered Jul 10, 2018 at 1:44
\$\endgroup\$
3
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Commented Jul 10, 2018 at 9:51
  • \$\begingroup\$ @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). \$\endgroup\$ Commented Jul 10, 2018 at 11:35
  • 1
    \$\begingroup\$ 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.) \$\endgroup\$ Commented Jul 10, 2018 at 11:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.