Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Random Numbers with Random

Learn to generate random numbers in Python using the random module. Covers randint, uniform, random, choice, and sample with practical examples, troubleshooting, and what to study next.

Focus: generate random numbers with the random module

Sponsored

Randomness is a fundamental need in programming, from seeding test data to powering game mechanics. The Python random module supplies a suite of functions to generate deterministic pseudorandom numbers, enabling you to simulate chance, shuffle collections, and create realistic data. Without these tools, you'd be forced to rely on external APIs or hard-coded sequences, both of which are slow and inflexible for everyday coding.

The problem this lesson solves

When you need non-deterministic behavior in a Python program—rolling dice, picking a random user, or generating a unique ID—Python's random module provides the answer. Without it, you're stuck writing brittle code that always produces the same output. The module gives you a single, standard library to produce reproducible random numbers, which is essential for testing, gaming, and data science.

Core concept / mental model

Think of the random module as a digital dice factory. Each call to a function like randint() or uniform() rolls an invisible pair of dice that produce a number within a range you define. The module uses a pseudorandom number generator called the Mersenne Twister, which means the sequence of numbers is deterministic given a starting seed. This is crucial because for debugging and testing, you can set the seed to get the same "random" sequence every time.

Key functions at a glance

Function Purpose Example
random() Float in [0.0, 1.0) random.random() → 0.374...
randint(a,b) Random integer between a and b (inclusive both ends) random.randint(1,6) → 4
uniform(a,b) Random float between a and b random.uniform(0.0, 1.0) → 0.765...
choice(seq) Pick a random element from a sequence random.choice(['a','b','c']) → 'b'
sample(seq,k) Pick k unique elements from a population random.sample(range(10),3) → [2,7,4]

Pro Tip: The random() function is the foundation for all others. randint(a,b) is implemented as a + int(random() * (b - a + 1)). Understanding this helps you debug edge cases.

How it works step by step

Let's build random numbers piece by piece.

Step 1: Import the module

import random

This loads all the functions you'll need.

Step 2: Generate a simple random float

default_random = random.random()
print(default_random)  # 0.748237... (changes each run)

Step 3: Set the seed for reproducibility

random.seed(42)  # Set once at the top of your script
print(random.random())  # 0.640... (always the same)

The seed initializes the internal state. Use the same seed for testing and a different one for production.

Step 4: Generate integers in a range

dice = random.randint(1, 6)        # Inclusive both ends: 1,2,3,4,5,6
lottery = random.randrange(1, 50, 5)  # 1,6,11,16,21,26,31,36,41,46

randrange is like range() but returns a random number from that sequence.

Step 5: Work with sequences

fruits = ['apple', 'banana', 'cherry', 'date']
pick = random.choice(fruits)
print(pick)  # 'banana'

# Pick 2 unique fruits
subset = random.sample(fruits, 2)
print(subset)  # ['date', 'apple']

Multiple Calls: Each call to random() advances the internal state. If you need multiple related numbers, call the function multiple times—not once and reuse the same value.

Hands-on walkthrough

Now you'll build a simulated dice game for two players.

Basic dice sim

import random

def roll_dice():
    return random.randint(1, 6)

player1 = roll_dice()
player2 = roll_dice()
print(f"Player 1: {player1}, Player 2: {player2}")
if player1 > player2:
    print("Player 1 wins!")
elif player2 > player1:
    print("Player 2 wins!")
else:
    print("It's a tie!")

Expected output (varies):

Player 1: 4, Player 2: 6
Player 2 wins!

Adding randomness to sequences

students = ["Alice", "Bob", "Charlie", "Diana"]
random.shuffle(students)  # Modifies the list in place!
print("After shuffle:", students)

# Randomly select a subset of winners
winners = random.sample(students, 2)
print("Winners:", winners)

Expected output (example):

After shuffle: ['Diana', 'Charlie', 'Alice', 'Bob']
Winners: ['Alice', 'Charlie']

Generating a random password

import random
import string

def random_password(length=12):
    chars = string.ascii_letters + string.digits
    return ''.join(random.choice(chars) for _ in range(length))

print(random_password())
print(random_password(8))

Expected output (varies):

aB3kLx9QmN5r
TsPj1Fc7

Reproducible random data for testing

