NumPy Random Introduction

NumPy's random module generates pseudo-random numbers for simulations, sampling, and testing, and a seed lets you make those results perfectly reproducible.

Pseudo-Random Numbers

Computers are deterministic machines, so they cannot produce truly random numbers on their own. Instead, NumPy relies on a pseudo-random number generator (PRNG): an algorithm that starts from an internal state and applies a fixed mathematical formula to spin out a long sequence of numbers that behaves statistically like randomness. Because that sequence comes from a formula rather than true chance, starting from the exact same internal state will always reproduce the exact same sequence of numbers.

Example

import numpy as np

# Five random floats between 0 and 1 (no seed set)
values = np.random.rand(5)
print(values)
# Output is different every time this script runs, e.g.:
# [0.372 0.914 0.055 0.612 0.788]

The numpy.random Module

The numpy.random module sits alongside Python's built-in random module but is built for arrays. A single call can fill an entire array with thousands of values far faster than looping with random.random(), because the work runs in optimized compiled code instead of the Python interpreter. This makes it the standard tool for simulations, shuffling datasets, initializing model weights, and any task that needs bulk randomness rather than one number at a time.

Example

import numpy as np

# Random integers and random floats in bulk
ints = np.random.randint(1, 100, size=6)
floats = np.random.random(size=3)

print("Random integers:", ints)
print("Random floats:", floats)

Seeding for Reproducible Results

A seed is the starting state fed into the PRNG. Calling np.random.seed(value) resets the generator to a known state, so every random function called afterward produces the same sequence on every run of the program. This matters when debugging a simulation, sharing code with a teammate, or writing an automated test that checks output built from random data - without a seed, the test would be different every time it runs.

  • Bug reports become reproducible: a teammate can seed the same value and see the exact failure you saw.
  • Automated tests can assert on exact random output instead of only checking ranges or shapes.
  • Benchmarks and experiments stay fair when every run starts from identical random data.
  • Demos and tutorials print the same numbers for every reader, matching the text around them.
FunctionPurpose
np.random.seed(n)Resets the generator to a known starting state
np.random.rand(size)Uniform floats in the range [0, 1)
np.random.randint(low, high, size)Random integers in the range [low, high)
np.random.choice(a, size)Random samples drawn from an existing array
np.random.shuffle(a)Shuffles an array in place, along its first axis

Example

import numpy as np

# Seeding makes the sequence repeatable
np.random.seed(42)
print(np.random.randint(0, 10, size=5))

np.random.seed(42)
print(np.random.randint(0, 10, size=5))
# Both lines print the exact same array of integers
Note: np.random.seed() changes a single global state shared by the whole program, so calling it in one module can silently affect randomness elsewhere. For larger projects, prefer creating an isolated generator with rng = np.random.default_rng(seed) and calling methods like rng.integers(...) on it directly.

Exercise: NumPy Random Introduction

Why does NumPy call its np.random output "pseudo-random" rather than truly random?