Table of contents
Implement code functionality

How to use the 'random' module in Python

May 30, 2025
 ・ by  
Claude and the Anthropic Team
Table of contents
H2 Link Template
Try Claude

Python's random module provides essential tools for generating random numbers and making random selections in your code. Understanding these functions helps you create games, simulations, and data analysis applications with unpredictable outcomes.

This guide covers practical techniques for implementing randomization in Python, with real-world examples and debugging tips. All code examples were created with Claude, an AI assistant built by Anthropic.

Basic usage of the random module

import random
random_number = random.random()
print(f"Random number between 0 and 1: {random_number}")
Random number between 0 and 1: 0.7254897563178143

The random.random() function generates a floating-point number between 0 and 1, following a uniform distribution. This means each value in the range has an equal probability of being selected. The function serves as a foundation for many randomization tasks in Python.

While seemingly simple, this uniform distribution proves essential for:

  • Creating fair probability systems in games and simulations
  • Generating test data for statistical analysis
  • Building random sampling mechanisms in data science applications

The code demonstrates proper module importing and basic function usage. Python's random number generator uses the Mersenne Twister algorithm, ensuring high-quality pseudo-random numbers suitable for most applications.

Common random operations

Building on the foundational random.random() function, Python's random module offers specialized methods for integers, custom ranges, and sequence selection—each serving distinct randomization needs.

Generating random integers with randint()

import random
random_integer = random.randint(1, 100)
print(f"Random integer: {random_integer}")
Random integer: 42

The randint() function generates random integers within a specified inclusive range. Unlike random(), it returns whole numbers only. The example generates integers between 1 and 100, including both endpoints.

  • Both arguments must be integers. The first number must be less than or equal to the second
  • The distribution remains uniform, giving each possible integer an equal chance of selection
  • This function excels at simulating dice rolls, generating random ages, or picking numbered items from a list

The f-string formatting in the print statement provides a clean way to display the randomly generated number. Each time you run this code, you'll get a different integer between 1 and 100.

Working with random floating-point numbers using uniform()

import random
random_float = random.uniform(5.0, 10.0)
print(f"Random float between 5.0 and 10.0: {random_float}")
Random float between 5.0 and 10.0: 7.823481978264493

The uniform() function generates random floating-point numbers within a specified range, giving you precise control over the minimum and maximum values. Unlike random(), which only works between 0 and 1, uniform() lets you define your own boundaries.

Each floating-point number between the given range has an equal probability of being selected. This makes uniform() ideal for simulating real-world measurements or creating realistic test data.

  • The function takes two arguments: the lower and upper bounds
  • Arguments can be integers or floating-point numbers
  • The distribution remains uniform across the entire range

In the example, random.uniform(5.0, 10.0) generates a random float between 5.0 and 10.0. You'll get a different value each time you run the code.

Making random choices from sequences with choice()

import random
fruits = ['apple', 'banana', 'cherry', 'durian', 'elderberry']
selected_fruit = random.choice(fruits)
print(f"Selected fruit: {selected_fruit}")
Selected fruit: cherry

The choice() function randomly selects a single item from any sequence like a list, tuple, or string. Each item has an equal probability of being chosen, making it perfect for simple randomization tasks.

  • Works with any sequence type. The example uses a list of fruits, but you could use it with any collection of items
  • Returns exactly one item from the sequence each time it's called
  • Maintains uniform distribution. Every item has the same chance of being selected

The function shines in scenarios where you need quick, fair selections. Think selecting random players for a game, picking test cases, or implementing basic game mechanics.

Advanced random techniques

Building on these foundational random operations, Python's random module offers sophisticated techniques for reordering sequences, controlling randomness, and modeling complex probability distributions.

Shuffling sequences with shuffle()

import random
cards = ['A', 'K', 'Q', 'J', '10']
print(f"Original order: {cards}")
random.shuffle(cards)
print(f"After shuffling: {cards}")
Original order: ['A', 'K', 'Q', 'J', '10']
After shuffling: ['J', 'A', '10', 'Q', 'K']

The shuffle() function randomly reorders all elements in a mutable sequence like a list. Unlike choice(), which selects a single item, shuffle() modifies the original sequence in place.

  • The function takes a list as input and returns None
  • Each element moves to a new random position in the sequence
  • The original list gets modified directly instead of creating a new copy

This functionality proves invaluable when implementing card games, randomizing quiz questions, or creating fair tournament matchups. The example demonstrates how a simple deck of cards changes from a sorted sequence to a randomly ordered list with a single function call.

Using random seeds for reproducibility

import random
random.seed(42)
print(random.random())
print(random.random())
random.seed(42)
print(random.random())
0.6394267984578837
0.025010755222666936
0.6394267984578837

