W3docs

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 shuffle mischen
  • Seeding für reproduzierbare Ergebnisse
  • Stetige Verteilungen: uniform, gauss, triangular
  • Wann secrets statt random verwendet werden sollte

Keine Installation notwendig — import random genügt.

Das Modul importieren

import random

Alle 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, shuffle

Zufä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.025010755222666936

Der 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)  # 6

Dies 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))   # 15

Wenn 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..65535

Dies 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 negative

choices vs. sample auf einen Blick:

choicessample
ZurücklegenJaNein
Doppelte ErgebnisseMöglichNie
Verändert OriginalNeinNein
Unterstützt GewichtungJaNein (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']))  # c

random.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.753983033817951

Nü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)  # NbrnTP3fAbnF

Fü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

FunktionBeschreibungRü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 Bitsint
random.choice(seq)Ein zufälliges ElementElementtyp
random.choices(pop, weights, k)k Elemente mit Zurücklegenlist
random.sample(pop, k)k Elemente ohne Zurücklegenlist
random.shuffle(seq)Liste in-place mischenNone
random.seed(a)Zufalls-Seed setzenNone
random.gauss(mu, sigma)Gaußsche (Normalverteilungs-)Zufallsgrößefloat
random.normalvariate(mu, sigma)Normalverteilungs-Zufallsgröße (thread-sicher)float
random.triangular(low, high, mode)Dreiecksverteilungs-Zufallsgrößefloat
random.expovariate(lambd)Exponentialverteilungs-Zufallsgrößefloat

Verwandte Kapitel

Übungen

Übung
Welche Funktion wählt Elemente ohne Zurücklegen aus (jedes Element kann im Ergebnis nur einmal vorkommen)?
Welche Funktion wählt Elemente ohne Zurücklegen aus (jedes Element kann im Ergebnis nur einmal vorkommen)?
Was this page helpful?