## Lesson Three: Random Numbers

Normally, computers are very predictable. However, your program may occasionally need to do something unexpected or random. Imagine a computer game where you want to generate a random number, secret code or shuffle a deck of cards. In this lesson, you'll learn about Python's functions for generating random numbers and picking random items from lists.

### Using the "random" Module

All of Python's randomization functions are in the random module. So, any time you want to use these functions, you must first add the "import random" statement at the top of your code.

import random

Unlike the datetime library, which contains multiple objects that have their own functions and properties, the random library is typically used as a collection of independent functions. This means you can perform all the random operations simply by writing the module name, random, then a dot (.) and the function name that you want to call.

### Generating Random Integers with randrange()

Random integers are useful in many applications. To generate a random integer between some minimum and maximum values, simply call the random.randrange() function. The first parameter is the minimum possible value and the second parameters is one more than the largest possible value. Therefore, randrange(0,10) will return a random number starting at 0 and going up to and including 9, but will never return 10.

random.randrange(<min>,<max>)          # returns random integer from <min> through <max> - 1

Let's create some random numbers. The example below will loop 5 times and print a random number from 0 through 9 on each loop. Every time you run the program, you should see a difference sequence of random numbers. Try it and see!

Try It Now

import random
for i in range(0,5):
rand = random.randrange(0,10)
print(rand,end=" ") # set end = " " to keep everything on the same line

You may remember from Chapter 3, Lesson 1 that the print() statement can take an optional "end" parameter to replace the default "new line" with some other character such as a space. We've added end=" " to our print() above to keep all the random numbers printed on the same line.

### The randint() Alternative

The random library defines another function called randint() that works very similarly to randrange(). However, the maximum value can be returned by randint(), so randint(0,10) will actually return the value 10 as well as 0 through 9.

random.randint(<min>,<max>)          # returns random integer from <min> through <max>
It can be confusing to keep track of two similar functions that behave "almost" the same way. For consistency, we'll use randrange() instead of randint() in our examples and activities. Just be aware of the difference in case you see randint() in someone else's code.

### Seeding the Random Number Generator

It may come as a surprise, but it's hard for computers to produce truly random results. Most random number generators are complex algorithms that give you pseudo-random (or mostly random) results that are good enough for everyday use. These algorithms use some input data as a starting point or seed in order to generate the pseudo-random results.

By default, the random library will use the current time as the starting point for generating random numbers. Since the current time changes continuously, this gives the computer a reasonably "random" seed for the random number generator.

You can set your own starting point by calling the random.seed() function. You can pass any numeric or string value into seed(), and that data will be used internally to initialize the random number generator.

random.seed(<any value>)          # re-initialize random number generator with this seed

The most important thing about seed() is that it allows you to generate the same sequence of "random" numbers each time you call seed() with the same value! For example, you might want a computer game to generate a new random challenge for players at each level, but you want every level to be the same for all players. One way to do this is to seed the random number generator with a known value before you generate each level.

To see this concept in action, look at the code below. We call random.seed() with a known value (simply 1), and then generate 10 random numbers from 0 up through 99. We then call random.seed() again with the same value and generate 10 more random numbers. Run the code to see the results.

Try It Now

import random
random.seed(1) # seed with known value
for i in range(0,10):
print(random.randrange(0,100),end=" ") # print new random number on this line
print("") # go to the next line
random.seed(1) # re-seed with same value
for i in range(0,10):
print(random.randrange(0,100),end=" ") # print new random number on this line

Both sets of random numbers are the same, because the starting seed was the same in each sequence!

### Random Elements from Lists

The random module contains the choice() function, which allows you to get an element at random from an input list or tuple. The input list is not changed but copy of a random element will be returned each time you call random.choice().

random.choice(<list or tuple>)          # get random value from input collection

In the example below, we have defined a tuple with 4 elements. We then use a "for" loop to iteration 10 times, calling random.choice() on the tuple each time and printing the result to the screen.

Try It Now

