Generating a unique key I am coming from a Ruby background and I am learning Python. This is a method I've created to generate a URL safe unique key:

import random;

def generate_unique_key():
    array = []
    for letter in range(97,123):
        array.append(chr(letter))
    for letter in range(65,91):
        array.append(chr(letter))
    for number in range(0,10):
        array.append(number)
    for char in ["-", ".", "_", "~"]:
        array.append(char)

    random_values = random.sample(array, 15)
    random_values = map(lambda x: str(x), random_values)
    return "".join(random_values)

print(generate_unique_key())


Coming from a Ruby background I was certainly puzzled first at not being able call join directly on my list, but having to call it from a string instance.

Also in Ruby I would have written something similar to random.sample(array, 15).join("") directly without having to convert them all to string, but this I believe this is how join() works.

While this works, how can this function be more Pythonic?
You can pass str to map rather than a lambda.
You can remove the need for map if you change your third loop to append str(number).
You can use string to remove the need for chr and int in the first three loops. By using:


string.ascii_letters:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
string.digits:
0123456789

You can combine all your loops into one string concatenation.
Don't use ; to end lines.
You can define array as a constant outside the function.
I recommend using Python 3, or changing print to be Python 3 compatible.




import random
import string

CHARACTERS = (
    string.ascii_letters
    + string.digits
    + '-._~'
)

def generate_unique_key():
    return ''.join(random.sample(CHARACTERS, 15))

print(generate_unique_key())




You can also use the secrets library (thanks @MathiasEttinger) which is a CSRNG version of random. It also contains the function secrets.token_urlsafe (thanks @Graipher) which generates a random string which is safe for use in URLs. Allowing:

def generate_unique_key(size=15):
    return secrets.token_urlsafe(size)[:size]