Part 7

# Randomness

This section concentrates on the module random from the Python standard library. It contains tools for generating random numbers and other randomized functionality.

The sections in this part of the material contain many links to the documentation of the Python standard library. We recommend following the links to familiarize yourself with how the documentation works.

## Generating a random number

The function randint(a, b) returns a random integer value between `a` and `b`, inclusive. For example, the following program works like a generic die:

``````from random import randint

print("The result of the throw:", randint(1, 6))``````

Executing this could print out:

Sample output

The result of the throw: 4

The following program throws the die ten times:

``````from random import randint

for i in range(10):
print("The result of the throw:", randint(1, 6))``````

Running the above could print out

Sample output

The result of the throw: 5 The result of the throw: 4 The result of the throw: 3 The result of the throw: 2 The result of the throw: 3 The result of the throw: 4 The result of the throw: 6 The result of the throw: 4 The result of the throw: 4 The result of the throw: 3

NB: it is worth remembering that the function `randint` works a bit differently when compared to, for example, slices, or the function `range`, which we've come across previously. The function call `randint(1, 6)` results in a number between 1 and 6 inclusive, but the function call `range(1, 6)` results in a range of numbers from 1 to 5.

## More randomizing functions

The function shuffle will shuffle any data structure passed as an argument, in place. For example, the following program shuffles a list of words:

``````from random import shuffle

words = ["atlas", "banana", "carrot"]
shuffle(words)
print(words)``````
Sample output

['banana', 'atlas', 'carrot']

The function `choice` returns a randomly picked item from a data structure:

``````from random import choice

words = ["atlas", "banana", "carrot"]
print(choice(words))``````
Sample output

'carrot'

## Lottery numbers

A common example for studying randomness is the case of lottery numbers. Let's try and draw some lottery numbers. In Finland the national lottery consists of a pool of 40 numbers, 7 of which are chose for each week's draw.

A first attempt at drawing a set of numbers could look like this:

``````from random import randint

for i in range(7):
print(randint(1, 40))``````

This would not work in the long run, however, as the same number may appear twice in a single weekly draw of seven numbers. We need a way to make sure the numbers drawn are all unique.

One possibility is to store the drawn numbers in a list, and only add a number if it is not already on the list. This can be repeated until the length of the list is seven:

``````from random import randint

weekly_draw = []
while len(weekly_draw) < 7:
new_rnd = randint(1, 40)
if new_rnd not in weekly_draw:
weekly_draw.append(new_rnd)

print(weekly_draw)``````

A more compact approach would be to use the `shuffle` function:

``````from random import shuffle

number_pool = list(range(1, 41))
shuffle(number_pool)
weekly_draw = number_pool[0:7]
print(weekly_draw)``````

Here the idea is that we first create a list containing the available numbers 1 to 40, rather like the balls in a lottery machine. The pool of numbers is then shuffled, and the first seven numbers chosen for the weekly draw. This saves us the trouble of writing a loop.

In fact, the `random` module contains an even easier way to select lottery numers: the sample function. It returns a random selection of a specified size from a given data structure:

``````from random import sample

number_pool = list(range(1, 41))
weekly_draw = sample(number_pool, 7)
print(weekly_draw)``````

## Where do these random numbers come from?

The features of the module random are based on an algorithm which produces random numbers based on a specific initialization value and some arithmetic operations. The initialization value is often called a seed value.

The seed value can be supplied by the user with the seed function:

``````from random import randint, seed

seed(1337)
# this will always produce the same "random" number
print(randint(1, 100))``````

If we have functions which rely on randomization, and we set seed value, the function will produce the same result each time it is executed. The result may be different with different Python versions, but in essence randomness is lost by setting a seed value. This can be a useful feature when testing a program, for example.