random.seed(99)
print("Seed 99:", [random.randint(1, 100) for _ in range(3)])
random.seed(99)
print("Seed 99 again:", [random.randint(1, 100) for _ in range(3)])

Expected output (always the same):

Seed 99: [39, 84, 22]
Seed 99 again: [39, 84, 22]

Remember: After calling random.seed(), all subsequent random function calls use that seeded state until you call seed() again.

Compare options / when to choose what

Function Return type Range Use case
random() Float [0.0, 1.0) Base for all others; rarely used directly
randint(a,b) Integer a ≤ x ≤ b Dice, lottery numbers, indices for lists
uniform(a,b) Float a ≤ x ≤ b Continuous values like percentages, coordinates
choice(seq) Element Any sequence Single random pick from list/tuple
sample(seq,k) List Without replacement Subset selection, random survey
shuffle(seq) Mutates list In-place reorder Card shuffling, random ordering

When to use each: - randint(): When you need a whole number in a specific interval. Most common for games. - uniform(): For continuous random values (e.g., random delays, dimensions). - sample(): When you need distinct elements without repetition (e.g., picking winners). - shuffle(): When you want to randomly reorder a list (note: it modifies the original). - choice(): For a single random pick, especially from a large population.

Troubleshooting & edge cases

1. Empty sequence with choice() or sample()

random.choice([])  # IndexError: Cannot choose from an empty sequence
random.sample([], 2)  # ValueError: Sample larger than population or is negative

Fix: Always check the sequence is non-empty before calling.

2. Sample larger than population

random.sample([1,2,3], 5)  # ValueError: Sample larger than population

Fix: Use random.choices() (with replacement) instead, or reduce k.

3. Forgetting that shuffle() modifies the list

numbers = [1,2,3]
saved = numbers
random.shuffle(numbers)
print(saved)  # [3,1,2] — both variables point to the same list!

Fix: Make a copy first: copy_list = numbers[:]

4. Inconsistent seeds across calls

random.seed(5)
a = random.random()
b = random.random()  # This is the second number from seed 5, not the same as a

Fix: If you need the same sequence, call seed() once before both calls.

5. Using random() for security-sensitive operations

random is not cryptographically secure. For passwords, tokens, or anything security-related, use secrets module instead.

What you learned & what's next

You now know how to generate random numbers with the random module: - Understanding the Mersenne Twister pseudorandom generator - Using random(), randint(), uniform(), choice(), sample(), and shuffle() - Setting seeds for reproducibility in testing - Handling common edge cases like empty sequences and population size - Choosing the right function for your specific scenario

This randomness engine is foundational for simulations, games, and data sampling. Your next lesson explores the datetime module to handle dates and times in Python, another core building block for real-world applications. Head there to learn how to work with timestamps, timedeltas, and date arithmetic.

Practice recap

Great work mastering random number generation! To cement your skills, write a short script that simulates rolling two dice 1000 times and prints how many times you rolled a 7. Use random.randint(1,6) for each die and a loop with a counter. Then modify it to set random.seed(42) and confirm you get the same result every time.

Common mistakes

  • Calling random.shuffle() and expecting it to return a new list — it modifies the list in place and returns None
  • Using random.choice() on an empty list, which raises IndexError — always check length first
  • Setting random.seed() inside a loop and wondering why results are identical — seed once per script
  • Using random() for security-critical tasks like password generation — use secrets module instead

Variations

  1. Use random.choices() for sampling with replacement (allowing duplicates, unlike sample())
  2. Use numpy.random for high-performance, vectorized random generation in data science
  3. Use secrets module for cryptographically secure random numbers in security applications

Real-world use cases

  • Simulating dice rolls for a board game prototype using random.randint(1,6)
  • Randomly selecting winning lottery tickets from a user database with random.sample(users, k=3)
  • Shuffling a playlist of songs for a music app using random.shuffle(song_list)

Key takeaways

  • Import random — it uses the Mersenne Twister pseudorandom generator for all functions
  • Use random.random() as the base function for floats in [0.0, 1.0); random.randint(a,b) for integers inclusive
  • Set random.seed(value) for reproducible results — essential for testing and debugging
  • random.choice(seq) picks one element; random.sample(seq,k) picks k unique elements without replacement
  • random.shuffle(seq) modifies the list in place — make a copy if you need the original order
  • For security-critical randomness (passwords, tokens), use the secrets module, not random

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.