import random
marbles = ("red","green","blue","yellow") # declare tuple of marble colors
for i in range(0,10):
print(random.choice(marbles), end=" ") # grab and print random element from marbles

When you run this code, you should see 10 random colors printed to the screen. The results will be different on each run because we have not specified any fixed starting seed.

### Shuffling Lists

The random library also allows you to shuffle the contents of a list, putting the elements in a random order. The random.shuffle() function will perform this trick. Of course, shuffle() will not work on tuples, because tuples can't be changed.

random.shuffle(<list>)          # re-order list elements randomly

In the example below, we have defined a list with 10 elements, initially in an obvious order. We then call random.shuffle() to mix up the list contents and print the results to the screen.

Try It Now

import random
countdown = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, "BLASTOFF"] # start with a list in some order
print("Before Shuffle: ",countdown)
random.shuffle(countdown) # mix things up!
print("After Shuffle : ",countdown)

Each time you run this code, the shuffle() function should change the list in a different random order.

### Real (Decimal) Random Numbers

The last common random feature we'll discuss is the generation of random decimal values. Simply call the random() function to produce a value between 0.0 and 1.0. The lower limit 0.0 is a possible output, while you will never get all the way up to 1.0 (but you might get very close as in .99999).

random.random()              # produce random decimal value between 0.0 and 1.0

If you'd rather get a random value within a specific range, you can call the uniform() function with upper and lower bounds.

random.uniform(<min>,<max>)  # produce random decimal value between <min> and <max>

To see these two functions in action, run the code below. We generate three random numbers with random() and then three more with uniform(). The uniform() min and max values are set at -5.0 and 5.0, so you should see random results in that range.

Try It Now

import random
print("random() results:")
for i in range(0,3):
print(random.random())
print("")
print("uniform(-5.0, 5.0) results:")
for i in range(0,3):
print(random.uniform(-5.0, 5.0))

Both random() and uniform() give results that are evenly distributed across the entire range. A value near the minimum or maximum is as likely to be chosen as a value near the middle. The random module has other functions that produce different kinds of results, such as a bell curve where numbers near the middle are the most likely to be chosen. To read more about the random module, click on the link below to see the official Python documentation.

https://docs.python.org/3/library/random.html

Work with Me: Games of Chance

Random values have many useful applications. In this exercise, you are going to shuffle a deck of cards, pull a random card from the deck and flip a coin 5 times to see the results. Here is some sample output.

['Queen', '6', '9', '10', 'Ace', 'King', '5', '2', '7', '4', '8', 'Jack', '3']
Card at index 6 = '5'
Coin-flip results: Tails
Coin-flip results: Tails
Coin-flip results: Heads

Remember, the index into a list is zero-based, so index 6 refers to the 7th element in the list.

We are giving you a little bit of starter code that defines a 13-card list (2 through Ace) and a tuple of coin-flip options ("Heads" and "Tails"). Follow the steps below to finish the code on your own.

1. Shuffle the deck of cards and then print the resulting list to the screen
2. Create a variable called cardIndex and set it equal to a random integer in the range 0 up through and including 12. This integer can be used to pull a specific element at that position from the deck of cards.
3. Create a variable called card and set it equal to the deck element at the cardIndex position (deck[cardIndex]).
4. Print the following formatted message to the screen: "Card at index <X> = '<Card>'". Use str.format() to create the message.
5. Inside the "for" loop (already written for you)
1. Create a variable called flip and set it equal to a random element pulled from the coinFlipOptions tuple. Use the random.choice() function to get a random element.
2. Print the formatted string "Coin-flip results: <flip>"

Try It Now

import random
deck = ["2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace"]
# shuffle the deck
# print the results
# get random card index from 0 through 12
# get and print card at that position
for i in range(0,5):
# get random choice from coinFlipOptions and print results

Console

You should get different results each time you run the program. The example below shows another valid run.

['2', 'Queen', 'Ace', '8', 'King', '5', '6', '9', '4', '3', 'Jack', '7', '10']
Card at index 2 = 'Ace'
Coin-flip results: Tails
Coin-flip results: Tails
Coin-flip results: Tails