- What is random module — generating random numbers and choices
- Random numbers — integers, floats, and ranges
- Random choices — picking from lists, weighted choices
- Shuffling — randomizing order of items
- Seeds — making random results reproducible
- Advanced functions — random distributions, sampling
What is Random Module?
The random module is Python's built-in tool for generating random numbers and making random choices. It's used in games, simulations, data science, security, and many other areas.
Think of the random module like a magic hat. You can pull out random numbers, pick random items from a list, or shuffle things around. But unlike a real magic hat, you can make it give you the same results every time if you want!
💡 Key concept: The random module generates pseudo-random numbers (they look random but are actually determined by a seed).
Generating Random Numbers
Integers, Floats, and Ranges
The random module gives you several ways to generate random numbers.
# Generating Random Numbers
import random
print("=" * 50)
print("GENERATING RANDOM NUMBERS")
print("=" * 50)
# ============================================================
# RANDOM FLOAT (0.0 to 1.0)
# ============================================================
print("\n1. RANDOM FLOAT (0 to 1)")
# random() returns a float between 0.0 and 1.0
for i in range(5):
print(f" random() = {random.random():.4f}")
# ============================================================
# RANDOM INTEGER IN A RANGE
# ============================================================
print("\n2. RANDOM INTEGER IN A RANGE")
# randint(a, b) returns integer between a and b (inclusive)
print(" random.randint(1, 10):")
for i in range(5):
print(f" {random.randint(1, 10)}")
# randrange(start, stop, step) similar to range()
print("\n random.randrange(10, 50, 5):")
for i in range(5):
print(f" {random.randrange(10, 50, 5)}")
# ============================================================
# RANDOM FLOAT IN A RANGE
# ============================================================
print("\n3. RANDOM FLOAT IN A RANGE")
# uniform(a, b) returns a float between a and b
print(" random.uniform(1.5, 5.5):")
for i in range(5):
print(f" {random.uniform(1.5, 5.5):.2f}")
# ============================================================
# RANDOM FROM NORMAL DISTRIBUTION
# ============================================================
print("\n4. RANDOM FROM NORMAL DISTRIBUTION")
# gauss(mu, sigma) returns numbers in a normal distribution
print(" random.gauss(10, 2) (mean=10, std=2):")
for i in range(5):
print(f" {random.gauss(10, 2):.2f}")
# ============================================================
# RANDOM BINARY CHOICE
# ============================================================
print("\n5. RANDOM BINARY CHOICE")
# getrandbits(k) returns random integer with k bits
print(" random.getrandbits(8):")
for i in range(5):
print(f" {random.getrandbits(8)}")
Random numbers key points:
- random() — float between 0 and 1
- randint(a, b) — integer between a and b
- uniform(a, b) — float between a and b
- randrange(start, stop, step) — integer from range
Quick Check: How do you generate a random integer between 1 and 100? (Answer: random.randint(1, 100))
Making Random Choices
Pick Random Items from Lists
The random module makes it easy to pick random items from sequences.
# Making Random Choices
import random
print("=" * 50)
print("MAKING RANDOM CHOICES")
print("=" * 50)
# ============================================================
# SINGLE RANDOM CHOICE
# ============================================================
print("\n1. SINGLE RANDOM CHOICE")
colors = ["red", "blue", "green", "yellow", "purple"]
# Pick one random item
for i in range(5):
print(f" random.choice(colors) = {random.choice(colors)}")
# Pick one random item from a string
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
print(f" random.choice(letters) = {random.choice(letters)}")
# ============================================================
# MULTIPLE RANDOM CHOICES (WITH REPLACEMENT)
# ============================================================
print("\n2. MULTIPLE RANDOM CHOICES (with replacement)")
# Pick 3 items with replacement (same item can appear multiple times)
picks = random.choices(colors, k=3)
print(f" random.choices(colors, k=3) = {picks}")
# Pick with weights
weights = [1, 2, 3, 4, 5] # Higher weight = more likely
picks = random.choices(colors, weights=weights, k=5)
print(f" With weights: {picks}")
# ============================================================
# MULTIPLE RANDOM CHOICES (WITHOUT REPLACEMENT)
# ============================================================
print("\n3. MULTIPLE RANDOM CHOICES (without replacement)")
# Pick 3 items without replacement (each item appears once)
sample = random.sample(colors, 3)
print(f" random.sample(colors, 3) = {sample}")
# Sample from a range
numbers = random.sample(range(1, 101), 10) # 10 random numbers from 1-100
print(f" 10 random numbers from 1-100: {numbers}")
# ============================================================
# WEIGHTED RANDOM CHOICE
# ============================================================
print("\n4. WEIGHTED RANDOM CHOICE")
# Different weights for each item
fruits = ["apple", "banana", "cherry", "date"]
probabilities = [0.4, 0.3, 0.2, 0.1] # Must sum to 1
# Pick 10 items based on probabilities
picks = random.choices(fruits, weights=probabilities, k=10)
print(f" 10 picks with weights: {picks}")
# Count occurrences
from collections import Counter
counts = Counter(picks)
print(f" Counts: {dict(counts)}")
# ============================================================
# RANDOMLY CHOOSE TRUE/FALSE
# ============================================================
print("\n5. RANDOM CHOOSE TRUE/FALSE")
# 50/50 chance
print(f" random.choice([True, False]) = {random.choice([True, False])}")
# Using random.random()
print(f" random.random() < 0.5 = {random.random() < 0.5}")
# With a probability
def prob_true(probability):
return random.random() < probability
print(f" prob_true(0.7) = {prob_true(0.7)}")
Random choices key points:
- choice() — pick one random item
- choices() — pick multiple items with replacement
- sample() — pick multiple items without replacement
- weights — control probability of each item
Quick Check: What's the difference between choices() and sample()? (Answer: choices() allows the same item to be picked multiple times; sample() doesn't)
Shuffling Data
Randomize the Order of Items
shuffle() randomly reorders items in a list. It's great for games, randomizing questions, or any time you need a random order.
# Shuffling Data
import random
print("=" * 50)
print("SHUFFLING DATA")
print("=" * 50)
# ============================================================
# BASIC SHUFFLE
# ============================================================
print("\n1. BASIC SHUFFLE")
# Create a list of numbers
numbers = list(range(10))
print(f" Original: {numbers}")
# Shuffle in place
random.shuffle(numbers)
print(f" Shuffled: {numbers}")
# Shuffle again
random.shuffle(numbers)
print(f" Shuffled again: {numbers}")
# ============================================================
# SHUFFLE A DECK OF CARDS
# ============================================================
print("\n2. SHUFFLE A DECK OF CARDS")
# Create a deck of cards
suits = ["♠", "♥", "♦", "♣"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
deck = [f"{rank}{suit}" for suit in suits for rank in ranks]
print(f" Deck size: {len(deck)}")
# Shuffle the deck
random.shuffle(deck)
print(f" First 5 cards: {deck[:5]}")
# Draw 5 cards
hand = deck[:5]
print(f" Your hand: {hand}")
# ============================================================
# SHUFFLE WITH SEED (Reproducible)
# ============================================================
print("\n3. SHUFFLE WITH SEED")
# Set a seed before shuffling
random.seed(42)
items = list("ABCDE")
random.shuffle(items)
print(f" Shuffle 1: {items}")
# Reset seed - same shuffle!
random.seed(42)
items = list("ABCDE")
random.shuffle(items)
print(f" Shuffle 2: {items}")
# ============================================================
# SHUFFLE A STRING
# ============================================================
print("\n4. SHUFFLE A STRING")
# Convert string to list, shuffle, join back
word = "PYTHON"
word_list = list(word)
random.shuffle(word_list)
shuffled = ''.join(word_list)
print(f" Original: {word}")
print(f" Shuffled: {shuffled}")
# ============================================================
# SHUFFLE MULTIPLE LISTS (same order)
# ============================================================
print("\n5. SHUFFLE MULTIPLE LISTS (same order)")
names = ["Alice", "Bob", "Charlie", "Diana"]
scores = [95, 87, 92, 88]
# Create pairs, shuffle, then separate
pairs = list(zip(names, scores))
random.shuffle(pairs)
names_shuffled, scores_shuffled = zip(*pairs)
print(f" Names shuffled: {list(names_shuffled)}")
print(f" Scores shuffled: {list(scores_shuffled)}")
Shuffle key points:
- shuffle() — randomizes order in place
- Works on lists — only mutable sequences
- Seed affects shuffle — same seed gives same shuffle
- Can shuffle multiple lists — by zipping them together
Quick Check: What function randomly reorders a list? (Answer: random.shuffle())
Using Seeds for Reproducibility
Make Random Results Repeatable
A seed is a number that initializes the random number generator. Using the same seed gives you the same sequence of "random" numbers.
# Using Seeds for Reproducibility
import random
print("=" * 50)
print("USING SEEDS")
print("=" * 50)
# ============================================================
# BASIC SEED
# ============================================================
print("\n1. BASIC SEED")
# Without seed - different each time
print(" Without seed:")
print(f" {random.randint(1, 10)}")
print(f" {random.randint(1, 10)}")
print(f" {random.randint(1, 10)}")
# With seed - same each time
random.seed(42)
print("\n With seed 42:")
print(f" {random.randint(1, 10)}")
print(f" {random.randint(1, 10)}")
print(f" {random.randint(1, 10)}")
# Reset seed - same sequence again
random.seed(42)
print("\n With seed 42 (again):")
print(f" {random.randint(1, 10)}")
print(f" {random.randint(1, 10)}")
print(f" {random.randint(1, 10)}")
# ============================================================
# SEED WITH DIFFERENT VALUES
# ============================================================
print("\n2. SEED WITH DIFFERENT VALUES")
# Different seeds give different sequences
seeds = [1, 2, 3, 42, 100]
for seed in seeds:
random.seed(seed)
values = [random.randint(1, 100) for _ in range(5)]
print(f" Seed {seed}: {values}")
# ============================================================
# SEED WITH STRING
# ============================================================
print("\n3. SEED WITH STRING")
# Seed can be any hashable object
random.seed("hello world")
print(f" Seed 'hello world': {random.randint(1, 10)}")
random.seed("hello world")
print(f" Seed 'hello world' again: {random.randint(1, 10)}")
# ============================================================
# WHEN TO USE SEEDS
# ============================================================
print("\n4. WHEN TO USE SEEDS")
print("""
Use seeds when:
- You want reproducible results (testing, debugging)
- You want the same random values for everyone
- You're doing A/B testing and need consistency
- You're demonstrating something and want it to work the same way
Don't use seeds when:
- You need true randomness (security, games)
- The results should be different each time
- You don't need reproducibility
""")
# ============================================================
# GETTING CURRENT SEED
# ============================================================
print("\n5. GETTING CURRENT SEED")
# There's no built-in way to get the current seed
# But you can save it before generating
seed = 123
random.seed(seed)
print(f" Used seed: {seed}")
print(f" Generated: {random.randint(1, 100)}")
Seeds key points:
- seed() — initializes the random generator
- Same seed — produces the same sequence
- Reproducibility — important for testing and debugging
- Different seeds — produce different sequences
Quick Check: Why would you use a seed? (Answer: To make random results reproducible for testing or debugging)
Advanced Random Functions
Distributions and Special Functions
The random module has functions for different statistical distributions.
# Advanced Random Functions
import random
import math
print("=" * 50)
print("ADVANCED RANDOM FUNCTIONS")
print("=" * 50)
# ============================================================
# NORMAL (GAUSSIAN) DISTRIBUTION
# ============================================================
print("\n1. NORMAL (GAUSSIAN) DISTRIBUTION")
# gauss(mu, sigma) - mean (mu) and standard deviation (sigma)
mu, sigma = 100, 15 # IQ scores typically have mean 100, std 15
print(f" IQ scores (mean={mu}, std={sigma}):")
scores = [random.gauss(mu, sigma) for _ in range(10)]
for i, score in enumerate(scores, 1):
print(f" {i}. {score:.0f}")
# Normal distribution - most values near the mean
print(f" Average: {sum(scores) / len(scores):.0f}")
# ============================================================
# EXPONENTIAL DISTRIBUTION
# ============================================================
print("\n2. EXPONENTIAL DISTRIBUTION")
# expovariate(lambd) - rate parameter (1/mean)
lambd = 0.5 # Rate parameter
print(f" Exponential (lambd={lambd}):")
values = [random.expovariate(lambd) for _ in range(10)]
for i, val in enumerate(values, 1):
print(f" {i}. {val:.2f}")
# ============================================================
# BETA DISTRIBUTION
# ============================================================
print("\n3. BETA DISTRIBUTION")
# betavariate(alpha, beta) - values between 0 and 1
print(f" Beta (alpha=2, beta=5):")
values = [random.betavariate(2, 5) for _ in range(10)]
for i, val in enumerate(values, 1):
print(f" {i}. {val:.3f}")
# ============================================================
# TRIANGULAR DISTRIBUTION
# ============================================================
print("\n4. TRIANGULAR DISTRIBUTION")
# triangular(low, high, mode) - values between low and high, peaking at mode
print(f" Triangular (low=0, high=10, mode=7):")
values = [random.triangular(0, 10, 7) for _ in range(10)]
for i, val in enumerate(values, 1):
print(f" {i}. {val:.2f}")
# ============================================================
# LOGNORMAL DISTRIBUTION
# ============================================================
print("\n5. LOGNORMAL DISTRIBUTION")
# lognormvariate(mu, sigma) - natural log is normally distributed
print(f" Lognormal (mu=1, sigma=0.5):")
values = [random.lognormvariate(1, 0.5) for _ in range(10)]
for i, val in enumerate(values, 1):
print(f" {i}. {val:.2f}")
# ============================================================
# CHOOSING THE RIGHT DISTRIBUTION
# ============================================================
print("\n6. CHOOSING THE RIGHT DISTRIBUTION")
print("""
Distribution types:
- uniform() - All values equally likely
- normal/gauss - Bell curve, most values near mean
- exponential - Values decrease exponentially
- beta - Values between 0 and 1
- triangular - Values between two extremes, with a peak
- lognormal - Values are positively skewed
""")
Advanced functions key points:
- gauss() — normal distribution
- expovariate() — exponential distribution
- betavariate() — beta distribution
- triangular() — triangular distribution
Quick Check: What distribution would you use for a bell-shaped curve? (Answer: Normal/Gaussian distribution with random.gauss())
Real-World Example
Building a Password Generator
# Real-World Example: Password Generator
import random
import string
print("=" * 60)
print("PASSWORD GENERATOR")
print("=" * 60)
# ============================================================
# PASSWORD GENERATOR CLASS
# ============================================================
class PasswordGenerator:
"""Generate random passwords with different strengths"""
def __init__(self, seed=None):
if seed is not None:
random.seed(seed)
self.char_sets = {
"lowercase": string.ascii_lowercase,
"uppercase": string.ascii_uppercase,
"digits": string.digits,
"symbols": "!@#$%^&*()_+-=[]{}|;:,.<>?"
}
def generate(self, length=12, use_uppercase=True, use_digits=True, use_symbols=True):
"""Generate a random password"""
# Build the character pool
pool = self.char_sets["lowercase"]
if use_uppercase:
pool += self.char_sets["uppercase"]
if use_digits:
pool += self.char_sets["digits"]
if use_symbols:
pool += self.char_sets["symbols"]
# Generate password
password = ''.join(random.choice(pool) for _ in range(length))
return password
def generate_secure(self, length=16):
"""Generate a secure password with all character types"""
return self.generate(length, True, True, True)
def generate_pin(self, length=4):
"""Generate a numeric PIN"""
return ''.join(random.choice(string.digits) for _ in range(length))
def generate_memorable(self, words, length=3, separator='-'):
"""Generate a memorable password from words"""
selected = random.sample(words, min(length, len(words)))
return separator.join(selected)
def measure_strength(self, password):
"""Measure password strength (simplified)"""
score = 0
if len(password) >= 8:
score += 1
if len(password) >= 12:
score += 1
if any(c.islower() for c in password):
score += 1
if any(c.isupper() for c in password):
score += 1
if any(c.isdigit() for c in password):
score += 1
if any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in password):
score += 1
strengths = {
0: "Very Weak",
1: "Very Weak",
2: "Weak",
3: "Medium",
4: "Strong",
5: "Very Strong",
6: "Excellent"
}
return strengths.get(score, "Weak")
# ============================================================
# DEMONSTRATION
# ============================================================
print("\n1. GENERATING PASSWORDS")
gen = PasswordGenerator()
# Basic password
p1 = gen.generate()
print(f" Basic password: {p1}")
print(f" Strength: {gen.measure_strength(p1)}")
# Secure password
p2 = gen.generate_secure(16)
print(f" Secure password: {p2}")
print(f" Strength: {gen.measure_strength(p2)}")
# PIN
p3 = gen.generate_pin(6)
print(f" PIN: {p3}")
print(f" Strength: {gen.measure_strength(p3)}")
# Memorable password
words = ["apple", "blue", "crystal", "dragon", "eagle", "flame", "golden", "heart"]
p4 = gen.generate_memorable(words, 3)
print(f" Memorable: {p4}")
print(f" Strength: {gen.measure_strength(p4)}")
print("\n2. GENERATE MULTIPLE PASSWORDS")
for i in range(5):
p = gen.generate(12, True, True, True)
print(f" Password {i+1}: {p}")
print("\n3. CUSTOM PASSWORDS")
# Only letters and digits
p5 = gen.generate(12, use_uppercase=True, use_digits=True, use_symbols=False)
print(f" Letters + Digits: {p5}")
# Only lowercase letters
p6 = gen.generate(10, use_uppercase=False, use_digits=False, use_symbols=False)
print(f" Lowercase only: {p6}")
print("\n4. STRENGTH MEASUREMENT")
passwords = [
"password",
"Pass123!",
"SecurePass123!",
"VeryStrongP@ssw0rd2024!",
"a"
]
print(" Password strength analysis:")
for pwd in passwords:
strength = gen.measure_strength(pwd)
print(f" '{pwd}' -> {strength}")
print("\n5. BULK GENERATION (100 passwords)")
passwords = [gen.generate(14) for _ in range(10)] # Show 10
for i, pwd in enumerate(passwords, 1):
print(f" {i}. {pwd}")
print("\n" + "=" * 60)
print("KEY TAKEAWAYS:")
print("=" * 60)
print("""
- random.choice: Pick random characters
- random.sample: Pick without replacement
- random.shuffle: Randomize order
- random.seed: Reproducible results
- Random module is perfect for password generation
""")
Real-world example key points:
- Password generator — practical application
- choice() — pick random characters
- sample() — pick random words for memorable passwords
- Strength checking — measure password complexity
Quick Check: What function would you use to pick random characters for a password? (Answer: random.choice())
Best Practices
Using Random Module Effectively
# Best Practices for Random Module
import random
import secrets # For security-critical randomness
print("=" * 60)
print("BEST PRACTICES FOR RANDOM MODULE")
print("=" * 60)
# ============================================================
# 1. USE SEEDS FOR REPRODUCIBILITY
# ============================================================
print("\n1. USE SEEDS FOR REPRODUCIBILITY")
# Good - set seed for testing
random.seed(42)
result = random.randint(1, 100)
print(f" Reproducible result: {result}")
# Bad - no seed (results vary)
# result = random.randint(1, 100)
# ============================================================
# 2. USE SECRETS FOR SECURITY
# ============================================================
print("\n2. USE SECRETS FOR SECURITY")
print("""
For security-critical applications (passwords, tokens, encryption):
import secrets
token = secrets.token_hex(16)
password = secrets.choice(string.ascii_letters)
The random module is not secure for cryptography!
""")
# Example with secrets
import string
try:
secure_char = secrets.choice(string.ascii_letters)
print(f" Secure random char: {secure_char}")
except:
print(" secrets module available in Python 3.6+")
# ============================================================
# 3. DON'T USE RANDOM FOR SECURITY
# ============================================================
print("\n3. DON'T USE RANDOM FOR SECURITY")
print("""
Security libraries:
- secrets: For passwords, tokens, security
- os.urandom(): For cryptographic randomness
- random: For games, simulations, testing
Use secrets for:
- Password generation
- Authentication tokens
- Session IDs
- Any security-critical randomness
""")
# ============================================================
# 4. USE CHOICES FOR WEIGHTED SELECTIONS
# ============================================================
print("\n4. USE CHOICES FOR WEIGHTED SELECTIONS")
# Good - explicit weights
items = ['A', 'B', 'C']
weights = [0.2, 0.5, 0.3]
selected = random.choices(items, weights=weights, k=10)
print(f" Weighted choices: {selected}")
# Bad - manual weighted selection
# total = sum(weights)
# r = random.random() * total
# for i, weight in enumerate(weights):
# r -= weight
# if r <= 0:
# selected = items[i]
# break
# ============================================================
# 5. SAVE AND RESTORE STATE
# ============================================================
print("\n5. SAVE AND RESTORE STATE")
state = random.getstate()
print(" State saved")
# Generate some random numbers
values = [random.randint(1, 100) for _ in range(3)]
print(f" Values: {values}")
# Restore state
random.setstate(state)
values2 = [random.randint(1, 100) for _ in range(3)]
print(f" After restore: {values2}")
# ============================================================
# 6. SUMMARY
# ============================================================
print("\n" + "=" * 60)
print("BEST PRACTICES SUMMARY")
print("=" * 60)
print("""
- Use seeds for reproducible results
- Use secrets for security-critical randomness
- Don't use random for passwords or tokens
- Use choices() for weighted selections
- Save state for exact reproduction
- random is for simulation, not security
""")
Best practices summary:
- Use seeds — for reproducibility in testing
- Use secrets — for security-critical randomness
- Don't use random for security — it's not cryptographically secure
- Use choices() for weights — makes weighted selections easy
Quick Check: Should you use the random module for password generation? (Answer: No, use the secrets module for security-critical applications)
Try It Yourself
Experiment with the random module in the editor below.
RANDOM MODULE - PRACTICE
==================================================
1. RANDOM NUMBERS
random(): 0.1234
randint(1, 10): 7
uniform(1.5, 5.5): 3.45
2. RANDOM CHOICES
choice(colors): blue
choices(colors, k=3): ['green', 'red', 'green']
sample(colors, 2): ['yellow', 'blue']
3. SHUFFLE
Shuffled cards: ['C', 'A', 'E', 'B', 'D']
4. SEED
With seed 123: 84
Again with seed 123: 84
5. RANDOM STRING
Random letter: G
Random string: aK4mXp8L
You've Got It!
You now understand the random module in Python. You know how to generate random numbers, make random choices, shuffle data, and use seeds for reproducibility.
Quick Quiz
Test what you've learned:
Frequently Asked Questions
What is the random module in Python?
What's the difference between random and secrets?
How do I make random results repeatable?
random.seed(number) before generating random numbers. The same seed always produces the same sequence of numbers, making your results reproducible.
Can I pick weighted random items?
random.choices(items, weights=weights) where weights is a list of numbers. Higher weights make items more likely to be selected.
How do I shuffle a list in place?
random.shuffle(list). It randomizes the order of items in the list. The list is modified in place and nothing is returned.
What's the fastest way to generate random integers?
random.randint() is efficient for most cases. For very high performance, random.randrange() or random.getrandbits() can be faster.
Where to Go From Here
Now that you understand the random module, check out these related topics:
Math Module
Learn about mathematical functions and constants.
Learn More →Datetime Module
Learn about working with dates and times.
Learn More →Collections Module
Learn about specialized container data types.
Learn More →