Generate Random Values with Python `random`

Learn how to use Python's random module to generate random numbers, pick random items, shuffle sequences, and control randomness with seeds.

7 min read

The random module in the Python standard library generates pseudo-random numbers and makes random selections from sequences. Use it for simulations, games, shuffling data, and sampling, or any task where you want values you cannot predict.

The module uses the Mersenne Twister algorithm, which is fast and produces high-quality randomness for non-security purposes. For passwords, authentication tokens, or cryptographic keys, use the secrets module instead.

pythonpython
import random
 
print(random.random())        # 0.7248319562104832
print(random.randint(1, 10))  # 7

random.random() returns a float from 0.0 up to but not including 1.0. random.randint(1, 10) returns a random integer between 1 and 10, including both endpoints, and your exact values will differ on every run.

Random floats

Three functions cover most needs for random floating-point numbers, from flat ranges to bell curves. Like everything else in the Python standard library, they are ready to use the moment you import the module.

pythonpython
import random
 
print(random.random())              # 0.3847192048561034
print(random.uniform(2.5, 5.5))     # 3.9281047518294476
print(random.gauss(mu=0, sigma=1))  # -0.5128374019263847

random.random() always stays between 0.0 and 1.0. random.uniform picks a float between the two bounds you give it, and random.gauss draws from a normal distribution with the given mean and standard deviation.

Use uniform when you need a random float in a specific range. Use gauss when modeling natural variation, like heights in a population or measurement errors.

Random integers

Use randint for inclusive ranges and randrange when you want a step between the possible values.

pythonpython
import random
 
print(random.randint(1, 6))         # 4
print(random.randrange(0, 100, 5))  # 65

random.randint(1, 6) works like a die roll and can return any integer from 1 to 6, with both endpoints included. random.randrange(0, 100, 5) picks from 0, 5, 10, and so on up to 95. The third argument is the step, just like the built-in range function, and the stop value is excluded.

Pick random items from a sequence

Use choice to select one item, and choices when you want to allow repeats in the selection.

pythonpython
import random
 
colors = ["red", "green", "blue", "yellow"]
 
print(random.choice(colors))        # blue
print(random.choices(colors, k=3))  # ['yellow', 'red', 'green']

random.choice picks a single element from the list. random.choices picks k elements and may return the same element more than once, because it selects with replacement.

You can also pass weights to bias the selection toward certain items:

pythonpython
import random
 
colors = ["red", "green", "blue", "yellow"]
picks = random.choices(colors, weights=[10, 1, 1, 1], k=5)
print(picks)  # ['red', 'red', 'green', 'red', 'red']

Here "red" is ten times more likely to be picked than any other color. The weights list must be the same length as the sequence you are choosing from.

When repeats are not acceptable, such as dealing cards or drawing lottery numbers, switch to random.sample, which selects without replacement:

pythonpython
import random
 
deck = list(range(1, 53))
hand = random.sample(deck, k=5)
print(sorted(hand))  # [3, 14, 27, 31, 48]

random.sample returns 5 unique numbers, like drawing cards from a shuffled deck. The original list is unchanged, and k must not exceed the length of the sequence.

Shuffle a list in place

random.shuffle reorders a list randomly and modifies it directly instead of returning a new list.

pythonpython
import random
 
cards = ["A", "K", "Q", "J", "10"]
random.shuffle(cards)
print(cards)  # ['Q', 'A', '10', 'K', 'J']

The call changes the order of the cards list in place and returns None. If you need to keep the original order, make a copy first, or use random.sample with k set to the full length of the list.

Reproducible randomness with seed

By default the module produces different values on every run. When you are debugging, testing, or running an experiment that must be repeatable, set a seed first.

pythonpython
import random
 
random.seed(42)
print(random.random())         # 0.6394267984578837
print(random.randint(1, 100))  # 4
 
random.seed(42)
print(random.random())         # 0.6394267984578837
print(random.randint(1, 100))  # 4

Calling random.seed(42) resets the generator to a fixed starting point, so the same calls produce the same results every time. Any integer, string, float, or bytes value works as a seed. Reproducible sequences are invaluable when comparing algorithm runs or chasing a bug.

Use secrets for security-sensitive values

The random module is not safe for security, because its output is predictable to an attacker who observes enough of it. For passwords, tokens, and session IDs, import secrets instead.

pythonpython
import secrets
 
token = secrets.token_hex(16)
print(token)  # a7f3c09e1b2d4588f6e04c3179a25bf3

secrets.token_hex(16) produces a cryptographically secure random string of 32 hexadecimal characters. The secrets module draws from the operating system's secure random source, which makes it safe for authentication and encryption work.

Practical example: dice rolling simulator

Combining a few of these functions produces a small, useful program. This one rolls a die with any number of sides, any number of times, and checks for a natural 20.

pythonpython
import random
 
def roll_dice(sides=6, count=1):
    return [random.randint(1, sides) for _ in range(count)]
 
results = roll_dice(sides=20, count=4)
print("D20 rolls:", results)     # D20 rolls: [17, 3, 14, 20]
print("Highest:", max(results))  # Highest: 20
 
if 20 in results:
    print("Critical hit!")       # Critical hit!

The roll_dice helper is a regular Python function that builds its result with randint inside a list comprehension. The final check looks for a 20 anywhere in the results and celebrates the critical hit.

Common mistakes

Watch for these three mistakes when using the module.

Calling shuffle on a tuple or string. random.shuffle works in place, so it only accepts mutable sequences like lists. Convert the sequence to a list first:

pythonpython
import random
 
directions = ("north", "south", "east", "west")
items = list(directions)
random.shuffle(items)
print(items)  # ['east', 'north', 'west', 'south']

The list call turns the tuple into a mutable list, which shuffle can then reorder without raising an error.

Using random for security. Always use secrets for tokens, passwords, and anything cryptographic. The random module is for simulations, games, and other non-security randomness.

Forgetting that choices allows repeats. random.choices can pick the same item multiple times. If you need unique items, use random.sample instead.

Rune AI

Rune AI

Key Insights

  • Use random.random() for floats between 0.0 and 1.0.
  • Use random.randint(a, b) for random integers including both endpoints.
  • Use random.choice(seq) to pick one item and random.choices(seq, k=n) with weights for biased picks.
  • Use random.sample(seq, k) to pick unique items without replacement.
  • Use random.shuffle(list) to reorder a list in place.
  • Use random.seed(n) to reproduce the same random sequence.
  • For security-sensitive randomness, use the secrets module instead of random.
RunePowered by Rune AI

Frequently Asked Questions

Is Python's random module safe for passwords?

No. The random module uses a predictable algorithm (Mersenne Twister) that is designed for simulations and games, not security. For passwords, tokens, or cryptographic keys, use the `secrets` module instead.

What does random.seed() do?

`random.seed(n)` initializes the random number generator with a fixed starting value. Using the same seed produces the same sequence of random values every time, which is useful for debugging, testing, and reproducible experiments.

How do I get a random float between two numbers?

Use `random.uniform(a, b)` to get a random float between a and b (inclusive of a, possibly inclusive of b depending on rounding). For a random float between 0.0 and 1.0, use `random.random()`.

Conclusion

The random module covers most everyday randomness needs: picking items, shuffling sequences, generating numbers, and making weighted selections. Remember to use secrets instead of random when you are generating passwords, tokens, or anything security-sensitive. Use seed() to make your random results reproducible for testing.