# Working with Random Numbers in Python

An overview for working with randomness in Python, using only functionality built into the standard library and CPython itself.

## Generating Random Floats Between 0.0 and 1.0

The `random.random()` function returns a random float in the interval [0.0, 1.0). This means the returned random number will always be smaller than the right-hand endpoint (1.0). This is also known as a semi-open range:

```>>> import random
>>> random.random()
0.11981376476232541
>>> random.random()
0.757859420322092
>>> random.random()
0.7384012347073081
```

## Generating Random Ints Between `x` and `y`

This is how you can generate a random integer between two endpoints in Python with the `random.randint()` function. This spans the full [x, y] interval and may include both endpoints:

```>>> import random
>>> random.randint(1, 10)
10
>>> random.randint(1, 10)
3
>>> random.randint(1, 10)
7
```

With the `random.randrange()` function you can exclude the right-hand side of the interval, meaning the generated number always lies within [x, y) and it will always be smaller than the right endpoint:

```>>> import random
>>> random.randrange(1, 10)
5
>>> random.randrange(1, 10)
3
>>> random.randrange(1, 10)
4
```

## Generating Random Floats Between `x` and `y`

If you need to generate random float numbers that lie within a specifc [x, y] interval you can use the `random.uniform` function:

```>>> import random
>>> random.uniform(1, 10)
7.850184644194309
>>> random.uniform(1, 10)
4.00388600011348
>>> random.uniform(1, 10)
6.888959882650279
```

## Picking a Random Element From a List

To pick a random element from a non-empty sequence (like a list or a tuple) you can use Python’s `random.choice` function:

```>>> import random
>>> items = ['one', 'two', 'three', 'four', 'five']
>>> random.choice(items)
'five'
>>> random.choice(items)
'one'
>>> random.choice(items)
'four'
```

This works for any non-empty sequence, however it will throw an `IndexError` exception if the sequence is empty.

## Randomizing a List of Elements

You can randomize a sequence in place using the `random.shuffle` function. This will modify the sequence object and randomize the order of elements:

```>>> import random
>>> items = ['one', 'two', 'three', 'four', 'five']
>>> random.shuffle(items)
>>> items
['four', 'one', 'five', 'three', 'two']
```

If you’d rather not mutate the original you’ll need to make a copy first and then shuffle the copy. You can create copies of Python objects with the `copy` module.

## Picking `n` Random Samples From a List of Elements

To pick a random sample of `n` unique elements from a sequence, use the `random.sample` function. It performs random sampling without replacement:

```>>> import random
>>> items = ['one', 'two', 'three', 'four', 'five']
>>> random.sample(items, 3)
['one', 'five', 'two']
>>> random.sample(items, 3)
['five', 'four', 'two']
>>> random.sample(items, 3)
['three', 'two', 'five']
```

## Generating Cryptographically Secure Random Numbers

If you need cryptographically secure random numbers for security purposes, use `random.SystemRandom` which uses a cryptographically secure pseudo-random number generator.

Instances of the `SystemRandom` class provide most of the random number generator operations available as function on the `random` module. Here’s an example:

```>>> import random
>>> rand_gen = random.SystemRandom()

>>> rand_gen.random()
0.6112441459034399

>>> rand_gen.randint(1, 10)
2

>>> rand_gen.randrange(1, 10)
5

>>> rand_gen.uniform(1, 10)
8.42357365980016

>>> rand_gen.choice('abcdefghijklmn')
'j'

>>> items = ['one', 'two', 'three', 'four', 'five']
>>> rand_gen.shuffle(items)
>>> items
['two', 'four', 'three', 'one', 'five']

>>> rand_gen.sample('abcdefghijklmn', 3)
['g', 'e', 'c']
```

Be aware that `SystemRandom` isn’t guaranteed to be available on all systems that run Python (although it typically will be.)

Python 3.6+ – The `secrets` Module:

If you’re working on Python 3 and your goal is to generate cryptographically secure random numbers, then be sure to check out the `secrets` module. This module is available in the Python 3.6 (and above) standard library. It makes generating secure tokens a breeze.

Here are a few examples:

```>>> import secrets

# Generate secure tokens:
>>> secrets.token_bytes(16)
b'\xc4\xf4\xac\x9e\x07\xb2\xdc\x07\x87\xc8 \xdf\x17\x85^{'
>>> secrets.token_hex(16)
'a20f016e133a2517414e0faf3ce4328f'
>>> secrets.token_urlsafe(16)
'eEFup5t7vIsoehe6GZyM8Q'

# Picking a random element from a sequence:
>>> secrets.choice('abcdefghij')
'h'

# Securely compare two strings for equality
# (Reduces the risk of timing attacks):
>>> secrets.compare_digest('abcdefghij', '123456789')
False
>>> secrets.compare_digest('123456789', '123456789')
True
```

You can learn more about the `secrets` module here in the Python 3 docs.

Improve Your Python with a fresh 🐍 Python Trick 💌 every couple of days