The random module is one of Python's most versatile standard libraries. Whether you need to generate random numbers, pick items from a list, shuffle data, or create simulations, random has you covered. This complete guide takes you from the basics to advanced techniques with practical examples.
Generating random data is essential across many fields: game development, software testing, scientific simulations, statistical sampling, machine learning, and beyond. Python makes this work simple and intuitive with its built-in random module.
If you are just getting started, check out our beginner's guide to Python before diving into this article.
Why Use the Random Module?
The random module implements pseudo-random number generators for various distributions. Although the numbers appear random, they are produced by a deterministic algorithm. For applications that require cryptographic randomness, Python offers the secrets module.
Key use cases include:
- Games: generating positions, attributes, loot boxes, and unpredictable behaviors
- Testing: creating varied and representative test data
- Simulations: modeling random phenomena like queues, traffic, and finance
- Sampling: selecting representative subsets from populations
- Machine Learning: shuffling data, initializing weights, and creating train/test splits
Another useful function is random.getrandbits(k), which returns an integer with k random bits. This function is efficient for generating large numbers without manually specifying ranges.
import random
8-bit number (0 to 255)
print(random.getrandbits(8)) # Example: 187
16-bit number (0 to 65535)
print(random.getrandbits(16)) # Example: 42351
With random, you can simulate complex scenarios in just a few lines of code. Let's explore the main features in practice.
Core Functions of the Random Module
The module offers dozens of functions. The official Python documentation is the complete reference, but we will focus on the most commonly used ones. All functions share the same underlying generator, so you can freely mix calls to different functions without any issues.
random.random() — Random Float Number
The most basic function: returns a random float in the range [0.0, 1.0).
import random
print(random.random()) # Example: 0.3746325874916233
print(random.random()) # Example: 0.8921567432810459
Useful for generating probabilities, percentages, or normalizing data.
random.randint() — Random Integer
Returns a random integer between A and B (inclusive):
import random
dice = random.randint(1, 6)
print(f'You rolled a {dice}')
lottery = random.randint(1, 60)
print(f'Lottery number: {lottery}')
This is probably the most popular function in the module. Use randint whenever you need an integer within a range.
random.randrange() — Integer with Step
Similar to randint, but accepts an optional step parameter, just like the range() function:
import random
Random even number between 0 and 20
even = random.randrange(0, 21, 2)
print(f'Even number: {even}')
Multiple of 5 between 0 and 50
mult5 = random.randrange(0, 51, 5)
print(f'Multiple of 5: {mult5}')
This function is useful when you need numbers that follow a specific pattern, such as generating even indices or arithmetic progression values.
random.uniform() — Float in a Custom Range
Similar to random(), but lets you set your own bounds:
import random
temperature = random.uniform(36.0, 40.0)
print(f'Simulated temperature: {temperature:.1f}°C')
price = random.uniform(10.50, 99.90)
print(f'Random price: ${price:.2f}')
random.choice() — Pick a Random Item
Selects one random element from a sequence (list, tuple, string):
import random
fruits = ['apple', 'banana', 'orange', 'grape', 'strawberry']
print(random.choice(fruits)) # Example: 'orange'
With strings
letter = random.choice('ABCDEFGH')
print(letter) # Example: 'C'
random.choice() is widely used in raffles, games, and A/B testing.
To better understand how lists work in Python, check out our complete guide to list manipulation.
random.choices() — Multiple Items with Replacement
Selects K items from a population, allowing repeats. Supports weights to define probabilities:
import random
colors = ['red', 'blue', 'green']
weights = [0.5, 0.3, 0.2] # 50% red, 30% blue, 20% green
result = random.choices(colors, weights=weights, k=10)
print(result)
Example: ['red', 'blue', 'red', 'green', 'blue', ...]
This function is fantastic for simulating custom probability distributions.
random.sample() — Sample Without Replacement
Selects K unique items from a population, no repeats:
import random
students = ['Alice', 'Bob', 'Carol', 'Daniel', 'Emma', 'Frank']
selected = random.sample(students, 3)
print(f'Selected: {selected}')
Lottery numbers
lottery = random.sample(range(1, 61), 6)
print(f'Lottery: {sorted(lottery)}')
Use sample when each item can be chosen only once, such as raffles, data splits for machine learning, and cross-validation.
random.shuffle() — Shuffle a List
Shuffles the elements of a list in-place (modifies the original list):
import random
cards = ['A♠', 'K♠', 'Q♠', 'J♠', '10♠', '9♠', '8♠']
random.shuffle(cards)
print(cards) # Example: ['Q♠', 'A♠', '10♠', 'K♠', '9♠', 'J♠', '8♠']
For training data
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
random.shuffle(data)
train, test = data[:7], data[7:]
print(f'Train: {train}')
print(f'Test: {test}')
Shuffling data is a critical preprocessing step in machine learning to avoid order bias.
Working with Seeds
Pseudo-random numbers are generated from a seed value. If you set the same seed, you get the exact same sequence. This is essential for reproducibility in scientific experiments and machine learning.
import random
random.seed(42)
print(random.randint(1, 100)) # Always 82
print(random.random()) # Always 0.639426798...
random.seed(42) # Resetting the seed
print(random.randint(1, 100)) # 82 again
According to Real Python, using seeds is one of the best practices in data science, as it guarantees your experiments can be reproduced by other researchers.
Pro Tip: Capturing Generator State
By default, Python seeds the generator from os.urandom(), which draws from truly random OS sources. You can capture the current state with random.getstate() and restore it later. This is especially useful for debugging — you can save the state before a sequence of operations, test repeatedly, and always return to the same starting point.
import random
state = random.getstate()
Generate as many numbers as needed...
random.setstate(state) # Back to the previous state
Statistical Distributions
The random module provides functions for various statistical distributions, which are fundamental for scientific simulations:
Uniform Distribution
import random
Uniformly distributed values between 0 and 10
for _ in range(5):
print(random.uniform(0, 10))
Normal (Gaussian) Distribution
import random
Mean 0, standard deviation 1
for _ in range(5):
print(random.gauss(0, 1))
Simulated population height
height = random.gauss(170, 10) # Mean 170cm, SD 10cm
print(f'Simulated height: {height:.1f} cm')
Triangular Distribution
The triangular distribution is useful when you know the minimum, maximum, and most likely (mode) value of a phenomenon:
import random
Simulate task completion time (optimistic: 2h, likely: 4h, pessimistic: 8h)
estimated_time = random.triangular(2, 8, 4)
print(f'Estimated time: {estimated_time:.1f} hours')
Popular in project management simulations (PERT)
duration = random.triangular(10, 30, 15)
print(f'Simulated duration: {duration:.1f} days')
This distribution is widely used in engineering simulations and project management when historical data is limited.
Exponential Distribution
import random
Simulate inter-arrival times in a queue
lambda_param = 2.0 # 2 arrivals per minute
time = random.expovariate(lambda_param)
print(f'Time until next arrival: {time:.2f} minutes')
For more robust distribution handling, NumPy offers optimized functions. Check out the numpy.random module for high-performance scientific applications. If you want to dive deeper into NumPy, see our complete NumPy guide.
Real-World Use Cases
1. Dice Roll Simulator
import random
def roll_dice(sides=6):
return random.randint(1, sides)
Simulate 1000 rolls
results = [rolldice() for in range(1000)]
frequencies = {i: results.count(i) for i in range(1, 7)}
print(frequencies)
2. Random Password Generator
import random
import string
def generate_password(length=12):
chars = string.asciiletters + string.digits + '!@#$%&*'
return ''.join(random.choice(chars) for in range(length))
print(generate_password()) # Example: 'aK7$mP9@xL2#'
For secure passwords, prefer the secrets module, which uses cryptographically secure sources.
3. Monte Carlo Simulation
One of the most powerful applications: estimating Pi using the Monte Carlo method:
import random
def estimatepi(points=100000):
inside = 0
for in range(points):
x, y = random.random(), random.random()
if xx + yy <= 1:
inside += 1
return 4 * inside / points
print(f'Estimated Pi: {estimate_pi()}') # ~3.1415
4. Train-Test Split for Machine Learning
import random
data = list(range(100))
random.shuffle(data)
split = int(0.8 * len(data))
train = data[:split]
test = data[split:]
print(f'Train: {len(train)} samples')
print(f'Test: {len(test)} samples')
Random vs NumPy Random vs Secrets
Python offers three main approaches to randomness:
| Module | When to Use | Performance |
|---|---|---|
random |
General purpose, games, simple scripts | Good |
numpy.random |
Large data volumes, multidimensional arrays | Excellent (vectorized) |
secrets |
Passwords, tokens, cryptography | Moderate |
The NumPy random is significantly faster for large datasets because it generates entire arrays at once using optimized C code. The secrets module is mandatory when security is critical.
Best Practices
- Always use a seed for reproducibility in experiments and scientific tests.
- Do not use random for cryptography — use the
secretsmodule instead. - Document your seeds so other researchers can replicate your results.
- Prefer numpy.random for large data volumes.
- Be careful with shuffle on large lists — it modifies the list in-place. If you need to preserve the original, make a copy with
copy = original.copy()before shuffling. - Test your generators: always verify that generated values fall within expected ranges, especially in critical applications like financial or medical simulations.
Performance and Limitations
The random module uses the Mersenne Twister algorithm (MT19937), which is fast and passes most statistical randomness tests. However, it is not suitable for:
- Cryptography (use
secrets) - Simulations requiring enormous quantities of random numbers (prefer NumPy)
- Applications sensitive to long-period patterns
The Mersenne Twister period is 2^19937 − 1, which is more than enough for virtually any non-cryptographic application. In practical terms, this means you can generate trillions of numbers before the cycle repeats. For applications that demand even more performance, NumPy implements the same algorithm in C with vectorization, achieving up to 50x faster throughput for large volumes. To learn more about the algorithm, the GeeksforGeeks article has an excellent technical deep dive.
Conclusion
Python's random module is a powerful and versatile tool every developer should master. From simple dice rolls to complex Monte Carlo simulations, it provides the essential functionality to work with randomness productively and reliably.
Quick reference of the most important functions:
random()— float in [0, 1)randint(a, b)— integer between a and bchoice(seq)— one random itemsample(pop, k)— sample without replacementshuffle(list)— shuffle in-placeseed(n)— set seed for reproducibility
Be sure to consult the official documentation to explore all available functions. Practice with the examples in this article and soon you will use the random module confidently in your projects.
To continue learning, also check out the interactive tutorial on PYnative and the W3Schools random examples.