Handling Randomness with Python’s Standard Library: random (Selection, Sampling, Shuffling, Reproducibility)

Series 04 – Generating Random Numbers and Mixing Data

"Pick something at random", "shuffle", "choose a few without duplicates", "assign different probabilities" – these tasks pop up in games, test data creation, simple simulations, and data splitting.

Wizard’s Casino Trick

Python’s random module solves these needs with concise code. Just remember it’s a pseudo‑random number generator (PRNG), not suitable for cryptographic purposes.


1. The Nature of “Randomness” Produced by random

random generates pseudo‑random numbers. Instead of truly unpredictable natural randomness, it creates a sequence that looks random based on an internal state.

  • Starting from the same seed yields identical sequences.
  • This predictability aids debugging and reproducible experiments.
  • It’s unsuitable for security scenarios where an attacker could infer the state (see secrets later).

2. Basic Random Numbers: Drawing Numbers

2.1 Uniform floats in [0, 1): random()

import random

x = random.random()
print(x)  # 0.0 <= x < 1.0

2.2 Integer ranges: randint(a, b) / randrange()

import random

print(random.randint(1, 6))   # 1–6 inclusive
print(random.randrange(0, 10, 2))  # 0,2,4,6,8
  • randint(a, b) includes both ends.
  • randrange(start, stop, step) follows the usual range rules (stop is exclusive).

2.3 Uniform floats in [a, b]: uniform(a, b)

import random

print(random.uniform(1.5, 3.5))

3. Choosing from Collections: Selection, Sampling, Shuffling

3.1 Pick one: choice()

import random

items = ["rock", "paper", "scissors"]
print(random.choice(items))

3.2 Pick many without replacement: sample()

import random

nums = list(range(1, 46))
picked = random.sample(nums, k=6)  # 6 unique numbers
print(picked)
  • sample() does not modify the original list.
  • It guarantees no duplicates.

3.3 Shuffle a list in place: shuffle()

import random

deck = list(range(10))
random.shuffle(deck)
print(deck)
  • shuffle() mutates the list directly.
  • To keep the original, create a shuffled copy with sample():
import random

deck = list(range(10))
shuffled = random.sample(deck, k=len(deck))
print(deck)
print(shuffled)

4. Weighted Choices: choices()

When you need “common, rare, legendary” probabilities, choices() is handy.

import random

items = ["common", "rare", "legendary"]
weights = [85, 14, 1]  # can be raw weights or probabilities

result = random.choices(items, weights=weights, k=10)
print(result)
  • By default, choices() allows duplicates.
  • weights can be raw counts or normalized probabilities.

5. Reproducible Results: seed()

Using the same seed guarantees the same sequence, which is invaluable for tests and demos.

import random

random.seed(42)
print(random.randint(1, 100))
print(random.randint(1, 100))

Even with a mix of functions, the order of calls determines the outcome.

Note: seed() affects the global state. In large projects, consider using a dedicated random.Random() instance.


6. Local RNGs with random.Random()

Avoid touching the global state by creating a separate RNG.

import random

rng = random.Random(42)  # local RNG
print(rng.randint(1, 100))
print(rng.randint(1, 100))

This pattern is especially useful in libraries or modules that need isolated randomness.


7. Cryptographic‑Safe Randomness: Use secrets Instead of random

random is predictable; for tokens, auth codes, or password reset links, use the secrets module.

import secrets

token = secrets.token_urlsafe(16)
print(token)

secrets taps into the operating system’s secure random source.


8. Common Patterns in Practice

8.1 Randomly pick one or more from data

import random

users = ["u1", "u2", "u3", "u4", "u5"]
print(random.choice(users))        # one user
print(random.sample(users, k=2))   # two unique users

8.2 Shuffle data and use the first part

import random

data = list(range(100))
random.shuffle(data)
train = data[:80]
test = data[80:]

8.3 Simple weighted roulette

import random

prizes = ["A", "B", "C", "D"]
weights = [1, 3, 10, 86]  # D appears most often
print(random.choices(prizes, weights=weights, k=1)[0])

9. Wrap‑up

random consolidates the broad concept of “random selection” into a small set of APIs:

  • Pick one: choice
  • Pick without replacement: sample
  • Shuffle: shuffle
  • Weighted pick: choices
  • Reproducibility: seed or random.Random()
  • Secure random: secrets

Next time, we’ll explore numeric‑oriented standard libraries like statistics and math.


Related posts: