Δημιουργία τυχαίας συμβολοσειράς με κεφαλαία γράμματα και ψηφία

Θέλω να δημιουργήσω μια συμβολοσειρά μεγέθους N.

Θα πρέπει να αποτελείται από αριθμούς και κεφαλαία αγγλικά γράμματα όπως:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Πώς μπορώ να το επιτύχω αυτό με πυθωνικό τρόπο;

Λύση

Απάντηση σε μία γραμμή:

''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))

ή ακόμα συντομότερα ξεκινώντας από την Python 3.6 χρησιμοποιώντας `random.choices():

''.join(random.choices(string.ascii_uppercase + string.digits, k=N))

Μια κρυπτογραφικά ασφαλέστερη έκδοση- δείτε https://stackoverflow.com/a/23728630/2213647:

''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))

Σε λεπτομέρειες, με μια καθαρή συνάρτηση για περαιτέρω επαναχρησιμοποίηση:

>>> import string
>>> import random
>>> def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
...    return ''.join(random.choice(chars) for _ in range(size))
...
>>> id_generator()
'G5G74W'
>>> id_generator(3, "6793YUIO")
'Y3U'

Πώς δουλεύει;

Εισάγουμε το string, μια ενότητα που περιέχει ακολουθίες κοινών χαρακτήρων ASCII, και το random, μια ενότητα που ασχολείται με την τυχαία παραγωγή.

Το string.ascii_uppercase + string.digits απλώς συνδέει τη λίστα χαρακτήρων που αντιπροσωπεύουν κεφαλαία ASCII και ψηφία:

>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_uppercase + string.digits
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

Στη συνέχεια χρησιμοποιούμε μια κατανόηση λίστας για να δημιουργήσουμε μια λίστα με 'n' στοιχεία:

>>> range(4) # range create a list of 'n' numbers
[0, 1, 2, 3]
>>> ['elem' for _ in range(4)] # we use range to create 4 times 'elem'
['elem', 'elem', 'elem', 'elem']

Στο παραπάνω παράδειγμα, χρησιμοποιούμε το [ για να δημιουργήσουμε τη λίστα, αλλά δεν το κάνουμε στη συνάρτηση id_generator, έτσι ώστε η Python να μην δημιουργεί τη λίστα στη μνήμη, αλλά να δημιουργεί τα στοιχεία εν κινήσει, ένα προς ένα (περισσότερα γι' αυτό εδώ).

Αντί να ζητάμε να δημιουργήσει 'n' φορές το αλφαριθμητικό elem, θα ζητήσουμε από την Python να δημιουργήσει 'n' φορές έναν τυχαίο χαρακτήρα, επιλεγμένο από μια ακολουθία χαρακτήρων:

>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'

Επομένως, η random.choice(chars) for _ in range(size) στην πραγματικότητα δημιουργεί μια ακολουθία χαρακτήρων του μεγέθους. Χαρακτήρες που επιλέγονται τυχαία από το chars:

>>> [random.choice('abcde') for _ in range(3)]
['a', 'b', 'b']
>>> [random.choice('abcde') for _ in range(3)]
['e', 'b', 'e']
>>> [random.choice('abcde') for _ in range(3)]
['d', 'a', 'c']

Στη συνέχεια, απλά τους ενώνουμε με ένα κενό αλφαριθμητικό ώστε η ακολουθία να γίνει ένα αλφαριθμητικό:

>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'
Σχόλια (27)

Ένας απλούστερος, ταχύτερος αλλά ελαφρώς λιγότερο τυχαίος τρόπος είναι να χρησιμοποιήσετε το random.sample αντί να επιλέγετε κάθε γράμμα ξεχωριστά, Αν επιτρέπονται n-επαναλήψεις, διευρύνετε την τυχαία βάση σας κατά n φορές, π.χ.

import random
import string

char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))

Σημείωση: Το random.sample αποτρέπει την επαναχρησιμοποίηση χαρακτήρων, ο πολλαπλασιασμός του μεγέθους της βάσης χαρακτήρων καθιστά δυνατές τις πολλαπλές επαναλήψεις, αλλά εξακολουθούν να είναι λιγότερο πιθανές από ό,τι σε μια καθαρά τυχαία επιλογή. Αν πάμε για μια συμβολοσειρά μήκους 6 και επιλέξουμε το 'X' ως πρώτο χαρακτήρα, στο παράδειγμα επιλογής, οι πιθανότητες να πάρουμε το 'X' για τον δεύτερο χαρακτήρα είναι ίδιες με τις πιθανότητες να πάρουμε το 'X' ως πρώτο χαρακτήρα. Στην εφαρμογή random.sample, οι πιθανότητες να λάβουμε το 'X' ως οποιονδήποτε επόμενο χαρακτήρα είναι μόνο 6/7 της πιθανότητας να το λάβουμε ως πρώτο χαρακτήρα.

Σχόλια (10)

Νόμιζα ότι κανένας δεν είχε απαντήσει σε αυτό ακόμα lol! Αλλά εδώ είναι η δική μου προσπάθεια:

import random

def random_alphanumeric(limit):
    #ascii alphabet of all alphanumerals
    r = (range(48, 58) + range(65, 91) + range(97, 123))
    random.shuffle(r)
    return reduce(lambda i, s: i + chr(s), r[:random.randint(0, len(r))], "")
Σχόλια (2)