Random seeds control the sequence of random numbers Python generates. Setting a seed with random.seed() ensures you'll get the same "random" numbers in the same order every time you run your code.

The example demonstrates this predictability. When we set random.seed(42), the first random.random() call produces 0.6394267984578837. After resetting to the same seed value, we get that exact number again.

  • Seeds enable reproducible results in scientific computing and testing
  • Different seed values produce different but equally random sequences
  • Without explicitly setting a seed, Python uses system time by default

This reproducibility proves essential when debugging random behavior or sharing code that needs consistent results across different runs.

Working with statistical distributions

import random
gaussian_values = [random.gauss(0, 1) for _ in range(5)]
exponential_value = random.expovariate(1.5)
print(f"Gaussian samples: {gaussian_values}")
print(f"Exponential sample: {exponential_value}")
Gaussian samples: [0.496714153011, -0.138264301171, 0.647689996795, 1.523030600511, -0.234153749427]
Exponential sample: 0.2845772583537913

Python's random module includes functions for generating numbers that follow specific statistical patterns. The gauss() function creates random numbers following a normal distribution, defined by a mean (0 in our example) and standard deviation (1). This distribution appears as the classic bell curve seen in natural phenomena like height distributions or measurement errors.

  • The list comprehension [random.gauss(0, 1) for _ in range(5)] generates 5 normally distributed random numbers
  • The expovariate() function produces numbers following an exponential distribution with rate parameter 1.5
  • Exponential distributions model real-world scenarios like customer arrival times or radioactive decay

These statistical functions help create more realistic random data for simulations and data analysis tasks where uniform randomness doesn't match real-world patterns.

Get unstuck faster with Claude

Claude is an AI assistant from Anthropic that helps developers write, understand, and debug Python code. It combines deep programming knowledge with natural conversation to provide clear, accurate guidance on technical challenges.

When you encounter tricky random module implementations or need help optimizing your code, Claude acts as your AI mentor. It can explain complex concepts like statistical distributions, suggest better approaches to shuffling sequences, or help you track down that elusive random seed bug.

Start accelerating your Python development today. Sign up for free at Claude.ai to get personalized coding assistance and unblock your development challenges faster.

Some real-world applications

Python's random module powers essential real-world applications, from strengthening cybersecurity to creating engaging games that millions enjoy.

Generating secure passwords with choice()

The choice() function enables robust password generation by randomly selecting characters from custom character sets—creating unique combinations that enhance security through unpredictability.

import random
import string
characters = string.ascii_letters + string.digits + string.punctuation
password = ''.join(random.choice(characters) for _ in range(12))
print(f"Generated password: {password}")

This code combines Python's built-in string and random modules to create a diverse character pool for password generation. The characters variable merges lowercase letters, uppercase letters, numbers, and special characters into one comprehensive string.

A list comprehension with random.choice() selects 12 random characters from this pool. The join() method then combines these selections into the final password string. This approach ensures each character position has an equal chance of containing any character type, creating strong randomization.

  • The string module provides predefined character sets through ascii_letters, digits, and punctuation
  • The empty string '' serves as the delimiter in join(), connecting characters without spaces
  • The f-string displays the generated password with clear formatting

Simulating a dice game with randint()

The randint() function enables realistic dice game simulations by generating random integers that mimic physical dice rolls, making it perfect for creating virtual versions of classic tabletop games.

import random

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

player1_score = sum(roll_dice() for _ in range(3))
player2_score = sum(roll_dice() for _ in range(3))

print(f"Player 1 scored: {player1_score}")
print(f"Player 2 scored: {player2_score}")
print(f"Winner: {'Player 1' if player1_score > player2_score else 'Player 2' if player2_score > player1_score else 'Tie'}")

This code simulates a simple dice game between two players. The roll_dice() function generates a random number between 1 and 6 using random.randint(), mimicking a six-sided die.

Each player rolls three dice through a list comprehension with range(3). The sum() function adds up their three rolls to calculate the total score. The final print statement uses a nested ternary operator to determine and display the winner based on score comparison.

  • Players roll three times each
  • Scores are automatically summed
  • The program handles ties and winning conditions in a single line

Common errors and challenges

Python's random module can trip up even experienced developers through subtle differences between functions, testing complexities, and security considerations.

Understanding the difference between randint() and randrange()

Developers often confuse randint() and randrange() when generating random numbers in Python. While both functions create random integers, they handle their upper bounds differently. This distinction can lead to unexpected results when you need precise number ranges.

import random
# Trying to get numbers from 1 to 10
numbers = [random.randrange(1, 10) for _ in range(5)]
print(f"Random numbers from 1-10: {numbers}")

The code produces incorrect output because randrange(1, 10) excludes 10 from possible results. This means you'll only get numbers from 1 to 9. Let's examine the corrected version below.

