Objectives
In this chapter, you’ll:
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 built-in range
function to repeat actions for a sequence of values.
Perform sentinel-controlled 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 functional-style programming features to write scripts that are more concise, clearer, easier to debug and easier to parallelize.
Outline
3.4 if else
and if elif else
Statements
3.6.1 Iterables, Lists and Iterators
3.8 Sequence-Controlled Iteration; Formatted Strings
3.9 Sentinel-Controlled Iteration
3.10 Built-In Function range
: A Deeper Look
3.11 Using Type Decimal
for Monetary Amounts
3.12 break
and continue
Statements
3.13 Boolean Operators and
, or
and not
3.14 Intro to Data Science: Measures of Central Tendency—Mean, Median and Mode
In this chapter, we present Python’s control statements—if
, if
else
, if
elif
else
, while
, for
, break
and continue
. You’ll use the for
statement to perform sequence-controlled- iteration—you’ll see that the number of items in a sequence of item determines the for
statement’s number of iterations. You’ll use the built-in function range
to generate sequences of integers.
We’ll show sentinel-controlled iteration with the while
statement. You’ll use the Python Standard Library’s Decimal
type for precise monetary calculations. We’ll format data in f-strings (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.
Python provides three selection statements that execute code based on a condition that evaluates to either True
or False
:
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 different 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.
Anywhere a single action can be placed, a group of actions can be placed.
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.
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 |
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if
StatementLet’s execute a Python if
statement:
In [1]: grade =85
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'
.
Indenting a suite is required; otherwise, an IndentationError
syntax error occurs:
In [3]:if
grade >=60
: ...: print('Passed'
)# statement is not indented properly
File "<ipython-input-3-f42783904220>", line 2print('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:
In [4]:if
grade >=60
: ...: print('Passed'
)# indented 4 spaces
...: print('Good job!
)# incorrectly indented only two spaces
File <ipython-input-4-8c0d75c127bf>, line 3print('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.
True
or False
You can base decisions on any expression. A nonzero value is True
. Zero is False
:
In [5]:if 1
: ...: 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
.
==
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.
if else
and if
elif
else
StatementsThe if
else
statement executes different suites, based on whether a condition is True
or False
:
In [1]: grade =85
In [2]:if
grade >=60
: ...: print('Passed'
) ...:else
: ...: print('Failed'
) ...: Passed
The condition above is True
, so the if
suite displays 'Passed'
. Note that when you press Enter after typing print('Passed')
, IPython indents the next line four spaces. 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 [3]: grade =57
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 re-executes 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 re-execute that code as snippet [6]
. Every recalled snippet that you execute gets a new ID:
In [5]: grade =99
In [6]:if
grade >=60
: ...: print('Passed'
) ...:else
: ...: print('Failed'
) ...: Passed
Sometimes the suites in an if
else
statement assign different values to a variable, based on a condition, as in:
In [7]: grade =87
In [8]:if
grade >=60
: ...: result ='Passed'
...:else
: ...: result ='Failed'
...:
We can then print
or evaluate that variable:
In [9]: result Out[9]: 'Passed'
You can write statements like snippet [8]
using a concise conditional expression:
In [10]: result = ('Passed' if
grade >=60 else 'Failed'
) In [11]: result Out[11]: 'Passed'
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:
In [12]:'Passed' if
grade >=60
else'Failed'
Out[12]: 'Passed'
The following code shows two statements in the else
suite of an if...
else
statement:
In [13]: grade =49
In [14]:if
grade >=60
: ...: print('Passed'
) ...:else
: ...: print('Failed'
) ...: print('You must take this course again'
) ...: Failed You must take this course again
In this case, grade
is less than 60
, so both statements in the else
’s suite execute.
If you do not indent the second print
, then it’s not in the else
’s suite. So, that statement always executes, possibly creating strange incorrect output:
In [15]: grade =100
In [16]:if
grade >=60
: ...: print('Passed'
) ...:else
: ...: print('Failed'
) ...: print('You must take this course again'
) ...: Passed You must take this course again
if...
elif...
else
StatementYou 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 [17]: grade =77
In [18]:if
grade >=90
: ...:'A'
) ...:elif
grade >=80
: ...:'B'
) ...:elif
grade >=70
: ...:'C'
) ...:elif
grade >=60
: ...:'D'
) ...:else
: ...:'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 OptionalThe 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.
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 Zero-DivisionError
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.
while
StatementThe 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 [1]: product =3
In [2]:while
product <=50
: ...: product = product *3
...: In [3]: product Out[3]: 81
Snippet [3]
evaluates product
to see its value, 81
, which is the first power of 3
larger than 50
.
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.
for
StatementThe for
statement allows you to repeat an action or several actions for each item in a sequence of items. For example, a string is a sequence of individual characters. Let’s display 'Programming'
with its characters separated by two spaces:
In [1]:for
characterin '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.
Using the target variable in the suite, as we did here to display its value, is common but not required.
print
’s end
Keyword ArgumentThe built-in function print
displays its argument(s), then moves the cursor to the next line. You can change this behavior with the argument end
, as in
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 ('
'
) by default. The Style Guide for Python Code recommends placing no spaces around a keyword argument’s =
.
print
’s sep
Keyword ArgumentYou can use the keyword argument sep
(short for separator) to specify the string that appears between the items that print
displays. When you do not specify this argument, print
uses a space character by default. Let’s display three numbers, each separated from the next by a comma and a space, rather than just a space:
In [2]: print(10
,20
,30
, sep=', '
) 10, 20, 30
To remove the default spaces, use sep=''
(that is, an empty string).
The sequence to the right of the for
statement’s in
keyword must be an iterable—that is, an object from which the for
statement can take one item at a time until no more items remain. Python has other iterable sequence types besides strings. One of the most common is a list, which is a comma-separated collection of items enclosed in square brackets ([
and ]
). The following code totals five integers in a list:
In [3]: total =0
In [4]:for
numberin
[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).
range
FunctionLet’s use a for
statement and the built-in range
function to iterate precisely 10
times, displaying the values from 0
through 9
:
In [6]:for
counterin
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 functional-style programming features. We’ll introduce more of these throughout the book.
A common type of off-by-one error occurs when you assume that range
’s argument value is included in the generated sequence. For example, if you provide 9
as range
’s argument when trying to produce the sequence 0
through 9
, range
generates only 0
through 8
.
Augmented assignments abbreviate assignment expressions in which the same variable name appears on the left and right of the assignment’s =
, as total
does in:
for
numberin
[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
numberin
[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
. The table below shows sample augmented assignments:
Augmented assignment |
Sample expression |
Explanation |
Assigns |
Assume: |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This section and the next solve two class-averaging 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.
1# class_average.py
2"""Class average program with sequence-controlled iteration."""
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
10for
gradein
grades: 11 total += grade# add current grade to the running total
12 grade_counter +=1
# indicate that one more grade was processed
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 functional-style programming to calculate the average of a list’s items more concisely.
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 f-string. 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.
Let’s generalize the class-average problem. Consider the following requirements statement:
Develop a class-averaging 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.
The following script solves the class average problem with sentinel-controlled 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.
1# class_average_sentinel.py
2"""Class average program with sentinel-controlled 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 11while
grade !=-1
: 12 total += grade 13 grade_counter +=1
14 grade = int(input('Enter grade, -1 to end: '
)) 15 16# termination phase
17if
grade_counter !=0
: 18 average = total / grade_counter 19 print(f'Class average is
{average:.2
f}'
) 20else
: 21 print('No grades were entered'
)
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
In sentinel-controlled iteration, the program reads the first value (line 9) before reaching the while
statement. The value input in line 9 determines whether the program’s flow of control should enter the while
’s suite (lines 12–14). If the condition in line 11 is False
, the user entered the sentinel value (-1
), so the suite does not execute because the user did not enter any grades. If the condition is True
, the suite executes, adding the grade
value to the total
and incrementing the grade_counter
.
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.
When the sentinel value is input, the loop terminates, and the program does not add –1 to total
. In a sentinel-controlled loop that performs user input, any prompts (lines 9 and 14) should remind the user of the sentinel value.
This example formatted the class average with two digits to the right of the decimal point. In an f-string, you can optionally follow a replacement-text 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 string-formatting features.
range
: A Deeper LookFunction range
also has two- and three-argument 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:
In [1]:for
numberin
range(5
,10
): ...: print(number, end=' '
) ...: 5 6 7 8 9
Function range
’s three-argument 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:
In [2]:for
numberin
range(0
,10
,2
): ...: 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:
In [3]:for
numberin
range(10
,0
,-2
): ...: print(number, end=' '
) ...: 10 8 6 4 2
Decimal
for Monetary AmountsIn this section, we introduce Decimal
capabilities for precise monetary calculations. If you’re in banking or other fields that require “to-the-penny” accuracy, you should investigate Decimal
’s capabilities in depth.
For most scientific and other mathematical applications that use numbers with decimal points, Python’s built-in 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.
Floating-point values are stored in binary format (we introduced binary in the first chapter and discuss it in depth in the online “Number Systems” appendix). Some floating-point values are represented only approximately when they’re converted to binary. For example, consider the variable amount
with the dollars-and-cents value 112.31
. If you display amount
, it appears to have the exact value you assigned to it:
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 floating-point value in memory is not exactly 112.31
—it’s only an approximation:
In [3]: print(f'
{amount:.20
f}'
) 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 to-the-penny precision.
The Python Standard Library1 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 to-the-penny 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.2
1https://docs.python.org/3.7/library/index.html
.
2For more decimal
module features, visit https://docs.python.org/3.7/library/decimal.html
.
Decimal
from the decimal
ModuleWe’ve used several built-in types—int
(for integers, like 10
), float
(for floating-point numbers, like 7.5
) and str
(for strings like 'Python'
). The Decimal
type is not built into Python. Rather, it’s part of the Python Standard Library, which is divided into groups of related capabilities called modules. The decimal
module defines type Decimal
and its capabilities.
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
decimalimport
Decimal
This import
s 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.
Decimal
sYou typically create a Decimal
from a string:
In [5]: principal = Decimal('1000.00'
) 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
ArithmeticDecimal
s support the standard arithmetic operators +
, -
, *
, /
, //
, **
and %
, as well as the corresponding augmented assignments:
In [9]: x = Decimal('10.5'
) 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 Decimal
s and integers, but not between Decimal
s and floating-point numbers.
Let’s compute compound interest using the Decimal
type for precise monetary calculations. Consider the following 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)n
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.
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:
In [15]:for
yearin
range(1
,11
): ...: amount = principal * (1
+ rate) ** year ...: print(f'
{year:>2
}{amount:>10.2
f}'
) ...: 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)n from the requirements statement is written as
(1
+ rate) ** year
where variable rate
represents r and variable year
represents n.
The statement
print(f'
{year:>2}{amount:>10.2f}'
)
uses an f-string with two placeholders to format the loop’s output.
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 single-digit year
values 1
–9
, the format specifier >2
displays a space character followed by the value, thus right aligning the year
s in the first column. The following diagram shows the numbers 1 and 10 each formatted in a field width of 2:
You can left align values with <.
The format specifier 10.2f
in the placeholder
{amount:>10.2f}
formats amount
as a floating-point 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 amount
s 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
:
break
and continue
StatementsThe 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
:
In [1]:for
numberin
range(100
): ...: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):
In [2]:for
numberin
range(10
): ...:if
number ==5
: ...:continue
...: print(number, end=' '
) ...: 0 1 2 3 4 6 7 8 9
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.
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 [1]: gender ='Female'
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.
The simple condition to the left of the and
operator evaluates first because ==
has higher precedence than and
. If necessary, the simple condition to the right of and
evaluates next, because >=
has higher precedence than and
. (We’ll discuss shortly why the right side of an and
operator evaluates only if the left side is True
.) The entire if
statement condition is True
if and only if both of the simple conditions are True
. The combined condition can be made clearer by adding redundant parentheses
(gender =='Female'
)and
(age >=65
)
The table below summarizes the and
operator by showing all four possible combinations of False
and True
values for expression1 and expression2—such tables are called truth tables:
expression1 |
expression2 |
expression1 |
|
|
|
|
|
|
|
|
|
|
|
|
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 [4]: semester_average =83
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 final-exam grade was an A
.
The truth table below summarizes the Boolean or
operator. Operator and
has higher precedence than or
.
expression1 |
expression2 |
expression1 |
|
|
|
|
|
|
|
|
|
|
|
|
Python stops evaluating an and
expression as soon as it knows whether the entire condition is False
. Similarly, Python stops evaluating an or
expression as soon as it knows whether the entire condition is True
. This is called short-circuit evaluation. So the condition
gender =='Female' and
age >=65
stops evaluating immediately if gender
is not equal to 'Female'
because the entire expression must be False
. If gender
is equal to 'Female'
, execution continues, because the entire expression will be True
if the age
is greater than or equal to 65
.
Similarly, the condition
semester_average >=90 or
final_exam >=90
stops evaluating immediately if semester_average
is greater than or equal to 90
because the entire expression must be True
. If semester_average
is less than 90
, execution continues, because the expression could still be True
if the final_exam
is greater than or equal to 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.
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 [7]: grade =87
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:
In [9]:if
grade !=-1
: ...: print('The next grade is'
, grade) ...: The next grade is 87
The truth table below summarizes the not
operator.
expression |
|
|
|
|
|
The following table shows the precedence and grouping of the operators introduced so far, from top to bottom, in decreasing order of precedence.
Operators |
Grouping |
|
left to right |
|
right to left |
|
left to right |
|
left to right |
|
left to right |
|
left to right |
|
left to right |
|
left to right |
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 built-in 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 [1]: grades = [85
,93
,45
,89
,85
] 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 built-in 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:
In [4]: statistics.mean(grades) 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 built-in 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 bimodal. Here, both 85
and 93
occur twice.
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 sequence-controlled iteration—it processes each item in an iterable, such as a range of integers, a string or a list. You used the built-in 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 sentinel-controlled iteration with the while
statement to create a loop that continues executing until a sentinel value is encountered. You used built-in function range
’s two-argument 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 three-argument 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 f-strings 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.
18.118.126.11