The random module of the Python standard library generates pseudorandom numbers and provides additional functions for applying random operations to basic data types.
Note: The random module doesn’t generate true random numbers, but so-called pseudorandom numbers. True random numbers are not computable by a computer. A pseudorandom number generator is initialized with an integer and generates a deterministic but apparently random sequence of pseudorandom numbers. This sequence of numbers repeats itself after a certain number of generated random numbers. In the case of the algorithm used by default in Python, this period is 219937 – 1 numbers.
The pseudorandom number generator implemented in random can be initialized using the seed function:
>>> import random
>>> random.seed(12)
If the seed is an integer, the random number generator is initialized directly with this number. Alternatively, an instance of the NoneType, float, str, bytes, and bytearray data types can be passed, which initializes the random number generator with the hash value of this instance. If no parameter is passed, the current system time serves as the seed. In this way, the generated numbers can be considered quasi-random:
>>> random.seed()
If the random number generator is initialized with the same value at different times, it will generate the same sequence of numbers each time. This is particularly useful for achieving reproducible program execution despite the use of random numbers.
Saving and Loading the Random State
The getstate function returns a tuple describing the current state of the random number generator. With the help of the setstate function, the status of the generator can be saved and restored at a later time—for example, after a reinitialization in the meantime:
>>> state = random.getstate()
>>> random.setstate(state)
The generator then continues to run as if the interruption had not occurred.
Generating Random Integers
To generate a (pseudo)random integer, you can use the randint function, to which the required interval boundaries can be passed:
>>> random.randint(0, 10)
4
In this case, integers between 0 and 10 are randomly generated, and the interval limits 0 and 10 can also be valid results.
A little more control over the possible results is provided by the randrange function. It returns a randomly chosen element from the number space that a call of the built-in range function with the same parameters would produce:
>>> random.randrange(0, 50, 2)
40
In this case, a random even number between 0 and 49 was generated.
Another way to generate random numbers is to use the getrandbits function, which generates a random bit sequence of fixed length and returns it as an integer:
>>> random.getrandbits(8)
156
In this case, the getrandbits function was used to generate a random byte (8 bits).
Generating Random Floats
The random module contains some functions to generate a random float according to a chosen probability distribution. The simplest of these functions is random, which is used to generate an uniformly distributed random number between 0 and 1:
>>> random.random()
0.6018018690250143
The related uniform function produces a uniformly distributed random number within the specified interval limits:
>>> random.uniform(0, 10)
5.044950881560962
In addition, the random module contains further functions that generate random numbers according to other probability distributions. The best known of these distributions is the normal or Gaussian distribution. You can generate a normally distributed random number as follows:
>>> random.gauss(0, 1)
1.4999823501567913
The expected value (μ) and standard deviation (σ) are passed as parameters.
Random Operations on Sequences
The random module contains several functions that perform random operations on sequences, including the choice function, which returns a random element of the passed nonempty sequence:
>>> random.choice([1,2,3,4,5])
5
>>> random.choice([1,2,3,4,5])
2
>>> random.choice(["A", "B", "C"])
'B'
Similar to choice, the function choices can be used to get k randomly chosen elements from the passed sequence. The elements are chosen with replacements which means that individual elements may be chosen multiple times.
>>> random.choices(range(100), k=4)
[76, 41, 39, 5]
The sample function is passed a population sequence and an integer k as parameters. The result is a new list with k randomly chosen elements from population. The elements are chosen without replacements which means that individual elements may be chosen at most once. In this way, for example, a certain number of winners could be drawn from a list of lottery participants. Note that the order of the generated list is also random and that values occurring multiple times in population can also be drawn multiple times:
>>> pop = [1,2,3,4,5,6,7,8,9,10]
>>> random.sample(pop, 3)
[7, 8, 5]
>>> random.sample(pop, 3)
[5, 9, 7]
The sample function can also be used in combination with the built-in range function:
>>> random.sample(range(10000000), 3)
[4571575, 2648561, 2009814]
The shuffle function puts the elements of sequence x in a random order. Note that this function is not without side effects as the passed sequence gets modified. For this reason, only instances of mutable sequential data types may be passed for x:
>>> l = [1,2,3,"A","B"]
>>> random.shuffle(l)
>>> l
[1, 'B', 2, 'A', 3]
In Python 3.9, the randbytes function was introduced, which generates a random byte sequence of a given length as a bytes string:
>>> random.randbytes(4)
b'\x86\x0f\xa3\xbe'
>>> random.randbytes(4)
b'A\x12u\xa3'
In this case, a sequence of four random bytes was generated. In the output representation of the result, these bytes are output as escape sequences if they do not correspond to printable ASCII characters.
26
SystemRandom([seed])
In addition to the functions described previously, the random module contains a class called SystemRandom that allows you to use the operating system's random number generator instead of Python's own. This class doesn’t exist on all operating systems, but on the most common ones.
When instantiating the class, a number or instance can be passed to initialize the random number generator. After that, the SystemRandom class can be used like the random module as it implements most of the functions contained in the module as methods.
Note, however, that not all the functionality of random is available in SystemRandom. Thus, a call of the seed method is ignored, while calls of the getstate and setstate methods raise a NotImplementedError exception:
>>> sr = random.SystemRandom()
>>> sr.randint(1, 10)
9
Editor’s note: This post has been adapted from a section of the book Python 3: The Comprehensive Guide by Johannes Ernesti and Peter Kaiser.
Comments