Python random Module
1Python random: overview
The random module draws pseudo-random numbers and picks from a seeded generator, so you can simulate dice, shuffle and sample lists, and repeat exactly the same results whenever you fix the seed.
Before this lesson: Python Lists, Python Modules and Imports
2Python random: diagram
3Python random: explained step by step
The numbers from random are not truly random. They come from a formula that starts from a number called the seed, and that is a feature: if you start from the same seed, you get exactly the same "random" sequence again. Games leave the seed alone so every play is different. Tests, simulations and tutorials fix it so results can be repeated. Every snippet on this page calls random.seed(...) first, so what you see is what you get.
Seeding: same seed, same numbers
random.seed(42) puts the generator into a known starting state. Seed again with the same value and the sequence starts over.
import random
random.seed(42)
print(random.random(), random.random())
random.seed(42)
print(random.random())Seed once, at the start of the program. Seeding again inside a loop restarts the sequence every time (see the mistakes below). Without a call to seed, Python seeds itself from the operating system, so each run differs.
Numbers: random, uniform, randint, randrange
import random
random.seed(1)
print(random.random())
print(random.uniform(10, 20))
print(random.randint(1, 6))
print(random.randrange(0, 10, 2))random() gives a float from 0 up to (not including) 1, and uniform(a, b) a float between a and b. For whole numbers there are two near-twins. randint(a, b) includes both ends, so randint(1, 6) is a die. randrange(a, b) works like range() and stops before b; a third argument sets the step, so randrange(0, 10, 2) is one of 0, 2, 4, 6, 8. To pick a position in a list, use randrange(len(items)).
Picking from a list: choice, choices, sample
choice(items)returns one item, and raisesIndexErroron an empty list.choices(items, k=3)draws 3 items with replacement, like putting each card back, so repeats can happen. It always returns a list, even fork=1, and acceptsweights=to make some items likelier.sample(items, 3)draws 3 items without replacement, like dealing cards: nothing appears twice. Asking for more items than the list holds is aValueError.
import random
random.seed(3)
colors = ["red", "green", "blue", "gold"]
print(random.choice(colors))
print(random.choices(colors, k=5))
print(random.choices(colors, weights=[10, 1, 1, 1], k=5))
print(random.sample(colors, 2))Use choices for independent events (a weighted loot drop) and sample for winners, teams or a hand of cards.
shuffle: reorder a list in place
random.shuffle(items) rearranges the list itself and returns None. Do not assign its result. It needs a mutable list, so a tuple fails with a TypeError. When you need the original order as well, copy first, or use sample(items, k=len(items)), which returns a new shuffled list.
import random
random.seed(8)
deck = ["A", "K", "Q", "J"]
original = list(deck)
result = random.shuffle(deck)
print(result)
print(deck, original)
print(random.sample(original, k=len(original)))Your own generator: random.Random(seed)
The functions above share one hidden generator. If two parts of a program both draw from it, they disturb each other's sequence. random.Random(seed) creates a private generator with the same methods (randint, choice, shuffle and the rest) and its own state.
import random
dice = random.Random(10)
cards = random.Random(10)
print([dice.randint(1, 6) for _ in range(5)])
print([cards.randint(1, 6) for _ in range(5)])
rng = random.Random(5)
first = rng.randint(1, 100)
random.random()
second = rng.randint(1, 100)
check = random.Random(5)
print([first, second] == [check.randint(1, 100), check.randint(1, 100)])The same seed gives the same stream, and drawing from the shared generator in between changes nothing. That makes a private generator the right choice for a function that must be reproducible, such as a test-data builder.
Simulations: dice, coins and events
Put a draw in a loop and you have a simulation. A coin flip is choice(["heads", "tails"]), and an event with a 25% chance is rng.random() < 0.25.
import random
rng = random.Random(7)
rolls = [rng.randint(1, 6) for _ in range(600)]
for face in range(1, 7):
print(face, rolls.count(face))
hits = sum(rng.random() < 0.25 for _ in range(1000))
print("Events at 25%:", hits, "out of 1000")The counts are near 100 each, never exactly 100. More trials land closer to the expected share. A guessing game follows the same pattern: draw secret = rng.randint(1, 100) once, then compare each guess with it.
Passwords and tokens: use secrets
random is predictable: whoever learns the seed, or enough outputs, can work out what comes next. For passwords, reset links and API tokens use the secrets module. It draws from the operating system's secure source and cannot be seeded, so its results can never be reproduced.
import secrets
token = secrets.token_hex(8)
pin = "".join(secrets.choice("0123456789") for _ in range(6))
print(len(token), len(pin), pin.isdigit())Only the lengths are printed because the values change on every run, and a real secret should never be printed or logged.
Which one should I use?
Use random for games, simulations and sample data, with a seed when you need repeatable results. Use secrets for anything an attacker would like to guess.
Quick reference: Python random
- Python Number Guessing Game Program — A number guessing game picks a secret number with `random.randint()`, then loops with `input()` telling the p…
- Python Random Password Generator Program — A Python password generator joins randomly chosen characters from `string.ascii_letters`, `string.digits` and…
- Python Rock Paper Scissors Game Program — A Python rock paper scissors game lets the computer pick with `random.choice()`, reads the player's choice wi…
4Python random: syntax
import random
random.seed(42) # repeatable results (call once, at the start)
random.random() # float: 0 <= x < 1
random.uniform(a, b) # float between a and b
random.randint(a, b) # whole number, a and b both possible
random.randrange(start, stop, step) # like range(): stop is excluded
random.choice(items) # one item
random.choices(items, weights=None, k=1) # list of k items, repeats allowed
random.sample(items, k) # list of k different items
random.shuffle(items) # reorders the list in place, returns None
rng = random.Random(42) # private generator with its own seed
rng.randint(1, 6) # same methods as the module
import secrets
secrets.token_hex(16) secrets.choice(items) # secure, never repeatable
5Python random: run the example
Press Run (or Ctrl + Enter). The output (step 6) appears directly below the code. Change anything and run it again.
import random
random.seed(21)
suits = ["S", "H", "D", "C"]
ranks = ["A"] + [str(n) for n in range(2, 11)] + ["J", "Q", "K"]
deck = [rank + suit for suit in suits for rank in ranks]
random.shuffle(deck)
asha_hand = deck[:5]
ben_hand = deck[5:10]
print("Asha:", asha_hand)
print("Ben:", ben_hand)
print("Cards left:", len(deck) - 10)
lucky = random.choice(asha_hand)
print("Asha plays", lucky)Expected outputAsha: ['7S', '9C', '3D', '4H', '9S']
Ben: ['6S', 'AC', 'KH', '5C', '9H']
Cards left: 42
Asha plays 9C
7Python random: how the example works
Hover or tap a step to highlight its lines in the example above.
- Line 1Import the
randommodule. - Line 3
random.seed(21)fixes the starting state, so the shuffle below is the same on every run. Remove this line and the hands change each time. - Line 5-7Build a 52-card deck: 4 suits times 13 ranks. The list comprehension joins a rank and a suit into one string, such as
"10H". - Line 8
random.shuffle(deck)reorders the list in place and returnsNone, so the result is not assigned to anything. - Line 10-11Slicing deals the cards. Asha gets the first five, Ben the next five, and no card can go to both players.
- Line 12-13Printing each hand shows the cards in the order they were dealt.
- Line 1452 cards minus the 10 dealt leaves 42 in the deck.
- Line 16-17
random.choice()picks one card from Asha's hand. It draws from the same seeded generator, so this pick is repeatable too.
8Python random: common mistakes
Using randint(0, len(items)) as an index
✗ Wrong
import random
random.seed(0)
moves = ["rock", "paper", "scissors"]
print(moves[random.randint(0, len(moves))])✓ Right
import random
random.seed(0)
moves = ["rock", "paper", "scissors"]
print(random.choice(moves))randint includes its upper end, so randint(0, 3) can return 3, but a three-item list stops at index 2. Use random.choice(moves), or random.randrange(len(moves)), which never reaches the length.
Assigning the result of shuffle()
✗ Wrong
import random
cards = ["A", "K", "Q", "J"]
shuffled = random.shuffle(cards)
print(shuffled)✓ Right
import random
cards = ["A", "K", "Q", "J"]
random.shuffle(cards)
print(cards)shuffle() reorders the list in place and returns None. Call it on its own line and use the original list, or use random.sample(cards, k=len(cards)) to get a new shuffled list.
Shuffling a tuple
✗ Wrong
import random
weekdays = ("Mon", "Tue", "Wed")
random.shuffle(weekdays)
print(weekdays)✓ Right
import random
random.seed(5)
weekdays = ("Mon", "Tue", "Wed")
print(random.sample(weekdays, k=len(weekdays)))A tuple cannot be changed, and shuffle works by swapping items in place. Make a shuffled list with random.sample(), or convert the tuple with list() first.
Calling seed() inside the loop
✗ Wrong
import random
for roll in range(3):
random.seed(5)
print(random.randint(1, 6))✓ Right
import random
random.seed(5)
for roll in range(3):
print(random.randint(1, 6))Every seed(5) rewinds the generator to the same starting point, so it repeats its first number. Seed once, before the loop.
Sampling more items than the list holds
✗ Wrong
import random
random.seed(1)
names = ["Asha", "Ben", "Cara"]
print(random.sample(names, 5))✓ Right
import random
random.seed(1)
names = ["Asha", "Ben", "Cara"]
print(random.sample(names, min(5, len(names))))sample() never repeats an item, so it cannot return more items than the list has. Ask for at most len(names), or use random.choices(names, k=5) if repeats are fine.
9Python random: exercises
Write your answer, then press Check. The checks run in your browser.
1. Roll the dice
Write code Easy ✓ CompletedWrite a function roll_dice(count) that returns a list of count random die rolls. Every roll is a whole number from 1 to 6, and 6 must be possible. Use random.randint.
import random
def roll_dice(count):
# return a list of count rolls, each from 1 to 6
pass
random.seed(11)
print(roll_dice(5))
import random
def roll_dice(count):
return [random.randint(1, 6) for _ in range(count)]
random.seed(11)
print(roll_dice(5))
2. Predict the random facts
Predict the output Easy ✓ CompletedNothing here depends on lucky numbers: every line prints something you can work out. Type exactly what the program prints, then press Check.
import random
random.seed(1)
first = random.randint(1, 6)
random.seed(1)
second = random.randint(1, 6)
print(first == second)
cards = ["A", "K", "Q"]
result = random.shuffle(cards)
print(result)
print(sorted(cards))
print(len(random.sample(range(10), 4)))
print(random.randint(5, 5))
True
None
['A', 'K', 'Q']
4
5
2 more exercises → 6 more examples
Questions learners ask
Is Python's random module really random?
No, it is pseudo-random. A formula (the Mersenne Twister) produces numbers that look random and pass statistical tests, but the whole sequence is decided by the seed. That is perfect for games, simulations and sample data. It is not safe for passwords, tokens or anything an attacker might guess. For those use the secrets module, which draws from the operating system's secure source.
How do I get the same random numbers every time I run my program?
Call random.seed(some_number) once, before any other random calls. The same seed always produces the same sequence, so your tests and bug reports become repeatable. If different parts of the program need their own repeatable streams, create private generators with random.Random(seed) so they cannot disturb each other.
What is the difference between random.choice, random.choices and random.sample?
choice(items) returns one item. choices(items, k=n) returns a list of n items drawn with replacement, so repeats are possible, and it supports weights. sample(items, n) returns a list of n different items drawn without replacement, like dealing cards, and raises ValueError if n is larger than the list.
Further reading
10Next lesson
Up nextPython datetime ModuleThe datetime module gives you date, time, datetime and timedelta objects that understand the calendar, so you can forma…Related:
Python else on LoopsPython List MethodsPython Modules and ImportsPython math and statistics
← Python math and statistics · All Functions and Modules lessons · Practise in the IDE