3. Control Statements
Objectives
- Make decisions with if, if else and if elif else.
- Execute statements repeatedly with while and for.
- Shorten assignment expressions with augmented assignments.
- Use the for statement and the builtin range function to repeat actions for a sequence of values.
- Perform sentinelcontrolled iteration with while.
- Create compound conditions with the Boolean operators and, or and not.
- Stop looping with break.
- Force the next iteration of a loop with continue.
- Use functionalstyle programming features to write scripts that are more concise, clearer, easier to debug and easier to parallelize.
3.1 INTRODUCTION
We’ll show sentinelcontrolled iteration with the while statement. You’ll use the Python Standard Library’s Decimal type for precise monetary calculations. We’ll format data in fstrings (that is, format strings) using various format specifiers. We’ll also show the Boolean operators and, or and not for creating compound conditions. In the Intro to Data Science section, we’ll consider measures of central tendency—mean, median and mode—using the Python Standard Library’s statistics module.
3.2 CONTROL STATEMENTS
- The if statement performs an action if a condition is True or skips the action if the condition is False.
- The if... else statement performs an action if a condition is True or performs a dif erent action if the condition is False.
- The if... elif... else statement performs one of many different actions, depending on the truth or falsity of several conditions.
Python provides two iteration statements—while and for:
- The while statement repeats an action (or a group of actions) as long as a condition remains True.
- The for statement repeats an action (or a group of actions) for every item in a sequence of items.
Keywords
The words if, elif, else, while, for, True and False are Python keywords. Using a keyword as an identifier such as a variable name is a syntax error. The following table lists Python’s keywords.
Python keywords
as
assert
break
for
in
not
True
3.3 IF STATEMENT
Let’s execute a Python if statement:
In [2]: if grade >= 60:
...: print('Passed')
...:
Passed
The condition grade >= 60 is True, so the indented print statement in the if’s suite displays 'Passed'.
Suite Indentation
Indenting a suite is required; otherwise, an IndentationError syntax error occurs:
...: print('Passed') # statement is not indented properly
File "<ipython-input-3-f42783904220>", line 2
print('Passed') # statement is not indented properly
IndentationError: expected an indented block
An IndentationError also occurs if you have more than one statement in a suite and those statements do not have the same indentation:
...: print('Passed') # indented 4 spaces
...: print('Good job!) # incorrectly indented only two spaces
File <ipython-input-4-8c0d75c127bf>, line 3
print('Good job!) # incorrectly indented only two spaces
^
IndentationError: unindent does not match any outer indentation level
Sometimes error messages may not be clear. The fact that Python calls attention to the line is usually enough for you to figure out what’s wrong. Apply indentation conventions uniformly throughout your code—programs that are not uniformly indented are hard to read.
Every Expression Can Be Interpreted as Either True or False
You can base decisions on any expression. A nonzero value is True. Zero is False:
...: print('Nonzero values are true, so this will print')
...:
Nonzero values are true, so this will print
In [6]: if 0:
...: print('Zero is false, so this will not print')
In [7]:
Strings containing characters are True and empty strings ('', "" or """""") are False.
Confusing == and =
Using the equality operator == instead of = in an assignment statement can lead to subtle problems. For example, in this session, snippet [1] defined grade with the assignment:
grade = 85
If instead we accidentally wrote:
grade == 85
then grade would be undefined and we’d get a NameError. If grade had been defined before the preceding statement, then grade == 85 would simply evaluate to True or False, and not perform an assignment. This is a logic error.
3.4 IF ELSE AND IF ELIF ELSE STATEMENTS
The if else statement executes different suites, based on whether a condition is True or False:
In [2]: if grade >= 60:
...: print('Passed')
...: else:
...: print('Failed')
...:
Passed
You must delete those four spaces so that the else: suite correctly aligns under the i in if. The following code assigns 57 to the variable grade, then shows the if else statement again to demonstrate that only the else suite executes when the condition is False:
In [4]: if grade >= 60:
...: print('Passed')
...: else:
...: print('Failed')
...:
Failed
Use the up and down arrow keys to navigate backwards and forwards through the current interactive session’s snippets. Pressing Enter reexecutes the snippet that’s displayed. Let’s set grade to 99, press the up arrow key twice to recall the code from snippet [4], then press Enter to reexecute that code as snippet [6]. Every recalled snippet that you execute gets a new ID:
In [6]: if grade >= 60:
...: print('Passed')
...: else:
...: print('Failed')
...:
Passed
Conditional Expressions
Sometimes the suites in an if else statement assign different values to a variable, based on a condition, as in:
In [8]: if grade >= 60:
...: result = 'Passed'
...: else:
...: result = 'Failed'
...:
We can then print or evaluate that variable:
Out[9]: 'Passed'
You can write statements like snippet [8] using a concise conditional expression:
In [11]: result
The parentheses are not required, but they make it clear that the statement assigns the conditional expression’s value to result. First, Python evaluates the condition grade >= 60:
- If it’s True, snippet [10] assigns to result the value of the expression to the left of if, namely 'Passed'. The else part does not execute.
- If it’s False, snippet [10] assigns to result the value of the expression to the right of else, namely 'Failed'.
In interactive mode, you also can evaluate the conditional expression directly, as in:
Out[12]: 'Passed'
Multiple Statements in a Suite
The following code shows two statements in the else suite of an if... else statement:
In [14]: if grade >= 60:
...: print('Passed')
...: else:
...: print('Failed')
...: print('You must take this course again')
...:
Failed
...: print('Passed')
...: else:
...: print('Failed')
...: print('You must take this course again')
...:
Passed
You must take this course again
if... elif... else Statement
You can test for many cases using the if... elif... else statement. The following code displays “A” for grades greater than or equal to 90, “B” for grades in the range 80–89, “C” for grades 70–79, “D” for grades 60–69 and “F” for all other grades. Only the action for the first True condition executes. Snippet [18] displays C, because grade is 77:
In [18]: if grade >= 90:
...: print('A')
...: elif grade >= 80:
...: print('B')
...: elif grade >= 70:
...: print('C')
...: elif grade >= 60:
...: print('D')
...: else:
...: print('F')
...:
C
The first condition—grade >= 90—is False, so print('A') is skipped. The second condition—grade >= 80—also is False, so print('B') is skipped. The third condition—grade >= 70—is True, so print('C') executes. Then all the remaining code in the if... elif... else statement is skipped. An if... elif... else is faster than separate if statements, because condition testing stops as soon as a condition is True.
else Is Optional
The else in the if... elif... else statement is optional. Including it enables you to handle values that do not satisfy any of the conditions. When an if... elif statement without an else tests a value that does not make any of its conditions True, the program does not execute any of the statement’s suites—the next statement in sequence after the if... elif... statement executes. If you specify the else, you must place it after the last elif; otherwise, a SyntaxError occurs.
Logic Errors
The incorrectly indented code segment in snippet [16] is an example of a nonfatal logic error. The code executes, but it produces incorrect results. For a fatal logic error in a script, an exception occurs (such as a ZeroDivisionError from an attempt to divide by 0), so Python displays a traceback, then terminates the script. A fatal error in interactive mode terminates only the current snippet—then IPython waits for your next input.
3.5 WHILE STATEMENT
The while statement allows you to repeat one or more actions while a condition remains True. Let’s use a while statement to find the first power of 3 larger than 50:
In [2]: while product <= 50:
...: product = product * 3
...:
In [3]: product
Out[3]: 81
Something in the while statement’s suite must change product’s value, so the condition eventually becomes False. Otherwise, an infinite loop occurs. In applications executed from a Terminal, Anaconda Command Prompt or shell, type Ctrl + c or control + c to terminate an infinite loop. IDEs typically have a toolbar button or menu option for stopping a program’s execution.
Snippet [3] evaluates product to see its value, 81, which is the first power of 3 larger than 50.
3.6 FOR STATEMENT
In [1]: for character in 'Programming':
...: print(character, end=' ')
...:
P r o g r a m m i n g
The for statement executes as follows:
- Upon entering the statement, it assigns the 'P' in 'Programming' to the target variable between keywords for and in—in this case, character.
- Next, the statement in the suite executes, displaying character’s value followed by two spaces—we’ll say more about this momentarily.
- After executing the suite, Python assigns to character the next item in the sequence (that is, the 'r' in 'Programming'), then executes the suite again.
- This continues while there are more items in the sequence to process. In this case, the statement terminates after displaying the letter 'g', followed by two spaces.
Function print’s end Keyword Argument
print(character, end=' ')
which displays character’s value followed by two spaces. So, all the characters display horizontally on the same line. Python calls end a keyword argument, but end itself is not a Python keyword. Keyword arguments are sometimes called named arguments. The end keyword argument is optional. If you do not include it, print uses a newline ('\n') by default. The Style Guide for Python Code recommends placing no spaces around a keyword argument’s =.
Function print’s sep Keyword Argument
In [2]: print(10, 20, 30, sep=', ')
10, 20, 30
To remove the default spaces, use sep='' (that is, an empty string).
3.6.1 Iterables, Lists and Iterators
In [3]: total = 0
In [4]: for number in [2, -3, 0, 17, 9]:
...: total = total + number
...:
In [5]: total
Out[5]: 25
Each sequence has an iterator. The for statement uses the iterator “behind the scenes” to get each consecutive item until there are no more to process. The iterator is like a bookmark—it always knows where it is in the sequence, so it can return the next item when it’s called upon to do so. We cover lists in detail in the “Sequences: Lists and Tuples” chapter. There, you’ll see that the order of the items in a list matters and that a list’s items are mutable (that is, modifiable).
3.6.2 Built-In range Function
In [6]: for counter in range(10):
...: print(counter, end=' ')
...:
0 1 2 3 4 5 6 7 8 9
The function call range(10) creates an iterable object that represents a sequence of consecutive integers starting from 0 and continuing up to, but not including, the argument value (10)—in this case, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. The for statement exits when it finishes processing the last integer that range produces. Iterators and iterable objects are two of Python’s functionalstyle programming features. We’ll introduce more of these throughout the article.
Off-By-One Errors
3.7 AUGMENTED ASSIGNMENTS
for number in [1, 2, 3, 4, 5]:
total = total + number
Snippet [2] reimplements this using an addition augmented assignment (+=) statement:
In [1]: total = 0
In [2]: for number in [1, 2, 3, 4, 5]:
...: total += number # add number to total
...:
In [3]: total
Out[3]: 15
The += expression in snippet [2] first adds number’s value to the current total, then stores the new value in total.
3.8 SEQUENCE-CONTROLLED ITERATION; FORMATTED STRINGS
This section and the next solve two classaveraging problems. Consider the following requirements statement:
A class of ten students took a quiz. Their grades (integers in the range 0 – 100) are 98, 76, 71, 87, 83, 90, 57, 79, 82, 94. Determine the class average on the quiz.
The following script for solving this problem keeps a running total of the grades, calculates the average and displays the result. We placed the 10 grades in a list, but you could input the grades from a user at the keyboard (as we’ll do in the next example) or read them from a file (as you’ll see how to do in the “Files and Exceptions” chapter). We show how to read data from SQL and NoSQL databases in Chapter 16.
3
4 # initialization phase
5 total = 0 # sum of grades
6 grade_counter = 0
7 grades = [98, 76, 71, 87, 83, 90, 57, 79, 82, 94] # list of 10 grades
8
9 # processing phase
10 for grade in grades:
11 total += grade # add current grade to the running total
12 grade_counter += 1 # indicate that one more grade was process
13
14 # termination phase
15 average = total / grade_counter
16 print(f'Class average is {average}')
Class average is 81.7
Lines 5–6 create the variables total and grade_counter and initialize each to 0. Line 7
grades = [98, 76, 71, 87, 83, 90, 57, 79, 82, 94] # list of 10 grades
creates the variable grades and initializes it with a list of 10 integer grades.
The for statement processes each grade in the list grades. Line 11 adds the current grade to the total. Then, line 12 adds 1 to the variable grade_counter to keep track of the number of grades processed so far. Iteration terminates when all 10 grades in the list have been processed. The Style Guide for Python Code recommends placing a blank line above and below each control statement (as in lines 8 and 13). When the for statement terminates, line 15 calculates the average and line 16 displays it. Later in this chapter, we use functionalstyle programming to calculate the average of a list’s items more concisely.
Introduction to Formatted Strings
Line 16 uses the following simple f-string (short for formatted string) to format this script’s result by inserting the value of average into a string:
f'Class average is {average}'
The letter f before the string’s opening quote indicates it’s an fstring. You specify where to insert values by using placeholders delimited by curly braces ({ and }). The placeholder
{average}
converts the variable average’s value to a string representation, then replaces {average} with that replacement text. Replacement-text expressions may contain values, variables or other expressions, such as calculations or function calls. In line 16, we could have used total / grade_counter in place of average, eliminating the need for line 15.
3.9 SENTINEL-CONTROLLED ITERATION
Develop a classaveraging program that processes an arbitrary number of grades each time the program executes.
The requirements statement does not state what the grades are or how many there are, so we’re going to have the user enter the grades. The program processes an arbitrary number of grades. The user enters grades one at a time until all the grades have been entered, then enters a sentinel value (also called a signal value, a dummy value or a flag value) to indicate that there are no more grades.
Implementing Sentinel-Controlled Iteration
The following script solves the class average problem with sentinelcontrolled iteration. Notice that we test for the possibility of division by zero. If undetected, this would cause a fatal logic error. In the “Files and Exceptions” chapter, we write programs that recognize such exceptions and take appropriate actions.
2 """Class average program with sentinelcontrolled iteration."""
3
4 # initialization phase
5 total = 0 # sum of grades
6 grade_counter = 0 # number of grades entered
7
8 # processing phase
9 grade = int(input('Enter grade, 1 to end: ')) # get one grade
10
11 while grade != -1:
12 total += grade
13 grade_counter += 1
14 grade = int(input('Enter grade, 1 to end: '))
15
16 # termination phase
17 if grade_counter != 0:
18 average = total / grade_counter
19 print(f'Class average is {average:.2f}')
20 else:
Enter grade, 1 to end: 97
Enter grade, 1 to end: 88
Enter grade, 1 to end: 72
Enter grade, 1 to end: 1
Class average is 85.67
Program Logic for Sentinel-Controlled Iteration
Next, line 14 inputs another grade from the user and the condition (line 11) is tested again, using the most recent grade entered by the user. The value of grade is always input immediately before the program tests the while condition, so we can determine whether the value just input is the sentinel before processing that value as a grade.
Formatting the Class Average with Two Decimal Places
This example formatted the class average with two digits to the right of the decimal point. In an fstring, you can optionally follow a replacementtext expression with a colon (:) and a format specifier that describes how to format the replacement text. The format specifier .2f (line 19) formats the average as a floating-point number (f) with two digits to the right of the decimal point (.2). In this example, the sum of the grades was 257, which, when divided by 3, yields 85.666666666.... Formatting the average with .2f rounds it to the hundredths position, producing the replacement text 85.67. An average with only one digit to the right of the decimal point would be formatted with a trailing zero (e.g., 85.50). The chapter “Strings: A Deeper Look” discusses many more stringformatting features.
3.10 BUILT-IN FUNCTION RANGE: A DEEPER LOOK
Function range also has two and threeargument versions. As you’ve seen, range’s one-argument version produces a sequence of consecutive integers from 0 up to, but not including, the argument’s value. Function range’s two-argument version produces a sequence of consecutive integers from its first argument’s value up to, but not including, the second argument’s value, as in:
...: print(number, end=' ')
...:
5 6 7 8 9
Function range’s threeargument version produces a sequence of integers from its first argument’s value up to, but not including, the second argument’s value, incrementing by the third argument’s value, which is known as the step:
...: print(number, end=' ')
...:
0 2 4 6 8
If the third argument is negative, the sequence progresses from the first argument’s value down to, but not including the second argument’s value, decrementing by the third argument’s value, as in:
...: print(number, end=' ')
...:
10 8 6 4 2
3.11 USING TYPE DECIMAL FOR MONETARY AMOUNTS
For most scientific and other mathematical applications that use numbers with decimal points, Python’s builtin floating-point numbers work well. For example, when we speak of a “normal” body temperature of 98.6, we do not need to be precise to a large number of digits. When we view the temperature on a thermometer and read it as 98.6, the actual value may be 98.5999473210643. The point here is that calling this number 98.6 is adequate for most body-temperature applications.
In [1]: amount = 112.31
In [2]: print(amount)
112.31
However, if you print amount with 20 digits of precision to the right of the decimal point, you can see that the actual floatingpoint value in memory is not exactly 112.31—it’s only an approximation:
112.31000000000000227374
Many applications require precise representation of numbers with decimal points. Institutions like banks that deal with millions or even billions of transactions per day have to tie out their transactions “to the penny.” Floating-point numbers can represent some but not all monetary amounts with tothepenny precision.
The Python Standard Library provides many predefined capabilities you can use in your Python code to avoid “reinventing the wheel.” For monetary calculations and other applications that require precise representation and manipulation of numbers with decimal points, the Python Standard Library provides type Decimal, which uses a special coding scheme to solve the problem of tothepenny precision. That scheme requires additional memory to hold the numbers and additional processing time to perform calculations but provides the precision required for monetary calculations. Banks also have to deal with other issues such as using a fair rounding algorithm when they’re calculating daily interest on accounts. Type Decimal offers such capabilities.
Importing Type Decimal from the decimal Module
To use type Decimal, you must first import the entire decimal module, as in
import decimal
and refer to the Decimal type as decimal.Decimal, or you must indicate a specific capability to import using from import, as we do here:
In [4]: from decimal import Decimal
This imports only the type Decimal from the decimal module so that you can use it in your code. We’ll discuss other import forms beginning in the next chapter.
Creating Decimals
You typically create a Decimal from a string:
In [6]: principal
Out[6]: Decimal('1000.00')
In [7]: rate = Decimal('0.05')
In [8]: rate
Out[8]: Decimal('0.05')
We’ll soon use these variables principal and rate in a compound-interest calculation.
Decimal Arithmetic
Decimals support the standard arithmetic operators +, , *, /, //, ** and %, as well as the corresponding augmented assignments:
In [10]: y = Decimal('2')
In [11]: x + y
Out[11]: Decimal('12.5')
In [12]: x // y
Out[12]: Decimal('5')
In [13]: x += y
In [14]: x
Out[14]: Decimal('12.5')
You may perform arithmetic between Decimals and integers, but not between Decimals and floating-point numbers.
Compound-Interest Problem Requirements Statement
A person invests $1000 in a savings account yielding 5% interest. Assuming that the person leaves all interest on deposit in the account, calculate and display the amount of money in the account at the end of each year for 10 years. Use the following formula for determining these amounts:
- a = p(1 + r)
- where
- p is the original amount invested (i.e., the principal),
- r is the annual interest rate,
- n is the number of years and
- a is the amount on deposit at the end of the nth year.
Calculating Compound Interest
To solve this problem, let’s use variables principal and rate that we defined in snippets [5] and [7], and a for statement that performs the interest calculation for each of the 10 years the money remains on deposit. For each year, the loop displays a formatted string containing the year number and the amount on deposit at the end of that year:
...: amount = principal * (1 + rate) ** year
...: print(f'{year:>2}{amount:>10.2f}')
...:
1 1050.00
2 1102.50
3 1157.62
4 1215.51
5 1276.28
6 1340.10
7 1407.10
8 1477.46
9 1551.33
10 1628.89
The algebraic expression (1 + r) from the requirements statement is written as
(1 + rate) ** year
where variable rate represents r and variable year represents n.
Formatting the Year and Amount on Deposit
The statement
print(f'{year:>2}{amount:>10.2f}')
The placeholder
{year:>2}
uses the format specifier >2 to indicate that year’s value should be right aligned (>) in a field of width 2—the field width specifies the number of character positions to use when displaying the value. For the singledigit year values 1–9, the format specifier >2 displays a space character followed by the value, thus right aligning the years in the first column. The following diagram shows the numbers 1 and 10 each formatted in a field width of 2:
![]() |
| By JuTT BaDshaH |
The format specifier 10.2f in the placeholder
{amount:>10.2f}
formats amount as a floatingpoint number (f) right aligned (>) in a field width of 10 with a decimal point and two digits to the right of the decimal point (.2). Formatting the amounts this way aligns their decimal points vertically, as is typical with monetary amounts. In the 10 character positions, the three rightmost characters are the number’s decimal point followed by the two digits to its right. The remaining seven character positions are the leading spaces and the digits to the decimal point’s left. In this example, all the dollar amounts have four digits to the left of the decimal point, so each number is formatted with three leading spaces. The following diagram shows the formatting for the value 1050.00:
![]() |
| By JuTT BaDshaH |
3.12 BREAK AND CONTINUE STATEMENTS
The break and continue statements alter a loop’s flow of control. Executing a break statement in a while or for immediately exits that statement. In the following code, range produces the integer sequence 0–99, but the loop terminates when number is 10:
...: if number == 10:
...: break
...: print(number, end=' ')
...:
0 1 2 3 4 5 6 7 8 9
In a script, execution would continue with the next statement after the for loop. The while and for statements each have an optional else clause that executes only if the loop terminates normally—that is, not as a result of a break.
Executing a continue statement in a while or for loop skips the remainder of the loop’s suite. In a while, the condition is then tested to determine whether the loop should continue executing. In a for, the loop processes the next item in the sequence (if any):
...: if number == 5:
...: continue
...: print(number, end=' ')
...:
0 1 2 3 4 6 7 8 9
3.13 BOOLEAN OPERATORS AND, OR AND NOT
The conditional operators >, <, >=, <=, == and != can be used to form simple conditions such as grade >= 60. To form more complex conditions that combine simple conditions, use the and, or and not Boolean operators.
Boolean Operator and
To ensure that two conditions are both True before executing a control statement’s suite, use the Boolean and operator to combine the conditions. The following code defines two variables, then tests a condition that’s True if and only if both simple conditions are True—if either (or both) of the simple conditions is False, the entire and expression is False:
In [2]: age = 70
In [3]: if gender == 'Female' and age >= 65:
...: print('Senior female')
...:
Senior female
The if statement has two simple conditions:
- gender == 'Female' determines whether a person is a female and
- age >= 65 determines whether that person is a senior citizen.
(gender == 'Female') and (age >= 65)
Boolean Operator or
Use the Boolean or operator to test whether one or both of two conditions are True. The following code tests a condition that’s True if either or both simple conditions are True—the entire condition is False only if both simple conditions are False:
In [5]: final_exam = 95
In [6]: if semester_average >= 90 or final_exam >= 90:
...: print('Student gets an A')
...:
Student gets an A
Snippet [6] also contains two simple conditions:
- semester_average >= 90 determines whether a student’s average was an A (90 or above) during the semester, and
- final_exam >= 90 determines whether a student’s finalexam grade was an A.
Improving Performance with Short-Circuit Evaluation
So the condition
gender == 'Female' and age >= 65
Similarly, the condition
semester_average >= 90 or final_exam >= 90
In expressions that use and, make the condition that’s more likely to be False the leftmost condition. In or operator expressions, make the condition that’s more likely to be True the leftmost condition. These techniques can reduce a program’s execution time.
Boolean Operator not
The Boolean operator not “reverses” the meaning of a condition—True becomes False and False becomes True. This is a unary operator—it has only one operand. You place the not operator before a condition to choose a path of execution if the original condition (without the not operator) is False, such as in the following code:
In [8]: if not grade == -1:
...: print('The next grade is', grade)
...:
The next grade is 87
Often, you can avoid using not by expressing the condition in a more “natural” or convenient manner. For example, the preceding if statement can also be written as follows:
...: print('The next grade is', grade)
...:
The next grade is 87
3.14 INTRO TO DATA SCIENCE: MEASURES OF CENTRAL TENDENCY—MEAN, MEDIAN AND MODE
Here we continue our discussion of using statistics to analyze data with several additional descriptive statistics, including:
- mean—the average value in a set of values.
- median—the middle value when all the values are arranged in sorted order.
- mode—the most frequently occurring value.
These are measures of central tendency—each is a way of producing a single value that represents a “central” value in a set of values, i.e., a value which is in some sense typical of the others.
Let’s calculate the mean, median and mode on a list of integers. The following session creates a list called grades, then uses the builtin sum and len functions to calculate the mean “by hand”—sum calculates the total of the grades (397) and len returns the number of grades (5):
In [2]: sum(grades) / len(grades)
Out[2]: 79.4
The previous chapter mentioned the descriptive statistics count and sum—implemented in Python as the builtin functions len and sum. Like functions min and max (introduced in the preceding chapter), sum and len are both examples of functional-style programming reductions—they reduce a collection of values to a single value—the sum of those values and the number of values, respectively. In Section 3.8’s class-average example, we could have deleted lines 10–15 of the script and replaced average in line 16 with snippet [2]’s calculation.
The Python Standard Library’s statistics module provides functions for calculating the mean, median and mode—these, too, are reductions. To use these capabilities, first import the statistics module:
In [3]: import statistics
Then, you can access the module’s functions with “statistics.” followed by the name of the function to call. The following calculates the grades list’s mean, median and mode, using the statistics module’s mean, median and mode functions:
Out[4]: 79.4
In [5]: statistics.median(grades)
Out[5]: 85
In [6]: statistics.mode(grades)
Out[6]: 85
Each function’s argument must be an iterable—in this case, the list grades. To confirm that the median and mode are correct, you can use the builtin sorted function to get a copy of grades with its values arranged in increasing order:
In [7]: sorted(grades)
Out[7]: [45, 85, 85, 89, 93]
The grades list has an odd number of values (5), so median returns the middle value (85). If the list’s number of values is even, median returns the average of the two middle values. Studying the sorted values, you can see that 85 is the mode because it occurs most frequently (twice). The mode function causes a StatisticsError for lists like
[85, 93, 45, 89, 85, 93]
in which there are two or more “most frequent” values. Such a set of values is said to be imodal. Here, both 85 and 93 occur twice.
3.15 WRAP-UP
In this chapter, we discussed Python’s control statements, including if, if... else, if... elif... else, while, for, break and continue. You saw that the for statement performs sequencecontrolled iteration—it processes each item in an iterable, such as a range of integers, a string or a list. You used the builtin function range to generate sequences of integers from 0 up to, but not including, its argument, and to determine how many times a for statement iterates.
You used sentinelcontrolled iteration with the while statement to create a loop that continues executing until a sentinel value is encountered. You used builtin function range’s twoargument version to generate sequences of integers from the first argument’s value up to, but not including, the second argument’s value. You also used the threeargument version in which the third argument indicated the step between integers in a range.
We introduced the Decimal type for precise monetary calculations and used it to calculate compound interest. You used fstrings and various format specifiers to create formatted output. We introduced the break and continue statements for altering the flow of control in loops. We discussed the Boolean operators and, or and not for creating conditions that combine simple conditions.
Finally, we continued our discussion of descriptive statistics by introducing measures of central tendency—mean, median and mode—and calculating them with functions from the Python Standard Library’s statistics module.
In the next chapter, you’ll create custom functions and use existing functions from Python’s math and random modules. We show several predefined functional-programming reductions and you’ll see additional functional-programming capabilities.

