top of page

Why Python's Random Library Isn't Actually Random

Introduction


For context, libraries allow us to use pre-written code and functions in their own projects so we don't have to 're-invent the wheel', so to speak.


In this article, we'll take a closer look at Python's 'random' module and why it's not truly capable of generating random values.


Importing Random


Before we do anything, we must signal to our program to load in all of the pre-written code we want to access using the import keyword.

import random

deck = ["ace", "queen", "joker"]

def main():
	...

main()

Let's write a simple program that prints a random string from this list:

import random

deck = ["ace", "queen", "joker"]

def main():
	print(random.choice(deck))

main()

Note how:

  • the name of the library went before the specific method (choice), separated by a dot

  • the name of our list, deck, was passed as a parameter into choice


Alternatively, instead of importing the entire library of code, we could just import the choice function (if that was all we needed) like so:

from random import choice

deck = ["ace", "queen", "joker"]

def main():
	print(choice(deck))

main()

This time, we don't need to specify "random" before the method call.


Okay, so this code may print one of the three options in the list each time we run the program.


K Parameter


Let's try a different method now: choices.

import random

deck = ["ace", "queen", "joker"]

def main():
	print(random.choices(deck, k=2))

main()

Here, the second argument, k, specifies how many items we want to return (in a list). So a sample output for this could be:

['ace', 'queen']

or...

['ace', 'ace']

Yes, the same value can appear multiple times--sampling with replacement.


To sample without replacement, simply use random.sample( ), which takes the same arguments, except is unable to output the same list item multiple times.


Weights Parameter


Another argument we can add to choices (or sample) is weights, which expects a list as a parameter:

import random

deck = ["ace", "queen", "joker"]

def main():
	print(random.choices(deck, k=2, weights=[80, 20, 0]))

main()

Each int corresponds to a string in deck, representing its probability in percent; here, "ace" is much more likely to be chosen and "joker" is impossible to be returned.


Seeds


The random module in Python, much like in any language, actually uses something called a Pseudo Random Number Generator (PRNG) under the hood, which uses a seed, a value that changes on each run.


Knowing the starting seed and the algorithm this PRNG uses makes random number generators predictable and not truly random.


In Python, we can use the seed function to specify a certain seed, resulting in the same output each time (kind of like a hash table).


import random

deck = ["ace", "queen", "joker"]

def main():
	random.seed(1)
	print(random.choices(deck, k=2))

main()

Now, our program will only ever return the same output on each run.


Final Thoughts


It might be useful to mention that manipulating the seed can prove powerful while debugging. Thanks for reading!

Comentarios


bottom of page