random.shuffle

The classic trap: shuffle() changes the list you pass and returns None, so x = random.shuffle(x) loses the list. Strings and tuples cannot be shuffled in place at all.

random functionAll Python 3 versions (random= parameter removed in 3.11)Live demo
Common call
random.shuffle(cards)
Returns
None (cards is now reordered)
Replaces
A hand-written Fisher-Yates loop
Watch out
Do not assign the result; use sample(x, k=len(x)) for a copy
random.shuffle(xx — Reordered in place. Needs len() and item assignment: a str or tuple raises TypeError.type: list (mutable sequence) · required)
→ None

Demo

Live evaluation
Keep the return value and the list side by side: one is None, the other is shuffled.
Try:
Inputs
seedint | stran int or a string
itemslist[str]comma-separated items
Code
import random
random.seed(42)
items = ['a', 'b', 'c', 'd']
result = random.shuffle(items)
(result, items)
Result
(None, ['c', 'b', 'd', 'a'])

shuffle() walks the list from the end: for each position i it draws j with _randbelow(i + 1) and swaps items i and j, so n items cost n - 1 calls to _randbelow. Same seed and same items, same order. Note that sample(items, k=len(items)) draws differently, so with seed 42 the copy is a, d, b, c while the in-place shuffle gives c, b, d, a.

Parameters

NameTypeRequiredDescription
xlist (mutable sequence)yesReordered in place. Needs len() and item assignment: a str or tuple raises TypeError.

Return value

None — Always None: the list itself is reordered.

Common patterns

Shuffle a deck and deal
Shuffle once, then slice.
import random
deck = [r + s for s in 'SHDC' for r in 'A23456789TJQK']
random.shuffle(deck)
hand, deck = deck[:5], deck[5:]
Shuffled copy, original untouched
Works for tuples and strings too.
import random
shuffled = random.sample(items, k=len(items))
Scramble a word
Strings are immutable: shuffle a list of characters and join.
import random
letters = list(word)
random.shuffle(letters)
scrambled = ''.join(letters)
Permutation test
Reshuffle the pooled data many times (from the random docs recipes).
import random
combined = drug + placebo
for _ in range(10_000):
    random.shuffle(combined)
    new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):])

Examples

1. Shuffle in place
import random random.seed(42) x = [1, 2, 3, 4, 5] random.shuffle(x) x
Returns
[4, 2, 3, 5, 1]
2. The return value is None
import random random.seed(42) x = [1, 2, 3, 4, 5] result = random.shuffle(x) (result, x)
Returns
(None, [4, 2, 3, 5, 1])
3. A shuffled copy with sample
import random random.seed(42) x = list('abcdef') y = random.sample(x, k=len(x)) (x, y)
Returns
(['a', 'b', 'c', 'd', 'e', 'f'], ['f', 'a', 'e', 'c', 'b', 'd'])
4. Scramble a word
import random random.seed(42) word = list('python') random.shuffle(word) ''.join(word)
Returns
'hytopn'
5. Same elements, new order
import random random.seed(42) x = list(range(8)) random.shuffle(x) sorted(x) == list(range(8))
Returns
True
6. Every name for the list sees it
import random random.seed(42) a = list(range(5)) b = a random.shuffle(b) a
Returns
[3, 1, 2, 4, 0]
7. A str cannot be shuffled
import random random.shuffle('abc')
Returns
TypeError: 'str' object does not support item assignment

Pitfalls

1. x = random.shuffle(x)
shuffle() returns None, like list.sort(). Assigning its result replaces your list with None.
assign the result
import random
random.seed(42)
x = [1, 2, 3, 4, 5]
x = random.shuffle(x)
print(x)
None
just call it
import random
random.seed(42)
x = [1, 2, 3, 4, 5]
random.shuffle(x)
x
[4, 2, 3, 5, 1]
2. Shuffling a temporary copy
shuffle(list(t)) shuffles a new list that is thrown away immediately; the tuple is unchanged. Keep the copy, or use sample().
shuffle(list(t))
import random
random.seed(42)
t = ('a', 'b', 'c')
random.shuffle(list(t))
t
('a', 'b', 'c')
sample(t, k=len(t))
import random
random.seed(42)
t = ('a', 'b', 'c')
random.sample(t, k=len(t))
['c', 'a', 'b']

When to use

Use it
  • Randomizing the order of a list you own: decks, playlists, quiz questions
  • Permutation tests and randomized algorithms
Reach for something else
  • Keeping the original order → sample(x, k=len(x))
  • Strings and tuples → sample() or a list copy
  • Very long lists when every permutation must be possible: the Mersenne Twister period only covers all orderings up to 2080 items

Notes

CPython impl
Lib/random.py: for i in reversed(range(1, len(x))): j = randbelow(i + 1); x[i], x[j] = x[j], x[i] — integer draws only, identical on every platform
Removed
The optional random= argument (a custom float function) was removed in Python 3.11
Period
The docs note that a sequence of length 2080 is the largest whose permutations can all be produced within the generator period

FAQ

It works in place, like list.sort(): the list you passed is reordered and None is returned so that nobody mistakes it for a copy. Use the list itself afterwards, or random.sample(x, k=len(x)) for a new list.