CIS 2020 · Python for Everyone · Module 3 · Study guide
This covers the math module and the vocabulary of a function call, the shorthand operators that combine assignment with arithmetic, and how a program talks to the person running it: reading input, converting it to a number, and printing it back out in a controlled format.
Python keeps a small set of tools in your hand at all times and leaves the rest in a toolbox you have to open first.
A module is a named collection of related functions and values that is not part of the core language. The math module is the one this section cares about: it holds mathematical functions and values that go beyond the arithmetic operators, such as square roots, trigonometric functions, and the constant pi.
Python loads only a small set of functions automatically. A built-in function, such as print, round, or abs, is always available with no preparation. Everything in a module stays out of the way until the program asks for it with an import statement, which is the request that makes a module's names usable in the rest of the program.
There are two forms, and they name the function differently afterward.
from math import sqrt result = sqrt(area) # plain name, because only sqrt was imported import math result = math.sqrt(area) # qualified name, because the whole module was imported
math.sqrt is a qualified name: a name written with the module it belongs to in front of it, joined by a period. Importing one function with from math import sqrt does not import the rest of the module, and import math alone does not let you drop the math. prefix. The form of the import fixes the form of the call.
Using sqrt(area) as the example: a function is a named block of code, written once, that can be called by name to run it. An argument is a value supplied inside the parentheses, the input the function works on; a function may take several, separated by commas, or none at all, in which case the parentheses stay empty. The return value is the result the function hands back to the place it was called from.
A function call is an expression: it stands for a value, so it can appear anywhere a value can, assigned to a variable, combined with an operator, printed, or passed as the argument to another call.
side = 5
area = side ** 2
diagonal = math.sqrt(2 * area) # the call is nested inside another expression
print("diagonal:", diagonal)
| Function | Rule | Needs an import? |
|---|---|---|
| round(x) | Nearest whole number; with a second argument, rounds to that many decimal places | No, built in |
| math.trunc(x) | Discards the fractional part entirely, no matter which whole number is nearer | Yes, import math |
| abs(x) | Magnitude of the number with the sign removed | No, built in |
| math.sqrt(x) | Square root of the argument | Yes, import math |
round and math.trunc disagree whenever the fractional part is large enough to round upward: round(7.8) is 8, but math.trunc(7.8) is 7. math.pi is a module constant, not a function; it is used without parentheses.
Import fails silently at parse time, loudly at run time. Calling sqrt(x) without an import is still a well-formed line, so Python does not complain while reading the file. It only fails when that line actually runs and Python looks for the name sqrt and finds nothing: a NameError, a run-time error, not a syntax error.
A pattern this common in real code earned its own shorthand operators.
Section 2.1 already showed the pattern of updating a variable from its own value:
total = 0 total = total + 2
Because "take a variable, combine it with something, and store the result back in the same variable" comes up constantly, Python provides an augmented assignment operator for every arithmetic operator, that folds the variable name and the arithmetic together into one shorter statement.
total = 0
total += 2 # exactly the same as: total = total + 2
| Shorthand | Same as | Meaning |
|---|---|---|
| x += n | x = x + n | add n to x |
| x -= n | x = x - n | subtract n from x |
| x *= n | x = x * n | multiply x by n |
| x /= n | x = x / n | divide x by n, result is a float |
| x //= n | x = x // n | floor-divide x by n |
| x %= n | x = x % n | replace x with the remainder of x / n |
| x **= n | x = x ** n | raise x to the power n |
Nothing new happens semantically: Python still computes the right-hand side first, using the variable's current value, and then stores the result back. The shorthand only saves you from typing the variable's name twice. It shows up constantly in running totals and counters.
count = 0 total_cost = 0.0 count += 1 # count is now 1 total_cost += 4.99 # total_cost is now 4.99 count += 1 # count is now 2 total_cost += 2.50 # total_cost is now 7.49 average = total_cost / count # 3.745
Getting a value in from the user, and putting a value back out in a shape a person can read.
The input function reads a line of text the user types at the keyboard and returns it. The program pauses at that statement and waits until the user presses Enter. The message displayed to tell the user what to type is the prompt, passed as the argument to input.
name = input("Enter your name: ")
print("Hello,", name)
Without a prompt the program looks like it has frozen, since nothing tells the user anything is expected. By convention a prompt ends with a space, or a colon and a space, so the typed response does not run into the message.
input always returns a string. Even when the user types digits, what comes back is a string of characters, not a number. Nothing about typing digits makes the result numeric; the type is fixed by the function, not by what the user happens to type.
Because input returns a string, a value read for arithmetic has to be converted before it is usable. int(text) converts a string of digits into an integer; float(text) converts a string into a floating-point number. Use int when the quantity is necessarily whole, such as a count of items, and float when a fractional part is meaningful, such as a price.
count = int(input("How many packs? "))
price = float(input("Price per pack: $"))
total = count * price
print("Total: $", total)
The book's advice is don't wait to convert: convert right where the value is read, rather than storing the raw string and converting later. Converting immediately means every variable holds the type it looks like it holds, which avoids a variable that appears numeric but is secretly a string, a mistake that usually surfaces much later and far from where it started.
If the user types something that is not a number, such as their name where a price was expected, the conversion raises a ValueError and the program stops. This is a run-time error: the statement is legal, and whether it fails depends entirely on what was typed.
Printing a value directly shows however Python happens to represent it, which can mean a price with one decimal digit on one line and fifteen on the next, with nothing lining up. Formatted output gives the programmer control over exactly how a value is displayed.
A format string mixes ordinary text with one or more format specifiers: placeholders that begin with % and end with a letter naming the type of value, with optional width and precision in between. %d is for an integer, %f is for a float, and %s is for a string. The format string sits to the left of the % operator; the value or values to format sit to the right, grouped in parentheses when there is more than one.
price = 4.5
quantity = 3
print("%s packs at $%.2f each" % ("Cola", price))
print("Total: $%.2f" % (price * quantity))
# output:
# Cola packs at $4.50 each
# Total: $13.50
In %10.2f, the 10 is the field width: the minimum number of character positions the value should occupy, padded with spaces and right justified if it needs fewer. The .2 is the precision: the number of digits shown after the decimal point, rounded for display only, the stored value is untouched. Field width is a minimum, not a maximum, so a wider value is never cut off, it just breaks the column alignment.
for price in (4.5, 129.0, 3.25):
print("$%10.2f" % price)
# output:
# $4.50
# $129.00
# $3.25
This % is not the remainder operator. Section 2.2 uses % between two numbers to mean remainder. Here, applied between a string and a value, it means format. The same symbol does two unrelated things depending on what sits to its left.
math besides round and abs, needs one.from math import sqrt gives you sqrt(x). import math gives you math.sqrt(x), a qualified name. You cannot mix the two forms of call.round rounds to the nearest whole number; math.trunc just drops the fraction. They disagree whenever rounding would move the value up.+= -= *= /= //= %= **=, means "combine with the current value, then store the result back." x += n is exactly x = x + n.input always returns a string, no matter what the user types. Convert it immediately with int() or float() if you need a number.%d is an integer, %f is a float, %s is a string. In %10.2f, 10 is the field width and 2 is the precision.