Python random-Modul
Python random-Modul: Zufallszahlen erzeugen, gewichtete Auswahl, Sequenzen mischen, Seed für Reproduzierbarkeit und kryptografische Zufälligkeit.
Pythons eingebautes random-Modul erzeugt pseudo-zufällige Zahlen und trifft zufällige Auswahlen. Es basiert auf dem Mersenne-Twister-Algorithmus, der hochwertige pseudo-zufällige Sequenzen erzeugt, die für Simulationen, Spiele, Stichproben und Tests geeignet sind — aber nicht für sicherheitskritische Zwecke wie Passwortgenerierung oder kryptografische Schlüssel. Dieses Kapitel behandelt:
- Zufällige Floats, Integer und Bereiche erzeugen
- Zufällige Elemente auswählen:
choice,choices,sample - Sequenzen in-place mit
shufflemischen - Seeding für reproduzierbare Ergebnisse
- Stetige Verteilungen:
uniform,gauss,triangular - Wann
secretsstattrandomverwendet werden sollte
Keine Installation notwendig — import random genügt.
Das Modul importieren
import randomAlle folgenden Beispiele setzen diesen Import voraus. Einzelne Funktionen können auch direkt importiert werden, um das random.-Präfix zu vermeiden — das Präfix macht jedoch deutlich, woher jede Funktion stammt:
from random import randint, choice, shuffleZufällige Floats erzeugen
random()
random.random() gibt einen Float in [0.0, 1.0) zurück — einschließlich 0.0, aber nie 1.0.
import random
print(random.random()) # e.g. 0.6394267984578837
print(random.random()) # e.g. 0.025010755222666936Der Wert ändert sich bei jedem Aufruf, weil der Generator seinen internen Zustand weiterführt.
uniform(a, b)
random.uniform(a, b) gibt einen Float N zurück, sodass a <= N <= b gilt:
import random
random.seed(42)
print(random.uniform(1.5, 10.5)) # 7.254841186120954
print(random.uniform(-1.0, 1.0)) # e.g. -0.82 (some float in [-1, 1])Im Unterschied zu random() erlaubt uniform die Angabe beider Enden des Bereichs, und die obere Grenze kann zurückgegeben werden.
Zufällige Integer erzeugen
randint(a, b)
random.randint(a, b) gibt einen zufälligen Integer N zurück, sodass a <= N <= b gilt. Beide Endpunkte sind inklusive:
import random
random.seed(42)
die = random.randint(1, 6)
print(die) # 6Dies ist die gängigste Methode, um Würfelwürfe, Kartenziehungen oder beliebige diskrete Integer-Bereiche zu simulieren.
randrange(start, stop[, step])
random.randrange spiegelt Pythons range() wider — stop ist exklusiv und ein Schritt kann angegeben werden:
import random
random.seed(42)
# Pick an even number from 0 to 98 (0, 2, 4, ..., 98)
print(random.randrange(0, 100, 2)) # e.g. a random even integer
# Pick a multiple of 5 from 0 to 95
random.seed(42)
print(random.randrange(0, 100, 5)) # 15Wenn zufällige Integer aus einem Bereich benötigt werden, der nicht bei 0 beginnt oder einen Schritt erfordert, ist randrange ausdrucksstärker als randint.
getrandbits(k)
random.getrandbits(k) gibt einen zufälligen nicht-negativen Integer mit genau k zufälligen Bits zurück:
import random
random.seed(42)
print(random.getrandbits(8)) # 163 (an integer in 0..255)
print(random.getrandbits(16)) # an integer in 0..65535Dies ist nützlich, wenn zufällige Integer benötigt werden, die größer sind als das, womit randint aufgerufen wird, oder wenn auf Bit-Ebene gearbeitet wird.
Aus Sequenzen auswählen
choice(seq)
random.choice(seq) wählt zufällig ein Element aus einer nicht-leeren Sequenz aus. Es funktioniert mit Listen, Tupeln und Strings:
import random
random.seed(42)
fruits = ['apple', 'banana', 'cherry']
print(random.choice(fruits)) # cherry
random.seed(42)
print(random.choice('ABCDE')) # A (picks one character)Wenn die Sequenz leer ist, wird ein IndexError ausgelöst.
choices(population, weights=None, k=1)
random.choices wählt k Elemente mit Zurücklegen aus (dasselbe Element kann mehrfach vorkommen). Die Auswahl kann mit weights gewichtet werden:
import random
colors = ['red', 'blue', 'green']
# Equal probability — each run may differ
print(random.choices(colors, k=3))
# e.g. ['blue', 'red', 'red']
# Weighted: green is 3× more likely than red, blue is 2×
random.seed(42)
print(random.choices(colors, weights=[1, 2, 3], k=4))
# ['green', 'red', 'blue', 'blue']choices gibt immer eine Liste zurück, auch wenn k=1. Das Argument weights ist relativ — [1, 2, 3] ergibt dieselbe Verteilung wie [10, 20, 30].
sample(population, k)
random.sample wählt k Elemente ohne Zurücklegen aus — jedes Element kann im Ergebnis nur einmal erscheinen. Die ursprüngliche Sequenz wird nicht verändert:
import random
random.seed(42)
# Pick 4 unique numbers from 0-9
print(random.sample(range(10), 4)) # [1, 0, 4, 9]
# Simulate a lottery: 6 unique numbers from 1-49
random.seed(7)
ticket = sorted(random.sample(range(1, 50), 6))
print(ticket) # [4, 5, 10, 21, 26, 42]Wenn k größer als die Populationsgröße ist, wirft random.sample einen ValueError:
import random
try:
random.sample([1, 2, 3], 5)
except ValueError as e:
print(e) # Sample larger than population or is negativechoices vs. sample auf einen Blick:
choices | sample | |
|---|---|---|
| Zurücklegen | Ja | Nein |
| Doppelte Ergebnisse | Möglich | Nie |
| Verändert Original | Nein | Nein |
| Unterstützt Gewichtung | Ja | Nein (verwende choices) |
Sequenzen mischen
random.shuffle(seq) mischt die Liste in-place und gibt None zurück. Die ursprüngliche Liste wird verändert:
import random
random.seed(42)
deck = [1, 2, 3, 4, 5]
random.shuffle(deck)
print(deck) # [4, 2, 3, 5, 1] (original list is modified)Wenn eine gemischte Kopie ohne Veränderung des Originals benötigt wird, kann random.sample verwendet werden:
import random
random.seed(42)
original = [1, 2, 3, 4, 5]
shuffled = random.sample(original, len(original))
print(original) # [1, 2, 3, 4, 5] (unchanged)
print(shuffled) # [4, 2, 3, 5, 1]Seeding für reproduzierbare Ergebnisse
Standardmäßig initialisiert sich das random-Modul mit der Systemzeit (oder os.urandom()), sodass jeder Lauf unterschiedliche Werte erzeugt. Durch Aufruf von random.seed() mit einem festen Wert wird die Sequenz gesperrt, sodass bei jedem Lauf identische Ausgaben entstehen — unverzichtbar für Debugging, Unit-Tests und reproduzierbare Simulationen:
import random
random.seed(42)
print(random.random()) # 0.6394267984578837
print(random.randint(1, 10)) # 1
print(random.choice(['a', 'b', 'c'])) # c
# Reset to the same seed — identical sequence
random.seed(42)
print(random.random()) # 0.6394267984578837 (same as before)
print(random.randint(1, 10)) # 1
print(random.choice(['a', 'b', 'c'])) # crandom.seed() akzeptiert einen Integer, einen string, einen Float, bytes oder None (womit der Seed erneut vom System gesetzt wird). Seeding ist eine globale Operation — es wirkt sich auf alle nachfolgenden Aufrufe im selben Programm aus. Daher sollte der Seed einmalig am Anfang eines reproduzierbaren Blocks gesetzt werden.
Reproduzierbare Testdaten erzeugen
import random
random.seed(999)
test_scores = [round(random.uniform(0, 100), 2) for _ in range(5)]
print(test_scores) # [78.13, 8.01, 87.25, 57.38, 49.06]Jeder Lauf mit seed(999) erzeugt exakt dieselbe Liste, was dies für Unit-Tests nützlich macht, die bestimmte Werte prüfen.
Stetige Verteilungen
Das random-Modul enthält mehrere stetige Wahrscheinlichkeitsverteilungen, die in Simulationen und statistischen Modellierungen nützlich sind.
uniform(a, b)
Bereits oben behandelt — eine gleichmäßige Verteilung, bei der jeder Wert in [a, b] gleich wahrscheinlich ist.
triangular(low, high, mode)
Gibt einen Float aus einer Dreiecksverteilung zurück, bei der mode der häufigste Wert ist:
import random
random.seed(42)
# Most values cluster near 5, between 0 and 10
t = random.triangular(0, 10, 5)
print(t) # 5.753983033817951Nützlich, wenn der Minimal-, Maximal- und wahrscheinlichste Wert bekannt sind, aber nicht die genaue Verteilung — häufig in der Projektschätzung und Risikomodellierung eingesetzt.
gauss(mu, sigma)
Gibt einen Float aus einer Gaußschen (Normalverteilungs-)Verteilung mit Mittelwert mu und Standardabweichung sigma zurück:
import random
random.seed(42)
# Heights in cm: mean 170, std 10
heights = [round(random.gauss(170, 10), 1) for _ in range(5)]
print(heights) # [168.6, 168.3, 168.9, 177.0, 168.7]random.normalvariate(mu, sigma) ist äquivalent, aber thread-sicher; in Multithread-Programmen sollte normalvariate verwendet werden.
expovariate(lambd)
Gibt einen Float aus einer Exponentialverteilung zurück, wobei lambd gleich 1 / Mittelwert ist. Nützlich zur Modellierung von Zeitintervallen zwischen Ereignissen (z. B. Kundenankunft, Netzwerkpakete):
import random
random.seed(42)
# Mean inter-arrival time = 5 minutes; lambd = 1/5
wait = random.expovariate(1 / 5)
print(round(wait, 2)) # 5.1 (minutes until next arrival)Praktische Beispiele
60 Würfelwürfe simulieren
import random
random.seed(42)
counts = {face: 0 for face in range(1, 7)}
for _ in range(60):
counts[random.randint(1, 6)] += 1
print(counts)
# {1: 15, 2: 10, 3: 8, 4: 7, 5: 10, 6: 10}Mit mehr Würfen nähert sich die Verteilung der theoretischen Wahrscheinlichkeit von 1/6 für jede Seite an.
Ein zufälliges Team auswählen
import random
random.seed(42)
players = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank']
random.shuffle(players)
team_a = players[:3]
team_b = players[3:]
print('Team A:', team_a)
print('Team B:', team_b)Einfaches zufälliges Passwort
Für nicht-sicherheitskritische Kontexte (Demos, Wegwerftoken) eignet sich random.choices gut:
import random
import string
random.seed(42)
chars = string.ascii_letters + string.digits
password = ''.join(random.choices(chars, k=12))
print(password) # NbrnTP3fAbnFFür echte Benutzerpasswörter oder Token sollte stattdessen das secrets-Modul verwendet werden (siehe unten).
Wann secrets statt random verwendet werden sollte
Das random-Modul ist nicht kryptografisch sicher. Ein Angreifer, der genügend Ausgaben beobachtet, kann zukünftige Werte vorhersagen. Für alles Sicherheitskritische sollte das secrets-Modul (Python 3.6+) verwendet werden, das auf die kryptografische Zufallsquelle des Betriebssystems zurückgreift:
import secrets
# Cryptographically secure random integer in [0, 100)
print(secrets.randbelow(100))
# Secure random token for a password-reset link (URL-safe base64)
token = secrets.token_urlsafe(32)
print(token) # e.g. 'gIg9XzExxFkHLAH9JCK8Zxb1aBEFZ...'
# Secure random hex string for an API key
api_key = secrets.token_hex(16)
print(api_key) # e.g. 'a3f1c2d4e5b6...'Faustregel: Wenn Token, Sitzungs-IDs, Passwörter oder Werte generiert werden, die ein Angreifer nicht erraten darf, sollte secrets verwendet werden. random eignet sich für alles andere (Spiele, Simulationen, Test-Fixtures, Stichproben).
Kurzreferenz
| Funktion | Beschreibung | Rückgabetyp |
|---|---|---|
random.random() | Float in [0.0, 1.0) | float |
random.uniform(a, b) | Float in [a, b] | float |
random.randint(a, b) | Integer in [a, b] (beide inklusive) | int |
random.randrange(start, stop[, step]) | Integer aus range(start, stop, step) | int |
random.getrandbits(k) | Nicht-negativer Integer mit k zufälligen Bits | int |
random.choice(seq) | Ein zufälliges Element | Elementtyp |
random.choices(pop, weights, k) | k Elemente mit Zurücklegen | list |
random.sample(pop, k) | k Elemente ohne Zurücklegen | list |
random.shuffle(seq) | Liste in-place mischen | None |
random.seed(a) | Zufalls-Seed setzen | None |
random.gauss(mu, sigma) | Gaußsche (Normalverteilungs-)Zufallsgröße | float |
random.normalvariate(mu, sigma) | Normalverteilungs-Zufallsgröße (thread-sicher) | float |
random.triangular(low, high, mode) | Dreiecksverteilungs-Zufallsgröße | float |
random.expovariate(lambd) | Exponentialverteilungs-Zufallsgröße | float |
Verwandte Kapitel
- Python Math — mathematische Funktionen und Konstanten
- Python Modules — Module importieren und organisieren
- Python Numbers — Integer-, Float- und Komplextypen
- Python Lists — mit geordneten Sequenzen arbeiten
- Python For Loops — Iteration zur Erzeugung zufälliger Daten
- Python Try Except — Fehler wie
ValueErrorvonsamplebehandeln