Borrowing code with import¶
Goal: import a module from Python's standard library, find out what it offers, and use it in your own programs.
Why this matters¶
So far you have written nearly every line of your programs yourself. Professional programmers do not work that way. Most of any real program is code that somebody else wrote, tested, and gave away, and the skill is in knowing how to find it and use it. Python comes with a large collection of this ready-made code. You have dipped into it twice already. This lesson shows you how it works, and how to find your way around it on your own.
What a module is¶
Twice in this course you have written a line starting with import. In Module 3, import random gave the guessing
game its secret number. In Module 6, import os let you check whether a file exists.
A module is a file of Python code, mostly functions, that is meant to be used by other programs. random is
a real file called random.py, sitting in the folder where Python was installed. import random tells Python to find
that file, run it, and make everything in it available to you under the name random.
The modules that are installed along with Python are called the standard library. There are around two hundred of them, for everything from dates to zip files, and they are on every computer that has Python. Nothing to download, nothing to pay for. This module of the course is a tour of the most useful ones.
The math module¶
Python's operators cover everyday arithmetic. For anything more, there is math:
import math
print(math.sqrt(49))
print(math.floor(7.8))
print(math.ceil(7.2))
print(math.pi)
radius = 3
area = math.pi * radius ** 2
print(f"A circle with radius {radius} has an area of {round(area, 2)}.")
math.sqrt()gives a square root, always as a float.math.floor()rounds down to a whole number, andmath.ceil()rounds up. The names are the floor and the ceiling of a room. Compareround(), which goes to the nearest.math.piis not a function. It is a value, stored in a variable inside the module, so there are no parentheses after it. Modules can hold variables as well as functions.
The dot means what it has always meant: math.sqrt is the sqrt that lives inside math. You have to write the
math. part every time. That can look like extra typing, but it tells anyone reading the program exactly where sqrt
came from.
Importing just what you need¶
There is a second way to import, which picks out particular names:
from math import sqrt, pi brings in only those two names, and brings them in directly, so you write sqrt(49) with
no math. in front. The other side of the bargain is that math itself is not imported: writing math.floor(7.8)
in this program would be a NameError.
Which one should you use?
import mathis the safe default. Every use saysmath.so a reader always knows where a function came from, and the module's names cannot collide with your own variables.from math import sqrtreads well when you use one or two names many times, and the names are clear on their own.sqrtis clear. A barechoice(...)orload(...)in the middle of a long program is not.
Avoid from math import *
You will see this in old tutorials. The star means everything, so it pours dozens of names into your program at once. You no longer know which names are taken, and a module's function can silently replace one of yours. Name what you import.
More from random¶
You know random.randint(). The module has other tools that are just as useful:
import random
print(random.randint(1, 6))
snacks = ["apple", "crisps", "chocolate", "nuts"]
print(random.choice(snacks))
random.shuffle(snacks)
print(snacks)
print(random.random())
Your output will differ, since it is random.
random.choice(a_list)picks one item from a list. It works on strings too, picking one character.random.shuffle(a_list)puts a list into random order. Like.sort()in Module 4, it changes the list itself and returnsNone. So you call it on its own line, as above, and never writesnacks = random.shuffle(snacks).random.random()gives a float from 0 up to, but not including, 1. It is useful for chances:if random.random() < 0.25:is true about a quarter of the time.
Finding out what a module can do¶
Nobody memorises the standard library. What experienced programmers have is the habit of looking things up, and that habit is the real subject of this lesson. There are three places to look.
1. help() shows the docstring of any function, as you saw in Module 5. It works on functions inside modules too:
Help on method choice in module random:
choice(seq) method of random.Random instance
Choose a random element from a non-empty sequence.
Help on method randint in module random:
randint(a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
Some of that is jargon you have not met, such as method of random.Random instance. Skip it. Reading documentation
does not mean understanding every word. It means finding the two things you need: the parameters, here seq, short
for sequence, meaning a list or a string, and the sentence that says what the function does. Notice that the
second entry answers a question you might really have: does randint(1, 6) ever return 6? Including both end points. Yes.
2. dir() lists every name inside a module:
['__doc__', '__loader__', '__name__', ... 'ceil', 'comb', 'copysign', 'cos', ... 'floor', ... 'gcd', 'hypot', ...
'log', 'log10', ... 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', ... 'trunc', 'ulp']
The real list is much longer, and it is shortened here. Ignore the names with underscores, which Python uses for
itself. The rest is a menu. When a name looks promising, ask help() about it.
3. The official documentation at docs.python.org/3/library has a page for every module, with explanations and examples. It is written for working programmers, so parts of it will be over your head for now. Use it the same way: search the page for the word you care about, read that entry, and leave the rest.
Project: a password generator¶
Here is how this works in practice. You want a program that makes random passwords. You know random.choice() can
pick a character from a string, so you need a string containing all the letters and digits. You could type out the
alphabet. But this feels like something Python would already have, and a quick search of the web for
python all letters leads to the string module:
import random
import string
def make_password(length):
"""Return a random password of letters and digits."""
characters = string.ascii_letters + string.digits
password = ""
for i in range(length):
password += random.choice(characters)
return password
print(string.ascii_letters)
print(string.digits)
print()
for i in range(3):
print(make_password(12))
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
aBdMLQrrAobg
ypTD59o2VRj7
QQiEdCdmUchZ
string.ascii_letters and string.digits are values, like math.pi, so no parentheses. The function builds the
password one character at a time, with a loop you could have written in Module 3. Two imports and one loop, and the
program is done. The module is called string because it holds helpers for working with strings. It is not the same
thing as the str type, even though the names are close.
When a program needs several modules, give each its own import line at the top of the file.
Do not use this for your bank account
random is built for games and simulations, not for security. For passwords that really matter, Python has a
separate module called secrets, and a password manager is better still.
Try it¶
Write a program that imports math and prints the square root of 2, then 2 to the power of 0.5 using **, and compare
the two. Next, run help(math.isqrt), ignore the / in its first line, and work out from the description what
math.isqrt(50) will give. Then check. Finally, make a list of five things you could have for dinner and let random.choice() decide.
Common mistakes¶
ModuleNotFoundError: No module named 'maths'
The module name is misspelled. It is math, without an s. Module names are all lower case.
NameError: name 'math' is not defined. Did you forget to import 'math'?
Python has guessed correctly: there is no import math at the top of the file. You get the same error if you
wrote from math import sqrt and then used math.pi, because that kind of import does not create the name math.
NameError: name 'sqrt' is not defined
You wrote import math and then called sqrt(49) on its own. Write math.sqrt(49), or import it with
from math import sqrt.
AttributeError: module 'math' has no attribute 'squareroot'
An attribute is a name that lives inside something, which is what comes after the dot. This error means the
module exists but has nothing called that. Check the spelling with dir(math). If the name is close, Python
suggests the right one: Did you mean: 'sqrt'?
AttributeError: module 'random' has no attribute 'randint'
But it does! This is the trap from Module 3: you have saved one of your own files as random.py, and
import random found yours first. Never give your files the name of a module: not random.py, math.py,
or string.py. Rename the file, and delete any __pycache__ folder next to it.
TypeError: 'float' object is not callable
You wrote math.pi(). pi is a value, not a function, so it takes no parentheses.
My list turned into None
You wrote cards = random.shuffle(cards). shuffle() changes the list and returns None. Put it on a line of its own.
ValueError: math domain error
You asked math for something that has no answer, such as math.sqrt(-4). Check the number before you pass it,
or catch the ValueError.
Exercises¶
- Circle. Ask for a radius and print the area and the circumference of the circle, each rounded to 2 decimal places. The area is pi times the radius squared, and the circumference is 2 times pi times the radius.
- Tins of paint. One tin of paint covers 5 square metres. Ask for the width and height of a wall, and print how many tins to buy. You cannot buy part of a tin. Test it with a wall of 4.5 by 2.4, and one of exactly 5 by 2.
- Coin flips. Flip a coin 1000 times using
random.choice()and count the heads and the tails in a dictionary. Run it several times. How close to 500 does it get? - Find it yourself. To simplify a fraction such as 12/18, you divide the top and the bottom by their greatest
common divisor, the largest number that divides both. Here that is 6, which gives 2/3. The
mathmodule has a function for this. Find it usingdir(),help(), or the documentation, then write a program that asks for the top and bottom of a fraction and prints the simplified version.
Solution 1
import math
radius = float(input("Radius: "))
area = math.pi * radius ** 2
circumference = 2 * math.pi * radius
print(f"Area: {round(area, 2)}")
print(f"Circumference: {round(circumference, 2)}")
A radius of 3 gives an area of 28.27 and a circumference of 18.85. To make it survive bad input, swap in the
ask_for_float() you wrote in Module 7.
Solution 2
import math
COVERAGE_PER_TIN = 5 # square metres
width = float(input("Wall width in metres: "))
height = float(input("Wall height in metres: "))
area = width * height
tins = math.ceil(area / COVERAGE_PER_TIN)
print(f"The wall is {round(area, 1)} square metres.")
print(f"You need {tins} tins of paint.")
The first wall is 10.8 square metres, which is 2.16 tins, so math.ceil() rounds up to 3. round() would have said
2 and left part of the wall bare. The second wall needs exactly 2 tins, and math.ceil(2.0) is 2: it only rounds up
when there is something to round.
Solution 3
import random
counts = {"heads": 0, "tails": 0}
for i in range(1000):
side = random.choice(["heads", "tails"])
counts[side] += 1
for side, count in counts.items():
print(f"{side}: {count}")
This is the counting pattern from Module 4. random.choice() picks the key, and that key's count goes up. Expect
results such as 519 and 481: close to 500 each, and almost never exactly 500.
Solution 4
import math
top = int(input("Top of the fraction: "))
bottom = int(input("Bottom of the fraction: "))
divisor = math.gcd(top, bottom)
print(f"{top}/{bottom} = {top // divisor}/{bottom // divisor}")
The function is math.gcd(). In the output of dir(math) the name gcd is the clue, and help(math.gcd) confirms
it. // is used for the division so that the results are whole numbers: 2/3, not 2.0/3.0. If you found the
function on your own, you have learned the most important thing in this lesson.
Summary¶
- A module is a file of ready-made code. The standard library is the set of modules that comes with Python.
import mathloads a module, and you use its contents with a dot:math.sqrt(49),math.pi.from math import sqrtimports a name directly. Prefer plainimport, and never useimport *.random.choice()picks an item,random.shuffle()reorders a list in place,random.random()gives a float below 1.- You do not need to memorise modules. Use
dir()for the menu,help()for the details, and docs.python.org for the rest. - Never name your own file after a module.