import random
# For numbers 1-10 with randrange (end is exclusive)
numbers = [random.randrange(1, 11) for _ in range(5)]
# Or using randint which includes both endpoints
numbers_alt = [random.randint(1, 10) for _ in range(5)]
print(f"Random numbers from 1-10: {numbers}")

The key difference lies in how these functions handle their upper bounds. randrange() excludes the upper bound while randint() includes it. To generate numbers from 1 to 10 with randrange(), you must specify randrange(1, 11). Alternatively, randint(1, 10) achieves the same result more intuitively.

  • Watch for this issue when porting code between Python versions or other programming languages
  • Double-check range boundaries when working with arrays or list indices
  • Consider using randint() when you want inclusive ranges for better code readability

Forgetting to reset the seed between test runs

Testing code that uses random numbers requires careful management of the random seed. Developers often forget that each random operation advances the sequence. This can lead to inconsistent test results when assertions depend on specific random values.

import random

def test_random_function():
    random.seed(42)
    result1 = random.random()
    # Doing other operations that use random
    random.random()
    result2 = random.random()
    assert result2 == 0.025010755222666936

The test fails because random.random() advances the sequence between result1 and result2. Each random operation moves the generator forward, making the expected value incorrect. Let's examine the corrected implementation below.

import random

def test_random_function():
    random.seed(42)
    result1 = random.random()
    
    # Reset seed for the next test
    random.seed(42)
    result2 = random.random()
    assert result1 == result2

The solution demonstrates proper seed management for testing random operations. By resetting the seed with random.seed(42) before each test, you ensure the random number generator starts from the same point. This creates predictable, reproducible results for testing.

  • Always reset seeds before each test case that uses random operations
  • Remember that every random function call advances the sequence
  • Consider creating helper functions to manage seed state in larger test suites

This pattern becomes especially important when testing games, simulations, or data processing functions that rely on randomization. Without proper seed management, your tests might pass sometimes and fail others. This inconsistency makes debugging much harder.

Avoiding random for security-sensitive operations

Python's random module generates predictable sequences that attackers can potentially exploit. Using it for security features like authentication tokens, encryption keys, or password reset codes creates significant vulnerabilities. The code below demonstrates this common but dangerous practice.

import random
import string

# Generating a security token (insecure)
chars = string.ascii_letters + string.digits
token = ''.join(random.choice(chars) for _ in range(20))
print(f"Security token: {token}")

The code generates tokens using random.choice(), which relies on Python's pseudo-random number generator. An attacker who discovers the seed value could predict future tokens. The following example demonstrates a more secure approach.

import secrets
import string

# Generating a security token (secure)
chars = string.ascii_letters + string.digits
token = ''.join(secrets.choice(chars) for _ in range(20))
print(f"Secure token: {token}")

The secrets module provides cryptographically strong random number generation, making it the right choice for security-sensitive operations. Unlike random, it draws from your operating system's secure random source to generate truly unpredictable values.

  • Use secrets for authentication tokens, password reset codes, and encryption keys
  • Reserve random for non-security tasks like games and simulations
  • The secrets.choice() function works as a drop-in replacement for random.choice()

Watch for this issue when building user authentication systems or handling sensitive data. A predictable random number generator can compromise your entire application's security.

Learning or leveling up? Use Claude

Claude combines expert Python knowledge with intuitive understanding to guide you through coding challenges and implementation questions. This AI assistant excels at explaining complex programming concepts while suggesting practical solutions tailored to your skill level.

Here are some prompts you can use to get Claude's help with Python's random module:

  • Debug random seeds: Ask "Why isn't my random seed producing consistent results?" and Claude will help identify common seed management issues and provide a reliable testing approach.
  • Choose the right function: Ask "Should I use random.choice() or random.sample() for my card game?" and Claude will explain the key differences with practical examples.
  • Secure randomization: Ask "How can I generate secure random tokens?" and Claude will guide you through using the secrets module instead of random for security-critical operations.
  • Statistical distributions: Ask "How do I simulate normal distribution data?" and Claude will demonstrate using random.gauss() with real-world applications.

Experience personalized programming guidance by signing up at Claude.ai today.

For seamless integration into your development workflow, Claude Code brings AI assistance directly to your terminal. Access Claude's capabilities while staying in your preferred coding environment.

FAQs

Additional Resources

How to print a dictionary in Python

2025-05-30
14 min
 read
Read more

Improve code maintainability using Claude

2025-05-30
6 min
 read
Read more

How to add a key value pair to a dictionary in Python

2025-05-30
14 min
 read
Read more

Leading companies build with Claude

ReplitCognitionGithub CopilotCursorSourcegraph
Try Claude
Get API Access
Copy
Expand