Zufallsgenerierung von Zeichenketten mit Großbuchstaben und Ziffern

Ich möchte eine Zeichenkette der Größe N erzeugen.

Sie soll aus Zahlen und englischen Großbuchstaben bestehen, wie z. B.:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Wie kann ich dies auf eine pythonische Weise erreichen?

Lösung

Antwort in einer Zeile:

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

oder noch kürzer ab Python 3.6 mit random.choices():

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

Eine kryptographisch sicherere Version; siehe https://stackoverflow.com/a/23728630/2213647:

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

Im Detail, mit einer sauberen Funktion zur Weiterverwendung:

>>> 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'

Wie funktioniert es?

Wir importieren string, ein Modul, das Sequenzen gängiger ASCII-Zeichen enthält, und random, ein Modul, das sich mit der Zufallsgenerierung beschäftigt.

string.ascii_uppercase + string.digits` verkettet einfach die Liste der Zeichen, die ASCII-Zeichen in Großbuchstaben und Ziffern darstellen:

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

Dann verwenden wir ein Listenverständnis, um eine Liste mit 'n' Elementen zu erstellen:

>>> 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']

Im obigen Beispiel verwenden wir [, um die Liste zu erstellen, aber nicht in der Funktion id_generator, so dass Python die Liste nicht im Speicher erstellt, sondern die Elemente nach und nach generiert (mehr dazu hier).

Anstatt 'n' mal die Zeichenkette elem zu erzeugen, werden wir Python bitten, 'n' mal ein zufälliges Zeichen zu erzeugen, das aus einer Folge von Zeichen ausgewählt wird:

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

Daher erzeugt random.choice(chars) for _ in range(size) wirklich eine Folge von size Zeichen. Zeichen, die zufällig aus Zeichen ausgewählt werden:

>>> [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']

Dann fügen wir sie einfach mit einer leeren Zeichenkette zusammen, damit die Folge zu einer Zeichenkette wird:

>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'
Kommentare (27)

Eine einfachere, schnellere, aber etwas weniger zufällige Methode ist die Verwendung von random.sample, anstatt jeden Buchstaben einzeln auszuwählen. Wenn n-Wiederholungen erlaubt sind, vergrößern Sie Ihre Zufallsbasis um n-mal, z.B.

import random
import string

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

Anmerkung: random.sample verhindert die Wiederverwendung von Zeichen, die Vervielfachung der Größe des Zeichensatzes macht mehrfache Wiederholungen möglich, aber sie sind immer noch weniger wahrscheinlich als bei einer reinen Zufallsauswahl. Wenn wir uns für eine Zeichenkette der Länge 6 entscheiden und "X" als erstes Zeichen wählen, ist die Wahrscheinlichkeit, "X" als zweites Zeichen zu erhalten, genauso groß wie die Wahrscheinlichkeit, "X" als erstes Zeichen zu erhalten. In der random.sample-Implementierung ist die Wahrscheinlichkeit, "X" als ein beliebiges nachfolgendes Zeichen zu erhalten, nur 6/7 der Wahrscheinlichkeit, es als erstes Zeichen zu erhalten

Kommentare (10)

Ich dachte, darauf hätte noch niemand geantwortet, lol! Aber hey, hier ist mein eigener Versuch dazu:

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))], "")
Kommentare (2)