Files
CSC110/full.html
Hykilpikonna 6fffdf686a deploy
2021-12-07 22:28:01 -05:00

13716 lines
1.7 MiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<meta name="author" content="David Liu and Mario Badr" />
<title>CSC110 Course Notes</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
</style>
<link rel="stylesheet" href="./tufte.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<div style="display:none">
\(
\newcommand{\NOT}{\neg}
\newcommand{\AND}{\wedge}
\newcommand{\OR}{\vee}
\newcommand{\XOR}{\oplus}
\newcommand{\IMP}{\Rightarrow}
\newcommand{\IFF}{\Leftrightarrow}
\newcommand{\TRUE}{\text{True}\xspace}
\newcommand{\FALSE}{\text{False}\xspace}
\newcommand{\IN}{\,{\in}\,}
\newcommand{\NOTIN}{\,{\notin}\,}
\newcommand{\TO}{\rightarrow}
\newcommand{\DIV}{\mid}
\newcommand{\NDIV}{\nmid}
\newcommand{\MOD}[1]{\pmod{#1}}
\newcommand{\MODS}[1]{\ (\text{mod}\ #1)}
\newcommand{\N}{\mathbb N}
\newcommand{\Z}{\mathbb Z}
\newcommand{\Q}{\mathbb Q}
\newcommand{\R}{\mathbb R}
\newcommand{\C}{\mathbb C}
\newcommand{\cA}{\mathcal A}
\newcommand{\cB}{\mathcal B}
\newcommand{\cC}{\mathcal C}
\newcommand{\cD}{\mathcal D}
\newcommand{\cE}{\mathcal E}
\newcommand{\cF}{\mathcal F}
\newcommand{\cG}{\mathcal G}
\newcommand{\cH}{\mathcal H}
\newcommand{\cI}{\mathcal I}
\newcommand{\cJ}{\mathcal J}
\newcommand{\cL}{\mathcal L}
\newcommand{\cK}{\mathcal K}
\newcommand{\cN}{\mathcal N}
\newcommand{\cO}{\mathcal O}
\newcommand{\cP}{\mathcal P}
\newcommand{\cQ}{\mathcal Q}
\newcommand{\cS}{\mathcal S}
\newcommand{\cT}{\mathcal T}
\newcommand{\cV}{\mathcal V}
\newcommand{\cW}{\mathcal W}
\newcommand{\cZ}{\mathcal Z}
\newcommand{\emp}{\emptyset}
\newcommand{\bs}{\backslash}
\newcommand{\floor}[1]{\left \lfloor #1 \right \rfloor}
\newcommand{\ceil}[1]{\left \lceil #1 \right \rceil}
\newcommand{\abs}[1]{\left | #1 \right |}
\newcommand{\xspace}{}
\newcommand{\proofheader}[1]{\underline{\textbf{#1}}}
\)
</div>
<header id="title-block-header">
<h1 class="title">CSC110 Course Notes</h1>
David Liu and Mario Badr
</header>
<h2 class="unnumbered" id="working-with-data">1. Working with Data</h2>
<a id="anchor-01-01"></a>
<header id="title-block-header-573d4e112b">
<h1 class="title">1.1 The Different Types of Data</h1>
</header>
<section>
<p>Data is all around us and the amount of data stored increases every single day. In todays world, decisions must be data-driven and so it is imperative that we be able to process, analyze, and understand the data we collect. Other important factors include the security and privacy of data. Businesses and governments need to answer important questions such as “Where should this data be stored?”; “How should this data be stored?”; and even, “Should this data be stored at all?”. The answers to these questions for Health Canada and personal health data is very different from the answers Nintendo might come up with for the next Animal Crossing game.</p>
<p>We begin our study of computer science by developing definitions for different categories of data. A <strong>data type</strong> is a way of categorizing data. A description of a data type conveys two important pieces of information:</p>
<ol type="1">
<li>The allowed <em>values</em> for a piece of data.</li>
<li>The allowed <em>operations</em> we can perform on a piece of data.</li>
</ol>
<p>For example, we could say that a persons age is a natural number, which would tell us that values like 25 and 100 would be expected, while an age of -2 or “David” would be nonsensical. Knowing that a persons age is a natural number also tells us what operations we could perform (e.g., “add 1 to the age”), and rules out other operations (e.g., “sort these ages alphabetically”).</p>
<p>In this section, well review the common data types that well make great use of in this course: numeric data, boolean data, textual data, and various forms of collections of data. Many terms and definitions may be review from your past studies, but be careful—they may differ slightly from what youve learned before, and it will be important to get these definitions exactly right.</p>
<h2 id="numeric-data-573d4e112b">Numeric data</h2>
<p>Here are some types of numeric data, represented as familiar sets of numbers.</p>
<ul>
<li>A <strong>natural number</strong> is a value from the set <span class="math inline">\(\{0, 1, 2, \dots \}\)</span>. We use the symbol <span class="math inline">\(\N\)</span> to denote the set of natural numbers.<label for="sn-0-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-573d4e112b" class="margin-toggle"/><span class="sidenote"> Note that our convention in computer science is to consider 0 a natural number!</span></li>
<li>An <strong>integer</strong> is a value from the set <span class="math inline">\(\{\dots, -2, -1, 0, 1, 2, \dots \}.\)</span> We use the symbol <span class="math inline">\(\Z\)</span> to denote the set of integers.</li>
<li>A <strong>rational number</strong> is a value from the set <span class="math inline">\(\{\frac{p}{q} \mid p, q \in \Z \text{ and } q \neq 0\}\)</span>—that is, the set of possible fractions. We use the symbol <span class="math inline">\(\Q\)</span> to denote the set of rational numbers.</li>
<li>An <strong>irrational number</strong> is a number with a infinite and non-repeating decimal expansion. Examples are <span class="math inline">\(\pi\)</span>, <span class="math inline">\(e\)</span>, and <span class="math inline">\(\sqrt 2\)</span>. We use the symbol <span class="math inline">\(\overline{\Q}\)</span> to denote the set of irrational numbers.</li>
<li>A <strong>real number</strong> is either a rational or irrational number. We use the symbol <span class="math inline">\(\R\)</span> to denote the set of real numbers.</li>
</ul>
<h3 id="operations-on-numeric-data-573d4e112b">Operations on numeric data</h3>
<p>All numeric data types support the standard arithmetic operations (addition, subtraction, multiplication, division, and exponentiation), as well as the standard comparisons for equality (using <span class="math inline">\(=\)</span>) and inequality (<span class="math inline">\(&lt;\)</span>, <span class="math inline">\(\leq\)</span>, <span class="math inline">\(&gt;\)</span>, <span class="math inline">\(\geq\)</span>). And of course, you are familiar with many more numeric functions, like log and sin; these will come up throughout the course.</p>
<p>One additional arithmetic operation that may be less familiar to you is the <em>modulo operator</em>, which produces the remainder when one integer is divided by another. Well use the percent symbol <span class="math inline">\(\%\)</span> to denote the modulo operator, writing <span class="math inline">\(a \% b\)</span> to mean “the remainder when <span class="math inline">\(a\)</span> is divided by <span class="math inline">\(b\)</span>”. For example, <span class="math inline">\(10 \% 4 = 2\)</span> and <span class="math inline">\(30 \% 3 = 0\)</span>.</p>
<p>Some arithmetic operations are undefined for particular numbers; for example, we cant divide by zero, and we cant take the square root of a negative number.</p>
<h2 id="boolean-data-573d4e112b">Boolean data</h2>
<p>A <strong>boolean</strong> is a value from the set <span class="math inline">\(\{\text{True}, \text{False}\}\)</span>. Think of a boolean value as an answer to a Yes/No question, e.g. “Is this person old enough to vote?”, “Is this country land-locked?”, and “Is this service free?”.</p>
<h3 id="operations-on-boolean-data-573d4e112b">Operations on boolean data</h3>
<p>Booleans can be combined using <em>logical operators</em>. The three most common ones are:</p>
<ul>
<li><strong>not</strong>: reverses the value of a boolean. “not True” is False, and “not False” is True.</li>
<li><strong>and</strong>: takes two boolean values and produces True when both of the values are True, and False otherwise. For example, “True and False” is False, while “True and True” is True.</li>
<li><strong>or</strong>: takes two boolean values and produces True when at least one of the values is True, and False otherwise. For example, “True or False” is True, while “False or False” is False.</li>
</ul>
<p>Next week, well discuss these logical operators in more detail and introduce a few others.</p>
<h2 id="textual-data-573d4e112b">Textual data</h2>
<p>A <strong>string</strong> is an ordered sequence of characters, and is used to represent text. A character can be more than just an English letter (<span class="math inline">\(a\)</span>, <span class="math inline">\(b\)</span>, <span class="math inline">\(c\)</span>, etc.): number digits, punctuation marks, spaces, glyphs from non-English alphabets, and even emojis are all considered characters, and can be part of strings. Examples include a persons name, your chat log, and the script of Shakespeares <em>Romeo and Juliet</em>.</p>
<h3 id="writing-textual-data-573d4e112b">Writing textual data</h3>
<p>We typically will surround strings with single-quotes to differentiate them from any surrounding text, e.g., David.<label for="sn-1-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-573d4e112b" class="margin-toggle"/><span class="sidenote"> We can also use double-quotes (“David”) to surround a string, but in this course we will generally prefer single-quotes for a reason well discuss in Section 1.3.</span></p>
<p>A string can have zero characters; this string is called the <em>empty string</em>, and is denoted by ` or the symbol <span class="math inline">\(\epsilon\)</span>.</p>
<h3 id="operations-on-textual-data-573d4e112b">Operations on textual data</h3>
<p>Here are some common operations on strings.<label for="sn-2-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-573d4e112b" class="margin-toggle"/><span class="sidenote"> <span class="math inline">\(s\)</span>, <span class="math inline">\(s_1\)</span>, and <span class="math inline">\(s_2\)</span> are all variables representing strings.</span></p>
<ul>
<li><p><span class="math inline">\(|s|\)</span>: <strong>string length/size</strong>. Returns the the number of characters in <span class="math inline">\(s\)</span>.</p></li>
<li><p><span class="math inline">\(s_1 = s_2\)</span>: <strong>string equality</strong>. Returns whether <span class="math inline">\(s_1\)</span> and <span class="math inline">\(s_2\)</span> have the same characters, in the same order.</p></li>
<li><p><span class="math inline">\(s + t\)</span>: <strong>string concatenation</strong>. Returns a new string consisting of the characters of <span class="math inline">\(s\)</span> followed by the characters of <span class="math inline">\(t\)</span>. For example, if <span class="math inline">\(s_1\)</span> represents the string Hello and <span class="math inline">\(s_2\)</span> represents the string Goodbye, then <span class="math inline">\(s_1 + s_2\)</span> is the string HelloGoodbye.</p></li>
<li><p><span class="math inline">\(s[i]\)</span>: <strong>string indexing</strong>. Returns the <span class="math inline">\(i\)</span>-th character of <span class="math inline">\(s\)</span>, where indexing starts at 0. (So <span class="math inline">\(s[0]\)</span> returns the first character of <span class="math inline">\(s\)</span>, <span class="math inline">\(s[1]\)</span> returns the second, etc.) For example, if <span class="math inline">\(s\)</span> represents the string Hello, then <span class="math inline">\(s[0]\)</span> is H and <span class="math inline">\(s[4]\)</span> is o.</p></li>
</ul>
<h2 id="set-data-unordered-distinct-values-573d4e112b">Set data (unordered distinct values)</h2>
<p>A <strong>set</strong> is an unordered collection of zero or more distinct values, called its <strong>elements</strong>. Examples include: the set of all people in Toronto; the set of words of the English language; and the set of all countries on Earth.</p>
<h3 id="writing-sets-573d4e112b">Writing sets</h3>
<p>We write sets using curly braces in two different ways:</p>
<ol type="1">
<li>Writing each element of the set within the braces, separated by commas. For example, <span class="math inline">\(\{1, 2, 3\}\)</span> or <span class="math inline">\(\{\text{hi&#39;}, \text{bye&#39;}\}\)</span>.</li>
<li>Using <em>set builder notation</em>, in which we define the form of elements of a set using variables. We saw an example of this earlier when defining the set of rational numbers, <span class="math inline">\(\{\frac{p}{q} \mid p, q \in \Z \text{ and } q \neq 0\}\)</span>.</li>
</ol>
<p>A set can have zero elements; this set is called the <em>empty set</em>, and is denoted by <span class="math inline">\(\{\}\)</span> or the symbol <span class="math inline">\(\emptyset\)</span>.</p>
<h3 id="operations-on-set-data-573d4e112b">Operations on set data</h3>
<p>Here are some common set operations.<label for="sn-3-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-573d4e112b" class="margin-toggle"/><span class="sidenote"><span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span> represent sets.</span></p>
<ul>
<li><p><span class="math inline">\(|A|\)</span>: returns the <strong>size</strong> of set <span class="math inline">\(A\)</span>, i.e., the number of elements in <span class="math inline">\(A\)</span>.</p></li>
<li><p><span class="math inline">\(x \in A\)</span>: returns True when <span class="math inline">\(x\)</span> is an element of <span class="math inline">\(A\)</span>; <span class="math inline">\(y \notin A\)</span> returns True when <span class="math inline">\(y\)</span> is <em>not</em> an element of <span class="math inline">\(A\)</span>.</p></li>
<li><p><span class="math inline">\(A \subseteq B\)</span>: returns True when every element of <span class="math inline">\(A\)</span> is also in <span class="math inline">\(B\)</span>. We say in this case that <span class="math inline">\(A\)</span> is a <strong>subset</strong> of <span class="math inline">\(B\)</span>.</p>
<p>A set <span class="math inline">\(A\)</span> is a subset of itself, and the empty set is a subset of every set: <span class="math inline">\(A \subseteq A\)</span> and <span class="math inline">\(\emptyset \subseteq A\)</span> are always True.</p></li>
<li><p><span class="math inline">\(A = B\)</span>: returns True when <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span> contain the exact same elements.</p></li>
</ul>
<p>The following operations return sets:</p>
<ul>
<li><p><span class="math inline">\(A \cup B\)</span>, the <strong>union</strong> of <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span>. Returns the set consisting of all elements that occur in <span class="math inline">\(A\)</span>, in <span class="math inline">\(B\)</span>, or in both.</p>
<p>Using set builder notation: <span class="math inline">\(A \cup B = \{x \mid x \in A \text{ or } x \in B\}\)</span>.</p></li>
<li><p><span class="math inline">\(A \cap B\)</span>, the <strong>intersection</strong> of <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span>. Returns the set consisting of all elements that occur in both <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span>.</p>
<p>Using set builder notation: <span class="math inline">\(A \cap B = \{x \mid x \in A \text{ and } x \in B\}\)</span>.</p></li>
<li><p><span class="math inline">\(A \setminus B\)</span>, the <strong>difference</strong> of <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span>. Returns the set consisting of all elements that are in <span class="math inline">\(A\)</span> but that are not in <span class="math inline">\(B\)</span>.</p>
<p>Using set builder notation: <span class="math inline">\(A \setminus B = \{x \mid x \in A \text{ and } x \notin B\}.\)</span></p></li>
<li><p><span class="math inline">\(A \times B\)</span>, the <strong>(Cartesian) product</strong> of <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span>. Returns the set consisting of all <em>pairs</em> <span class="math inline">\((a, b)\)</span> where <span class="math inline">\(a\)</span> is an element of <span class="math inline">\(A\)</span> and <span class="math inline">\(b\)</span> is an element of <span class="math inline">\(B\)</span>.</p>
<p>Using set builder notation: <span class="math inline">\(A \times B = \{(x, y) \mid x \in A \text{ and } y \in B\}.\)</span></p></li>
<li><p><span class="math inline">\(\cP(A)\)</span>, the <strong>power set</strong> of <span class="math inline">\(A\)</span>, returns the set consisting of all subsets of <span class="math inline">\(A\)</span>.<label for="sn-4-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-573d4e112b" class="margin-toggle"/><span class="sidenote">Food for thought: what is the relationship between <span class="math inline">\(|A|\)</span> and <span class="math inline">\(|\cP(A)|\)</span>?</span> For example, if <span class="math inline">\(A = \{1,2,3\}\)</span>, then <span class="math display">\[\cP(A) = \big\{ \emptyset, \{1\},\{2\},\{3\},\{1,2\},\{1,3\},\{2,3\},\{1,2,3\}\big\}.\]</span></p>
<p>Using set builder notation: <span class="math inline">\(\cP(A) = \{S \mid S \subseteq A\}\)</span>.</p></li>
</ul>
<h2 id="list-data-ordered-values-573d4e112b">List data (ordered values)</h2>
<p>A <strong>list</strong> is an ordered collection of zero or more (possibly duplicated) values, called its elements. List data is used instead of a set when the elements of the collection should be in a specified order, or if it may contain duplicates. Examples include: the list of all people in Toronto, ordered by age; the list of words of the English language, ordered alphabetically, and the list of names of students at U of T (two students may have the same name!), ordered alphabetically.</p>
<h3 id="writing-lists-573d4e112b">Writing lists</h3>
<p>Lists are written with square brackets enclosing zero or more values separated by commas. For example, <span class="math inline">\([1, 2, 3]\)</span>.</p>
<p>A list can have zero elements; this list is called the <em>empty list</em>, and is denoted by <span class="math inline">\([]\)</span>.</p>
<h3 id="operations-on-list-data-573d4e112b">Operations on list data</h3>
<p>Here are some common list operations.<label for="sn-5-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-573d4e112b" class="margin-toggle"/><span class="sidenote"><span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span> represent lists.</span></p>
<ul>
<li><p><span class="math inline">\(|A|\)</span>: returns the <strong>size</strong> of <span class="math inline">\(A\)</span>, i.e., the number of elements in <span class="math inline">\(A\)</span> (counting all duplicates).</p></li>
<li><p><span class="math inline">\(x \in A\)</span>: same meaning as for sets.</p></li>
<li><p><span class="math inline">\(A = B\)</span>: <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span> have the same elements in the same order.</p></li>
<li><p><span class="math inline">\(A[i]\)</span>: <strong>list indexing</strong>. Returns the <span class="math inline">\(i\)</span>-th element of <span class="math inline">\(A\)</span>, where the indexing starts at 0. So <span class="math inline">\(A[0]\)</span> returns the first element of <span class="math inline">\(A\)</span>, <span class="math inline">\(A[1]\)</span> returns the second, etc.</p></li>
<li><p><span class="math inline">\(A + B\)</span>: <strong>list concatenation</strong>. Returns a new list consisting of the elements of <span class="math inline">\(A\)</span> followed by the elements of <span class="math inline">\(B\)</span>. This is similar to set union, but duplicates are kept, and order is preserved.</p>
<p>For example, <span class="math inline">\([1, 2, 3] + [2, 4, 6] = [1, 2, 3, 2, 4, 6]\)</span>.</p></li>
</ul>
<h2 id="mapping-data-573d4e112b">Mapping data</h2>
<p>Finally, a <strong>mapping</strong> is an unordered collection of pairs of values. Each pair consists of a <em>key</em> and an associated <em>value</em>; the keys must be unique in the mapping, but the values can be duplicated. A key cannot exist in the mapping without a corresponding value.</p>
<p>Mappings are used to represent associations between two collections of data. For example: a mapping from the name of a country to its GDP; a mapping from student number to name; and a mapping from food item to price.</p>
<h3 id="writing-mappings-573d4e112b">Writing mappings</h3>
<p>We use curly braces to represent a mapping.<label for="sn-6-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-573d4e112b" class="margin-toggle"/><span class="sidenote"> This is similar to sets, because mappings are quite similar to sets. Both data types are unordered, and both have a uniqueness constraint (a sets elements are unique; a mappings keys are unique).</span> Each key-value pair in a mapping is written using a colon, with the key on the left side of the colon and its associated value on the right. For example, here is how we could write a mapping representing the menu items of a restaurant: <span class="math display">\[\{\text{`fries&#39;}: 5.99, \text{`steak&#39;}: 25.99, \text{`soup&#39;}: 8.99\}.\]</span></p>
<h3 id="operations-on-mappings-573d4e112b">Operations on mappings</h3>
<p>Here are some common set operations.<label for="sn-7-573d4e112b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7-573d4e112b" class="margin-toggle"/><span class="sidenote"><span class="math inline">\(M\)</span> and <span class="math inline">\(N\)</span> represent mappings.</span></p>
<ul>
<li><span class="math inline">\(|M|\)</span>: returns the <strong>size</strong> of the mapping <span class="math inline">\(M\)</span>, i.e., the number of key-value pairs in <span class="math inline">\(M\)</span>.</li>
<li><span class="math inline">\(M = N\)</span>: returns whether two mappings are equal, i.e., when they contain exactly the same key-value pairs.</li>
<li><span class="math inline">\(k \in M\)</span>: returns whether <span class="math inline">\(k\)</span> is a <em>key</em> contained in the mapping <span class="math inline">\(M\)</span>.</li>
<li><span class="math inline">\(M[k]\)</span>: when <span class="math inline">\(k\)</span> is a key in <span class="math inline">\(M\)</span>, this operation returns the value that corresponds to <span class="math inline">\(k\)</span> in the mapping <span class="math inline">\(M\)</span>.</li>
</ul>
<h2 id="and-more-573d4e112b">…and more!</h2>
<p>The data types weve studied so far are not the only kinds of data that we encounter in the real world, but they do form a basis for representing all kinds of more complex data. Well study how to represent more complex forms of data later in this course, but heres one teaser: representing image data.</p>
<p><img src="images/chelsea_channels.png" alt="Chelsea Cat Split by Colour Channel" /><br />
</p>
<p>Images can be represented as a list of integers. Each element in the list corresponds to a very tiny dot on your screen—a <em>pixel</em>. For each dot, three integer values are used to represent three colour channels: red, green, and blue. We can then add these channels together to get a very wide range of colours (this is called the RGB colour model). Somehow, our computers are able to take these sequences of integers and translate them into a sequence of visible lights and if these lights are arranged in a particular way, well, a cat appears!</p>
<h2 id="references-573d4e112b">References</h2>
<ol type="1">
<li>Check out <a href="https://en.wikipedia.org/wiki/Our_World_in_Data">Our World in Data</a> to see how data-driven research is being used to tackle global problems.</li>
<li>If youd like to read more about the RGB colour model, the Wikipedia entry is a good start: <a href="https://en.wikipedia.org/wiki/RGB_color_model" class="uri">https://en.wikipedia.org/wiki/RGB_color_model</a>.</li>
</ol>
</section>
<br/> <a id="anchor-01-02"></a>
<header id="title-block-header-78de7a7446">
<h1 class="title">1.2 Introducing the Python Programming Language</h1>
</header>
<section>
<p>For the thousands of years of human history before the mid-twentieth century, humans collected, analysed, and created data by hand. Digital computers were a revolution not just in technology but in civilization because of their ability to store more data than could fit on all the sheets of paper in the world, and to perform computations on this data faster and more reliably than an army of humans. Today, we rely on complex computer programs to operate on data in a variety of ways, from sending messages back and forth with loved ones, organizing data in documents and media, to running simulations of physical, social, and biological systems.</p>
<p>Yet for all their computation power, computers have one fundamental limitation: they have no agency, no inherent ability to make decisions about what to do. All they can do is take a set of (possibly very complex!) instructions, what we call a <em>computer program</em>, and execute them—no more, and no less. And so if we, as computer scientists, want to harness the awesome power of computers, we need to learn how give these instructions in a way that a computer understands. We need to learn how to speak to a computer.</p>
<h2 id="what-is-a-programming-language-78de7a7446">What is a programming language?</h2>
<p>A <strong>programming language</strong> is a way of communicating a set of instructions to a computer. Like human languages such as English, a programming language consists of a set of allowed words and the rules for putting those words together to form phrases with a coherent meaning.<label for="sn-0-78de7a7446" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-78de7a7446" class="margin-toggle"/><span class="sidenote"> In your past learning of a (human) language, youve likely referred to these rules as the <em>grammar</em> of a language.</span> Unlike human languages, a programming language must be precise enough to be understood by a computer, and so operates with a relatively small set of words and very structured rules for putting them together. Learning a programming language can be frustrating at first, because even a slight deviation from these rules results in the computer being unable to comprehend what weve written. But our time and efforts spent mastering the rules of a programming language yield a wonderful reward: the computer will not just understand what were saying, but faithfully execute them.</p>
<p>A <strong>program</strong> is simply the text of the instructions we wish to instruct the computer to execute; we call this text program <strong>code</strong> to differentiate it from other forms of text. To write programs in a particular language, we need to understand two key properties of the language. The first is the <strong>syntax</strong> of a programming language, which is the name we give to the rules governing what constitutes a valid program in the language. Before a computer can execute a program, it must read the instructions for the program; the syntax of the programming language specifies the format of these instructions. The second concept is the <strong>semantics</strong> of a programming language, which refers to the rules governing the <em>meaning</em> of different instructions in the language. Once the computer has read the instructions in a program, it begins executing them. The language semantics specifies what the computer should do for each instruction.</p>
<h2 id="the-python-programming-language-78de7a7446">The Python programming language</h2>
<p>Just as there are thousands of human languages in the world today, each with their own vocabulary, grammar, and stylistic conventions, so too is there a plethora of programming languages that we can choose from. In this course, well use the Python programming language, which offers a simple, beginner-friendly syntax and a set of language instructions whose semantics are both powerful and accessible.</p>
<p>Now, neither our computer hardware nor operating system understand the Python programming language. Instead, the creators of the Python language developed a program called the <strong>Python interpreter</strong>, whose job is to take programs written in the Python language and execute the instructions.<label for="sn-1-78de7a7446" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-78de7a7446" class="margin-toggle"/><span class="sidenote"> So when you “download Python”, what youre actually downloading and installing is this Python interpreter software.</span> You can think of the Python interpreter as a mediator between you the programmer, writing communicating in Python, and the computer hardware that actually executes instructions.</p>
<p>There are two ways of writing code in the Python language to be understood by the interpreter. The first is to write full programs in the Python language, saving them as text files,<label for="sn-2-78de7a7446" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-78de7a7446" class="margin-toggle"/><span class="sidenote"> Python programs use the <code>.py</code> file extension to distinguish them from other text files.</span> and then running them through the Python interpreter. This is the standard way of writing programs: write the instructions, and then run them with the interpreter. The second way is to run the Python interpreter in an interactive mode, which we call the <strong>Python console</strong> or <strong>Python shell</strong>. In this mode, we can write small fragments of Python code and ask the Python interpreter to execute each fragment one at a time. The Python console is useful for experimenting and exploring the language, as you get feedback after every single instruction. The drawback is that interactions with the interpreter in the Python console are ephemeral, lost every time you restart the console. So well use the following approach through the course: <em>use the Python console to learn about and experiment with the Python language, and write full programs in <code>.py</code> files</em>.</p>
<div class="fullwidth">
<p><video src="videos/python_console_demo.webm" autoplay="true" muted="true" loop="true" controls=""><a href="videos/python_console_demo.webm">Python console Demo</a></video><br />
</p>
</div>
</section>
<br/> <a id="anchor-01-03"></a>
<header id="title-block-header-cb522239e7">
<h1 class="title">1.3 Representing Data in Python</h1>
</header>
<section>
<p>Data is all around us, but so are computers. If decisions must be data-driven then computers are an excellent tool for processing that data. Especially when we consider that computers are several orders of magnitude faster at computing data than a human. The problem is that computers need to be told exactly <em>how</em> to process the data, and we can do so using one of several programming languages. In this section, we see how data types are represented in Python and how we can use Python to perform operations for us. Well learn about some subtle, but crucial, differences between our theoretical definitions of data types from Section 1.1 and what Python can actually represent. But first, well introduce some general terminology for using the interactive Python console.</p>
<h2 id="the-python-console-cb522239e7">The Python console</h2>
<p>When we first start the Python console, we see the following:</p>
<div class="sourceCode" id="cb1-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-cb522239e7"><a href="#cb1-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span></span></code></pre></div>
<p>The text <code>&gt;&gt;&gt;</code> is called the Python <strong>prompt</strong>: the console is “prompting” us to type in some Python code to execute. If we type in a simple arithmetic expression,</p>
<div class="sourceCode" id="cb2-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-cb522239e7"><a href="#cb2-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span> <span class="op">+</span> <span class="dv">5</span></span></code></pre></div>
<p>and press Enter, we see the following output:</p>
<div class="sourceCode" id="cb3-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-cb522239e7"><a href="#cb3-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span> <span class="op">+</span> <span class="dv">5</span></span>
<span id="cb3-2-cb522239e7"><a href="#cb3-2-cb522239e7"></a><span class="dv">9</span></span></code></pre></div>
<p>The interpreter took our bit of code, <code>4 + 5</code>, and calculated its value, <code>9</code>. A piece of Python code that produces a value is called an <strong>expression</strong>, and the act of calculating the value of an expression is called <strong>evaluating</strong> the expression.</p>
<p>The expression <code>4 + 5</code> looks simple enough, but technically it is formed from two smaller expressions—the numbers <code>4</code> and <code>5</code> themselves. We can ask <code>Python</code> to evaluate each of these, though the result is not very interesting.</p>
<div class="sourceCode" id="cb4-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-cb522239e7"><a href="#cb4-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span></span>
<span id="cb4-2-cb522239e7"><a href="#cb4-2-cb522239e7"></a><span class="dv">4</span></span>
<span id="cb4-3-cb522239e7"><a href="#cb4-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">5</span></span>
<span id="cb4-4-cb522239e7"><a href="#cb4-4-cb522239e7"></a><span class="dv">5</span></span></code></pre></div>
<p>A Python <strong>literal</strong> is the simplest kind of Python expression: it is a piece of code that represents the exact value as written. For example, <code>4</code> is an integer literal representing the number 4.</p>
<p>To sum up,<label for="sn-0-cb522239e7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-cb522239e7" class="margin-toggle"/><span class="sidenote">The pun was not originally intended, but we are pointing it out…</span> the expression <code>4 + 5</code> consists of two smaller expressions, the literals <code>4</code> and <code>5</code>, joined together with the arithmetic operator <code>+</code>, representing addition. Well devote the rest of this section to exploring the different kinds of data types we can use in Python: both how to write their literals, and what operations we can perform on them.</p>
<h2 id="numeric-data-in-python-int-float-cb522239e7">Numeric data in Python (<code>int</code>, <code>float</code>)</h2>
<p>Python has two data types for representing numeric data: <code>int</code> and <code>float</code>. Lets start with <code>int</code>, which stands for “integer”, and is the data type that Python uses to represent integers.</p>
<p>An <code>int</code> literal is simply the number as a sequence of digits with an optional <code>-</code> sign, like <code>110</code> or <code>-3421</code>.</p>
<p>Python supports all of the arithmetic operations we discussed in Section 1.1. Here are some examples; try typing them into the Python console yourself to follow along!</p>
<div class="sourceCode" id="cb5-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-cb522239e7"><a href="#cb5-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">2</span> <span class="op">+</span> <span class="dv">3</span></span>
<span id="cb5-2-cb522239e7"><a href="#cb5-2-cb522239e7"></a><span class="dv">5</span></span>
<span id="cb5-3-cb522239e7"><a href="#cb5-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">2</span> <span class="op">-</span> <span class="dv">5</span></span>
<span id="cb5-4-cb522239e7"><a href="#cb5-4-cb522239e7"></a><span class="op">-</span><span class="dv">3</span></span>
<span id="cb5-5-cb522239e7"><a href="#cb5-5-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="op">-</span><span class="dv">2</span> <span class="op">*</span> <span class="dv">10</span></span>
<span id="cb5-6-cb522239e7"><a href="#cb5-6-cb522239e7"></a><span class="op">-</span><span class="dv">20</span></span>
<span id="cb5-7-cb522239e7"><a href="#cb5-7-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">2</span> <span class="op">**</span> <span class="dv">5</span> <span class="co"># This is &quot;2 to the power of 5&quot;</span></span>
<span id="cb5-8-cb522239e7"><a href="#cb5-8-cb522239e7"></a><span class="dv">32</span></span></code></pre></div>
<p>In the last prompt, we included some additional text—<code># This is "2 to the power of 5"</code>. In Python, we use the character <code>#</code> in code to begin a <strong>comment</strong>, which is code that is ignored by the Python interpreter. Comments are only meant for humans to read, and are a useful way of providing additional information about some Python code. We used it above to explain the meaning of the <code>**</code> operator in our demo.</p>
<p>Python supports the standard precedence rules for arithmetic operations,<label for="sn-1-cb522239e7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-cb522239e7" class="margin-toggle"/><span class="sidenote">sometimes referred to as “BEDMAS” or “PEMDAS”</span> performing exponentiation before multiplication, and multiplication before addition and subtraction:</p>
<div class="sourceCode" id="cb6-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-cb522239e7"><a href="#cb6-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">1</span> <span class="op">+</span> <span class="dv">2</span> <span class="op">**</span> <span class="dv">3</span> <span class="op">*</span> <span class="dv">5</span> <span class="co"># Equal to &quot;1 plus ((2 to the power of 3) times 5)&quot;</span></span>
<span id="cb6-2-cb522239e7"><a href="#cb6-2-cb522239e7"></a><span class="dv">41</span></span></code></pre></div>
<p>Just like in mathematics, long expressions like this one can be hard to read. So Python also allows you to use parentheses to group expressions together:</p>
<div class="sourceCode" id="cb7-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-cb522239e7"><a href="#cb7-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">1</span> <span class="op">+</span> ((<span class="dv">2</span> <span class="op">**</span> <span class="dv">3</span>) <span class="op">*</span> <span class="dv">5</span>) <span class="co"># Equivalent to the previous expression</span></span>
<span id="cb7-2-cb522239e7"><a href="#cb7-2-cb522239e7"></a><span class="dv">41</span></span>
<span id="cb7-3-cb522239e7"><a href="#cb7-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> (<span class="dv">1</span> <span class="op">+</span> <span class="dv">2</span>) <span class="op">**</span> (<span class="dv">3</span> <span class="op">*</span> <span class="dv">5</span>) <span class="co"># Different grouping: &quot;(1 plus 2) to the power of (3 times 5)&quot;</span></span>
<span id="cb7-4-cb522239e7"><a href="#cb7-4-cb522239e7"></a><span class="dv">14348907</span></span></code></pre></div>
<p>When we add, subtract, multiply, and use exponentiation on two integers, the result is always an integer, and so Python always produces an <code>int</code> value for these operations. But <em>dividing</em> two integers certainly doesnt always produce an integer—what does Python do in this case? It turns out that Python has two different forms of division. The first is the operator <code>//</code>, and is called <strong>floor division</strong> (or sometimes <strong>integer division</strong>). For two integers <code>x</code> and <code>y</code>, the result of <code>x // y</code> is equal to the quotient <span class="math inline">\(\frac{\texttt{x}}{\texttt{y}}\)</span>, rounded down to the nearest integer. Here are some examples:</p>
<div class="sourceCode" id="cb8-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-cb522239e7"><a href="#cb8-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">6</span> <span class="op">//</span> <span class="dv">2</span></span>
<span id="cb8-2-cb522239e7"><a href="#cb8-2-cb522239e7"></a><span class="dv">3</span></span>
<span id="cb8-3-cb522239e7"><a href="#cb8-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">15</span> <span class="op">//</span> <span class="dv">2</span> <span class="co"># 15 ÷ 2 = 7.5, and // rounds down</span></span>
<span id="cb8-4-cb522239e7"><a href="#cb8-4-cb522239e7"></a><span class="dv">7</span></span>
<span id="cb8-5-cb522239e7"><a href="#cb8-5-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="op">-</span><span class="dv">15</span> <span class="op">//</span> <span class="dv">2</span> <span class="co"># Careful! -15 ÷ 2 = -7.5, which rounds down to -8</span></span>
<span id="cb8-6-cb522239e7"><a href="#cb8-6-cb522239e7"></a><span class="op">-</span><span class="dv">8</span></span></code></pre></div>
<p>But what about “real” division? This is done using the division operator <code>/</code>:</p>
<div class="sourceCode" id="cb9-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-cb522239e7"><a href="#cb9-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">5</span> <span class="op">/</span> <span class="dv">2</span></span>
<span id="cb9-2-cb522239e7"><a href="#cb9-2-cb522239e7"></a><span class="fl">2.5</span></span></code></pre></div>
<p>This returns <code>2.5</code>, which is a value of Pythons <code>float</code> type, which Python uses to represent arbitrary real numbers. A <code>float</code> literal is written as a sequence of digits followed by a decimal point (<code>.</code>) and then another sequence of digits. <code>2.5</code>, <code>.123</code>, and <code>1000.00000001</code> are all examples of <code>float</code> literals.</p>
<p>All of the arithemtic operations weve looked at so far work with <code>float</code> values too:</p>
<div class="sourceCode" id="cb10-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-cb522239e7"><a href="#cb10-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="fl">3.5</span> <span class="op">+</span> <span class="fl">2.4</span></span>
<span id="cb10-2-cb522239e7"><a href="#cb10-2-cb522239e7"></a><span class="fl">5.9</span></span>
<span id="cb10-3-cb522239e7"><a href="#cb10-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="fl">3.5</span> <span class="op">-</span> <span class="fl">20.9</span></span>
<span id="cb10-4-cb522239e7"><a href="#cb10-4-cb522239e7"></a><span class="op">-</span><span class="fl">17.4</span></span>
<span id="cb10-5-cb522239e7"><a href="#cb10-5-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="fl">3.5</span> <span class="op">*</span> <span class="fl">2.5</span></span>
<span id="cb10-6-cb522239e7"><a href="#cb10-6-cb522239e7"></a><span class="fl">8.75</span></span>
<span id="cb10-7-cb522239e7"><a href="#cb10-7-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="fl">3.5</span> <span class="op">/</span> <span class="fl">2.5</span></span>
<span id="cb10-8-cb522239e7"><a href="#cb10-8-cb522239e7"></a><span class="fl">1.4</span></span>
<span id="cb10-9-cb522239e7"><a href="#cb10-9-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">2</span> <span class="op">**</span> <span class="fl">0.5</span></span>
<span id="cb10-10-cb522239e7"><a href="#cb10-10-cb522239e7"></a><span class="fl">1.4142135623730951</span></span></code></pre></div>
<p>The last expression, <code>2 ** 0.5</code>, calculates the square root of 2. However, this actually poses a problem for Python: since <span class="math inline">\(\sqrt 2\)</span> is an irrational number, its decimal expansion is infinite, and so it cannot be represented in any finite amount of computer memory.<label for="sn-2-cb522239e7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-cb522239e7" class="margin-toggle"/><span class="sidenote"> More precisely, computers use a binary system where all data, including numbers, are represented as a sequence of 0s and 1s. This sequence of 0s and 1s is finite since computer memory is finite, and so cannot exactly represent <span class="math inline">\(\sqrt 2\)</span>. We will discuss this binary representation of numbers later this year.</span></p>
<p>] The <code>float</code> value thats produced, <code>1.4142135623730951</code>, is an approximation of <span class="math inline">\(\sqrt 2\)</span>, but is not equal to it. Lets see what happens if we try to square it:</p>
<div class="sourceCode" id="cb11-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-cb522239e7"><a href="#cb11-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="fl">1.4142135623730951</span> <span class="op">*</span> <span class="fl">1.4142135623730951</span></span>
<span id="cb11-2-cb522239e7"><a href="#cb11-2-cb522239e7"></a><span class="fl">2.0000000000000004</span></span></code></pre></div>
<p>This illustrates a fundamental limitation of <code>float</code>: this data type is used to represent real numbers, but cannot always represent them exactly. Rather, a <code>float</code> value <em>approximates</em> the value of the real number; sometimes that approximation is exact, like <code>2.5</code>, but most of the time it isnt.</p>
<h3 id="vs.-3.0-cb522239e7"><code>3</code> vs. <code>3.0</code></h3>
<p>Heres an oddity:</p>
<div class="sourceCode" id="cb12-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-cb522239e7"><a href="#cb12-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">6</span> <span class="op">//</span> <span class="dv">2</span></span>
<span id="cb12-2-cb522239e7"><a href="#cb12-2-cb522239e7"></a><span class="dv">3</span></span>
<span id="cb12-3-cb522239e7"><a href="#cb12-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">6</span> <span class="op">/</span> <span class="dv">2</span></span>
<span id="cb12-4-cb522239e7"><a href="#cb12-4-cb522239e7"></a><span class="fl">3.0</span></span></code></pre></div>
<p>Even though <span class="math inline">\(\frac{6}{2}\)</span> is mathematically an integer, the results of the division using <code>//</code> and <code>/</code> are subtly different in Python. When <code>x</code> and <code>y</code> are <code>int</code>s, <code>x // y</code> <em>always</em> evaluates to an <code>int</code>, and <code>x / y</code> <em>always</em> evaluates to a <code>float</code>, even if the value of <span class="math inline">\(\frac{\texttt{x}}{\texttt{y}}\)</span> is an integer! So <code>6 // 2</code> has value <code>3</code>, but <code>6 / 2</code> has value <code>3.0</code>. These two values represent the same mathematical quantity—the number 3—but are stored as different data types in Python, something well explore more later in this course when we study how <code>int</code>s and <code>float</code>s actually work in Python.</p>
<h3 id="mixing-ints-and-floats-cb522239e7">Mixing <code>int</code>s and <code>float</code>s</h3>
<p>So to summarize: for two <code>int</code>s <code>x</code> and <code>y</code>, <code>x + y</code>, <code>x - y</code>, <code>x * y</code>, <code>x // y</code>, and <code>x ** y</code> all produce <code>int</code>s, and <code>x / y</code> always produces a <code>float</code>. For two <code>float</code>s, its even simpler: all six of these arithmetic operations produce a <code>float</code>.<label for="sn-3-cb522239e7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-cb522239e7" class="margin-toggle"/><span class="sidenote">Even <code>//</code>. Try it!</span></p>
<p>But what happens when we mix these two types? <em>An arithmetic operation that is given one <code>int</code> and one <code>float</code> always produces a <code>float</code>.</em> You can think of a <code>float</code> as a parasite—even in long arithmetic expressions where only one value is a <code>float</code>, the whole expression will evaluate to a <code>float</code>.</p>
<div class="sourceCode" id="cb13-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-cb522239e7"><a href="#cb13-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">12</span> <span class="op">-</span> <span class="dv">4</span> <span class="op">*</span> <span class="dv">5</span> <span class="op">//</span> (<span class="fl">3.0</span> <span class="op">**</span> <span class="dv">2</span>) <span class="op">+</span> <span class="dv">100</span></span>
<span id="cb13-2-cb522239e7"><a href="#cb13-2-cb522239e7"></a><span class="fl">110.0</span></span></code></pre></div>
<table>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>a + b</code></td>
<td>Returns the sum of the <code>a</code> and <code>b</code></td>
</tr>
<tr class="even">
<td><code>a - b</code></td>
<td>Returns the result of subtraction of <code>b</code> from <code>a</code></td>
</tr>
<tr class="odd">
<td><code>a * b</code></td>
<td>Returns the result of multiplying <code>a</code> by <code>b</code></td>
</tr>
<tr class="even">
<td><code>a / b</code></td>
<td>Return the result of dividing <code>a</code> by <code>b</code></td>
</tr>
<tr class="odd">
<td><code>a % b</code></td>
<td>Return the remainder when <code>a</code> is divided by <code>b</code></td>
</tr>
<tr class="even">
<td><code>a ** b</code></td>
<td>Return the result of <code>a</code> being raised to the power of <code>b</code></td>
</tr>
<tr class="odd">
<td><code>a // b</code></td>
<td>Return the floored division <code>a</code> / <code>b</code></td>
</tr>
</tbody>
</table>
<h3 id="comparison-operators-cb522239e7">Comparison operators</h3>
<p>Finally, the numeric comparison operators are represented in Python as follows:</p>
<table>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>a == b</code></td>
<td>Returns whether <code>a</code> and <code>b</code> are equal.</td>
</tr>
<tr class="even">
<td><code>a != b</code></td>
<td>Returns whether <code>a</code> and <code>b</code> are <em>not</em> equal (opposite of <code>==</code>).</td>
</tr>
<tr class="odd">
<td><code>a &gt; b</code></td>
<td>Returns whether <code>a</code> is greater than the value of <code>b</code>.</td>
</tr>
<tr class="even">
<td><code>a &lt; b</code></td>
<td>Returns whether <code>a</code> is less than the value of <code>b</code>.</td>
</tr>
<tr class="odd">
<td><code>a &gt;= b</code></td>
<td>Returns whether <code>a</code> is greater than or equal to <code>b</code>.</td>
</tr>
<tr class="even">
<td><code>a &lt;= b</code></td>
<td>Returns whether <code>a</code> is less than or equal to the value <code>b</code>.</td>
</tr>
</tbody>
</table>
<p>Here are a few examples:</p>
<div class="sourceCode" id="cb14-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-cb522239e7"><a href="#cb14-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span> <span class="op">==</span> <span class="dv">4</span></span>
<span id="cb14-2-cb522239e7"><a href="#cb14-2-cb522239e7"></a><span class="va">True</span></span>
<span id="cb14-3-cb522239e7"><a href="#cb14-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span> <span class="op">!=</span> <span class="dv">6</span></span>
<span id="cb14-4-cb522239e7"><a href="#cb14-4-cb522239e7"></a><span class="va">True</span></span>
<span id="cb14-5-cb522239e7"><a href="#cb14-5-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span> <span class="op">&lt;</span> <span class="dv">2</span></span>
<span id="cb14-6-cb522239e7"><a href="#cb14-6-cb522239e7"></a><span class="va">False</span></span>
<span id="cb14-7-cb522239e7"><a href="#cb14-7-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span> <span class="op">&gt;=</span> <span class="dv">1</span></span>
<span id="cb14-8-cb522239e7"><a href="#cb14-8-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<p>And returning to our discussion earlier, we can see that even though <code>int</code>s and <code>float</code>s are different types, Python can recognize when their values represent the exact same number:</p>
<div class="sourceCode" id="cb15-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-cb522239e7"><a href="#cb15-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">4</span> <span class="op">==</span> <span class="fl">4.0</span></span>
<span id="cb15-2-cb522239e7"><a href="#cb15-2-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<p>In these examples, weve seen the values <code>True</code> and <code>False</code> produced as a result of these comparison expressions. You can probably tell exactly what they mean, but lets take a moment to introduce them formally.</p>
<h2 id="boolean-data-in-python-bool-cb522239e7">Boolean data in Python (<code>bool</code>)</h2>
<p>In Python, boolean data is represented using the data type <code>bool</code>. Unlike the broad range of numbers we just saw, there are only two literal values of type <code>bool</code>: <code>True</code> and <code>False</code>.</p>
<p>There are three boolean operators we can perform on boolean values: <code>not</code>, <code>and</code>, and <code>or</code>.</p>
<div class="sourceCode" id="cb16-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1-cb522239e7"><a href="#cb16-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="kw">not</span> <span class="va">True</span></span>
<span id="cb16-2-cb522239e7"><a href="#cb16-2-cb522239e7"></a><span class="va">False</span></span>
<span id="cb16-3-cb522239e7"><a href="#cb16-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="va">True</span> <span class="kw">and</span> <span class="va">True</span></span>
<span id="cb16-4-cb522239e7"><a href="#cb16-4-cb522239e7"></a><span class="va">True</span></span>
<span id="cb16-5-cb522239e7"><a href="#cb16-5-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="va">True</span> <span class="kw">and</span> <span class="va">False</span></span>
<span id="cb16-6-cb522239e7"><a href="#cb16-6-cb522239e7"></a><span class="va">False</span></span>
<span id="cb16-7-cb522239e7"><a href="#cb16-7-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="va">False</span> <span class="kw">or</span> <span class="va">True</span></span>
<span id="cb16-8-cb522239e7"><a href="#cb16-8-cb522239e7"></a><span class="va">True</span></span>
<span id="cb16-9-cb522239e7"><a href="#cb16-9-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="va">False</span> <span class="kw">or</span> <span class="va">False</span></span>
<span id="cb16-10-cb522239e7"><a href="#cb16-10-cb522239e7"></a><span class="va">False</span></span></code></pre></div>
<p>One note about the <code>or</code> operator in Python is that it is the <strong>inclusive or</strong>, meaning it produces <code>True</code> when both of its operand expressions are <code>True</code>.</p>
<div class="sourceCode" id="cb17-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1-cb522239e7"><a href="#cb17-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="va">True</span> <span class="kw">or</span> <span class="va">True</span></span>
<span id="cb17-2-cb522239e7"><a href="#cb17-2-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<p>Just as we saw how arithmetic operator expressions can be nested within each other, we can combine boolean operator expressions, and even the arithmetic comparison operators:</p>
<div class="sourceCode" id="cb18-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb18-1-cb522239e7"><a href="#cb18-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="va">True</span> <span class="kw">and</span> (<span class="va">False</span> <span class="kw">or</span> <span class="va">True</span>)</span>
<span id="cb18-2-cb522239e7"><a href="#cb18-2-cb522239e7"></a><span class="va">True</span></span>
<span id="cb18-3-cb522239e7"><a href="#cb18-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> (<span class="dv">3</span> <span class="op">==</span> <span class="dv">4</span>) <span class="kw">or</span> (<span class="dv">5</span> <span class="op">&gt;</span> <span class="dv">10</span>)</span>
<span id="cb18-4-cb522239e7"><a href="#cb18-4-cb522239e7"></a><span class="va">False</span></span></code></pre></div>
<h2 id="textual-data-in-python-str-cb522239e7">Textual data in Python (<code>str</code>)</h2>
<p>All Python code is text that we type into the computer, so how do we distinguish between text thats code and text thats data, like a persons name? Python uses the <code>str</code> (short for “string”) data type to represent textual data. A <code>str</code> literal is a sequence of characters surrounded by single-quotes (<code>'</code>).<label for="sn-4-cb522239e7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-cb522239e7" class="margin-toggle"/><span class="sidenote"> Python allows string literals to be written using either single-quotes or double-qutoes (<code>"</code>). Well tend to use single-quotes in this course to match how Python displays strings, as well see in this section.</span> For example, we could write this courses name in Python as the string literal <code>'Foundations of Computer Science I'</code>.</p>
<!--
A common introductory string literal is `'Hello, World!'`.
But what happens when we would like to use the single-quote as an apostrophe inside the string literal?
For example, `David's Tea` cannot simply be written as `'David's Tea'` because the apostrophe would mark the end of the string literal.
To overcome this issue we could, of course, simply use double-quotes: `"David's Tea"`.
But another option is to use the **escape character** `\`.
This allows us to *escape* the typical meaning of a single-quote (i.e., to mark the end of the string literal).
Thus, we could write `David's Tea` as: `'David\'s Tea`.
The combination of the escape character and the following character is called an **escape sequence**.
There are many different kinds of escape sequences in Python that can be used with string literals.
We will not enumerate them here, but it is useful to keep a mental note of new escape sequences you come across while reading code.
-->
<p>Now lets see what kinds of operations we can perform on strings. First, we can compare strings using <code>==</code>, just like we can for <code>int</code>s and <code>float</code>s:</p>
<div class="sourceCode" id="cb19-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb19-1-cb522239e7"><a href="#cb19-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;David&#39;</span> <span class="op">==</span> <span class="st">&#39;David&#39;</span></span>
<span id="cb19-2-cb522239e7"><a href="#cb19-2-cb522239e7"></a><span class="va">True</span></span>
<span id="cb19-3-cb522239e7"><a href="#cb19-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;David&#39;</span> <span class="op">==</span> <span class="st">&#39;david&#39;</span> <span class="co"># String comparisons are case-sensitive</span></span>
<span id="cb19-4-cb522239e7"><a href="#cb19-4-cb522239e7"></a><span class="va">False</span></span></code></pre></div>
<p>Python supports <strong>string indexing</strong> to extract a single character from a string.<label for="sn-5-cb522239e7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-cb522239e7" class="margin-toggle"/><span class="sidenote"> Remember, string indexing starts at 0. <code>s[0]</code> represents the <em>first</em> character in the string <code>s</code>.</span></p>
<div class="sourceCode" id="cb20-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb20-1-cb522239e7"><a href="#cb20-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;David&#39;</span>[<span class="dv">0</span>]</span>
<span id="cb20-2-cb522239e7"><a href="#cb20-2-cb522239e7"></a><span class="co">&#39;D&#39;</span></span>
<span id="cb20-3-cb522239e7"><a href="#cb20-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;David&#39;</span>[<span class="dv">3</span>]</span>
<span id="cb20-4-cb522239e7"><a href="#cb20-4-cb522239e7"></a><span class="co">&#39;i&#39;</span></span></code></pre></div>
<p>And Python supports <strong>concatenation</strong> using the familiar <code>+</code> operator:</p>
<div class="sourceCode" id="cb21-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb21-1-cb522239e7"><a href="#cb21-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;One string&#39;</span> <span class="op">+</span> <span class="st">&#39;to rule them all.&#39;</span></span>
<span id="cb21-2-cb522239e7"><a href="#cb21-2-cb522239e7"></a><span class="co">&#39;One stringto rule them all.&#39;</span></span>
<span id="cb21-3-cb522239e7"><a href="#cb21-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;One string &#39;</span> <span class="op">+</span> <span class="st">&#39;to rule them all.&#39;</span> <span class="co"># Note the extra space!</span></span>
<span id="cb21-4-cb522239e7"><a href="#cb21-4-cb522239e7"></a><span class="co">&#39;One string to rule them all.&#39;</span></span></code></pre></div>
<p>One operation that we did not cover in Section 1.1 is a fun quirk of Python: string repetition.</p>
<div class="sourceCode" id="cb22-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb22-1-cb522239e7"><a href="#cb22-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;David&#39;</span> <span class="op">*</span> <span class="dv">3</span></span>
<span id="cb22-2-cb522239e7"><a href="#cb22-2-cb522239e7"></a><span class="co">&#39;DavidDavidDavid&#39;</span></span></code></pre></div>
<p>And of course, all of these string operation expressions can be nested within each other:</p>
<div class="sourceCode" id="cb23-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb23-1-cb522239e7"><a href="#cb23-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> (<span class="st">&#39;David&#39;</span> <span class="op">+</span> <span class="st">&#39;Mario&#39;</span>) <span class="op">*</span> <span class="dv">3</span></span>
<span id="cb23-2-cb522239e7"><a href="#cb23-2-cb522239e7"></a><span class="co">&#39;DavidMarioDavidMarioDavidMario&#39;</span></span></code></pre></div>
<h2 id="set-data-in-python-set-cb522239e7">Set data in Python (<code>set</code>)</h2>
<p>Python uses the <code>set</code> data type to store set data. A <code>set</code> literal matches the notation we use in mathematics: the literal begins with a <code>{</code> and ends with a <code>}</code>, and each element of the list is written inside the braces, separated from each other by commas. For example, <code>{1, 2, 3}</code> is a set of <code>int</code>s, and <code>{1, 2.0, 'three'}</code> is a set of elements of mixed types.</p>
<p>Like other data types, sets can be compared for equality using <code>==</code>. Remember that element order does not matter when comparing sets!</p>
<div class="sourceCode" id="cb24-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb24-1-cb522239e7"><a href="#cb24-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>} <span class="op">==</span> {<span class="dv">3</span>, <span class="dv">1</span>, <span class="dv">2</span>}</span>
<span id="cb24-2-cb522239e7"><a href="#cb24-2-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<p>Python also supports the “element of” (<span class="math inline">\(\in\)</span>) set operation using the <code>in</code> operator.</p>
<div class="sourceCode" id="cb25-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb25-1-cb522239e7"><a href="#cb25-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">1</span> <span class="kw">in</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>}</span>
<span id="cb25-2-cb522239e7"><a href="#cb25-2-cb522239e7"></a><span class="va">True</span></span>
<span id="cb25-3-cb522239e7"><a href="#cb25-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">10</span> <span class="kw">in</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>}</span>
<span id="cb25-4-cb522239e7"><a href="#cb25-4-cb522239e7"></a><span class="va">False</span></span></code></pre></div>
<p>Python also allows <code>not</code> and <code>in</code> to be combined to form an operator that corresponds to the set operation <span class="math inline">\(\notin\)</span>:</p>
<div class="sourceCode" id="cb26-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb26-1-cb522239e7"><a href="#cb26-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">1</span> <span class="kw">not</span> <span class="kw">in</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>}</span>
<span id="cb26-2-cb522239e7"><a href="#cb26-2-cb522239e7"></a><span class="va">False</span></span>
<span id="cb26-3-cb522239e7"><a href="#cb26-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">10</span> <span class="kw">not</span> <span class="kw">in</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>}</span>
<span id="cb26-4-cb522239e7"><a href="#cb26-4-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<p>Well see in the next chapter how other set operations such as union and intersection are supported in Python.</p>
<h2 id="list-data-in-python-list-tuple-cb522239e7">List data in Python (<code>list</code>, <code>tuple</code>)</h2>
<p>Python uses two different data types to store list data: <code>list</code> and <code>tuple</code>. <code>list</code> literals are written the same way as <code>set</code> literals, except using square brackets instead of curly braces. Lists support the same operations we saw for strings and sets earlier:</p>
<div class="sourceCode" id="cb27-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb27-1-cb522239e7"><a href="#cb27-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>] <span class="op">==</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>] <span class="co"># List equality comparison; order matters!</span></span>
<span id="cb27-2-cb522239e7"><a href="#cb27-2-cb522239e7"></a><span class="va">True</span></span>
<span id="cb27-3-cb522239e7"><a href="#cb27-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>] <span class="op">==</span> [<span class="dv">3</span>, <span class="dv">2</span>, <span class="dv">1</span>]</span>
<span id="cb27-4-cb522239e7"><a href="#cb27-4-cb522239e7"></a><span class="va">False</span></span>
<span id="cb27-5-cb522239e7"><a href="#cb27-5-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> ([<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Mario&#39;</span>, <span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Diane&#39;</span>])[<span class="dv">0</span>] <span class="co"># List indexing</span></span>
<span id="cb27-6-cb522239e7"><a href="#cb27-6-cb522239e7"></a><span class="co">&#39;David&#39;</span></span>
<span id="cb27-7-cb522239e7"><a href="#cb27-7-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> [<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Mario&#39;</span>] <span class="op">+</span> [<span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Diane&#39;</span>] <span class="co"># List concatenation</span></span>
<span id="cb27-8-cb522239e7"><a href="#cb27-8-cb522239e7"></a>[<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Mario&#39;</span>, <span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Diane&#39;</span>]</span>
<span id="cb27-9-cb522239e7"><a href="#cb27-9-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">1</span> <span class="kw">in</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>] <span class="co"># List &quot;element of&quot; operation</span></span>
<span id="cb27-10-cb522239e7"><a href="#cb27-10-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<p><code>tuple</code> literals are written using regular parentheses instead, but otherwise support the above operations as well.</p>
<div class="sourceCode" id="cb28-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb28-1-cb522239e7"><a href="#cb28-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>) <span class="op">==</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>) <span class="co"># Tuple equality comparison</span></span>
<span id="cb28-2-cb522239e7"><a href="#cb28-2-cb522239e7"></a><span class="va">True</span></span>
<span id="cb28-3-cb522239e7"><a href="#cb28-3-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>) <span class="op">==</span> (<span class="dv">3</span>, <span class="dv">2</span>, <span class="dv">1</span>)</span>
<span id="cb28-4-cb522239e7"><a href="#cb28-4-cb522239e7"></a><span class="va">False</span></span>
<span id="cb28-5-cb522239e7"><a href="#cb28-5-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> (<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Mario&#39;</span>, <span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Diane&#39;</span>)[<span class="dv">0</span>] <span class="co"># Tuple indexing</span></span>
<span id="cb28-6-cb522239e7"><a href="#cb28-6-cb522239e7"></a><span class="co">&#39;David&#39;</span></span>
<span id="cb28-7-cb522239e7"><a href="#cb28-7-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> (<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Mario&#39;</span>) <span class="op">+</span> (<span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Diane&#39;</span>) <span class="co"># Tuple concatenation</span></span>
<span id="cb28-8-cb522239e7"><a href="#cb28-8-cb522239e7"></a>(<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Mario&#39;</span>, <span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Diane&#39;</span>)</span>
<span id="cb28-9-cb522239e7"><a href="#cb28-9-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">1</span> <span class="kw">in</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>) <span class="co"># Tuple &quot;element of&quot; operation</span></span>
<span id="cb28-10-cb522239e7"><a href="#cb28-10-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<p>So why does Python have two different data types that represent the same kind of data? There is an important technical distinction between <code>list</code> and <code>tuple</code> that well learn about later in this course, but for now well generally stick with <code>list</code>.</p>
<h2 id="mapping-data-in-python-dict-cb522239e7">Mapping data in Python (<code>dict</code>)</h2>
<p>Python stores mapping data using a data type called <code>dict</code>, short for “dictionary”. <code>dict</code> literals are written similarly to sets, with each key-value pair separated by a colon. For example, we can represent the mapping from the previous section with the dictionary literal <code>{'fries': 5.99, 'steak': 25.99, 'soup': 8.99}</code>. In this dictionary, the keys are strings, and the values are <code>float</code>s.</p>
<p>But if both sets and dictionaries use curly braces, then does the literal <code>{}</code> represent an empty set or an empty dictionary? The answer (for historical reasons) is an empty dictionary—Python has no literal to represent an empty set.<label for="sn-6-cb522239e7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-cb522239e7" class="margin-toggle"/><span class="sidenote"> Instead, we represent an empty set with <code>set()</code>, which is syntax we havent yet seen and will explore later.</span></p>
<p>Dictionaries also support equality comparison using <code>==</code>. They support key lookup using the same syntax as string and list indexing:</p>
<div class="sourceCode" id="cb29-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb29-1-cb522239e7"><a href="#cb29-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> ({<span class="st">&#39;fries&#39;</span>: <span class="fl">5.99</span>, <span class="st">&#39;steak&#39;</span>: <span class="fl">25.99</span>, <span class="st">&#39;soup&#39;</span>: <span class="fl">8.99</span>})[<span class="st">&#39;fries&#39;</span>]</span>
<span id="cb29-2-cb522239e7"><a href="#cb29-2-cb522239e7"></a><span class="fl">5.99</span></span></code></pre></div>
<p>And finally, they support checking whether a key is present in a dictionary using the <code>in</code> operator:</p>
<div class="sourceCode" id="cb30-cb522239e7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb30-1-cb522239e7"><a href="#cb30-1-cb522239e7"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;fries&#39;</span> <span class="kw">in</span> {<span class="st">&#39;fries&#39;</span>: <span class="fl">5.99</span>, <span class="st">&#39;steak&#39;</span>: <span class="fl">25.99</span>, <span class="st">&#39;soup&#39;</span>: <span class="fl">8.99</span>}</span>
<span id="cb30-2-cb522239e7"><a href="#cb30-2-cb522239e7"></a><span class="va">True</span></span></code></pre></div>
<h2 id="references-cb522239e7">References</h2>
<ul>
<li>CSC108 videos: Python as a Calculator (<a href="https://youtu.be/E6aJGrCTlTQ">Part 1</a>, <a href="https://youtu.be/mJqjTh6Srlg">Part 2</a>, <a href="https://youtu.be/LVHjVcMug30">Part 3</a>)</li>
<li>CSC108 videos: Type bool (<a href="https://youtu.be/pTk0QR0KhpU">Part 1</a>, <a href="https://youtu.be/ffRQyyIbyAI">Part 2</a>, <a href="https://youtu.be/U4RQx1_Z-RA">Part 3</a>, <a href="https://youtu.be/h5mocjb3SVE">Part 4</a>)</li>
<li>CSC108 videos: Type str (<a href="https://youtu.be/eMsfkkNg3J4">Part 1</a>, <a href="https://youtu.be/QM2WtjjYgzY">Part 2</a>)</li>
<li><a href="../A-python-builtins/02-types.html">Appendix A.2 Python Built-In Data Types Reference</a></li>
</ul>
</section>
<br/> <a id="anchor-01-04"></a>
<header id="title-block-header-487cdcace1">
<h1 class="title">1.4 Storing Data in Variables</h1>
</header>
<section>
<p>So far, weve been writing expressions in the Python console using only literals and operators. But as the computations we want to perform get more complex, relying on just literals and operators is very cumbersome. We can write very complex nested expressions, but this makes our code very hard to understand.</p>
<p>For example, suppose were given three points in the Cartesian plane <span class="math inline">\((1, 3)\)</span>, <span class="math inline">\((2, 5)\)</span>, <span class="math inline">\((10, -1)\)</span> that form a path, and we want to find the length of this path.</p>
<p><img src="images/0104-diagram-v2.png" alt="Cartesian Plane Diagram" /><br />
</p>
<p>Wed like to use this formula for the distance <span class="math inline">\(d\)</span> between two points <span class="math inline">\((x_1, y_1)\)</span> and <span class="math inline">\((x_2, y_2)\)</span>:</p>
<p><span class="math display">\[ d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}. \]</span></p>
<p>We <em>could</em> write this as a single arithmetic expression and have Python evaluate it:</p>
<div class="sourceCode" id="cb1-487cdcace1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-487cdcace1"><a href="#cb1-1-487cdcace1"></a><span class="op">&gt;&gt;&gt;</span> ((<span class="dv">1</span> <span class="op">-</span> <span class="dv">2</span>) <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> (<span class="dv">3</span> <span class="op">-</span> <span class="dv">5</span>) <span class="op">**</span> <span class="dv">2</span>) <span class="op">**</span> <span class="fl">0.5</span> <span class="op">+</span> ((<span class="dv">2</span> <span class="op">-</span> <span class="dv">10</span>) <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> (<span class="dv">5</span> <span class="op">+</span> <span class="dv">1</span>) <span class="op">**</span> <span class="dv">2</span>) <span class="op">**</span> <span class="fl">0.5</span></span>
<span id="cb1-2-487cdcace1"><a href="#cb1-2-487cdcace1"></a><span class="fl">12.23606797749979</span></span></code></pre></div>
<p>But typing in this expression is quite error-prone, and hard to understand. Just like in mathematics, we can improve our code by breaking down this problem into intermediate steps. Python (like all other programming languages) gives us a ways to bind values to names, so that we can refer to those values later on in subsequent calculations.</p>
<h2 id="variables-487cdcace1">Variables</h2>
<p>A <strong>variable</strong> is a piece of code that is a name that <em>refers</em> to a value. We create variables in Python using the syntax:</p>
<div class="sourceCode" id="cb2-487cdcace1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-487cdcace1"><a href="#cb2-1-487cdcace1"></a><span class="op">&lt;</span>variable<span class="op">&gt;</span> <span class="op">=</span> <span class="op">&lt;</span>expression<span class="op">&gt;</span></span></code></pre></div>
<p>which is a form of Python code called an <strong>assignment statement</strong>. You might wonder why we use the term “statement” rather than “expression” for assignment. An <em>expression</em> is a piece of Python code that is evaluated to produce a value. When we execute an assignment statement, it doesnt produce a value—it instead defines a variable.</p>
<p>Python executes an assignment statement in two steps:</p>
<ol type="1">
<li>First, the expression on the right-hand side of the <code>=</code> is evaluated, producing a value.</li>
<li>Second, that value is bound to the variable on the left-hand side.</li>
</ol>
<p>After the assignment statement is executed, the variable may be used to refer to the value. Heres how we can use variables to simplify the calculation above:</p>
<div class="sourceCode" id="cb3-487cdcace1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-487cdcace1"><a href="#cb3-1-487cdcace1"></a><span class="op">&gt;&gt;&gt;</span> distance1 <span class="op">=</span> ((<span class="dv">1</span> <span class="op">-</span> <span class="dv">2</span>) <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> (<span class="dv">3</span> <span class="op">-</span> <span class="dv">5</span>) <span class="op">**</span> <span class="dv">2</span>) <span class="op">**</span> <span class="fl">0.5</span> <span class="co"># Distance between (1, 3) and (2, 5)</span></span>
<span id="cb3-2-487cdcace1"><a href="#cb3-2-487cdcace1"></a><span class="op">&gt;&gt;&gt;</span> distance2 <span class="op">=</span> ((<span class="dv">2</span> <span class="op">-</span> <span class="dv">10</span>) <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> (<span class="dv">5</span> <span class="op">+</span> <span class="dv">1</span>) <span class="op">**</span> <span class="dv">2</span>) <span class="op">**</span> <span class="fl">0.5</span> <span class="co"># Distance between (2, 5) and (10, -1)</span></span>
<span id="cb3-3-487cdcace1"><a href="#cb3-3-487cdcace1"></a><span class="op">&gt;&gt;&gt;</span> distance1 <span class="co"># A variable is an expression; evaluating it produces the value it refers to</span></span>
<span id="cb3-4-487cdcace1"><a href="#cb3-4-487cdcace1"></a><span class="fl">2.23606797749979</span></span>
<span id="cb3-5-487cdcace1"><a href="#cb3-5-487cdcace1"></a><span class="op">&gt;&gt;&gt;</span> distance2</span>
<span id="cb3-6-487cdcace1"><a href="#cb3-6-487cdcace1"></a><span class="fl">10.0</span></span>
<span id="cb3-7-487cdcace1"><a href="#cb3-7-487cdcace1"></a><span class="op">&gt;&gt;&gt;</span> distance1 <span class="op">+</span> distance2 <span class="co"># The total distance</span></span>
<span id="cb3-8-487cdcace1"><a href="#cb3-8-487cdcace1"></a><span class="fl">12.23606797749979</span></span></code></pre></div>
<h2 id="choosing-good-variable-names-487cdcace1">Choosing good variable names</h2>
<p>Because variables are used to store intermediate values in computations, it is important to choose good variable names so that you can remember what the purpose of each variable is. This might not seem that important in our above example because there were only two variables, but as you start writing larger programs, youll have to grapple with dozens, if not hundreds, of variables, and choosing good names will be paramount.</p>
<p>For now, well introduce a few simple rules that you should follow when choosing variable names:</p>
<ol type="1">
<li><p>All variable names should use only lowercase letters, digits, and underscores. So <code>distance1</code>, not <code>Distance1</code>.</p></li>
<li><p>When a variable name consists of multiple words, write each word in lowercase and separate them with an underscore.<label for="sn-0-487cdcace1" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-487cdcace1" class="margin-toggle"/><span class="sidenote"> You arent allowed to use spaces in variable names.</span> For example, we might create a variable to refer to the total distance by doing</p>
<div class="sourceCode" id="cb4-487cdcace1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-487cdcace1"><a href="#cb4-1-487cdcace1"></a><span class="op">&gt;&gt;&gt;</span> total_distance <span class="op">=</span> distance1 <span class="op">+</span> distance2</span></code></pre></div>
<p>We use the name <code>total_distance</code> rather than <code>totaldistance</code> or <code>totalDistance</code> (the latter is a naming style used in other programming languages, but not here).</p></li>
<li><p>Avoid single-letter variable names and non-standard acronyms/abbreviations, outside of some mathematical contexts.</p>
<p>For example, we might have used <code>d1</code> and <code>d2</code> instead of <code>distance1</code> and <code>distance2</code> because <code>d</code> is the variable we used for distance in our above formula. However, we should <em>not</em> use <code>td</code> instead of <code>total_distance</code>, because a second person wouldnt immediately understand what <code>td</code> stands for.</p></li>
</ol>
<h2 id="the-value-based-python-memory-model-487cdcace1">The value-based Python memory model</h2>
<p>As our programs get larger, it is useful to have a principled way to keep track of the variables and data used by the programs. A <strong>memory model</strong> is a structured way of representing variables and data in a program.<label for="sn-1-487cdcace1" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-487cdcace1" class="margin-toggle"/><span class="sidenote"> The term “memory” here refers to the computer memory used to actually store the data.</span> For the next few weeks, were going to use the <em>value-based Python memory model</em>, which simply uses a table to represent the associations between variables and their associated values. For example, the value-based memory model for our above example is the following:</p>
<div class="memory-model-values">
<table>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>distance1</code></td>
<td><code>2.23606797749979</code></td>
</tr>
<tr class="even">
<td><code>distance2</code></td>
<td><code>10.0</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="references-487cdcace1">References</h2>
<ul>
<li>CSC108 videos: Variable Assignment (<a href="https://www.youtube.com/watch?v=E6aJGrCTlTQ">Part 1</a>, <a href="https://www.youtube.com/watch?v=CPmVn_hQzBs">Part 2</a>, <a href="https://www.youtube.com/watch?v=SkWSVsvgxYE">Part 3</a>)</li>
<li>CSC108 videos: Assignment Statement Visualizer (<a href="https://youtu.be/p-h8bDG8VPA">Part 1</a>)</li>
</ul>
</section>
<br/> <a id="anchor-01-05"></a>
<header id="title-block-header-a8c75071cc">
<h1 class="title">1.5 Building Up Data with Comprehensions</h1>
</header>
<section>
<p>To wrap up our introduction to data in Python, were going to learn about one last kind of expression that allows to build up and transform large collections of data in Python.</p>
<h2 id="from-set-builder-notation-to-set-comprehensions-a8c75071cc">From set builder notation to set comprehensions</h2>
<p>Recall <em>set builder notation</em>, which is a concise way of defining a mathematical set by specifying the values of the elements in terms of a larger domain. For example, suppose we have a set <span class="math inline">\(S = \{1, 2, 3, 4, 5\}\)</span>. We can express a set of squares of the elements of <span class="math inline">\(S\)</span>: <span class="math display">\[\{ x^2 \mid x \in S \}.\]</span></p>
<p>It turns out that this notation translates naturally to Python! To start, lets go into the Python Console and create a variable that refers to a set of numbers:</p>
<div class="sourceCode" id="cb1-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-a8c75071cc"><a href="#cb1-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> numbers <span class="op">=</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>}</span></code></pre></div>
<p>Now, we introduce a new kind of expression called a <strong>set comprehension</strong>, which has the following syntax:<label for="sn-0-a8c75071cc" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-a8c75071cc" class="margin-toggle"/><span class="sidenote"> Careful with this: even though set comprehensions also use curly braces, they are <em>not</em> the same as set literals. We arent writing out the individual elements separated by commas.</span></p>
<div class="sourceCode" id="cb2-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-a8c75071cc"><a href="#cb2-1-a8c75071cc"></a>{ <span class="op">&lt;</span>expr<span class="op">&gt;</span> <span class="cf">for</span> <span class="op">&lt;</span>variable<span class="op">&gt;</span> <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span> }</span></code></pre></div>
<p>Evaluating a set comprehension is done by taking the <code>&lt;expr&gt;</code> and evaluating it once for each value in <code>&lt;collection&gt;</code> assigned to the <code>&lt;variable&gt;</code>. This is exactly analogous to set builder notation, except using <code>for</code> instead of <span class="math inline">\(|\)</span> and <code>in</code> instead of <span class="math inline">\(\in\)</span>. Heres how we can repeat our initial example in Python using a set comprehension:</p>
<div class="sourceCode" id="cb3-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-a8c75071cc"><a href="#cb3-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> {x <span class="op">**</span> <span class="dv">2</span> <span class="cf">for</span> x <span class="kw">in</span> numbers}</span>
<span id="cb3-2-a8c75071cc"><a href="#cb3-2-a8c75071cc"></a>{<span class="dv">1</span>, <span class="dv">4</span>, <span class="dv">9</span>, <span class="dv">16</span>, <span class="dv">25</span>}</span></code></pre></div>
<p>Pretty cool, eh? If you arent sure exactly what happened here, its useful to write out the expanded form of the set comprehension:</p>
<div class="sourceCode" id="cb4-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-a8c75071cc"><a href="#cb4-1-a8c75071cc"></a> {x <span class="op">**</span> <span class="dv">2</span> <span class="cf">for</span> x <span class="kw">in</span> numbers}</span>
<span id="cb4-2-a8c75071cc"><a href="#cb4-2-a8c75071cc"></a><span class="op">==</span> {<span class="dv">1</span> <span class="op">**</span> <span class="dv">2</span>, <span class="dv">2</span> <span class="op">**</span> <span class="dv">2</span>, <span class="dv">3</span> <span class="op">**</span> <span class="dv">2</span>, <span class="dv">4</span> <span class="op">**</span> <span class="dv">2</span>, <span class="dv">5</span> <span class="op">**</span> <span class="dv">2</span>} <span class="co"># Replacing x with 1, 2, 3, 4, and 5.</span></span></code></pre></div>
<p>It goes even further—we can use set comprehensions with a Python list as well.</p>
<div class="sourceCode" id="cb5-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-a8c75071cc"><a href="#cb5-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> {x <span class="op">**</span> <span class="dv">2</span> <span class="cf">for</span> x <span class="kw">in</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]}</span>
<span id="cb5-2-a8c75071cc"><a href="#cb5-2-a8c75071cc"></a>{<span class="dv">1</span>, <span class="dv">4</span>, <span class="dv">9</span>, <span class="dv">16</span>, <span class="dv">25</span>}</span></code></pre></div>
<p>In fact, as well see later in this course, set comprehensions can be used with any “collection” data type in Python, not just sets and lists.</p>
<h2 id="list-and-dictionary-comprehensions-a8c75071cc">List and dictionary comprehensions</h2>
<p>Even though set comprehensions draw their inspiration from set builder notation in mathematics, Python has extended them to other data types.</p>
<p>A <strong>list comprehension</strong> is very similar to a set comprehension, except its syntax uses square brackets instead of curly braces:</p>
<div class="sourceCode" id="cb6-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-a8c75071cc"><a href="#cb6-1-a8c75071cc"></a>[ <span class="op">&lt;</span>expr<span class="op">&gt;</span> <span class="cf">for</span> <span class="op">&lt;</span>variable<span class="op">&gt;</span> <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span> ]</span></code></pre></div>
<p>Once again, <code>&lt;collection&gt;</code> can be a set or a list:</p>
<div class="sourceCode" id="cb7-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-a8c75071cc"><a href="#cb7-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> [x <span class="op">+</span> <span class="dv">4</span> <span class="cf">for</span> x <span class="kw">in</span> {<span class="dv">10</span>, <span class="dv">20</span>, <span class="dv">30</span>}]</span>
<span id="cb7-2-a8c75071cc"><a href="#cb7-2-a8c75071cc"></a>[<span class="dv">14</span>, <span class="dv">24</span>, <span class="dv">34</span>]</span>
<span id="cb7-3-a8c75071cc"><a href="#cb7-3-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> [x <span class="op">*</span> <span class="dv">3</span> <span class="cf">for</span> x <span class="kw">in</span> [<span class="dv">100</span>, <span class="dv">200</span>, <span class="dv">300</span>]]</span>
<span id="cb7-4-a8c75071cc"><a href="#cb7-4-a8c75071cc"></a>[<span class="dv">300</span>, <span class="dv">600</span>, <span class="dv">900</span>]</span></code></pre></div>
<p>One word of warning: because sets are unordered but lists are ordered, you should <em>not</em> assume a particular ordering of the elements when a list comprehension generates elements from a set—the results can be unexpected!</p>
<div class="sourceCode" id="cb8-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-a8c75071cc"><a href="#cb8-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> [x <span class="cf">for</span> x <span class="kw">in</span> {<span class="dv">20</span>, <span class="dv">10</span>, <span class="dv">30</span>}]</span>
<span id="cb8-2-a8c75071cc"><a href="#cb8-2-a8c75071cc"></a>[<span class="dv">10</span>, <span class="dv">20</span>, <span class="dv">30</span>]</span></code></pre></div>
<p>A <strong>dictionary comprehension</strong> is again similar to a set comprehension, but specifies both an expression to generate keys and an expression to generate their associated values:</p>
<div class="sourceCode" id="cb9-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-a8c75071cc"><a href="#cb9-1-a8c75071cc"></a>{ <span class="op">&lt;</span>key_expr<span class="op">&gt;</span> : <span class="op">&lt;</span>value_expr<span class="op">&gt;</span> <span class="cf">for</span> <span class="op">&lt;</span>variable<span class="op">&gt;</span> <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span> }</span></code></pre></div>
<p>Out of all three comprehension types, dictionary comprehensions are the most complex, because the left-hand side (before the <code>for</code>) consists of two expressions instead of one. Here is one example of a dictionary comprehension that creates a “table of values” for the function <span class="math inline">\(f(x) = x^2 + 1\)</span>.</p>
<div class="sourceCode" id="cb10-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-a8c75071cc"><a href="#cb10-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> {x : x <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> <span class="dv">1</span> <span class="cf">for</span> x <span class="kw">in</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>}}</span>
<span id="cb10-2-a8c75071cc"><a href="#cb10-2-a8c75071cc"></a>{<span class="dv">1</span>: <span class="dv">2</span>, <span class="dv">2</span>: <span class="dv">5</span>, <span class="dv">3</span>: <span class="dv">10</span>, <span class="dv">4</span>: <span class="dv">17</span>, <span class="dv">5</span>: <span class="dv">26</span>}</span></code></pre></div>
<h2 id="comprehensions-with-multiple-variables-a8c75071cc">Comprehensions with multiple variables</h2>
<p>Our last example in this section will be to illustrate how multiple variables are used within the same comprehension expression. First, recall how we defined the <em>Cartesian product</em> of two sets using set builder notation: <span class="math display">\[ A \times B = \{ (x, y) \mid x \in A \text{ and } y \in B \}.\]</span> In this expression, the expression <span class="math inline">\((x, y)\)</span> is evaluated once for every possible combination of elements <span class="math inline">\(x\)</span> of <span class="math inline">\(A\)</span> and elements <span class="math inline">\(y\)</span> of <span class="math inline">\(B\)</span>.</p>
<p>The same holds for set, list, and dictionary comprehensions. We can specify additional variables in a comprehension by adding extra <code>for &lt;variable&gt; in &lt;collection&gt;</code> clauses to the comprehension. For example, if we define the following sets:</p>
<div class="sourceCode" id="cb11-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-a8c75071cc"><a href="#cb11-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> nums1 <span class="op">=</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>}</span>
<span id="cb11-2-a8c75071cc"><a href="#cb11-2-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> nums2 <span class="op">=</span> {<span class="dv">10</span>, <span class="dv">20</span>, <span class="dv">30</span>}</span></code></pre></div>
<p>then we can calculate their Cartesian product using the following set comprehension:<label for="sn-1-a8c75071cc" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-a8c75071cc" class="margin-toggle"/><span class="sidenote"> Remember, sets are unordered! Dont get hung up on the unusual order in the output.</span></p>
<div class="sourceCode" id="cb12-a8c75071cc"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-a8c75071cc"><a href="#cb12-1-a8c75071cc"></a><span class="op">&gt;&gt;&gt;</span> {(x, y) <span class="cf">for</span> x <span class="kw">in</span> nums1 <span class="cf">for</span> y <span class="kw">in</span> nums2}</span>
<span id="cb12-2-a8c75071cc"><a href="#cb12-2-a8c75071cc"></a>{(<span class="dv">3</span>, <span class="dv">30</span>), (<span class="dv">2</span>, <span class="dv">20</span>), (<span class="dv">2</span>, <span class="dv">10</span>), (<span class="dv">1</span>, <span class="dv">30</span>), (<span class="dv">3</span>, <span class="dv">20</span>), (<span class="dv">1</span>, <span class="dv">20</span>), (<span class="dv">3</span>, <span class="dv">10</span>), (<span class="dv">1</span>, <span class="dv">10</span>), (<span class="dv">2</span>, <span class="dv">30</span>)}</span></code></pre></div>
<p>In general, if we have a comprehension with clauses <code>for v1 in collection1</code>, <code>for v2 in collection2</code>, etc., then the comprehensions inner expression is evaluated <em>once for each combination of values for the variables</em>. This illustrates yet another pretty impressive power of Python: the ability to combine different collections of data together in a short amount of code.</p>
</section>
<br/> <a id="anchor-01-06"></a>
<header id="title-block-header-85b2c1f9bd">
<h1 class="title">1.6 Application: Representing Colour</h1>
</header>
<section>
<p>The physics behind how we perceive colour is incredibly interesting, but also complex. Humans have developed a broad range of names of colours to identify categories like “red” in everyday language.<label for="sn-0-85b2c1f9bd" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-85b2c1f9bd" class="margin-toggle"/><span class="sidenote"> Although the names we use for colours vary widely from language to language!</span> Yet these categories can be fairly broad and imprecise; useful for everyday communication, but not for computer graphics and design. So in this section, well learn about how computers represent colour data.</p>
<p><img src="https://images.unsplash.com/photo-1534872471805-7a1c5a014651?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1052&amp;q=80" alt="color image" /><br />
</p>
<p>Mathematics can help us represent colours by a combination of numbers; the rules for how numbers map to colours is called a <em>colour model</em>. Many colour models exist, but one of the most common is the <em>RGB colour model</em>. At some point in your youth, you may have discovered that mixing two colours together (i.e., with paint, crayons, etc.) produces a different colour. The RGB colour model is based on the same idea: each colour is represented by three numbers, one for the “amount” of red, green, and blue to be mixed together.</p>
<p>A common form of the RGB colour model in a computer is called the <strong>RGB24</strong> colour model, and allows for each of the red, green, and blue amounts to be a number between 0 and 255, inclusive.<label for="sn-1-85b2c1f9bd" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-85b2c1f9bd" class="margin-toggle"/><span class="sidenote"> Though RGB24 is quite common, software like Photoshop allow for a larger range of numbers, enabling more granularity it their colour representations. You can look up the term <em>deep colour</em> to find out more about more sophisticated colour models</span> Formally, we can define the set <span class="math inline">\(S = \{0, 1, \dots, 255\}\)</span> and <span class="math inline">\(\mathcal{C}\)</span> to be the set of all possible colours in the universe. Then the RGB colour model is a function <span class="math inline">\(RGB_{24}: S \times S \times S \to \mathcal{C}\)</span> that takes in red, green, and blue values from <span class="math inline">\(S\)</span> and returns a colour. This <span class="math inline">\(RGB_{24}\)</span> function is <em>one-to-one</em>, as every combination of (red, green, blue) values produces a different colour.</p>
<table>
<colgroup>
<col style="width: 21%" />
<col style="width: 78%" />
</colgroup>
<thead>
<tr class="header">
<th>RGB Value</th>
<th>Colour</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>(0, 0, 0)</td>
<td><div height="10px" style="background-color: rgb(0,0,0)">
 
</div></td>
</tr>
<tr class="even">
<td>(255, 0, 0)</td>
<td><div height="10px" style="background-color: rgb(255,0,0)">
 
</div></td>
</tr>
<tr class="odd">
<td>(0, 255, 0)</td>
<td><div height="10px" style="background-color: rgb(0,255,0)">
 
</div></td>
</tr>
<tr class="even">
<td>(0, 0, 255)</td>
<td><div height="10px" style="background-color: rgb(0,0,255)">
 
</div></td>
</tr>
<tr class="odd">
<td>(181, 57, 173)</td>
<td><div height="10px" style="background-color: rgb(181,57,173)">
 
</div></td>
</tr>
<tr class="even">
<td>(255, 255, 255)</td>
<td><div height="10px" style="background-color: rgb(255,255,255)">
 
</div></td>
</tr>
</tbody>
</table>
<h3 id="colours-in-python-85b2c1f9bd">Colours in Python</h3>
<p>The RGB24 colour model translates naturally to Python: we represent a colour value as a tuple of three integers, where each integer is between 0 and 255, inclusive. For example, we can use <code>(0, 0, 0)</code> to represent a pure black, and <code>(181, 57, 173)</code> to represent a shade of purple. Of course, just representing these values as tuples doesnt automatically make them colours:</p>
<div class="sourceCode" id="cb1-85b2c1f9bd"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-85b2c1f9bd"><a href="#cb1-1-85b2c1f9bd"></a><span class="op">&gt;&gt;&gt;</span> (<span class="dv">181</span>, <span class="dv">57</span>, <span class="dv">173</span>) <span class="co"># This tuple evaluates to... itself</span></span>
<span id="cb1-2-85b2c1f9bd"><a href="#cb1-2-85b2c1f9bd"></a>(<span class="dv">181</span>, <span class="dv">57</span>, <span class="dv">173</span>)</span></code></pre></div>
<p>But as youll see in your first tutorial this year, we can pass these tuples to operations that expect colour values, and get remarkable results.</p>
<p><img src="images/colour_gradient.png" alt="Pygame demo of colour gradient" /><br />
</p>
<h2 id="references-85b2c1f9bd">References</h2>
<ul>
<li><a href="https://www.mathsisfun.com/hexadecimal-decimal-colors.html">Hexadecimal Colors</a></li>
<li><a href="http://learn.colorotate.org/color-models/">Color Theory</a></li>
</ul>
</section>
<br/>
<h2 class="unnumbered" id="functions">2. Functions</h2>
<a id="anchor-02-01"></a>
<header id="title-block-header-7b0fdd8160">
<h1 class="title">2.1 Pythons Built-In Functions</h1>
</header>
<section>
<p>In the previous chapter, we began our study of programming in Python by studying three main ingredients: literals, operators, and variables. We can express complex computations using just these forms of Python code, but as the tasks we want to perform grow more complex, so too does the code we need to write. In this chapter, well learn about using <em>functions</em> in Python to organize our code into useful logical blocks that can be worked on separately and reused again and again in our programs.</p>
<h2 id="review-functions-in-mathematics-7b0fdd8160">Review: Functions in mathematics</h2>
<p>Before looking at functions in Python, well first review some of the mathematical definitions related to functions from the <a href="https://q.utoronto.ca/courses/160038/pages/sets-and-functions-review">First-Year CS Summer Prep</a>.</p>
<p>Let <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span> be sets. A <strong>function</strong> <span class="math inline">\(f : A \to B\)</span> is a mapping from elements in <span class="math inline">\(A\)</span> to elements in <span class="math inline">\(B\)</span>. <span class="math inline">\(A\)</span> is called the <strong>domain</strong> of the function, and <span class="math inline">\(B\)</span> is called the <strong>codomain</strong> of the function.</p>
<p>Functions can have more than one input. For sets <span class="math inline">\(A_1, A_2, \dots, A_k\)</span> and <span class="math inline">\(B\)</span>, a <span class="math inline">\(k\)</span>-ary function <span class="math inline">\(f: A_1 \times A_2 \times \dots \times A_k \to B\)</span> is a function that takes <span class="math inline">\(k\)</span> arguments, where for each <span class="math inline">\(i\)</span> between <span class="math inline">\(1\)</span> and <span class="math inline">\(k\)</span>, the <span class="math inline">\(i\)</span>-th argument of <span class="math inline">\(f\)</span> must be an element of <span class="math inline">\(A_i\)</span>, and where <span class="math inline">\(f\)</span> returns an element of <span class="math inline">\(B\)</span>. We have common English terms for small values of <span class="math inline">\(k\)</span>: unary, binary, and ternary functions take one, two, and three inputs, respectively. For example, the addition operator <span class="math inline">\(+ : \R \times \R \to \R\)</span> is a <em>binary</em> function that takes two real numbers and returns their sum. For readability, we usually write this function as <span class="math inline">\(x+y\)</span> instead of <span class="math inline">\(+(x,y)\)</span>.</p>
<h2 id="pythons-built-in-functions-in-python-7b0fdd8160">Pythons built-in functions in Python</h2>
<p>Weve seen that Python has many operators, like <code>+</code> that can be used on various data types. These operators are actually functions represented by symbols (e.g., addition through the <code>+</code> symbol). But there arent enough symbols to represent every function we could ever want. So Python also defines several functions that we can use to perform additional operations; these functions are called <strong>built-in functions</strong>, as they are made automatically available to us anywhere in a Python program. For example, the Python function <code>abs</code> takes a single numeric input and returns its absolute value. But how do we actually use it?</p>
<p>A Python expression that uses a function to operate on a given input is called a <strong>function call</strong>, and has the same syntax as mathematics: <code>&lt;function_name&gt;(&lt;argument&gt;, &lt;argument&gt;, ...)</code>. For example, here are two examples of a function call expressions that call <code>abs</code>:</p>
<div class="sourceCode" id="cb1-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-7b0fdd8160"><a href="#cb1-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">abs</span>(<span class="op">-</span><span class="dv">10</span>) <span class="co"># Returns the absolute value of -10.</span></span>
<span id="cb1-2-7b0fdd8160"><a href="#cb1-2-7b0fdd8160"></a><span class="dv">10</span></span>
<span id="cb1-3-7b0fdd8160"><a href="#cb1-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">abs</span>(<span class="dv">100</span>)</span>
<span id="cb1-4-7b0fdd8160"><a href="#cb1-4-7b0fdd8160"></a><span class="dv">100</span></span></code></pre></div>
<p>Function calls are central to programming, and come with some new terminology that well introduce now and use throughout the next year.</p>
<ul>
<li>In a function call expression, the input expressions are called <strong>arguments</strong> to the function call. <em>Example</em>: in the expression <code>abs(-10)</code>, the <code>-10</code> is the argument of the function call.</li>
<li>When we evaluate a function call, we say that the arguments are <strong>passed</strong> to the function. <em>Example</em>: in <code>abs(-10)</code>, we say that <code>-10</code> is passed to <code>abs</code>.</li>
<li>When the function call produces a value, we say that the function call <strong>returns</strong> a value, and refer to this value as the <strong>return value</strong> of the function call expression. <em>Example</em>: the return value of <code>abs(-10)</code> is <code>10</code>.</li>
</ul>
<p>In your mathematical studies so far, youve mainly studied <em>unary numeric</em> functions, i.e., functions that take in just one numeric argument and return another number.<label for="sn-0-7b0fdd8160" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-7b0fdd8160" class="margin-toggle"/><span class="sidenote"> Examples include the sin and log functions.</span> In programming, however, it is very common to work with functions that operate on a wide variety of data types, and a wide number of arguments. Here are a few examples of built-in functions that go beyond taking a single numeric argument:</p>
<ul>
<li><p>The <code>len</code> function takes a string or collection data type (e.g., <code>set</code>, <code>list</code>) and returns the size of its input.<label for="sn-1-7b0fdd8160" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-7b0fdd8160" class="margin-toggle"/><span class="sidenote"> While we defined “size” of these data types back in Section 1.1, we didnt cover them in Python in the last chapter because we were waiting to get to functions.</span></p>
<div class="sourceCode" id="cb2-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-7b0fdd8160"><a href="#cb2-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">len</span>({<span class="dv">10</span>, <span class="dv">20</span>, <span class="dv">30</span>})</span>
<span id="cb2-2-7b0fdd8160"><a href="#cb2-2-7b0fdd8160"></a><span class="dv">3</span></span>
<span id="cb2-3-7b0fdd8160"><a href="#cb2-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">len</span>(<span class="st">&#39;&#39;</span>)</span>
<span id="cb2-4-7b0fdd8160"><a href="#cb2-4-7b0fdd8160"></a><span class="dv">0</span></span>
<span id="cb2-5-7b0fdd8160"><a href="#cb2-5-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">len</span>([<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>, <span class="st">&#39;c&#39;</span>, <span class="st">&#39;d&#39;</span>, <span class="st">&#39;e&#39;</span>])</span>
<span id="cb2-6-7b0fdd8160"><a href="#cb2-6-7b0fdd8160"></a><span class="dv">5</span></span>
<span id="cb2-7-7b0fdd8160"><a href="#cb2-7-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">len</span>({<span class="st">&#39;David&#39;</span>: <span class="dv">100</span>, <span class="st">&#39;Mario&#39;</span>: <span class="dv">0</span>})</span>
<span id="cb2-8-7b0fdd8160"><a href="#cb2-8-7b0fdd8160"></a><span class="dv">2</span></span></code></pre></div></li>
<li><p>The <code>sum</code> function takes a collection of numbers (e.g., a <code>set</code> or <code>list</code> whose elements are all numbers) and returns the sum of the numbers.</p>
<div class="sourceCode" id="cb3-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-7b0fdd8160"><a href="#cb3-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sum</span>({<span class="dv">10</span>, <span class="dv">20</span>, <span class="dv">30</span>})</span>
<span id="cb3-2-7b0fdd8160"><a href="#cb3-2-7b0fdd8160"></a><span class="dv">60</span></span>
<span id="cb3-3-7b0fdd8160"><a href="#cb3-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sum</span>([<span class="op">-</span><span class="fl">4.5</span>, <span class="op">-</span><span class="dv">10</span>, <span class="dv">2</span>, <span class="dv">0</span>])</span>
<span id="cb3-4-7b0fdd8160"><a href="#cb3-4-7b0fdd8160"></a><span class="op">-</span><span class="fl">12.5</span></span></code></pre></div></li>
<li><p>The <code>sorted</code> function takes a collection and returns a <code>list</code> that contains the same elements as the input collection, sorted in ascending order.</p>
<div class="sourceCode" id="cb4-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-7b0fdd8160"><a href="#cb4-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sorted</span>([<span class="dv">10</span>, <span class="dv">3</span>, <span class="dv">20</span>, <span class="op">-</span><span class="dv">4</span>])</span>
<span id="cb4-2-7b0fdd8160"><a href="#cb4-2-7b0fdd8160"></a>[<span class="op">-</span><span class="dv">4</span>, <span class="dv">3</span>, <span class="dv">10</span>, <span class="dv">20</span>]</span>
<span id="cb4-3-7b0fdd8160"><a href="#cb4-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sorted</span>({<span class="dv">10</span>, <span class="dv">3</span>, <span class="dv">20</span>, <span class="op">-</span><span class="dv">4</span>}) <span class="co"># Works with sets, too!</span></span>
<span id="cb4-4-7b0fdd8160"><a href="#cb4-4-7b0fdd8160"></a>[<span class="op">-</span><span class="dv">4</span>, <span class="dv">3</span>, <span class="dv">10</span>, <span class="dv">20</span>]</span></code></pre></div></li>
<li><p>The <code>max</code> function is a bit special, because there are two ways it can be used. When it is called with two or more inputs, those inputs must be numeric, and in this case <code>max</code> returns the largest one.</p>
<div class="sourceCode" id="cb5-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-7b0fdd8160"><a href="#cb5-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">max</span>(<span class="dv">2</span>, <span class="dv">3</span>)</span>
<span id="cb5-2-7b0fdd8160"><a href="#cb5-2-7b0fdd8160"></a><span class="dv">3</span></span>
<span id="cb5-3-7b0fdd8160"><a href="#cb5-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">max</span>(<span class="op">-</span><span class="dv">2</span>, <span class="dv">10</span>, <span class="dv">3</span>, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">7</span>)</span>
<span id="cb5-4-7b0fdd8160"><a href="#cb5-4-7b0fdd8160"></a><span class="dv">10</span></span></code></pre></div>
<p>But <code>max</code> can also be called with just a single argument, a non-empty collection of numbers. In this case, <code>max</code> returns the largest number in the collection.</p>
<div class="sourceCode" id="cb6-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-7b0fdd8160"><a href="#cb6-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">max</span>({<span class="dv">2</span>, <span class="dv">3</span>})</span>
<span id="cb6-2-7b0fdd8160"><a href="#cb6-2-7b0fdd8160"></a><span class="dv">3</span></span>
<span id="cb6-3-7b0fdd8160"><a href="#cb6-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">max</span>([<span class="op">-</span><span class="dv">2</span>, <span class="dv">10</span>, <span class="dv">3</span>, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">7</span>])</span>
<span id="cb6-4-7b0fdd8160"><a href="#cb6-4-7b0fdd8160"></a><span class="dv">10</span></span></code></pre></div></li>
<li><p>The <code>range</code> function we saw in the last chapter takes in two integers <code>start</code> and <code>stop</code> and returns a value representing a range of consecutive numbers between <code>start</code> and <code>stop - 1</code>, inclusive. For example, <code>range(5, 10)</code> represents the sequence of numbers <code>5</code>, <code>6</code>, <code>7</code>, <code>8</code>, <code>9</code>. If <code>start &gt;= end</code>, then <code>range(start, end)</code> represents an <em>empty</em> sequence.</p></li>
</ul>
<h3 id="one-special-function-type-7b0fdd8160">One special function: <code>type</code></h3>
<p>The last built-in function well cover in this section is <code>type</code>, which takes <em>any</em> Python value and returns its type. Lets check it out:<label for="sn-2-7b0fdd8160" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-7b0fdd8160" class="margin-toggle"/><span class="sidenote"> The term <code>class</code> that you see returned here is the name Python uses to refer to mean “data type”. More on this later.</span></p>
<div class="sourceCode" id="cb7-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-7b0fdd8160"><a href="#cb7-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(<span class="dv">3</span>)</span>
<span id="cb7-2-7b0fdd8160"><a href="#cb7-2-7b0fdd8160"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;int&#39;</span><span class="op">&gt;</span></span>
<span id="cb7-3-7b0fdd8160"><a href="#cb7-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(<span class="fl">3.0</span>)</span>
<span id="cb7-4-7b0fdd8160"><a href="#cb7-4-7b0fdd8160"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;float&#39;</span><span class="op">&gt;</span></span>
<span id="cb7-5-7b0fdd8160"><a href="#cb7-5-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(<span class="st">&#39;David&#39;</span>)</span>
<span id="cb7-6-7b0fdd8160"><a href="#cb7-6-7b0fdd8160"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;str&#39;</span><span class="op">&gt;</span></span>
<span id="cb7-7-7b0fdd8160"><a href="#cb7-7-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>([<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>])</span>
<span id="cb7-8-7b0fdd8160"><a href="#cb7-8-7b0fdd8160"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;list&#39;</span><span class="op">&gt;</span></span>
<span id="cb7-9-7b0fdd8160"><a href="#cb7-9-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>({<span class="st">&#39;a&#39;</span>: <span class="dv">1</span>, <span class="st">&#39;b&#39;</span>: <span class="dv">2</span>})</span>
<span id="cb7-10-7b0fdd8160"><a href="#cb7-10-7b0fdd8160"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;dict&#39;</span><span class="op">&gt;</span></span></code></pre></div>
<p>If youre ever unsure about the type of a particular value or variable, you can always call <code>type</code> on it to check!</p>
<h3 id="nested-function-calls-7b0fdd8160">Nested function calls</h3>
<p>Just like other Python expressions, you can write function calls within each other, or mix them with other kinds of expressions.</p>
<div class="sourceCode" id="cb8-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-7b0fdd8160"><a href="#cb8-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">max</span>(<span class="bu">abs</span>(<span class="op">-</span><span class="dv">100</span>), <span class="dv">15</span>, <span class="dv">3</span> <span class="op">*</span> <span class="dv">20</span>)</span>
<span id="cb8-2-7b0fdd8160"><a href="#cb8-2-7b0fdd8160"></a><span class="dv">100</span></span></code></pre></div>
<p>However, just as we saw with deeply nested arithmetic expressions earlier, too much nesting can make Python expressions difficult to read and understand, and so it is a good practice to break down a complex series of function calls into intermediate steps using variables:</p>
<div class="sourceCode" id="cb9-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-7b0fdd8160"><a href="#cb9-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> v1 <span class="op">=</span> <span class="bu">abs</span>(<span class="op">-</span><span class="dv">100</span>)</span>
<span id="cb9-2-7b0fdd8160"><a href="#cb9-2-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> v2 <span class="op">=</span> <span class="dv">15</span></span>
<span id="cb9-3-7b0fdd8160"><a href="#cb9-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> v3 <span class="op">=</span> <span class="dv">3</span> <span class="op">*</span> <span class="dv">20</span></span>
<span id="cb9-4-7b0fdd8160"><a href="#cb9-4-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;&gt;</span> <span class="bu">max</span>(v1, v2, v3)</span>
<span id="cb9-5-7b0fdd8160"><a href="#cb9-5-7b0fdd8160"></a><span class="dv">100</span></span></code></pre></div>
<h2 id="methods-functions-belonging-to-data-types-7b0fdd8160">Methods: functions belonging to data types</h2>
<p>The built-in functions weve studied so far all have one interesting property in common: they can all be given arguments of at least two different data types: for example, <code>abs</code> works with both <code>int</code> and <code>float</code>, <code>len</code> and <code>sorted</code> work with <code>set</code> <code>list</code> (and others), and <code>type</code> works with values of absolutely any data type. In fact, this is true for almost all built-in functions in Python, as part of the design of the language itself.</p>
<p>However, Pythons data types also support operations that are specific that that particular data type: for example, there are many operations we can perform on strings that a specific to textual data, and that wouldnt make sense for other data types.</p>
<p>Python comes with many functions that perform these operations, but handles them a bit differently than the built-in functions weve seen so far. A function that is defined as part of a data type is called a <strong>method</strong>.<label for="sn-3-7b0fdd8160" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-7b0fdd8160" class="margin-toggle"/><span class="sidenote"> The terms <em>function</em> and <em>method</em> are sometimes blurred in programming, particularly from language to language, but for us these terms have precise and distinct meanings!</span> All methods are functions, but not all functions are methods. For example, the built-in functions we looked at above are all <em>not</em> methods. We refer to functions that are not methods as <strong>top-level functions</strong>. Well see later how we define functions and methods in Python, but for now lets look at a few examples of methods.</p>
<p>One <code>str</code> method in Python is called <code>lower</code>, and has the effect of taking a string like <code>'David'</code> and returning a new string with all uppercase letters turned into lowercase: <code>'david'</code>. To call this method, we refer to it by first specifying the name of the data type it belongs to (<code>str</code>), followed by a period (<code>.</code>) and then the name of the method.</p>
<div class="sourceCode" id="cb10-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-7b0fdd8160"><a href="#cb10-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.lower(<span class="st">&#39;David&#39;</span>)</span>
<span id="cb10-2-7b0fdd8160"><a href="#cb10-2-7b0fdd8160"></a><span class="co">&#39;david&#39;</span></span></code></pre></div>
<p>Here are a few other examples of methods for different data types, just to give you a sense of the kinds of operations that are allowed.</p>
<div class="sourceCode" id="cb11-7b0fdd8160"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-7b0fdd8160"><a href="#cb11-1-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.split(<span class="st">&#39;David wuz hear&#39;</span>) <span class="co"># str.split splits a string into words</span></span>
<span id="cb11-2-7b0fdd8160"><a href="#cb11-2-7b0fdd8160"></a>[<span class="st">&#39;David&#39;</span>, <span class="st">&#39;wuz&#39;</span>, <span class="st">&#39;hear&#39;</span>]</span>
<span id="cb11-3-7b0fdd8160"><a href="#cb11-3-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">set</span>.union({<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>}, {<span class="dv">2</span>, <span class="dv">10</span>, <span class="dv">20</span>}) <span class="co"># set.union performs the set union operation</span></span>
<span id="cb11-4-7b0fdd8160"><a href="#cb11-4-7b0fdd8160"></a>{<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">20</span>, <span class="dv">10</span>}</span>
<span id="cb11-5-7b0fdd8160"><a href="#cb11-5-7b0fdd8160"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.count([<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">4</span>, <span class="dv">2</span>], <span class="dv">2</span>) <span class="co"># list.count counts the number of times a value appears in a list</span></span>
<span id="cb11-6-7b0fdd8160"><a href="#cb11-6-7b0fdd8160"></a><span class="dv">3</span> <span class="co"># (remember, a list can have duplicates!)</span></span></code></pre></div>
<h2 id="references-7b0fdd8160">References</h2>
<ul>
<li>CSC108 videos: Functions (<a href="https://youtu.be/gbyIl_NFOaQ">Part 1</a>, <a href="https://youtu.be/gH7R03lh5PM">Part 2</a>, <a href="https://youtu.be/DvbCym5XHAs">Part 3</a>)</li>
<li><a href="../A-python-builtins/02-builtins.md">Appendix A.1 Python Built-In Function Reference</a></li>
<li><a href="../A-python-builtins/02-types.md">Appendix A.2 Python Built-In Data Types Reference</a> (includes descriptions of methods)</li>
</ul>
</section>
<br/> <a id="anchor-02-02"></a>
<header id="title-block-header-829103af00">
<h1 class="title">2.2 Defining Our Own Functions</h1>
</header>
<section>
<p>Python provides many built-in top-level functions and methods for us, but as we start writing more code, it is essential for us to be able to create our own functions specific to the problem we are solving. In this section, well learn how to define our own top-level functions in Python.<label for="sn-0-829103af00" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-829103af00" class="margin-toggle"/><span class="sidenote"> And later on, well study how to define our own data types and methods as well.</span></p>
<p>First, lets recall how we define a function in mathematics. We first specify the function name, domain, and codomain: for example, <span class="math inline">\(f: \R \to \R\)</span>. Then, we write the function header and body, usually in a single line: for example, <span class="math inline">\(f(x) = x^2\)</span>. We do this so often in mathematics that we often take parts of this for granted, for example leaving out the domain/codomain specification, and usually choosing <span class="math inline">\(f\)</span> as the function name and <span class="math inline">\(x\)</span> as the parameter name. However, the functions well implement in Python are much more diverse, and so it will be important to be explicit in every part of this process.</p>
<h2 id="defining-a-python-function-829103af00">Defining a Python function</h2>
<p>Here is the complete definition of a “squaring” function in Python. Take a moment to read through the whole definition, and then continue reading to learn about this definitions different parts.</p>
<div class="sourceCode" id="cb1-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-829103af00"><a href="#cb1-1-829103af00"></a><span class="kw">def</span> square(x: <span class="bu">float</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb1-2-829103af00"><a href="#cb1-2-829103af00"></a> <span class="co">&quot;&quot;&quot;Return x squared.</span></span>
<span id="cb1-3-829103af00"><a href="#cb1-3-829103af00"></a></span>
<span id="cb1-4-829103af00"><a href="#cb1-4-829103af00"></a><span class="co"> &gt;&gt;&gt; square(3.0)</span></span>
<span id="cb1-5-829103af00"><a href="#cb1-5-829103af00"></a><span class="co"> 9.0</span></span>
<span id="cb1-6-829103af00"><a href="#cb1-6-829103af00"></a><span class="co"> &gt;&gt;&gt; square(2.5)</span></span>
<span id="cb1-7-829103af00"><a href="#cb1-7-829103af00"></a><span class="co"> 6.25</span></span>
<span id="cb1-8-829103af00"><a href="#cb1-8-829103af00"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-9-829103af00"><a href="#cb1-9-829103af00"></a> <span class="cf">return</span> x <span class="op">**</span> <span class="dv">2</span></span></code></pre></div>
<p>This function definition is the most complex form of Python code weve seen so far, so lets break this down part by part.</p>
<ol type="1">
<li><p>The first line, <code>def square(x: float) -&gt; float:</code> is called the <strong>function header</strong>. Its purpose is to convey the following pieces of information:</p>
<ul>
<li>The functions name (<code>square</code>).</li>
<li>The number and type of arguments the function expects. A <strong>parameter</strong> is a variable in a function definition that refers to a argument when the function is called. In this example, the function has one parameter with name <code>x</code> and type <code>float</code>.</li>
<li>The functions <strong>return type</strong>, which is the type following the <code>-&gt;</code>, <code>float</code>.<label for="sn-1-829103af00" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-829103af00" class="margin-toggle"/><span class="sidenote"> In this example, the functions parameter and return type are the same, but this wont always be the case. </span></li>
</ul>
<p>The syntax for a function header for a unary function is:</p>
<div class="sourceCode" id="cb2-829103af00"><pre class="sourceCode python fullwidth"><code class="sourceCode python"><span id="cb2-1-829103af00"><a href="#cb2-1-829103af00"></a><span class="kw">def</span> <span class="op">&lt;</span>function_name<span class="op">&gt;</span>(<span class="op">&lt;</span>parameter_name<span class="op">&gt;</span>: <span class="op">&lt;</span>parameter_type<span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="op">&lt;</span>return_type<span class="op">&gt;</span>:</span></code></pre></div>
<p>Compared to our mathematical version, there are two main differences. First, we chose the name <code>square</code> rather than <code>f</code> as the function name; in Python, we will always pick descriptive names for our functions rather than relying on the conventional “<span class="math inline">\(f\)</span>”. And second, we use data types to specify the function domain and codomain: the code <code>x: float</code> specifies that the parameter <code>x</code> must be a <code>float</code> value, and the code <code>-&gt; float</code> specifies that this function always returns a <code>float</code> value.</p>
<p>We can express this restriction in an analogous way to <span class="math inline">\(f: \R \to \R\)</span> by writing <code>float -&gt; float</code>; we call <code>float -&gt; float</code> the <strong>type contract</strong> of the <code>square</code> function.</p></li>
<li><p>The next seven lines, which start and end with triple-quotes (<code>"""</code>), is called the <strong>function docstring</strong>. This is another way of writing a comment in Python: text that is meant to be read by humans, but not executed as Python code. The goal of the function docstring is to communicate what the function does.</p>
<p>The first part of the docstring, <code>Return x squared.</code>, is an English description of the function. The second part might look a bit funny at first, since it seems like Python code:<label for="sn-2-829103af00" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-829103af00" class="margin-toggle"/><span class="sidenote">Or more precisely, it looks like the Python console!</span></p>
<div class="sourceCode" id="cb3-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-829103af00"><a href="#cb3-1-829103af00"></a><span class="op">&gt;&gt;&gt;</span> square(<span class="fl">3.0</span>)</span>
<span id="cb3-2-829103af00"><a href="#cb3-2-829103af00"></a><span class="fl">9.0</span></span>
<span id="cb3-3-829103af00"><a href="#cb3-3-829103af00"></a><span class="op">&gt;&gt;&gt;</span> square(<span class="fl">2.5</span>)</span>
<span id="cb3-4-829103af00"><a href="#cb3-4-829103af00"></a><span class="fl">6.25</span></span></code></pre></div>
<p>This part of the docstring shows example uses of the function, just like the examples we showed of built-in functions in the previous section. You can read the first example literally as “when you type <code>square(3.0)</code> into the Python console, <code>9.0</code> is returned” and the second as “when you type <code>square(2.5)</code> into the Python console, <code>6.25</code> is returned”. These examples are called <strong>doctest examples</strong>, for a reason well see in a future section. While a English description may technically be enough to specify the functions behaviour, doctest examples are invaluable for aiding understanding of the function behaviour (which is why we use them in teaching as well!).</p>
<p>The function docstring is indented inside the function header, as a visual indicator that it is part of the overall function definition.<label for="sn-3-829103af00" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-829103af00" class="margin-toggle"/><span class="sidenote"> Unlike many other programming languages, this kind of indentation in Python is <strong>mandatory</strong> rather than merely recommended. Pythons designers felt strongly enough about indentation improving readability of Python programs that they put indentation requirements like this into the language itself.</span></p></li>
<li><p>The final line, <code>return x ** 2</code>, is called the <strong>body</strong> of the function, and is the code that is executed when the function is called. Like the function docstring, the function body is also indented so that it is “inside” the function definition.</p>
<p>This code uses another keyword, <code>return</code>, which signals a new kind of statement: the <strong>return statement</strong>, which has the form:</p>
<div class="sourceCode" id="cb4-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-829103af00"><a href="#cb4-1-829103af00"></a><span class="cf">return</span> <span class="op">&lt;</span>expression<span class="op">&gt;</span></span></code></pre></div>
<p>When a return statement is executed, the following happens:</p>
<ol type="1">
<li>The <code>&lt;expression&gt;</code> is evaluated, producing a value.</li>
<li>That value is then returned to wherever the function was called. No more code in the function body is executed after this point.</li>
</ol></li>
</ol>
<h2 id="what-happens-when-a-function-is-called-829103af00">What happens when a function is called?</h2>
<p>In the previous section, we called built-in functions, and took for granted that they worked properly, without worrying about how they work. Now that were able to define our own functions, we are ready to fully understand what happens when a function is called.</p>
<p>As an example, suppose weve defined <code>square</code> as above, and then call it in the Python console:</p>
<div class="sourceCode" id="cb5-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-829103af00"><a href="#cb5-1-829103af00"></a><span class="op">&gt;&gt;&gt;</span> square(<span class="fl">2.5</span>)</span></code></pre></div>
<p>When we press Enter, the Python interpreter evaluates the function call by doing the following:</p>
<ol type="1">
<li>Evaluate the argument <code>2.5</code>, and then assign <code>2.5</code> to the function parameter <code>x</code>.</li>
<li>Evaluate the body of the <code>square</code> function, by doing:
<ol type="a">
<li>First evaluate <code>x ** 2</code>, which is <code>6.25</code> (since <code>x</code> refers to the value <code>2.5</code>).</li>
<li>Then stop executing the function body, and return the value <code>6.25</code> back to the Python console.</li>
</ol></li>
<li>The function call <code>square(2.5)</code> evaluates to <code>6.25</code>, and this is displayed on the screen.</li>
</ol>
<p>As we observed in the previous section, we can combine multiple function calls within a single expression. What happens when we call <code>square</code> twice in the same expression? For example:</p>
<div class="sourceCode" id="cb6-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-829103af00"><a href="#cb6-1-829103af00"></a><span class="op">&gt;&gt;&gt;</span> square(<span class="fl">2.5</span>) <span class="op">+</span> square(<span class="op">-</span><span class="fl">1.0</span>)</span></code></pre></div>
<p>We can step through this as well; notice how weve duplicated the text from before to illustrate the similarities between calling <code>square(2.5)</code> and <code>-square(-1.0)</code>.</p>
<ol type="1">
<li>Python evaluates the operands to <code>+</code> in left-to-right order, so evaluate <code>square(2.5)</code> first.
<ol type="i">
<li>Evaluate <code>2.5</code>, and then assign <code>2.5</code> to the function parameter <code>x</code>.</li>
<li>Evaluate the body of the <code>square</code> function, by doing:
<ol type="a">
<li>First evaluate <code>x ** 2</code>, which is <code>6.25</code> (since <code>x</code> refers to <code>2.5</code>).</li>
<li>Then stop executing the function body, and return the value <code>6.25</code> back to the Python console.</li>
</ol></li>
</ol></li>
<li>Nothing is displayed yet! Theres still <code>square(-1.0)</code> to be evaluated.
<ol type="i">
<li>Evaluate <code>-1.0</code>, and then assign <code>-1.0</code> to the function parameter <code>x</code>.</li>
<li>Evaluate the body of the <code>square</code> function, by doing:
<ol type="a">
<li>First evaluate <code>x ** 2</code>, which is <code>1.0</code> (since <code>x</code> refers to <code>-1.0</code>).</li>
<li>Then stop executing the function body, and return the value <code>1.0</code> back to the Python console.</li>
</ol></li>
</ol></li>
<li>Now the expression to evaluate has been simplified to <code>6.25 + 1.0</code>, which evaluates to <code>7.25</code>. This value is displayed on the screen.</li>
</ol>
<h2 id="defining-functions-in-files-829103af00">Defining functions in files</h2>
<p>While it is possible to define functions directly in the Python console, this isnt a good approach: every time we restart the Python console, we lose all our previous definitions. So instead, we save functions in files so that we can reuse them across multiple sessions in the Python console (and in other files).</p>
<p>For example, suppose we have the following file called <code>my_functions.py</code>:</p>
<div class="sourceCode" id="cb7-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-829103af00"><a href="#cb7-1-829103af00"></a><span class="kw">def</span> square(x: <span class="bu">float</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb7-2-829103af00"><a href="#cb7-2-829103af00"></a> <span class="co">&quot;&quot;&quot;Return x squared.</span></span>
<span id="cb7-3-829103af00"><a href="#cb7-3-829103af00"></a></span>
<span id="cb7-4-829103af00"><a href="#cb7-4-829103af00"></a><span class="co"> &gt;&gt;&gt; square(3.0)</span></span>
<span id="cb7-5-829103af00"><a href="#cb7-5-829103af00"></a><span class="co"> 9.0</span></span>
<span id="cb7-6-829103af00"><a href="#cb7-6-829103af00"></a><span class="co"> &gt;&gt;&gt; square(2.5)</span></span>
<span id="cb7-7-829103af00"><a href="#cb7-7-829103af00"></a><span class="co"> 6.25</span></span>
<span id="cb7-8-829103af00"><a href="#cb7-8-829103af00"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-9-829103af00"><a href="#cb7-9-829103af00"></a> <span class="cf">return</span> x <span class="op">**</span> <span class="dv">2</span></span></code></pre></div>
<p>In PyCharm, we can right-click and select “Run File in Python Console”. This will start the Python console and run our file, which then allows us to call our function <code>square</code> just like any built-in function:</p>
<div class="sourceCode" id="cb8-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-829103af00"><a href="#cb8-1-829103af00"></a><span class="op">&gt;&gt;&gt;</span> square(<span class="fl">3.0</span>)</span>
<span id="cb8-2-829103af00"><a href="#cb8-2-829103af00"></a><span class="fl">9.0</span></span></code></pre></div>
<p><video src="videos/running_file_demo.webm" controls=""><a href="videos/running_file_demo.webm">Demo of running Python file in PyCharm</a></video><br />
</p>
<h2 id="defining-functions-with-multiple-parameters-829103af00">Defining functions with multiple parameters</h2>
<p>Lets now look at a more complex example that will illustrate a function definition that takes in more than one parameter.</p>
<p>Recall the <a href="../01-working-with-data/04-variables.html">distance formula from Section 1.4</a> to calculate the distance between two points <span class="math inline">\((x_1, y_1), (x_2, y_2)\)</span> in the Cartesian plane: <span class="math display">\[d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\]</span></p>
<p>Well now write a function in Python that calculates this formula. This function will take two inputs, where each input is a <code>tuple</code> of two <code>float</code>s, representing the <span class="math inline">\(x\)</span>- and <span class="math inline">\(y\)</span>-coordinates of each point. When we define a function with multiple parameters, we write the name and type of each parameter using the same format we saw earlier, with parameters separated by commas from each other. Here is the function header and docstring:</p>
<div class="sourceCode" id="cb9-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-829103af00"><a href="#cb9-1-829103af00"></a><span class="kw">def</span> calculate_distance(p1: <span class="bu">tuple</span>, p2: <span class="bu">tuple</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb9-2-829103af00"><a href="#cb9-2-829103af00"></a> <span class="co">&quot;&quot;&quot;Return the distance between points p1 and p2.</span></span>
<span id="cb9-3-829103af00"><a href="#cb9-3-829103af00"></a></span>
<span id="cb9-4-829103af00"><a href="#cb9-4-829103af00"></a><span class="co"> p1 and p2 are tuples of the form (x, y), where the x- and y-coordinates are points.</span></span>
<span id="cb9-5-829103af00"><a href="#cb9-5-829103af00"></a></span>
<span id="cb9-6-829103af00"><a href="#cb9-6-829103af00"></a><span class="co"> &gt;&gt;&gt; calculate_distance((0, 0), (3.0, 4.0))</span></span>
<span id="cb9-7-829103af00"><a href="#cb9-7-829103af00"></a><span class="co"> 5.0</span></span>
<span id="cb9-8-829103af00"><a href="#cb9-8-829103af00"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>In order to use the above formula, we need to extract the coordinates from each point. This is a good reminder of <code>tuple</code> indexing, and the fact that function bodies can consist of more than one statement.<label for="sn-4-829103af00" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-829103af00" class="margin-toggle"/><span class="sidenote"> Remember: the function bodys statements are executed one at a time until a <code>return</code> statement is executed.</span></p>
<div class="sourceCode" id="cb10-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-829103af00"><a href="#cb10-1-829103af00"></a> <span class="co"># The start of the body of calculate_distance</span></span>
<span id="cb10-2-829103af00"><a href="#cb10-2-829103af00"></a> x1 <span class="op">=</span> p1[<span class="dv">0</span>]</span>
<span id="cb10-3-829103af00"><a href="#cb10-3-829103af00"></a> y1 <span class="op">=</span> p1[<span class="dv">1</span>]</span>
<span id="cb10-4-829103af00"><a href="#cb10-4-829103af00"></a> x2 <span class="op">=</span> p2[<span class="dv">0</span>]</span>
<span id="cb10-5-829103af00"><a href="#cb10-5-829103af00"></a> y2 <span class="op">=</span> p2[<span class="dv">1</span>]</span></code></pre></div>
<p>Now that we have the four coordinates, we can apply the above formula and return the result</p>
<div class="sourceCode" id="cb11-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-829103af00"><a href="#cb11-1-829103af00"></a> <span class="co"># Continuing the function body</span></span>
<span id="cb11-2-829103af00"><a href="#cb11-2-829103af00"></a> <span class="cf">return</span> ((x1 <span class="op">-</span> x2) <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> (y1 <span class="op">-</span> y2) <span class="op">**</span> <span class="dv">2</span>) <span class="op">**</span> <span class="fl">0.5</span></span></code></pre></div>
<p>Putting this all together, we have:</p>
<div class="sourceCode" id="cb12-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-829103af00"><a href="#cb12-1-829103af00"></a><span class="kw">def</span> calculate_distance(p1: <span class="bu">tuple</span>, p2: <span class="bu">tuple</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb12-2-829103af00"><a href="#cb12-2-829103af00"></a> <span class="co">&quot;&quot;&quot;Return the distance between points p1 and p2.</span></span>
<span id="cb12-3-829103af00"><a href="#cb12-3-829103af00"></a></span>
<span id="cb12-4-829103af00"><a href="#cb12-4-829103af00"></a><span class="co"> p1 and p2 are tuples of the form (x, y), where the x- and y-coordinates are points.</span></span>
<span id="cb12-5-829103af00"><a href="#cb12-5-829103af00"></a></span>
<span id="cb12-6-829103af00"><a href="#cb12-6-829103af00"></a><span class="co"> &gt;&gt;&gt; calculate_distance((0, 0), (3.0, 4.0))</span></span>
<span id="cb12-7-829103af00"><a href="#cb12-7-829103af00"></a><span class="co"> 5.0</span></span>
<span id="cb12-8-829103af00"><a href="#cb12-8-829103af00"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb12-9-829103af00"><a href="#cb12-9-829103af00"></a> x1 <span class="op">=</span> p1[<span class="dv">0</span>]</span>
<span id="cb12-10-829103af00"><a href="#cb12-10-829103af00"></a> y1 <span class="op">=</span> p1[<span class="dv">1</span>]</span>
<span id="cb12-11-829103af00"><a href="#cb12-11-829103af00"></a> x2 <span class="op">=</span> p2[<span class="dv">0</span>]</span>
<span id="cb12-12-829103af00"><a href="#cb12-12-829103af00"></a> y2 <span class="op">=</span> p2[<span class="dv">1</span>]</span>
<span id="cb12-13-829103af00"><a href="#cb12-13-829103af00"></a> <span class="cf">return</span> ((x1 <span class="op">-</span> x2) <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> (y1 <span class="op">-</span> y2) <span class="op">**</span> <span class="dv">2</span>) <span class="op">**</span> <span class="fl">0.5</span></span></code></pre></div>
<h2 id="function-reuse-829103af00">Function reuse</h2>
<p>Our above function body is perfectly correct, but you might notice that the <code>** 2</code> expressions exactly mimic the body of the first function we defined in this section: <code>square</code>. And so we can reuse the <code>square</code> function inside the body of <code>calculate_distance</code>:</p>
<div class="sourceCode" id="cb13-829103af00"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-829103af00"><a href="#cb13-1-829103af00"></a><span class="kw">def</span> calculate_distance(p1: <span class="bu">tuple</span>, p2: <span class="bu">tuple</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb13-2-829103af00"><a href="#cb13-2-829103af00"></a> <span class="co">&quot;&quot;&quot;Return the distance between points p1 and p2.</span></span>
<span id="cb13-3-829103af00"><a href="#cb13-3-829103af00"></a></span>
<span id="cb13-4-829103af00"><a href="#cb13-4-829103af00"></a><span class="co"> p1 and p2 are tuples of the form (x, y), where the x- and y-coordinates are points.</span></span>
<span id="cb13-5-829103af00"><a href="#cb13-5-829103af00"></a></span>
<span id="cb13-6-829103af00"><a href="#cb13-6-829103af00"></a><span class="co"> &gt;&gt;&gt; calculate_distance((0, 0), (3.0, 4.0))</span></span>
<span id="cb13-7-829103af00"><a href="#cb13-7-829103af00"></a><span class="co"> 5.0</span></span>
<span id="cb13-8-829103af00"><a href="#cb13-8-829103af00"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-9-829103af00"><a href="#cb13-9-829103af00"></a> x1 <span class="op">=</span> p1[<span class="dv">0</span>]</span>
<span id="cb13-10-829103af00"><a href="#cb13-10-829103af00"></a> y1 <span class="op">=</span> p1[<span class="dv">1</span>]</span>
<span id="cb13-11-829103af00"><a href="#cb13-11-829103af00"></a> x2 <span class="op">=</span> p2[<span class="dv">0</span>]</span>
<span id="cb13-12-829103af00"><a href="#cb13-12-829103af00"></a> y2 <span class="op">=</span> p2[<span class="dv">1</span>]</span>
<span id="cb13-13-829103af00"><a href="#cb13-13-829103af00"></a> <span class="cf">return</span> (square(x1 <span class="op">-</span> x2) <span class="op">+</span> square(y1 <span class="op">-</span> y2)) <span class="op">**</span> <span class="fl">0.5</span></span></code></pre></div>
<p>This example of function reuse is quite small, but as our programs grow larger, it will be essential to organize our code into different functions. Well explore this idea in more detail, and other principles of good function and program design, throughout this course.</p>
<h2 id="references-829103af00">References</h2>
<ul>
<li>CSC108 videos: Defining Functions (<a href="https://www.youtube.com/watch?v=5xajzCaBWAs">Part 1</a>, <a href="https://www.youtube.com/watch?v=8V9SQtHo-Z0">Part 2</a>)</li>
<li>CSC108 videos: Docstrings and Function <code>help</code> (<a href="https://www.youtube.com/watch?v=4LDodz_Bwx0">Video</a>)</li>
<li>CSC108 videos: Function Reuse (<a href="https://www.youtube.com/watch?v=H2mKu9Vfyxs">Part 1</a>, <a href="https://www.youtube.com/watch?v=c9o7Q81TqW0">Part 2</a>, <a href="https://www.youtube.com/watch?v=WvwDSMZW_r8">Example</a>)</li>
</ul>
</section>
<br/> <a id="anchor-02-03"></a>
<header id="title-block-header-61586da6fb">
<h1 class="title">2.3 Local Variables and Function Scope</h1>
</header>
<section>
<p>One of the key purposes of functions is to separate different computations in a program, so that we dont have to worry about them all at once. When we write our code in separate functions, we can focus on working with just a single function, and ignore the rest of the code in other functions.</p>
<p>One way in which Python support this way of designing programs is through separating the variables in each functions so that <em>a function call can only access its own variables, but not variables defined within other functions</em>. In this section, well explore how this works, learning more about how Python keep track of function calls and variables.</p>
<h2 id="example-1-introducing-local-variable-scope-61586da6fb">Example 1: introducing local variable scope</h2>
<p>Consider the example from the previous section:</p>
<div class="sourceCode" id="cb1-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-61586da6fb"><a href="#cb1-1-61586da6fb"></a><span class="kw">def</span> square(x: <span class="bu">float</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb1-2-61586da6fb"><a href="#cb1-2-61586da6fb"></a> <span class="co">&quot;&quot;&quot;Return x squared.</span></span>
<span id="cb1-3-61586da6fb"><a href="#cb1-3-61586da6fb"></a></span>
<span id="cb1-4-61586da6fb"><a href="#cb1-4-61586da6fb"></a><span class="co"> &gt;&gt;&gt; square(3.0)</span></span>
<span id="cb1-5-61586da6fb"><a href="#cb1-5-61586da6fb"></a><span class="co"> 9.0</span></span>
<span id="cb1-6-61586da6fb"><a href="#cb1-6-61586da6fb"></a><span class="co"> &gt;&gt;&gt; square(2.5)</span></span>
<span id="cb1-7-61586da6fb"><a href="#cb1-7-61586da6fb"></a><span class="co"> 6.25</span></span>
<span id="cb1-8-61586da6fb"><a href="#cb1-8-61586da6fb"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-9-61586da6fb"><a href="#cb1-9-61586da6fb"></a> <span class="cf">return</span> x <span class="op">**</span> <span class="dv">2</span></span></code></pre></div>
<p>The parameter <code>x</code> is a <em>variable</em> that is assigned a value based on when the function was called. Because this variable is only useful inside the function body, Python does not allow it to be accessible from outside the body. We say that <code>x</code> is a <strong>local variable</strong> of <code>square</code> because it is limited to the function body. Here is another way to put it, using an important new definition. The <strong>scope</strong> of a variable is the places in the code where that variable can be accessed. A <em>local variable</em> of a function is a variable whose scope is the body of that function.</p>
<p>Lets illustrate by first creating a variable in the Python console, and then calling <code>square</code>.</p>
<div class="sourceCode" id="cb2-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-61586da6fb"><a href="#cb2-1-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> n <span class="op">=</span> <span class="fl">10.0</span></span>
<span id="cb2-2-61586da6fb"><a href="#cb2-2-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> result <span class="op">=</span> square(n <span class="op">+</span> <span class="fl">3.5</span>)</span></code></pre></div>
<p>We know that when <code>square</code> is called, its argument expression <code>n + 3.5</code> is evaluated first, producing the value <code>13.5</code>, which is then assigned to the parameter <code>x</code>. Now lets consider what the memory model looks like when the <code>return</code> statement is evaluated. A naive diagram would simply show the two variables <code>n</code> and <code>x</code> and their corresponding values:<label for="sn-0-61586da6fb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-61586da6fb" class="margin-toggle"/><span class="sidenote"> We do not show <code>result</code> because it hasnt been assigned a value yet; this only happens <em>after</em> <code>square</code> returns.</span></p>
<div class="memory-model-values">
<table>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>n</code></td>
<td><code>10.0</code></td>
</tr>
<tr class="even">
<td><code>x</code></td>
<td><code>13.5</code></td>
</tr>
</tbody>
</table>
</div>
<p>But this is very misleading! In our memory model diagrams, we group the variables together based on whether they are introduced in the Python console or inside a function:</p>
<div class="memory-model-values">
<table>
<caption><code>__main__</code> (console)</caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>n</code></td>
<td><code>10.0</code></td>
</tr>
</tbody>
</table>
<table>
<caption><code>square</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>13.5</code></td>
</tr>
</tbody>
</table>
</div>
<p>We use the name <code>__main__</code> to label the table for variables defined in the Python console.<label for="sn-1-61586da6fb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-61586da6fb" class="margin-toggle"/><span class="sidenote"> This is a special name in Python—more on this later.</span> Inside the body of <code>square</code>, the <em>only</em> variable that can be used is <code>x</code>, and the outside in the Python console, the <em>only</em> variable that can be used is <code>n</code>. This may seem a tricky at first, but these memory model diagrams are a good way to visualize whats going on. At the point that the body of square is evaluated, only the “<code>square</code>” table in the memory model is active:</p>
<div class="memory-model-values">
<table>
<caption><code>__main__</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>n</code></td>
<td><code>10.0</code></td>
</tr>
</tbody>
</table>
<table>
<caption><mark><strong><code>square</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>13.5</code></td>
</tr>
</tbody>
</table>
</div>
<p>But after <code>square</code> returns and were back to the Python console, the “<code>square</code>” table is no longer accessible, and only the <code>__main__</code> table is active:</p>
<div class="memory-model-values">
<table>
<caption><mark><strong><code>__main__</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>n</code></td>
<td><code>10.0</code></td>
</tr>
<tr class="even">
<td><code>result</code></td>
<td><code>182.25</code></td>
</tr>
</tbody>
</table>
<div class="memory-model-values-inactive">
<table>
<caption><code>square</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>13.5</code></td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Trying to access variable <code>x</code> from the Python console results in an error:</p>
<div class="sourceCode" id="cb3-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-61586da6fb"><a href="#cb3-1-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> n <span class="op">=</span> <span class="fl">10.0</span></span>
<span id="cb3-2-61586da6fb"><a href="#cb3-2-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> square(n <span class="op">+</span> <span class="fl">3.5</span>)</span>
<span id="cb3-3-61586da6fb"><a href="#cb3-3-61586da6fb"></a><span class="fl">182.25</span></span>
<span id="cb3-4-61586da6fb"><a href="#cb3-4-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> x</span>
<span id="cb3-5-61586da6fb"><a href="#cb3-5-61586da6fb"></a>Traceback (most recent call last):</span>
<span id="cb3-6-61586da6fb"><a href="#cb3-6-61586da6fb"></a> File <span class="st">&quot;&lt;stdin&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb3-7-61586da6fb"><a href="#cb3-7-61586da6fb"></a><span class="pp">NameError</span>: name <span class="st">&#39;x&#39;</span> <span class="kw">is</span> <span class="kw">not</span> defined</span></code></pre></div>
<h2 id="example-2-duplicate-variable-names-61586da6fb">Example 2: duplicate variable names</h2>
<p>The principle of “separate tables” in our memory model applies even when we use the same variable name in two different places. Suppose we modify our example above to use <code>x</code> instead of <code>n</code> in the Python console:</p>
<div class="sourceCode" id="cb4-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-61586da6fb"><a href="#cb4-1-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="fl">10.0</span></span>
<span id="cb4-2-61586da6fb"><a href="#cb4-2-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> result <span class="op">=</span> square(x <span class="op">+</span> <span class="fl">3.5</span>)</span></code></pre></div>
<p>Following the same reasoning as above, the argument expression <code>x + 3.5</code> is evaluated to produce <code>13.5</code>, which is then assigned to the parameter <code>x</code>. Does this modify the <code>x</code> variable in the Python console? No! They are different variables even though they share the same name.</p>
<div class="memory-model-values">
<table>
<caption><code>__main__</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>10.0</code></td>
</tr>
</tbody>
</table>
<table>
<caption><code>square</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>13.5</code></td>
</tr>
</tbody>
</table>
</div>
<p>We can confirm this after the function call is evaluated by checking the value of the original <code>x</code>.</p>
<div class="sourceCode" id="cb5-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-61586da6fb"><a href="#cb5-1-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="fl">10.0</span></span>
<span id="cb5-2-61586da6fb"><a href="#cb5-2-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> result <span class="op">=</span> square(x <span class="op">+</span> <span class="fl">3.5</span>)</span>
<span id="cb5-3-61586da6fb"><a href="#cb5-3-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> result</span>
<span id="cb5-4-61586da6fb"><a href="#cb5-4-61586da6fb"></a><span class="fl">182.25</span></span>
<span id="cb5-5-61586da6fb"><a href="#cb5-5-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> x</span>
<span id="cb5-6-61586da6fb"><a href="#cb5-6-61586da6fb"></a><span class="fl">10.0</span></span></code></pre></div>
<p>Here is what our memory model looks like after <code>square</code> has returned:</p>
<div class="memory-model-values">
<table>
<caption><mark><strong><code>__main__</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>10.0</code></td>
</tr>
<tr class="even">
<td><code>result</code></td>
<td><code>182.25</code></td>
</tr>
</tbody>
</table>
<div class="memory-model-values-inactive">
<table>
<caption><code>square</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>13.5</code></td>
</tr>
</tbody>
</table>
</div>
</div>
<h2 id="example-3-not-accessing-another-functions-variables-61586da6fb">Example 3: (not) accessing another functions variables</h2>
<p>Our last example in this section involves two functions, one of which calls the other:</p>
<div class="sourceCode" id="cb6-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-61586da6fb"><a href="#cb6-1-61586da6fb"></a><span class="kw">def</span> square(x: <span class="bu">float</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb6-2-61586da6fb"><a href="#cb6-2-61586da6fb"></a> <span class="co">&quot;&quot;&quot;Return x squared.</span></span>
<span id="cb6-3-61586da6fb"><a href="#cb6-3-61586da6fb"></a></span>
<span id="cb6-4-61586da6fb"><a href="#cb6-4-61586da6fb"></a><span class="co"> &gt;&gt;&gt; square(3.0)</span></span>
<span id="cb6-5-61586da6fb"><a href="#cb6-5-61586da6fb"></a><span class="co"> 9.0</span></span>
<span id="cb6-6-61586da6fb"><a href="#cb6-6-61586da6fb"></a><span class="co"> &gt;&gt;&gt; square(2.5)</span></span>
<span id="cb6-7-61586da6fb"><a href="#cb6-7-61586da6fb"></a><span class="co"> 6.25</span></span>
<span id="cb6-8-61586da6fb"><a href="#cb6-8-61586da6fb"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb6-9-61586da6fb"><a href="#cb6-9-61586da6fb"></a> <span class="cf">return</span> x <span class="op">**</span> <span class="dv">2</span></span>
<span id="cb6-10-61586da6fb"><a href="#cb6-10-61586da6fb"></a></span>
<span id="cb6-11-61586da6fb"><a href="#cb6-11-61586da6fb"></a></span>
<span id="cb6-12-61586da6fb"><a href="#cb6-12-61586da6fb"></a><span class="kw">def</span> square_of_sum(numbers: <span class="bu">list</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb6-13-61586da6fb"><a href="#cb6-13-61586da6fb"></a> <span class="co">&quot;&quot;&quot;Return the square of the sum of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb6-14-61586da6fb"><a href="#cb6-14-61586da6fb"></a> total <span class="op">=</span> <span class="bu">sum</span>(numbers)</span>
<span id="cb6-15-61586da6fb"><a href="#cb6-15-61586da6fb"></a> <span class="cf">return</span> square(total)</span></code></pre></div>
<p>Lets first call our new function <code>square_of_sum</code> in the Python console:</p>
<div class="sourceCode" id="cb7-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-61586da6fb"><a href="#cb7-1-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> nums <span class="op">=</span> [<span class="fl">1.5</span>, <span class="fl">2.5</span>]</span>
<span id="cb7-2-61586da6fb"><a href="#cb7-2-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> result <span class="op">=</span> square_of_sum(nums)</span>
<span id="cb7-3-61586da6fb"><a href="#cb7-3-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> result</span>
<span id="cb7-4-61586da6fb"><a href="#cb7-4-61586da6fb"></a><span class="fl">16.0</span></span></code></pre></div>
<p>We can trace what happens at three points when we call <code>square_of_sum</code>:</p>
<table class="fullwidth" style="border: 1px solid black;">
<tr>
<td>
Right before <code>square_of_sum</code> is called (from console)
</td>
<td>
Right before <code>square</code> is called (from <code>square_of_sum</code>)
</td>
<td>
Right before <code>square</code> returns
</td>
</tr>
<tr>
<td>
<div class="memory-model-values">
<table>
<caption><mark><strong><code>__main__</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>nums</code></td>
<td><code>[1.5, 2.5]</code></td>
</tr>
</tbody>
</table>
</div>
</td>
<td>
<div class="memory-model-values">
<table>
<caption><code>__main__</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>nums</code></td>
<td><code>[1.5, 2.5]</code></td>
</tr>
</tbody>
</table>
<table>
<caption><mark><strong><code>square_of_sum</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>numbers</code></td>
<td><code>[1.5, 2.5]</code></td>
</tr>
<tr class="even">
<td><code>total</code></td>
<td><code>4.0</code></td>
</tr>
</tbody>
</table>
</div>
</td>
<td>
<div class="memory-model-values">
<table>
<caption><code>__main__</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>nums</code></td>
<td><code>[1.5, 2.5]</code></td>
</tr>
</tbody>
</table>
<table>
<caption><code>square_of_sum</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>numbers</code></td>
<td><code>[1.5, 2.5]</code></td>
</tr>
<tr class="even">
<td><code>total</code></td>
<td><code>4.0</code></td>
</tr>
</tbody>
</table>
<table>
<caption><mark><strong><code>square</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>4.0</code></td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</table>
<p>From these diagrams, we see how the list <code>[1.5, 2.5]</code> is passed from the console to <code>square_of_sum</code>, and how the number <code>4.0</code> is passed from <code>square_of_sum</code> to <code>square</code>.</p>
<p>Now suppose we wanted to do something a bit silly: have <code>square</code> access <code>total</code> instead of <code>x</code>. We know from our memory model that these variables should be assigned the same value, so the programs behaviour shouldnt change, right?</p>
<div class="sourceCode" id="cb8-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-61586da6fb"><a href="#cb8-1-61586da6fb"></a><span class="kw">def</span> square(x: <span class="bu">float</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb8-2-61586da6fb"><a href="#cb8-2-61586da6fb"></a> <span class="co">&quot;&quot;&quot;Return x squared.</span></span>
<span id="cb8-3-61586da6fb"><a href="#cb8-3-61586da6fb"></a></span>
<span id="cb8-4-61586da6fb"><a href="#cb8-4-61586da6fb"></a><span class="co"> &gt;&gt;&gt; square(3.0)</span></span>
<span id="cb8-5-61586da6fb"><a href="#cb8-5-61586da6fb"></a><span class="co"> 9.0</span></span>
<span id="cb8-6-61586da6fb"><a href="#cb8-6-61586da6fb"></a><span class="co"> &gt;&gt;&gt; square(2.5)</span></span>
<span id="cb8-7-61586da6fb"><a href="#cb8-7-61586da6fb"></a><span class="co"> 6.25</span></span>
<span id="cb8-8-61586da6fb"><a href="#cb8-8-61586da6fb"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb8-9-61586da6fb"><a href="#cb8-9-61586da6fb"></a> <span class="cf">return</span> total <span class="op">**</span> <span class="dv">2</span> <span class="co"># Now we&#39;re using total instead of x</span></span>
<span id="cb8-10-61586da6fb"><a href="#cb8-10-61586da6fb"></a></span>
<span id="cb8-11-61586da6fb"><a href="#cb8-11-61586da6fb"></a></span>
<span id="cb8-12-61586da6fb"><a href="#cb8-12-61586da6fb"></a><span class="kw">def</span> square_of_sum(numbers: <span class="bu">list</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb8-13-61586da6fb"><a href="#cb8-13-61586da6fb"></a> <span class="co">&quot;&quot;&quot;Return the square of the sum of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb8-14-61586da6fb"><a href="#cb8-14-61586da6fb"></a> total <span class="op">=</span> <span class="bu">sum</span>(numbers)</span>
<span id="cb8-15-61586da6fb"><a href="#cb8-15-61586da6fb"></a> <span class="cf">return</span> square(total)</span></code></pre></div>
<p>Lets see what happens when we try to call <code>square_of_sum</code> in the Python console now:</p>
<div class="sourceCode" id="cb9-61586da6fb"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-61586da6fb"><a href="#cb9-1-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> nums <span class="op">=</span> [<span class="fl">1.5</span>, <span class="fl">2.5</span>]</span>
<span id="cb9-2-61586da6fb"><a href="#cb9-2-61586da6fb"></a><span class="op">&gt;&gt;&gt;</span> square_of_sum(nums)</span>
<span id="cb9-3-61586da6fb"><a href="#cb9-3-61586da6fb"></a>Traceback (most recent call last):</span>
<span id="cb9-4-61586da6fb"><a href="#cb9-4-61586da6fb"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb9-5-61586da6fb"><a href="#cb9-5-61586da6fb"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">15</span>, <span class="kw">in</span> square_of_sum</span>
<span id="cb9-6-61586da6fb"><a href="#cb9-6-61586da6fb"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">9</span>, <span class="kw">in</span> square</span>
<span id="cb9-7-61586da6fb"><a href="#cb9-7-61586da6fb"></a><span class="pp">NameError</span>: name <span class="st">&#39;total&#39;</span> <span class="kw">is</span> <span class="kw">not</span> defined</span></code></pre></div>
<p>An error occurs! Lets take a look at the state of memory when <code>square</code> is called (this is the same as above):</p>
<div class="memory-model-values">
<table>
<caption><code>__main__</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>nums</code></td>
<td><code>[1.5, 2.5]</code></td>
</tr>
</tbody>
</table>
<table>
<caption><code>square_of_sum</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>numbers</code></td>
<td><code>[1.5, 2.5]</code></td>
</tr>
<tr class="even">
<td><code>total</code></td>
<td><code>4.0</code></td>
</tr>
</tbody>
</table>
<table>
<caption><mark><strong><code>square</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>4.0</code></td>
</tr>
</tbody>
</table>
</div>
<p>Well, there is indeed both a <code>total</code> variable and an <code>x</code> variable with the same value, <code>4.0</code>. So why are we getting this error? Pythons rule for local scope: <em>a local variable can only be accessed in the function body it is defined</em>. Here, the statement <code>return total ** 2</code> is in the body of <code>square</code>, but attempts to access the local variable of a different function (<code>square_of_sum</code>). When the Python interpreter attempts to retrive the value of <code>total</code>, it looks only in the scope of <code>square</code>, and doesnt find <code>total</code>, resulting in a <code>NameError</code>.</p>
<p>The somewhat non-intuitive point about this behaviour is that this happens <em>even when <code>square_of_sum</code> is still active</em>. In our example, <code>square</code> is called from within <code>square_of_sum</code>, and so the variable <code>total</code> <em>does</em> exist in Pythons memory—it just isnt accessible. While this might seem like a limitation of the language, its actually a good thing: this prevents you from accidentally using a variable from a completely different function when working on a function.</p>
<h2 id="summary-61586da6fb">Summary</h2>
<p>In this section, we learned about how Python handles <em>local variables</em>, by making them accessible only from within the function that they are defined. Though we hope this makes intuitive sense, some of the details and diagrams we presented here were fairly technical. We recommend coming back to this section in a few days and reviewing this material, perhaps by explaining in your own words whats happening in each example. You can also practice drawing this style of memory model diagram for future code that you write.</p>
</section>
<br/> <a id="anchor-02-04"></a>
<header id="title-block-header-5eedb7ff14">
<h1 class="title">2.4 Importing Modules</h1>
</header>
<section>
<p>So far we have learned about Pythons built-in functions and various data type methods. But these form a small fraction of all the functions that the Python programming language comes with. Pythons other functions (and even other data types) are separated into various <strong>modules</strong>, which is another name we give to Python code files. Unlike the functions and data types weve seen so far, these modules are not automatically loaded when run the Python interpreter, as they contain more specialized functions and data types. So in this section, were going to learn how to load one of these modules and use their definitions.</p>
<h2 id="the-import-statement-5eedb7ff14">The <code>import</code> statement</h2>
<p>To load a Python module, we use a piece of code called an <strong>import statement</strong>, which has the following syntax:</p>
<div class="sourceCode" id="cb1-5eedb7ff14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-5eedb7ff14"><a href="#cb1-1-5eedb7ff14"></a><span class="im">import</span> <span class="op">&lt;</span>module_name<span class="op">&gt;</span></span></code></pre></div>
<p>For example, here is how we could load the <code>math</code> module in the Python console:</p>
<div class="sourceCode" id="cb2-5eedb7ff14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-5eedb7ff14"><a href="#cb2-1-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> math</span></code></pre></div>
<p>Like the other statements weve seen so far, import statements do not produce a value, but they do have an important effect. An <code>import</code> statement introduces a new variable (the name of the module being imported) that can be used to refer to all definitions from that module.</p>
<p>For example, the <code>math</code> module defines a function <code>log2</code> which computes the base-2 logarithm of a number. To access this function, we use dot notation:<label for="sn-0-5eedb7ff14" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-5eedb7ff14" class="margin-toggle"/><span class="sidenote"> This notation is the same as accessing data type methods, but <code>log2</code> is <em>not</em> a method. Its a top-level function, just one that happens to be defined in the <code>math</code> module.</span></p>
<div class="sourceCode" id="cb3-5eedb7ff14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-5eedb7ff14"><a href="#cb3-1-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> math.log2(<span class="dv">1024</span>)</span>
<span id="cb3-2-5eedb7ff14"><a href="#cb3-2-5eedb7ff14"></a><span class="fl">10.0</span></span></code></pre></div>
<p>What other functions are contained in the <code>math</code> module? Well make use of a few other later in this course, but if youre curious you can call the special built-in function <code>dir</code> on the the module (or any other module) to see a list of functions and other variables defined in the module:</p>
<div class="sourceCode" id="cb4-5eedb7ff14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-5eedb7ff14"><a href="#cb4-1-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">dir</span>(math)</span>
<span id="cb4-2-5eedb7ff14"><a href="#cb4-2-5eedb7ff14"></a>[<span class="st">&#39;__doc__&#39;</span>, <span class="st">&#39;__loader__&#39;</span>, <span class="st">&#39;__name__&#39;</span>, <span class="st">&#39;__package__&#39;</span>, <span class="st">&#39;__spec__&#39;</span>, <span class="st">&#39;acos&#39;</span>, <span class="st">&#39;acosh&#39;</span>, <span class="st">&#39;asin&#39;</span>, <span class="st">&#39;asinh&#39;</span>, <span class="st">&#39;atan&#39;</span>, <span class="st">&#39;atan2&#39;</span>, <span class="st">&#39;atanh&#39;</span>, <span class="st">&#39;ceil&#39;</span>, <span class="st">&#39;comb&#39;</span>, <span class="st">&#39;copysign&#39;</span>, <span class="st">&#39;cos&#39;</span>, <span class="st">&#39;cosh&#39;</span>, <span class="st">&#39;degrees&#39;</span>, <span class="st">&#39;dist&#39;</span>, <span class="st">&#39;e&#39;</span>, <span class="st">&#39;erf&#39;</span>, <span class="st">&#39;erfc&#39;</span>, <span class="st">&#39;exp&#39;</span>, <span class="st">&#39;expm1&#39;</span>, <span class="st">&#39;fabs&#39;</span>, <span class="st">&#39;factorial&#39;</span>, <span class="st">&#39;floor&#39;</span>, <span class="st">&#39;fmod&#39;</span>, <span class="st">&#39;frexp&#39;</span>, <span class="st">&#39;fsum&#39;</span>, <span class="st">&#39;gamma&#39;</span>, <span class="st">&#39;gcd&#39;</span>, <span class="st">&#39;hypot&#39;</span>, <span class="st">&#39;inf&#39;</span>, <span class="st">&#39;isclose&#39;</span>, <span class="st">&#39;isfinite&#39;</span>, <span class="st">&#39;isinf&#39;</span>, <span class="st">&#39;isnan&#39;</span>, <span class="st">&#39;isqrt&#39;</span>, <span class="st">&#39;ldexp&#39;</span>, <span class="st">&#39;lgamma&#39;</span>, <span class="st">&#39;log&#39;</span>, <span class="st">&#39;log10&#39;</span>, <span class="st">&#39;log1p&#39;</span>, <span class="st">&#39;log2&#39;</span>, <span class="st">&#39;modf&#39;</span>, <span class="st">&#39;nan&#39;</span>, <span class="st">&#39;perm&#39;</span>, <span class="st">&#39;pi&#39;</span>, <span class="st">&#39;pow&#39;</span>, <span class="st">&#39;prod&#39;</span>, <span class="st">&#39;radians&#39;</span>, <span class="st">&#39;remainder&#39;</span>, <span class="st">&#39;sin&#39;</span>, <span class="st">&#39;sinh&#39;</span>, <span class="st">&#39;sqrt&#39;</span>, <span class="st">&#39;tan&#39;</span>, <span class="st">&#39;tanh&#39;</span>, <span class="st">&#39;tau&#39;</span>, <span class="st">&#39;trunc&#39;</span>]</span></code></pre></div>
<p>Ignoring the first few with the double underscore, we see some familiar looking names, like <code>ceil</code>, <code>floor</code>, <code>pi</code>, and <code>sin</code>. Weve linked to the documentation for the <code>math</code> module in the <a href="#references-5eedb7ff14">References</a> section below.</p>
<h2 id="the-datetime-module-5eedb7ff14">The <code>datetime</code> module</h2>
<p>Python comes with far more modules than well have time to learn about in this course. However, just to illustrate the breadth of these modules, well briefly introduce one more that will be useful occasionally throughout the course.</p>
<p>The <code>datetime</code> module provides not just functions but new <em>data types</em> for representing time-based data. The first data type well study here is <code>date</code>, which is a data type that represents a specific date.</p>
<div class="sourceCode" id="cb5-5eedb7ff14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-5eedb7ff14"><a href="#cb5-1-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> datetime</span>
<span id="cb5-2-5eedb7ff14"><a href="#cb5-2-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> canada_day <span class="op">=</span> datetime.date(<span class="dv">1867</span>, <span class="dv">7</span>, <span class="dv">1</span>) <span class="co"># Create a new date</span></span>
<span id="cb5-3-5eedb7ff14"><a href="#cb5-3-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(canada_day)</span>
<span id="cb5-4-5eedb7ff14"><a href="#cb5-4-5eedb7ff14"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;datetime.date&#39;</span><span class="op">&gt;</span></span>
<span id="cb5-5-5eedb7ff14"><a href="#cb5-5-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> term_start <span class="op">=</span> datetime.date(<span class="dv">2020</span>, <span class="dv">9</span>, <span class="dv">10</span>)</span>
<span id="cb5-6-5eedb7ff14"><a href="#cb5-6-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> datetime.date.weekday(term_start) <span class="co"># Return the day of the week of the date</span></span>
<span id="cb5-7-5eedb7ff14"><a href="#cb5-7-5eedb7ff14"></a><span class="dv">3</span> <span class="co"># 0 = Monday, 1 = Tuesday, etc.</span></span></code></pre></div>
<p>Note the double use of dot notation in that last expression. <code>datetime.date</code> is the data type being accessed, and <code>.weekday</code> accesses a method of that data type.</p>
<p>We can compare dates for equality using <code>==</code> and chronological order (e.g., <code>&lt;</code> for comparing one date comes before another). We can also subtract dates, which is pretty cool:</p>
<div class="sourceCode" id="cb6-5eedb7ff14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-5eedb7ff14"><a href="#cb6-1-5eedb7ff14"></a><span class="op">&gt;&gt;&gt;</span> term_start <span class="op">-</span> canada_day</span>
<span id="cb6-2-5eedb7ff14"><a href="#cb6-2-5eedb7ff14"></a>datetime.timedelta(days<span class="op">=</span><span class="dv">55954</span>)</span></code></pre></div>
<p>The difference between two dates is an instance of the <code>datetime.timedelta</code> data type, which is used to represent an interval of time. What the above expression tells us is that 55,954 days have passed between the first day of the fall semester and the day of Canadas confederation.<label for="sn-1-5eedb7ff14" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-5eedb7ff14" class="margin-toggle"/><span class="sidenote"> Fun fact: Canadas confederation first consisted of only four provinces: Ontario, Quebec, Nova Scotia, and New Brunswick.</span></p>
<h2 id="theres-a-lot-of-python-out-theredont-worry-5eedb7ff14">Theres a lot of Python out there—dont worry!</h2>
<p>Up to this point, weve covered several different data types, functions, methods, and now modules in Python. It might be starting to feel a bit daunting, and we wanted to take a moment to pause and look at the bigger picture. Our goal in showing you these elements of Python is not to overwhelm you, but instead to give you a taste of the languages powerful computational capabilities. But this course is not about memorizing different functions, data types, and modules in Python! All throughout this course, youll have access to references and documentation that describe the functionality of these different elements, and will have lots of opportunities to practice using them. For now, all we want you to know is simply that these capabilities exist, how to experiment with them in the Python console, and how to look up information about them.</p>
<h2 id="references-5eedb7ff14">References</h2>
<ul>
<li><a href="https://docs.python.org/3/library/datetime.html"><code>datetime</code> module documentation</a></li>
<li><a href="https://docs.python.org/3/library/math.html"><code>math</code> module documentation</a></li>
</ul>
</section>
<br/> <a id="anchor-02-05"></a>
<header id="title-block-header-52ec81553a">
<h1 class="title">2.5 The Function Design Recipe</h1>
</header>
<section>
<p>Often when beginners are tasked with writing a program to solve a problem, they jump immediately to writing code. Doesnt matter whether the code is correct or not, or even if they fully understand the problem: somehow the allure of filling up the screen with text is too tempting. So before we go further in our study of the Python programming language, well introduce the <em>Function Design Recipe</em>, a structured process for taking a problem description and designing and implementing a function in Python to solve this problem.</p>
<h2 id="the-function-design-recipe-by-example-52ec81553a">The Function Design Recipe by example</h2>
<p>Consider the following example problem: write a function to determine whether or not a number is even. Well use this example to illustrate the five steps of the Function Design Recipe.</p>
<div class="fullwidth">
<table>
<colgroup>
<col style="width: 63%" />
<col style="width: 36%" />
</colgroup>
<tbody>
<tr class="odd">
<td><p><strong>1. Write example uses.</strong></p>
<p>Pick a name for the function (often a verb or verb phrase). Sometimes a good name is a short answer to the question “What does your function do?” Write one or two examples of calls to your function and the expected returned values. Include an example of a standard case (as opposed to a tricky case). Put the examples inside a triple-quoted string that youve indented since it will be the beginning of the docstring.</p></td>
<td><div class="sourceCode" id="cb1-52ec81553a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-52ec81553a"><a href="#cb1-1-52ec81553a"></a> <span class="co">&quot;&quot;&quot;</span></span>
<span id="cb1-2-52ec81553a"><a href="#cb1-2-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(2)</span></span>
<span id="cb1-3-52ec81553a"><a href="#cb1-3-52ec81553a"></a><span class="co"> True</span></span>
<span id="cb1-4-52ec81553a"><a href="#cb1-4-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(17)</span></span>
<span id="cb1-5-52ec81553a"><a href="#cb1-5-52ec81553a"></a><span class="co"> False</span></span>
<span id="cb1-6-52ec81553a"><a href="#cb1-6-52ec81553a"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
 </td>
</tr>
<tr class="even">
<td><p><strong>2. Write the function header.</strong></p>
<p>Write the function header above the docstring (not indented). Choose a meaningful name for each parameter (often nouns). Include the type contract (the types of the parameters and return value).</p></td>
<td><div class="sourceCode" id="cb2-52ec81553a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-52ec81553a"><a href="#cb2-1-52ec81553a"></a><span class="kw">def</span> is_even(value: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-2-52ec81553a"><a href="#cb2-2-52ec81553a"></a> <span class="co">&quot;&quot;&quot;</span></span>
<span id="cb2-3-52ec81553a"><a href="#cb2-3-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(2)</span></span>
<span id="cb2-4-52ec81553a"><a href="#cb2-4-52ec81553a"></a><span class="co"> True</span></span>
<span id="cb2-5-52ec81553a"><a href="#cb2-5-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(17)</span></span>
<span id="cb2-6-52ec81553a"><a href="#cb2-6-52ec81553a"></a><span class="co"> False</span></span>
<span id="cb2-7-52ec81553a"><a href="#cb2-7-52ec81553a"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
 </td>
</tr>
<tr class="odd">
<td><p><strong>3. Write the function description.</strong></p>
<p>Before the examples, add a description of what the function does and mention each parameter by name or otherwise make sure the purpose of each parameter is clear. Describe the return value.</p></td>
<td><div class="sourceCode" id="cb3-52ec81553a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-52ec81553a"><a href="#cb3-1-52ec81553a"></a><span class="kw">def</span> is_even(value: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb3-2-52ec81553a"><a href="#cb3-2-52ec81553a"></a> <span class="co">&quot;&quot;&quot;Return whether value is even.</span></span>
<span id="cb3-3-52ec81553a"><a href="#cb3-3-52ec81553a"></a></span>
<span id="cb3-4-52ec81553a"><a href="#cb3-4-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(2)</span></span>
<span id="cb3-5-52ec81553a"><a href="#cb3-5-52ec81553a"></a><span class="co"> True</span></span>
<span id="cb3-6-52ec81553a"><a href="#cb3-6-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(17)</span></span>
<span id="cb3-7-52ec81553a"><a href="#cb3-7-52ec81553a"></a><span class="co"> False</span></span>
<span id="cb3-8-52ec81553a"><a href="#cb3-8-52ec81553a"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
 </td>
</tr>
<tr class="even">
<td><p><strong>4. Implement the function body.</strong></p>
<p>Write the body of the function and indent it to match the docstring. To help yourself write the body, review your examples from the first step and consider how you determined the return values. You may find it helpful to write a few more example calls.</p></td>
<td><div class="sourceCode" id="cb4-52ec81553a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-52ec81553a"><a href="#cb4-1-52ec81553a"></a><span class="kw">def</span> is_even(value: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb4-2-52ec81553a"><a href="#cb4-2-52ec81553a"></a> <span class="co">&quot;&quot;&quot;Return whether value is even.</span></span>
<span id="cb4-3-52ec81553a"><a href="#cb4-3-52ec81553a"></a></span>
<span id="cb4-4-52ec81553a"><a href="#cb4-4-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(2)</span></span>
<span id="cb4-5-52ec81553a"><a href="#cb4-5-52ec81553a"></a><span class="co"> True</span></span>
<span id="cb4-6-52ec81553a"><a href="#cb4-6-52ec81553a"></a><span class="co"> &gt;&gt;&gt; is_even(17)</span></span>
<span id="cb4-7-52ec81553a"><a href="#cb4-7-52ec81553a"></a><span class="co"> False</span></span>
<span id="cb4-8-52ec81553a"><a href="#cb4-8-52ec81553a"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-9-52ec81553a"><a href="#cb4-9-52ec81553a"></a> <span class="cf">return</span> value <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
 </td>
</tr>
<tr class="odd">
<td><p><strong>5. Test the function.</strong></p>
<p>Test your function on all your example cases including any additional cases you created in the previous step. Additionally, try it on extra tricky or corner cases.</p>
<p>One simple way to test your function is by calling it in the Python console. In the next section, well discuss more powerful ways of testing your code.</p>
<p>If you encounter any errors/incorrect return values, first make sure that your tests are correct, and then go back to Step 4 and try to identify and fix any possible errors in your code. This is called <em>debugging</em> your code, a process well discuss throughout this course.</p></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<h2 id="the-importance-of-documenting-your-functions-52ec81553a">The importance of documenting your functions</h2>
<p>The Function Design Recipe places a large emphasis on developing a precise and detailed function header and docstring before writing any code for the function body. There are two main benefits to doing this.</p>
<p>First, when you are given a programming task—“Write a function to do X”—you want to make sure you fully understand the goal of that function before trying to solve it. Forcing yourself to write out the function header and docstring, with examples, is an excellent way to reinforce your understanding about what you need to do.</p>
<p>Second, as you begin to work on larger projects and writing dozens or hundreds of functions, it is easy to lose track of what each function does. The function header and docstring serve as <em>documentation</em> for the function, communicating to othersand to your future self—what that function is supposed to to. Your choices for the functions name, its parameter names, its type contract, its docstring examples, and its description, can make the difference between code that is easy to work on and maintain, and code that is undecipherable.</p>
<p>So the bottom line is you should follow this process for all of the functions youll write in this course, and beyond—trust us, it will save you lots of time and headaches!</p>
<h2 id="references-52ec81553a">References</h2>
<ul>
<li>CSC108 videos: Function Design Recipe (<a href="https://youtu.be/v63oukRbJHE">Part 1</a>, <a href="https://youtu.be/ntZEFEp3xVY">Part 2</a>)</li>
</ul>
</section>
<br/> <a id="anchor-02-06"></a>
<header id="title-block-header-d7b3e8cb48">
<h1 class="title">2.6 Testing Functions I: <code>doctest</code> and <code>pytest</code></h1>
</header>
<section>
<p>The last step of the <a href="05-the-function-design-recipe.html">Function Design Recipe</a> is to test your code—but how? In this section, well discuss the different strategies for testing code that youll use during the term, and beyond. As you write more and more complex programs in this course, it will be vital to maintain good habits to support you in your programming. One of these habits is developing good tests that will ensure your code is correct, and—often overlooked—using good <em>tools</em> to make those tests as easy to run as possible. You want to get in the habit of writing tests early in the process of programming, and running them as often as possible to detect coding errors as soon as you make them.</p>
<h2 id="doctests-basic-examples-in-docstrings-d7b3e8cb48">Doctests: basic examples in docstrings</h2>
<p>By following the Function Design Recipe, you naturally create a few tests for each function in the form of <em>doctest examples</em>, the examples you write in the function docstring. The simplest form of testing your function is import your function into the Python console, and then manually evaluate each doctest example one at a time and compare the output with the expected output in the docstring. This is a form of <strong>manual testing</strong>, as it requires human interaction to complete. Manual testing is often tedious and error-prone, so while it may be good for a quick check, we can certainly do better.</p>
<p>Our first improvement is to use the Python library <code>doctest</code>, which can automatically extract doctest examples from docstrings and convert them into runnable tests. To use <code>doctest</code>, you can add the following code to the very bottom of any Python file:<label for="sn-0-d7b3e8cb48" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-d7b3e8cb48" class="margin-toggle"/><span class="sidenote"> Dont worry about the <code>if __name__ == '__main__'</code> part for now; we will discuss this later on.</span></p>
<div class="sourceCode" id="cb1-d7b3e8cb48"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-d7b3e8cb48"><a href="#cb1-1-d7b3e8cb48"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb1-2-d7b3e8cb48"><a href="#cb1-2-d7b3e8cb48"></a> <span class="im">import</span> doctest <span class="co"># import the doctest library</span></span>
<span id="cb1-3-d7b3e8cb48"><a href="#cb1-3-d7b3e8cb48"></a> doctest.testmod() <span class="co"># run the tests</span></span></code></pre></div>
<p>Then when you run the file, all of the doctest examples are automatically run, and you receive a report about which tests failed.</p>
<p><video src="videos/doctests_passing_default_runner.webm" controls=""><a href="videos/doctests_passing_default_runner.webm">Video demo of running doctests</a></video><br />
</p>
<p>One warning: in order to use <code>doctest</code>, your docstring examples must be correctly formatted and valid Python code. For more information about the <code>doctest</code> module, check out <a href="../B-python-libraries/01-doctest.html">Appendix B.1 <code>doctest</code></a>.</p>
<h2 id="creating-test-suites-with-pytest-d7b3e8cb48">Creating test suites with <code>pytest</code></h2>
<p>Though <code>doctest</code> is an extremely useful module, the examples we write in docstrings are only simple cases meant to illustrate typical uses of the function. As functions get more complex, well require more extensive tests to verify that they are correct. We could put all these tests into the function docstrings, but that would make the docstrings far too long.</p>
<p>So instead, we will use another Python library, <code>pytest</code>, to write our tests in a separate file, and so include an exhaustive set of tests without cluttering our code files. Lets illustrate this with an example. Suppose we have defined the following function in a files <code>trues.py</code>:<label for="sn-1-d7b3e8cb48" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-d7b3e8cb48" class="margin-toggle"/><span class="sidenote"> Weve not included the body of this function, as we do not need to know how a function is implemented in order to write tests for it!</span></p>
<div class="sourceCode" id="cb2-d7b3e8cb48"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-d7b3e8cb48"><a href="#cb2-1-d7b3e8cb48"></a><span class="co"># In file trues.py</span></span>
<span id="cb2-2-d7b3e8cb48"><a href="#cb2-2-d7b3e8cb48"></a></span>
<span id="cb2-3-d7b3e8cb48"><a href="#cb2-3-d7b3e8cb48"></a><span class="kw">def</span> has_more_trues(booleans: <span class="bu">list</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-4-d7b3e8cb48"><a href="#cb2-4-d7b3e8cb48"></a> <span class="co">&quot;&quot;&quot;Return whether booleans contains more True values than False values.</span></span>
<span id="cb2-5-d7b3e8cb48"><a href="#cb2-5-d7b3e8cb48"></a></span>
<span id="cb2-6-d7b3e8cb48"><a href="#cb2-6-d7b3e8cb48"></a><span class="co"> &gt;&gt;&gt; has_more_trues([True, False, True])</span></span>
<span id="cb2-7-d7b3e8cb48"><a href="#cb2-7-d7b3e8cb48"></a><span class="co"> True</span></span>
<span id="cb2-8-d7b3e8cb48"><a href="#cb2-8-d7b3e8cb48"></a><span class="co"> &gt;&gt;&gt; has_more_trues([True, False, False])</span></span>
<span id="cb2-9-d7b3e8cb48"><a href="#cb2-9-d7b3e8cb48"></a><span class="co"> False</span></span>
<span id="cb2-10-d7b3e8cb48"><a href="#cb2-10-d7b3e8cb48"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-11-d7b3e8cb48"><a href="#cb2-11-d7b3e8cb48"></a> <span class="co"># Function body omitted</span></span></code></pre></div>
<p>Now, well see how to write tests for this function in a new file, which well call <code>test_trues.py</code>.<label for="sn-2-d7b3e8cb48" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-d7b3e8cb48" class="margin-toggle"/><span class="sidenote"> By convention, all Python modules which contain tests are named with the prefix <code>test_</code>.</span> Now let us introduce some terminology. A <strong>unit test</strong> is a block of code that checks for the correct behaviour of a function for one specific input. A <strong>test suite</strong> is a collection of tests that check the behaviour of a function or (usually small) set of functions. Every test file contains a test suite.</p>
<p>In Python, we express a unit test as a function whose name starts with the prefix <code>test_</code>. The body of the function contains an <code>assert</code> statement, which is a new form of Python statement used to check whether some boolean expression is <code>True</code> or <code>False</code>. Here are two examples of unit tests we could write that are direct translations of the doctest examples from above:</p>
<div class="sourceCode" id="cb3-d7b3e8cb48"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-d7b3e8cb48"><a href="#cb3-1-d7b3e8cb48"></a><span class="co"># In file test_trues.py</span></span>
<span id="cb3-2-d7b3e8cb48"><a href="#cb3-2-d7b3e8cb48"></a></span>
<span id="cb3-3-d7b3e8cb48"><a href="#cb3-3-d7b3e8cb48"></a><span class="im">from</span> trues <span class="im">import</span> has_more_trues</span>
<span id="cb3-4-d7b3e8cb48"><a href="#cb3-4-d7b3e8cb48"></a></span>
<span id="cb3-5-d7b3e8cb48"><a href="#cb3-5-d7b3e8cb48"></a></span>
<span id="cb3-6-d7b3e8cb48"><a href="#cb3-6-d7b3e8cb48"></a><span class="kw">def</span> test_mixture_one_more_true() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-7-d7b3e8cb48"><a href="#cb3-7-d7b3e8cb48"></a> <span class="co">&quot;&quot;&quot;Test has_more_trues on a list with a mixture of True and False,</span></span>
<span id="cb3-8-d7b3e8cb48"><a href="#cb3-8-d7b3e8cb48"></a><span class="co"> with one more True than False.</span></span>
<span id="cb3-9-d7b3e8cb48"><a href="#cb3-9-d7b3e8cb48"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-10-d7b3e8cb48"><a href="#cb3-10-d7b3e8cb48"></a> <span class="cf">assert</span> has_more_trues([<span class="va">True</span>, <span class="va">False</span>, <span class="va">True</span>])</span>
<span id="cb3-11-d7b3e8cb48"><a href="#cb3-11-d7b3e8cb48"></a></span>
<span id="cb3-12-d7b3e8cb48"><a href="#cb3-12-d7b3e8cb48"></a></span>
<span id="cb3-13-d7b3e8cb48"><a href="#cb3-13-d7b3e8cb48"></a><span class="kw">def</span> test_mixture_one_more_false() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-14-d7b3e8cb48"><a href="#cb3-14-d7b3e8cb48"></a> <span class="co">&quot;&quot;&quot;Test has_more_trues on a list with a mixture of True and False,</span></span>
<span id="cb3-15-d7b3e8cb48"><a href="#cb3-15-d7b3e8cb48"></a><span class="co"> with one more False than True.</span></span>
<span id="cb3-16-d7b3e8cb48"><a href="#cb3-16-d7b3e8cb48"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-17-d7b3e8cb48"><a href="#cb3-17-d7b3e8cb48"></a> <span class="cf">assert</span> <span class="kw">not</span> has_more_trues([<span class="va">True</span>, <span class="va">False</span>, <span class="va">False</span>])</span></code></pre></div>
<p>These unit test functions are similar to the functions weve defined previously, with a few differences:</p>
<ul>
<li>Each test name and docstring documents what the test is by describing the test input.</li>
<li>The return type of the test function is <code>None</code>, which is a special type that indicates that no value at all is returned by the function.<label for="sn-3-d7b3e8cb48" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-d7b3e8cb48" class="margin-toggle"/><span class="sidenote"> Pythons <code>None</code> is a bit special, and well see more of this later in the course.</span> In the body of the test function, there is indeed no <code>return</code> statement—instead, theres an <code>assert</code>.</li>
</ul>
<p>So what exactly does an <code>assert</code> statement do? In Python, an <code>assert</code> statement has the form <code>assert &lt;expression&gt;</code>, and when executed it does the following:</p>
<ol type="1">
<li><p>First, it evaluates <code>&lt;expression&gt;</code>, which should produce a boolean value.</p></li>
<li><p>If the value is <code>True</code>, nothing else happens, and the program continues onto the next statement.</p>
<p>But if the value is <code>False</code>, an <code>AssertionError</code> is raised. This signals to <code>pytest</code> that the test has failed.</p></li>
</ol>
<p>So when <code>pytest</code> “runs” a unit test, whats actually going on is it calls a test function like <code>test_mixture_one_more_true</code>. If the function call ends without raising an <code>AssertionError</code>, the test <em>passes</em>; if the function call does raise an <code>AssertionError</code>, the test <em>fails</em>. A single unit test function can contain multiple <code>assert</code> statements; the test passes if all of the <code>assert</code> statements pass, and fails if any of the <code>assert</code> statements raise an error.</p>
<p>Finally, how do we use <code>pytest</code> to actually run our unit test functions? Similar to <code>doctest</code>, we need to first import <code>pytest</code> and then call a specific test function.</p>
<div class="sourceCode" id="cb4-d7b3e8cb48"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-d7b3e8cb48"><a href="#cb4-1-d7b3e8cb48"></a><span class="co"># At the bottom of test_trues.py</span></span>
<span id="cb4-2-d7b3e8cb48"><a href="#cb4-2-d7b3e8cb48"></a></span>
<span id="cb4-3-d7b3e8cb48"><a href="#cb4-3-d7b3e8cb48"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb4-4-d7b3e8cb48"><a href="#cb4-4-d7b3e8cb48"></a> <span class="im">import</span> pytest</span>
<span id="cb4-5-d7b3e8cb48"><a href="#cb4-5-d7b3e8cb48"></a> pytest.main([<span class="st">&#39;test_trues.py&#39;</span>])</span></code></pre></div>
<p>Now if we run this file, we see that our two unit test functions are run:</p>
<p><video src="videos/pytests_passing_pytest_runner.webm" controls=""><a href="videos/pytests_passing_pytest_runner.webm">Video demo of running pytest</a></video><br />
</p>
<h2 id="references-d7b3e8cb48">References</h2>
<ul>
<li>CSC108 videos: Doctest (<a href="https://youtu.be/R1rDpZjfzZg">Part 1</a>, <a href="https://youtu.be/imLlb6Gyziw">Part 2</a>)</li>
<li>CSC108 videos: Writing a <code>__main__</code> program (<a href="https://youtu.be/7KnXMIf6Z90">Part 1</a>, <a href="https://youtu.be/k7Hr0sfYUrM">Part 2</a>) <!-- - Unittest (CSC108 videos - [Part 1](https://youtu.be/9J6-PEtwuGs), [Part 2](https://youtu.be/W1dOdRqQ-M4)) --> <!-- Note that there are also videos in "choosing test cases", but they're not linked because that section might be moved --></li>
<li><a href="../B-python-libraries/01-doctest.html">Appendix B.1 <code>doctest</code></a></li>
<li><a href="../B-python-libraries/02-pytest.html">Appendix B.2 <code>pytest</code></a></li>
</ul>
</section>
<!-- TODO: introduce assert statement with message -->
<!--
ODO: move to new section
## Choosing test cases
We said earlier that keeping our tests in separate files from our source code enables us to write an exhaustive set of tests without worrying about length.
But what exactly do we mean by "exhaustive?"
In general, it is actually a pretty hard problem to choose test cases to verify the correctness of your program.
You want to capture every possible scenario, while avoiding writing redundant tests.
A good rule of thumb is to structure your tests around **properties of the inputs**.
For example:
- *integers*: 0, 1, positive, negative, "small", "large"
- *lists*: empty, length 1, no duplicates, duplicates, sorted, unsorted
- *strings*: empty, length 1, alphanumeric characters only, special characters like punctuation marks
For functions that take in multiple inputs, we often also choose properties based on the *relationships between the inputs*.
For example, for a function that takes two numbers as input, we might have a test for when the first is larger than the second, and another for when the second is larger than the first.
For an input of one object and a list, we might have a test for when the object is in the list, and another for when the object isn't.
And finally, keep in mind that these are rules of thumb only;
none of these properties will always be relevant to a given function.
For a complete set of tests, you must understand *exactly* what the function does, to be able to identify what properties of the inputs really matter. -->
<br/> <a id="anchor-02-07"></a>
<header id="title-block-header-c393769a24">
<h1 class="title">2.7 Type Conversion Functions</h1>
</header>
<section>
<p>There is another useful set of built-in functions that we have not yet discussed: functions that allow us to convert values between different data types. For example, given a string <code>'10'</code>, can we convert it into the integer <code>10</code>? Or given a list <code>[1, 2, 3]</code>, can we convert it into a set <code>{1, 2, 3}</code>?</p>
<p>The answer to these questions is yes, and the way to do so in Python is quite elegant. Each data type that we have learned about so far, from <code>int</code> to <code>dict</code>, is also a function that takes an argument and attempts to convert it to a value of that data type.</p>
<p>Here are some examples:<label for="sn-0-c393769a24" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-c393769a24" class="margin-toggle"/><span class="sidenote"> Some of these are more “obvious” than others. Dont worry about the exact rules for conversions between types, as you wont be expected to memorize them. Instead, we just want you to know that these conversions are possible using data types as functions.</span></p>
<div class="sourceCode" id="cb1-c393769a24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-c393769a24"><a href="#cb1-1-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">int</span>(<span class="st">&#39;10&#39;</span>)</span>
<span id="cb1-2-c393769a24"><a href="#cb1-2-c393769a24"></a><span class="dv">10</span></span>
<span id="cb1-3-c393769a24"><a href="#cb1-3-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">float</span>(<span class="st">&#39;10&#39;</span>)</span>
<span id="cb1-4-c393769a24"><a href="#cb1-4-c393769a24"></a><span class="fl">10.0</span></span>
<span id="cb1-5-c393769a24"><a href="#cb1-5-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">bool</span>(<span class="dv">1000</span>)</span>
<span id="cb1-6-c393769a24"><a href="#cb1-6-c393769a24"></a><span class="va">True</span></span>
<span id="cb1-7-c393769a24"><a href="#cb1-7-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">bool</span>(<span class="dv">0</span>)</span>
<span id="cb1-8-c393769a24"><a href="#cb1-8-c393769a24"></a><span class="va">False</span></span>
<span id="cb1-9-c393769a24"><a href="#cb1-9-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>({<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>})</span>
<span id="cb1-10-c393769a24"><a href="#cb1-10-c393769a24"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb1-11-c393769a24"><a href="#cb1-11-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">set</span>([<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>])</span>
<span id="cb1-12-c393769a24"><a href="#cb1-12-c393769a24"></a>{<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>}</span>
<span id="cb1-13-c393769a24"><a href="#cb1-13-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">set</span>() <span class="co"># Giving set no arguments results in the empty set</span></span>
<span id="cb1-14-c393769a24"><a href="#cb1-14-c393769a24"></a><span class="bu">set</span>()</span>
<span id="cb1-15-c393769a24"><a href="#cb1-15-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">dict</span>([(<span class="st">&#39;a&#39;</span>, <span class="dv">1</span>), (<span class="st">&#39;b&#39;</span>, <span class="dv">2</span>), (<span class="st">&#39;c&#39;</span>, <span class="dv">3</span>)])</span>
<span id="cb1-16-c393769a24"><a href="#cb1-16-c393769a24"></a>{<span class="st">&#39;a&#39;</span>: <span class="dv">1</span>, <span class="st">&#39;b&#39;</span>: <span class="dv">2</span>, <span class="st">&#39;c&#39;</span>: <span class="dv">3</span>}</span></code></pre></div>
<p>In particular, <code>str</code> is the most versatile of these data types. <em>Every</em> value of the data types weve studied so far has a string represention which corresponds directly to how you would write the value as a Python literal.</p>
<div class="sourceCode" id="cb2-c393769a24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-c393769a24"><a href="#cb2-1-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>(<span class="dv">10</span>)</span>
<span id="cb2-2-c393769a24"><a href="#cb2-2-c393769a24"></a><span class="co">&#39;10&#39;</span></span>
<span id="cb2-3-c393769a24"><a href="#cb2-3-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>(<span class="op">-</span><span class="fl">5.5</span>)</span>
<span id="cb2-4-c393769a24"><a href="#cb2-4-c393769a24"></a><span class="co">&#39;-5.5&#39;</span></span>
<span id="cb2-5-c393769a24"><a href="#cb2-5-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>(<span class="va">True</span>)</span>
<span id="cb2-6-c393769a24"><a href="#cb2-6-c393769a24"></a><span class="co">&#39;True&#39;</span></span>
<span id="cb2-7-c393769a24"><a href="#cb2-7-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>({<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>})</span>
<span id="cb2-8-c393769a24"><a href="#cb2-8-c393769a24"></a><span class="co">&#39;{1, 2, 3}&#39;</span></span>
<span id="cb2-9-c393769a24"><a href="#cb2-9-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>([<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>])</span>
<span id="cb2-10-c393769a24"><a href="#cb2-10-c393769a24"></a><span class="co">&#39;[1, 2, 3]&#39;</span></span>
<span id="cb2-11-c393769a24"><a href="#cb2-11-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>({<span class="st">&#39;a&#39;</span>: <span class="dv">1</span>, <span class="st">&#39;b&#39;</span>: <span class="dv">2</span>})</span>
<span id="cb2-12-c393769a24"><a href="#cb2-12-c393769a24"></a><span class="co">&quot;{&#39;a&#39;: 1, &#39;b&#39;: 2}&quot;</span></span></code></pre></div>
<h2 id="warning-conversion-errors-c393769a24">Warning: conversion errors</h2>
<p>You often have to be careful when attempting to convert between different data types, as not all values of one type can be converted into another. Attempting to convert an “invalid” value often results in a Python exception to be raised:<label for="sn-1-c393769a24" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-c393769a24" class="margin-toggle"/><span class="sidenote"> These exceptions typically have type <code>ValueError</code> or <code>TypeError</code>.</span></p>
<div class="sourceCode" id="cb3-c393769a24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-c393769a24"><a href="#cb3-1-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">int</span>(<span class="st">&#39;David&#39;</span>)</span>
<span id="cb3-2-c393769a24"><a href="#cb3-2-c393769a24"></a>Traceback (most recent call last):</span>
<span id="cb3-3-c393769a24"><a href="#cb3-3-c393769a24"></a> File <span class="st">&quot;&lt;stdin&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb3-4-c393769a24"><a href="#cb3-4-c393769a24"></a><span class="pp">ValueError</span>: invalid literal <span class="cf">for</span> <span class="bu">int</span>() <span class="cf">with</span> base <span class="dv">10</span>: <span class="st">&#39;David&#39;</span></span>
<span id="cb3-5-c393769a24"><a href="#cb3-5-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="dv">1000</span>)</span>
<span id="cb3-6-c393769a24"><a href="#cb3-6-c393769a24"></a>Traceback (most recent call last):</span>
<span id="cb3-7-c393769a24"><a href="#cb3-7-c393769a24"></a> File <span class="st">&quot;&lt;stdin&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb3-8-c393769a24"><a href="#cb3-8-c393769a24"></a><span class="pp">TypeError</span>: <span class="st">&#39;int&#39;</span> <span class="bu">object</span> <span class="kw">is</span> <span class="kw">not</span> iterable</span></code></pre></div>
<h2 id="preview-creating-values-of-arbitrary-data-types-c393769a24">Preview: creating values of arbitrary data types</h2>
<p>The ability to create values of a given type by calling the data type as a function is not unique to the built-in data types in this section. Weve actually seen two examples of doing this so far in the course!</p>
<h3 id="range-revisited-c393769a24"><code>range</code> revisited</h3>
<p>Earlier, we saw that we could call <code>range</code> to create a sequence of numbers. But if you just try calling <code>range</code> by itself in the Python console, you see something kind of funny:</p>
<div class="sourceCode" id="cb4-c393769a24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-c393769a24"><a href="#cb4-1-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">range</span>(<span class="dv">5</span>, <span class="dv">10</span>)</span>
<span id="cb4-2-c393769a24"><a href="#cb4-2-c393769a24"></a><span class="bu">range</span>(<span class="dv">5</span>, <span class="dv">10</span>)</span></code></pre></div>
<p>Whereas you might have expected to see a list (<code>[5, 6, 7, 8, 9]</code>), in the Python console output it looks like nothing happened at all! This is because <code>range</code> is actually a type conversion function: Python also has a <code>range</code> data type that is distinct from lists (or other collection data types).</p>
<div class="sourceCode" id="cb5-c393769a24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-c393769a24"><a href="#cb5-1-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> five_to_nine <span class="op">=</span> <span class="bu">range</span>(<span class="dv">5</span>, <span class="dv">10</span>)</span>
<span id="cb5-2-c393769a24"><a href="#cb5-2-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(five_to_nine)</span>
<span id="cb5-3-c393769a24"><a href="#cb5-3-c393769a24"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;range&#39;</span><span class="op">&gt;</span></span>
<span id="cb5-4-c393769a24"><a href="#cb5-4-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> five_to_nine <span class="op">==</span> [<span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>, <span class="dv">9</span>]</span>
<span id="cb5-5-c393769a24"><a href="#cb5-5-c393769a24"></a><span class="va">False</span></span></code></pre></div>
<h3 id="datetime.date-revisited-c393769a24"><code>datetime.date</code> revisited</h3>
<p>Recall an example from the last section in <a href="04-importing-modules.html">Section 2.4 Importing Modules</a>:</p>
<div class="sourceCode" id="cb6-c393769a24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-c393769a24"><a href="#cb6-1-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> datetime</span>
<span id="cb6-2-c393769a24"><a href="#cb6-2-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> canada_day <span class="op">=</span> datetime.date(<span class="dv">1867</span>, <span class="dv">7</span>, <span class="dv">1</span>) <span class="co"># Create a new date</span></span>
<span id="cb6-3-c393769a24"><a href="#cb6-3-c393769a24"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(canada_day)</span>
<span id="cb6-4-c393769a24"><a href="#cb6-4-c393769a24"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;datetime.date&#39;</span><span class="op">&gt;</span></span></code></pre></div>
<p>In this case, the data type is <code>datetime.date</code>, and it is called on three arguments instead of one. In this context, <code>datetime.date</code> is called to <em>create</em> a new <code>date</code> value given three arguments (the year, month, and day).<label for="sn-2-c393769a24" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-c393769a24" class="margin-toggle"/><span class="sidenote"> This is a more general form of type “conversion”, which created a data type of a new value given a single argument.</span> And of course, this behaviour isnt unique to <code>datetime.date</code> either. As well see a bit later in this course, youll be able to take <em>any</em> data type—even ones you define yourself—and create values of that type by calling the data type as a function.</p>
</section>
<br/> <a id="anchor-02-08"></a>
<header id="title-block-header-e4a71e8435">
<h1 class="title">2.8 Application: Representing Text</h1>
</header>
<section>
<p>We have mentioned that computers use a series of 0s and 1s to store data. These 0s and 1s represent numbers. So then, how can numbers represent textual data (i.e., a string)? The answer is functions.</p>
<p>Once upon a time, humans interacted with computers through punched paper tape (or simply punched tape). A hole (or the lack of a hole) at a particular location on the tape represented a 0 or a 1 (i.e., binary). Today we would call each 0 or 1 a <strong>bit</strong>. Obviously, this is much more tedious than using our modern input peripherals: keyboards, mice, touch screens, etc. Eventually, a standard for representing characters (e.g., letters, numbers) with holes was settled on. Using only 7 locations on the tape, 128 different characters could be represented (<span class="math inline">\(2^7 = 128\)</span>).</p>
<p>The standard was called ASCII (pronounced ass-key) and it persists to this day. You can think of the ASCII standard as a function with domain <span class="math inline">\(\{0, 1, \dots, 127\}\)</span>, whose codomain is the set of all possible characters. This function is <em>one-to-one</em>, meaning no two numbers map to the same character—this would be redundant for the purpose of encoding the characters. This standard covered all English letters (lowercase and uppercase), digits, punctuation, and various others (e.g., to communicate a new line). For example, the number 65 mapped to the letter <code>'A'</code> and the number 126 mapped to the punctuation mark <code>'~'</code>.</p>
<p>But what about other languages? Computer scientists extended ASCII from length-7 to length-8 sequences of bits, and hence its domain increased to size 256 (<span class="math inline">\(\{0, 1, \dots, 255\}\)</span>). This allowed “extended ASCII” to support some other characters used in similar Latin-based languages, such as <code>'é'</code> (233), <code>'ö'</code> (246), <code>'€'</code> (128), and other useful symbols like <code>'©'</code> (169) and <code>'½'</code> (189). But what about characters used in very different languages (e.g., Greek, Mandarin, Arabic)?</p>
<p>The latest standard, Unicode, uses <strong>up to 32 bits</strong> that gives us a domain of <span class="math inline">\(\{0, 1, \dots, 2^{32} - 1\}\)</span>, over 4 billion different numbers. This number is in fact larger than the number of distinct characters in use across all different languages! There are several <em>unused numbers</em> in the domain of Unicode—Unicode is not technically a function defined over <span class="math inline">\(\{0, 1, \dots, 2^{32} - 1\}\)</span> because of this.</p>
<p>But with the pervasiveness of the Internet, these unused numbers are being used to <a href="https://home.unicode.org/emoji/emoji-frequency/">map to emojis</a>. Of course, this can cause some lost-in-translation issues. The palm tree emoji may appear different on your device than a friends. In extreme cases, your friends device may not see a palm tree at all or see a completely different emoji. Part of the process involves <a href="https://unicode.org/emoji/proposals.html">submitting a proposal for a new emoji</a>. But the second half of that process means that computer scientists need to support newly approved emojis by updating their software. And, of course, in order to do that computer scientists need to have a firm understanding of functions!</p>
<h2 id="pythons-unicode-conversion-functions-e4a71e8435">Pythons Unicode conversion functions</h2>
<p>Python has two built-in functions that implement the (partial) mapping between characters and their Unicode number. The first is <code>ord</code>, which takes a single-character string and returns its Unicode number as an <code>int</code>.</p>
<div class="sourceCode" id="cb1-e4a71e8435"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-e4a71e8435"><a href="#cb1-1-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">ord</span>(<span class="st">&#39;A&#39;</span>)</span>
<span id="cb1-2-e4a71e8435"><a href="#cb1-2-e4a71e8435"></a><span class="dv">65</span></span>
<span id="cb1-3-e4a71e8435"><a href="#cb1-3-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">ord</span>(<span class="st">&#39;é&#39;</span>)</span>
<span id="cb1-4-e4a71e8435"><a href="#cb1-4-e4a71e8435"></a><span class="dv">233</span></span>
<span id="cb1-5-e4a71e8435"><a href="#cb1-5-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">ord</span>(<span class="st">&#39;♥&#39;</span>)</span>
<span id="cb1-6-e4a71e8435"><a href="#cb1-6-e4a71e8435"></a><span class="dv">9829</span></span></code></pre></div>
<p>The second is <code>chr</code>, which computes the <em>inverse</em> of <code>ord</code>: given an integer representing a Unicode number, <code>chr</code> returns a string containing the corresponding character.</p>
<div class="sourceCode" id="cb2-e4a71e8435"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-e4a71e8435"><a href="#cb2-1-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">chr</span>(<span class="dv">65</span>)</span>
<span id="cb2-2-e4a71e8435"><a href="#cb2-2-e4a71e8435"></a><span class="co">&#39;A&#39;</span></span>
<span id="cb2-3-e4a71e8435"><a href="#cb2-3-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">chr</span>(<span class="dv">233</span>)</span>
<span id="cb2-4-e4a71e8435"><a href="#cb2-4-e4a71e8435"></a><span class="co">&#39;é&#39;</span></span>
<span id="cb2-5-e4a71e8435"><a href="#cb2-5-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">chr</span>(<span class="dv">9829</span>)</span>
<span id="cb2-6-e4a71e8435"><a href="#cb2-6-e4a71e8435"></a><span class="co">&#39;♥&#39;</span></span></code></pre></div>
<p>Unicode representations are a source of one common source of surprise for Python programmers: string ordering comparisons (<code>&lt;</code>, <code>&gt;</code>) are based on Unicode numeric values! For example, the Unicode value of <code>'Z'</code> is 90 and the Unicode value of <code>'a'</code> is 97, and so the following holds:</p>
<div class="sourceCode" id="cb3-e4a71e8435"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-e4a71e8435"><a href="#cb3-1-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;Z&#39;</span> <span class="op">&lt;</span> <span class="st">&#39;a&#39;</span></span>
<span id="cb3-2-e4a71e8435"><a href="#cb3-2-e4a71e8435"></a><span class="va">True</span></span>
<span id="cb3-3-e4a71e8435"><a href="#cb3-3-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;Zebra&#39;</span> <span class="op">&lt;</span> <span class="st">&#39;animal&#39;</span></span>
<span id="cb3-4-e4a71e8435"><a href="#cb3-4-e4a71e8435"></a><span class="va">True</span></span></code></pre></div>
<p>This means that sorting a collection of strings can seem alphabetical, but treats lowercase and uppercase letters differently:</p>
<div class="sourceCode" id="cb4-e4a71e8435"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-e4a71e8435"><a href="#cb4-1-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sorted</span>({<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Mario&#39;</span>, <span class="st">&#39;Jacqueline&#39;</span>})</span>
<span id="cb4-2-e4a71e8435"><a href="#cb4-2-e4a71e8435"></a>[<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Mario&#39;</span>]</span>
<span id="cb4-3-e4a71e8435"><a href="#cb4-3-e4a71e8435"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sorted</span>({<span class="st">&#39;david&#39;</span>, <span class="st">&#39;Mario&#39;</span>, <span class="st">&#39;Jacqueline&#39;</span>})</span>
<span id="cb4-4-e4a71e8435"><a href="#cb4-4-e4a71e8435"></a>[<span class="st">&#39;Jacqueline&#39;</span>, <span class="st">&#39;Mario&#39;</span>, <span class="st">&#39;david&#39;</span>]</span></code></pre></div>
<!-- Python also provides us with a built-in function to convert an integer value into a binary value.
This lets us see the sequence of 0s and 1s that would have been used decades ago when making holes in punch tape.
The built-in function is called `bin`, and we need to pass it an integer.
```python
>>> bin(0)
'0b0'
>>> bin(1)
'0b1'
>>> bin(2)
'0b10'
```
The result is a string where a sequence of 0s and 1s are prefixed with `'0b'`.
Let us now use this to find out the binary sequence of the letters `A` and `a`.
```python
>>> unicode_A = ord('A')
>>> bin(unicode_A)
'0b1000001'
>>> bin(ord('a'))
'0b1100001'
``` -->
<h2 id="references-e4a71e8435">References</h2>
<ul>
<li><a href="https://www.ascii-code.com/">ASCII Code: The extended ASCII table</a></li>
<li><a href="https://unicode-table.com/en/">Unicode Character Table</a></li>
</ul>
</section>
<br/>
<h2 class="unnumbered" id="formal-logic-in-computer-science">3. Formal Logic in Computer Science</h2>
<a id="anchor-03-01"></a>
<header id="title-block-header-8de32c6d33">
<h1 class="title">3.1 Propositional Logic</h1>
</header>
<section>
<p>As we get ready to write larger and more complex programs, were going to take a pause on programming to study formal mathematical logic. You might wonder what logic has to do with software development. As well see over the course of this chapter, a firm understanding of logic allows us to precisely identify, define, and write <em>boolean expressions</em> and use them in our programs.</p>
<p>It might seem counter-intuitive to spend a whole chapter on logic, as <code>bool</code> is the simplest data type in Python. But writing boolean expressions that correctly capture definitions and conditions in a given problem domain can be tricky as these definitions and conditions grow in complexity. It will turn out to be very useful to have a formal mathematical language—logic—to express these complex boolean expressions before turning them into code.</p>
<h2 id="propositions-8de32c6d33">Propositions</h2>
<p>We will start our study in this chapter with <em>propositional logic</em>, an elementary system of logic that is a crucial building block underlying other, more expressive systems of logic that we will need in this course.</p>
<div class="definition" data-terms="proposition, propositional variable, propositional/logical operator, propositional formula">
<p>A <strong>proposition</strong> is a statement that is either True or False. Examples of propositions are:</p>
<ul>
<li><span class="math inline">\(2+4 =6\)</span></li>
<li><span class="math inline">\(3-5 &gt; 0\)</span></li>
<li>Every even integer greater than <span class="math inline">\(2\)</span> is the sum of two prime numbers.</li>
<li>Pythons implementation of <code>list.sort</code> is correct on every input list.</li>
</ul>
<p>We use <strong>propositional variables</strong> to represent propositions; by convention, propositional variable names are lowercase letters starting at <span class="math inline">\(p\)</span>.<label for="sn-0-8de32c6d33" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-8de32c6d33" class="margin-toggle"/><span class="sidenote"> The concept of a propositional variable is different from other forms of variables you have seen before, and even ones that we will see later in this chapter. Heres a rule of thumb: if you read an expression involving a propositional variable <span class="math inline">\(p\)</span>, you should be able to replace <span class="math inline">\(p\)</span> with the statement “CSC110 is cool” and still have the expression make sense.</span></p>
<p>A <strong>propositional/logical operator</strong> is an operator whose arguments must all be either True or False. Finally, a <strong>propositional formula</strong> is an expression that is built up from propositional variables by applying these operators.</p>
</div>
<p>In the following sections, we describe the various operators we will use in this course. It is important to keep in mind when reading that these operators inform both the <em>structure</em> of formulas (what they look like) as well as the <em>truth value</em> of these formulas (what they mean: whether the formula is True or False based on the truth values of the individual propositional variables).</p>
<h2 id="the-basic-operators-not-and-or-8de32c6d33">The basic operators <strong>NOT</strong>, <strong>AND</strong>, <strong>OR</strong></h2>
<p>We have seen these operators earlier when discussing different types of data. The fact that Python has specific keywords dedicated to these operators should at least hint that they are frequently used. Here, we spend some time introducing the operators more formally and developing our first truth tables.</p>
<div class="margintable">
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><span class="math inline">\(p\)</span></th>
<th style="text-align: right;"><span class="math inline">\(\lnot p\)</span></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">False</td>
<td style="text-align: right;">True</td>
</tr>
<tr class="even">
<td style="text-align: center;">True</td>
<td style="text-align: right;">False</td>
</tr>
</tbody>
</table>
</div>
<p>The unary operator <strong>NOT</strong> (also called “negation”) is denoted by the symbol <span class="math inline">\(\lnot\)</span>. It negates the truth value of its input. So if <span class="math inline">\(p\)</span> is True, then <span class="math inline">\(\lnot p\)</span> is False, and vice versa. This is shown in the <em>truth table</em> at the side. In Python, we use the <code>not</code> keyword to represent this operation.</p>
<div class="margintable">
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><span class="math inline">\(p\)</span></th>
<th style="text-align: center;"><span class="math inline">\(q\)</span></th>
<th style="text-align: right;"><span class="math inline">\(p \land q\)</span></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">False</td>
<td style="text-align: center;">False</td>
<td style="text-align: right;">False</td>
</tr>
<tr class="even">
<td style="text-align: center;">False</td>
<td style="text-align: center;">True</td>
<td style="text-align: right;">False</td>
</tr>
<tr class="odd">
<td style="text-align: center;">True</td>
<td style="text-align: center;">False</td>
<td style="text-align: right;">False</td>
</tr>
<tr class="even">
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
<td style="text-align: right;">True</td>
</tr>
</tbody>
</table>
</div>
<p>The binary operator <strong>AND</strong> (also called “conjunction”) is denoted by the symbol <span class="math inline">\(\land\)</span>. It returns True when both its arguments are True. In Python, we use the <code>and</code> keyword to represent this operation.</p>
<p>The binary operator <strong>OR</strong> (also called “disjunction”) is denoted by the symbol <span class="math inline">\(\lor\)</span>, and returns True if one or both of its arguments are True. In Python, we use the <code>or</code> keyword to represent this operation.</p>
<div class="margintable">
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><span class="math inline">\(p\)</span></th>
<th style="text-align: center;"><span class="math inline">\(q\)</span></th>
<th style="text-align: center;"><span class="math inline">\(p \lor q\)</span></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">False</td>
<td style="text-align: center;">False</td>
<td style="text-align: center;">False</td>
</tr>
<tr class="even">
<td style="text-align: center;">False</td>
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
</tr>
<tr class="odd">
<td style="text-align: center;">True</td>
<td style="text-align: center;">False</td>
<td style="text-align: center;">True</td>
</tr>
<tr class="even">
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
</tr>
</tbody>
</table>
</div>
<p>The truth tables for <strong>AND</strong> and <strong>NOT</strong> agree with the popular English usage of the terms; however, the operator <strong>OR</strong> may seem somewhat different from your intuition, because the word “or” has two different meanings to most English speakers. Consider the English statement “You can have cake or ice cream.” From a nutritionist, this might be an <em>exclusive or</em>: you can have cake or you can have ice cream, but not both. But from a kindly relative at a family reunion, this might be an <em>inclusive or</em>: you can have both cake and ice cream if you want! The study of mathematical logic is meant to eliminate the ambiguity by picking one meaning of <strong>OR</strong> and sticking with it. In our case, we will always use <strong>OR</strong> to mean the <em>inclusive or</em>, as illustrated in the last row of its truth table.<label for="sn-1-8de32c6d33" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-8de32c6d33" class="margin-toggle"/><span class="sidenote">The symbol <span class="math inline">\(\oplus\)</span> is often used to represent the <em>exclusive or</em> operator, but we will not use it in this course.</span> This is also the behaviour of the <code>or</code> operator in Python, which evaluates to <code>True</code> when both of its operands are <code>True</code>.</p>
<p><strong>AND</strong> and <strong>OR</strong> are similar in that they are both <em>binary</em> operators on propositional variables. However, the distinction between <strong>AND</strong> and <strong>OR</strong> is very important. Consider for example a rental agreement that reads “first and last months rent <em>and</em> a $1000 deposit” versus a rental agreement that reads “first and last months rent <em>or</em> a $1000 deposit.” The second contract is fulfilled with much less money down than the first contract.</p>
<h2 id="the-implication-operator-8de32c6d33">The implication operator</h2>
<p>One of the most subtle and powerful relationships between two propositions is <em>implication</em>, which is represented by the symbol <span class="math inline">\(\Rightarrow\)</span>. The implication <span class="math inline">\(p \Rightarrow q\)</span> asserts that whenever <span class="math inline">\(p\)</span> is True, <span class="math inline">\(q\)</span> must also be True. An example of logical implication in English is the statement: “If you push that button, then the fire alarm will go off.”<label for="sn-2-8de32c6d33" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-8de32c6d33" class="margin-toggle"/><span class="sidenote"> In some contexts, we think of logical implication as the temporal relationship that <span class="math inline">\(q\)</span> is inevitable if <span class="math inline">\(p\)</span> occurs. But this is <em>not</em> always the case! Be careful not to confuse implication with causation.</span> Implications are so important that the parts have been given names. The statement <span class="math inline">\(p\)</span> is called the <em>hypothesis</em> of the implication and the statement <span class="math inline">\(q\)</span> is called the <em>conclusion</em> of the implication.</p>
<div class="margintable">
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><span class="math inline">\(p\)</span></th>
<th style="text-align: center;"><span class="math inline">\(q\)</span></th>
<th style="text-align: center;"><span class="math inline">\(p \Rightarrow q\)</span></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">False</td>
<td style="text-align: center;">False</td>
<td style="text-align: center;">True</td>
</tr>
<tr class="even">
<td style="text-align: center;">False</td>
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
</tr>
<tr class="odd">
<td style="text-align: center;">True</td>
<td style="text-align: center;">False</td>
<td style="text-align: center;">False</td>
</tr>
<tr class="even">
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
</tr>
</tbody>
</table>
</div>
<p>How should the truth table be defined for <span class="math inline">\(p \Rightarrow q\)</span>? First, when both <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> are True, then <span class="math inline">\(p \Rightarrow q\)</span> should be True, since when <span class="math inline">\(p\)</span> occurs, <span class="math inline">\(q\)</span> also occurs. Similarly, it is clear that when <span class="math inline">\(p\)</span> is True and <span class="math inline">\(q\)</span> is False, then <span class="math inline">\(p \Rightarrow q\)</span> is False (since then <span class="math inline">\(q\)</span> is not inevitably True when <span class="math inline">\(p\)</span> is True). But what about the other two cases, when <span class="math inline">\(p\)</span> is False and <span class="math inline">\(q\)</span> is either True or False? This is another case where our intuition from both English language it a little unclear. Perhaps somewhat surprisingly, in both of these remaining cases, we will still define <span class="math inline">\(p \Rightarrow q\)</span> to be True.</p>
<p>The two cases when <span class="math inline">\(p\)</span> is False but <span class="math inline">\(p \Rightarrow q\)</span> is True are called the <strong>vacuous truth</strong> cases. How do we justify this assignment of truth values? The key intuition is that because the statement doesnt say anything about whether or not <span class="math inline">\(q\)</span> should occur when <span class="math inline">\(p\)</span> is False, it cannot be disproven when <span class="math inline">\(p\)</span> is False. In our example above, if the alarm button is <em>not</em> pushed, then the statement is not saying anything about whether or not the fire alarm will go off. It is entirely consistent with this statement that if the button is not pushed, the fire alarm can still go off, or may not go off.</p>
<p>The formula <span class="math inline">\(p \Rightarrow q\)</span> has two equivalent<label for="sn-3-8de32c6d33" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-8de32c6d33" class="margin-toggle"/><span class="sidenote">Here, “equivalent” means that the two formulas have the same truth values; for any setting of their propositional variables to True and False, the formulas will either both be True or both be False.</span> formulas which are often useful. To make this concrete, well use our example “If you are a Pittsburgh Pens fan, then you are not a Flyers fan” from the introduction.</p>
<p>The following two formulas are equivalent to <span class="math inline">\(p \Rightarrow q\)</span>:</p>
<ul>
<li><p><span class="math inline">\(\lnot p \lor q\)</span>. On our example: “You are not a Pittsburgh Pens fan, or you are not a Flyers fan.” This makes use of the vacuous truth cases of implication, in that if <span class="math inline">\(p\)</span> is False then <span class="math inline">\(p \Rightarrow q\)</span> is True, and if <span class="math inline">\(p\)</span> is True then <span class="math inline">\(q\)</span> must be True as well.</p></li>
<li><p><span class="math inline">\(\lnot q \Rightarrow \lnot p\)</span>. On our example: “If you <em>are</em> a Flyers fan, then you are <em>not</em> a Pittsburgh Pens fan.” Intuitively, this says that if <span class="math inline">\(q\)</span> doesnt occur, then <span class="math inline">\(p\)</span> cannot have occurred either.</p>
<p>This equivalent formula is in fact so common that we give it a special name: the <strong>contrapositive</strong> of the implication <span class="math inline">\(p \Rightarrow q\)</span>.</p></li>
</ul>
<p>There is one more related formula that we will discuss before moving on. If we take <span class="math inline">\(p \Rightarrow q\)</span> and switch the hypothesis and conclusion, we obtain the implication <span class="math inline">\(q \Rightarrow p\)</span>, which is called the <strong>converse</strong> of the original implication.</p>
<p>Unlike the two formulas in the list above, the converse of an implication is <em>not</em> logically equivalent to the original implication. Consider the statement “If you can solve any problem in this course, then you will get an A.” Its converse is “If you will get an A, then you can solve any problem in this course.” These two statements certainly dont mean the same thing!</p>
<p>In Python, there is no operator or keyword that represents implication directly. If you do want to express an implication as a Python expression, we can use the first equivalent form from above, writing <span class="math inline">\(p \Rightarrow q\)</span> as <span class="math inline">\(\lnot p \lor q\)</span>. This is less common in Python programs; however, implication has other uses in manipulating data and expressing algorithms that well explore later in this course.</p>
<h2 id="biconditional-if-and-only-if-8de32c6d33">Biconditional (“if and only if”)</h2>
<p>The final logical operator that we will consider is the <em>biconditional</em>, denoted by <span class="math inline">\(p \Leftrightarrow q\)</span>. This operator returns True when the implication <span class="math inline">\(p \Rightarrow q\)</span> and its converse <span class="math inline">\(q \Rightarrow p\)</span> are both True.</p>
<div class="margintable">
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><span class="math inline">\(p\)</span></th>
<th style="text-align: center;"><span class="math inline">\(q\)</span></th>
<th style="text-align: center;"><span class="math inline">\(p \Leftrightarrow q\)</span></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">False</td>
<td style="text-align: center;">False</td>
<td style="text-align: center;">True</td>
</tr>
<tr class="even">
<td style="text-align: center;">False</td>
<td style="text-align: center;">True</td>
<td style="text-align: center;">False</td>
</tr>
<tr class="odd">
<td style="text-align: center;">True</td>
<td style="text-align: center;">False</td>
<td style="text-align: center;">False</td>
</tr>
<tr class="even">
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
<td style="text-align: center;">True</td>
</tr>
</tbody>
</table>
</div>
<p>In other words, <span class="math inline">\(p \Leftrightarrow q\)</span> is an abbreviation for <span class="math inline">\((p \Rightarrow q) \land (q \Rightarrow p)\)</span>. A nice way of thinking about the biconditional is that it asserts that its two arguments have the <em>same</em> truth value.</p>
<p>While we could use the natural translation of <span class="math inline">\(\Rightarrow\)</span> and <span class="math inline">\(\land\)</span> into English to also translate <span class="math inline">\(\Leftrightarrow\)</span>, the result is a little clunky: <span class="math inline">\(p \Leftrightarrow q\)</span> becomes “if <span class="math inline">\(p\)</span> then <span class="math inline">\(q\)</span>, and if <span class="math inline">\(q\)</span> then <span class="math inline">\(p\)</span>.” Instead, we often shorten this using a quite nice turn of phrase: “<span class="math inline">\(p\)</span> if and only if <span class="math inline">\(q\)</span>,” which is abbreviated to “<span class="math inline">\(p\)</span> iff <span class="math inline">\(q\)</span>.”</p>
<p>In Python, we dont need a separate operator to represent <span class="math inline">\(\Leftrightarrow\)</span>, since we can simply use <code>==</code> to determine whether two boolean values are the same!</p>
<h2 id="summary-8de32c6d33">Summary</h2>
<p>We have now seen all five propositional operators that we will use in this course. Now is an excellent time to review these and make sure you understand the notation, meaning, and English words used to indicate each one.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">operator</th>
<th style="text-align: center;">notation</th>
<th style="text-align: center;">English</th>
<th style="text-align: center;">Python operation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><strong>NOT</strong></td>
<td style="text-align: center;"><span class="math inline">\(\lnot p\)</span></td>
<td style="text-align: center;"><span class="math inline">\(p\)</span> is not true</td>
<td style="text-align: center;"><code>not p</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><strong>AND</strong></td>
<td style="text-align: center;"><span class="math inline">\(p \land q\)</span></td>
<td style="text-align: center;"><span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span></td>
<td style="text-align: center;"><code>p and q</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><strong>OR</strong></td>
<td style="text-align: center;"><span class="math inline">\(p \lor q\)</span></td>
<td style="text-align: center;"><span class="math inline">\(p\)</span> or <span class="math inline">\(q\)</span> (or both!)</td>
<td style="text-align: center;"><code>p or q</code></td>
</tr>
<tr class="even">
<td style="text-align: center;">implication</td>
<td style="text-align: center;"><span class="math inline">\(p \Rightarrow q\)</span></td>
<td style="text-align: center;">if <span class="math inline">\(p\)</span>, then <span class="math inline">\(q\)</span></td>
<td style="text-align: center;"><code>not p or q</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;">biconditional</td>
<td style="text-align: center;"><span class="math inline">\(p \Leftrightarrow q\)</span></td>
<td style="text-align: center;"><span class="math inline">\(p\)</span> if and only if <span class="math inline">\(q\)</span></td>
<td style="text-align: center;"><code>p == q</code></td>
</tr>
</tbody>
</table>
<!--div exercise>
<div questions data-series="chapter1">
\item
A **tautology** is a formula that is True for every possible assignment of values
to its propositional variables.
Decide if each of the following propositional formulas are tautologies.
a) $((p \Rightarrow q) \land (p \Rightarrow r)) \Leftrightarrow (p \Rightarrow (q \land r))$
b) $(p \Rightarrow q) \Leftrightarrow (\lnot p \lor q)$
c) $(\lnot (p \lor q)) \Leftrightarrow (\lnot p \land \lnot q)$
</div>
</div-->
</section>
<br/> <a id="anchor-03-02"></a>
<header id="title-block-header-c4aef35be5">
<h1 class="title">3.2 Predicate Logic</h1>
</header>
<section>
<p>While propositional logic is a good starting point, most interesting statements in mathematics contain variables over domains larger than simply <span class="math inline">\(\{\TRUE, \FALSE\}\)</span>. For example, the statement “<span class="math inline">\(x\)</span> is a power of 2” is not a proposition because its truth value depends on the value of <span class="math inline">\(x\)</span>. It is only after we <em>substitute</em> a value for <span class="math inline">\(x\)</span> that we may determine whether the resulting statement is True or False. For example, if <span class="math inline">\(x = 8\)</span>, then the statement becomes “8 is a power of 2”, which is True. But if <span class="math inline">\(x = 7\)</span>, then the statement becomes “7 is a power of 2”, which is False.</p>
<p>A statement whose truth value depends on one or more variables from any set is a <strong>predicate</strong>: a function whose codomain is <span class="math inline">\(\{\TRUE, \FALSE\}\)</span>. We typically use uppercase letters starting from <span class="math inline">\(P\)</span> to represent predicates, differentiating them from propositional variables. For example, if <span class="math inline">\(P(x)\)</span> is defined to be the statement “<span class="math inline">\(x\)</span> is a power of <span class="math inline">\(2\)</span>”, then <span class="math inline">\(P(8)\)</span> is True and <span class="math inline">\(P(7)\)</span> is False. Thus a predicate is like a proposition except that it contains one or more variables; when we substitute particular values for the variables, we obtain a proposition.</p>
<p>As with all functions, predicates can depend on more than one variable. For example, if we define the predicate <span class="math inline">\(Q(x,y)\)</span> to mean “<span class="math inline">\(x^2 = y\)</span>,” then <span class="math inline">\(Q(5,25)\)</span> is True since <span class="math inline">\(5^2 = 25\)</span>, but <span class="math inline">\(Q(5,24)\)</span> is False.<label for="sn-0-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-c4aef35be5" class="margin-toggle"/><span class="sidenote">Just as how common arithmetic operators like <span class="math inline">\(+\)</span> are really binary functions, the common comparison operators like <span class="math inline">\(=\)</span> and <span class="math inline">\(&lt;\)</span> are <em>binary predicates</em>, taking two numbers and returning True or False.</span></p>
<p>We usually define a predicate by giving the statement that involves the variables, e.g., “<span class="math inline">\(P(x)\)</span> is the statement <span class="math inline">\(x\)</span> is a power of 2.’” However, there is another component which is crucial to the definition of a predicate: the domain that each of the predicates variable(s) belong to. You must always give the domain of a predicate as part of its definition. So we would complete the definition of <span class="math inline">\(P(x)\)</span> as follows:</p>
<p><span class="math display">\[P(x): \text{``$x$ is a power of 2,&#39;&#39; where $x \in \N$.}\]</span></p>
<h2 id="quantification-of-variables-c4aef35be5">Quantification of variables</h2>
<p>Unlike propositional formulas, a predicate by itself does not have a truth value: as we discussed earlier, “<span class="math inline">\(x\)</span> is a power of 2” is neither True nor False, since we dont know the value of <span class="math inline">\(x\)</span>. We have seen one way to obtain a truth value in substituting a concrete element of the predicates domain for its input, e.g., setting <span class="math inline">\(x = 8\)</span> in the statement “<span class="math inline">\(x\)</span> is a power of 2,” which is now True.</p>
<p>However, we often dont care about whether a specific value satisfies a predicate, but rather some aggregation of the predicates truth values over <em>all</em> elements of its domain. For example, the statement “every real number <span class="math inline">\(x\)</span> satisfies the inequality <span class="math inline">\(x^2 - 2x + 1 \geq 0\)</span>” doesnt make a claim about a specific real number like 5 or <span class="math inline">\(\pi\)</span>, but rather <em>all possible</em> values of <span class="math inline">\(x\)</span>!</p>
<p>There are two types of “truth value aggregation” we want to express; each type is represented by a <strong>quantifier</strong> that modifies a predicate by specifying how a certain variable should be interpreted.</p>
<h3 id="existential-quantifier-c4aef35be5">Existential quantifier</h3>
<div class="definition" data-terms="existential quantifier">
<p>The <strong>existential quantifier</strong> is written as <span class="math inline">\(\exists\)</span>, and represents the concept of “<em>there exists</em> an element in the domain that satisfies the given predicate.”</p>
</div>
<div class="example">
<p>For example, the statement <span class="math inline">\(\exists x \in \N,~ x \geq 0\)</span> can be translated as “there exists a natural number <span class="math inline">\(x\)</span> that is greater than or equal to zero.” This statement is True since (for example) when <span class="math inline">\(x=1\)</span>, we know that <span class="math inline">\(x \geq 0\)</span>.</p>
<p>Note that there are many more natural numbers that are greater than or equal to <span class="math inline">\(0\)</span>. The existential quantifier says only that there has to be <em>at least one</em> element of the domain satisfying the predicate, but it doesnt say exactly how many elements do so.</p>
</div>
<p>One should think of <span class="math inline">\(\exists x \in S\)</span> as an abbreviation for a big <strong>OR</strong> that runs through all possible values for <span class="math inline">\(x\)</span> from the domain <span class="math inline">\(S\)</span>. For the previous example, we can expand it by substituting all possible natural numbers for <span class="math inline">\(x\)</span>:<label for="sn-1-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-c4aef35be5" class="margin-toggle"/><span class="sidenote">In this case, the <strong>OR</strong> expression is technically infinite, since there are infinitely many natural numbers.</span> <span class="math display">\[(0 \geq 0) \lor (1 \geq 0) \lor (2 \geq 0) \lor (3 \geq 0) \lor \cdots\]</span></p>
<h3 id="universal-quantifier-c4aef35be5">Universal quantifier</h3>
<div class="definition" data-terms="universal quantifier">
<p>The <strong>universal quantifier</strong> is written as <span class="math inline">\(\forall\)</span>, and represents the concept that “<em>every</em> element in the domain satisfies the given predicate.”</p>
</div>
<div class="example">
<p>For example, the statement <span class="math inline">\(\forall x \in \N,~ x \geq 0\)</span> can be translated as “every natural number <span class="math inline">\(x\)</span> is greater than or equal to zero.” This statement is True since the smallest natural number is zero itself. However, the statement <span class="math inline">\(\forall x \in \N,~ x \geq 10\)</span> is False, since not every natural number is greater than or equal to 10.</p>
</div>
<p>One should think of <span class="math inline">\(\forall x \in S\)</span> as an abbreviation for a big <strong>AND</strong> that runs through all possible values of <span class="math inline">\(x\)</span> from <span class="math inline">\(S\)</span>. Thus, <span class="math inline">\(\forall x \in \N,~ x \geq 0\)</span> is the same as <span class="math display">\[(0 \geq 0) \land (1 \geq 0) \land (2 \geq 0) \land (3 \geq 0) \land \cdots\]</span></p>
<div class="example">
<p>Let us look at a simple example of these quantifiers. Suppose we define <span class="math inline">\(Loves(a,b)\)</span> to be a binary predicate that is <span class="math inline">\(\TRUE\)</span> whenever person <span class="math inline">\(a\)</span> loves person <span class="math inline">\(b\)</span>.</p>
<!--
<div class="marginfigure">
\begin{tikzpicture}
% A
\node [left] at (0,0) {Ella};
\node [left] at (0,1) {Patrick};
\node [left] at (0,2) {Malena};
\node [left] at (0,3) {Breanna};
% B
\node [right] at (2,0) {Laura};
\node [right] at (2,1) {Stanley};
\node [right] at (2,2) {Thelonious};
\node [right] at (2,3) {Sophia};
% Ella
\draw [red, ultra thick, ->] (0,0) -- (2,0); % Ella loves Laura
\draw [red, ultra thick, ->] (0,0) -- (2,1); % Ella loves Stanley
% Patrick
\draw [green, ultra thick, ->] (0,1) -- (2,1); % Patrick loves Stanley
% Malena
\draw [blue, ultra thick, ->] (0,2) -- (2,0); % Malena loves Laura
\draw [blue, ultra thick, ->] (0,2) -- (2,1); % Malena loves Stanley
\draw [blue, ultra thick, ->] (0,2) -- (2,2); % Malena loves Thelonious
% Breanna
\draw [black, ultra thick, ->] (0,3) -- (2,1); % Breanna loves Stanley
\draw [black, ultra thick, ->] (0,3) -- (2,2); % Breanna loves Thelonious
\end{tikzpicture}
</div> -->
<p>For example, the diagram below defines the relation “Loves” for two collections of people: <span class="math inline">\(A\)</span> = {Ella, Patrick, Malena, Breanna}, and <span class="math inline">\(B\)</span> = {Laura, Stanley, Thelonious, Sophia}. A line between two people indicates that the person on the left loves the person on the right.</p>
<div style="text-align: center">
<p><img src="images/loves.png" width="400" alt="Loves diagram" /><br />
</p>
</div>
<p>Consider the following statements.</p>
<ul>
<li><span class="math inline">\(\exists a \in A,~Loves(a, \text{Thelonious})\)</span>, which means “there exists someone in <span class="math inline">\(A\)</span> who loves Thelonious.” This is True since Malena loves Thelonious.<label for="sn-2-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-c4aef35be5" class="margin-toggle"/><span class="sidenote">We could also have said here that Breanna loves Thelonious.</span></li>
<li><span class="math inline">\(\exists a \in A,~Loves(a, \text{Sophia})\)</span>, which means “there exists someone in <span class="math inline">\(A\)</span> who loves Sophia.” This is False since no one loves Sophia.</li>
<li><span class="math inline">\(\forall a \in A,~Loves(a, \text{Stanley})\)</span>, which means “every person in <span class="math inline">\(A\)</span> loves Stanley.” This is True, since all four people in <span class="math inline">\(A\)</span> love Stanley.</li>
<li><span class="math inline">\(\forall a \in A,~Loves(a, \text{Thelonious})\)</span>, which means “every person in <span class="math inline">\(A\)</span> loves Thelonious.” This is False, since Ella does not love Thelonius.</li>
</ul>
</div>
<h2 id="python-built-ins-any-and-all-c4aef35be5">Python built-ins: <code>any</code> and <code>all</code></h2>
<p>In Python, the built-in function <code>any</code> allows us to represent logical statements using the existential quantifier. The function <code>any</code> takes a collection of boolean values and returns <code>True</code> when there exists a <code>True</code> value in the collection:</p>
<div class="sourceCode" id="cb1-c4aef35be5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-c4aef35be5"><a href="#cb1-1-c4aef35be5"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">any</span>([<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>])</span>
<span id="cb1-2-c4aef35be5"><a href="#cb1-2-c4aef35be5"></a><span class="va">True</span></span>
<span id="cb1-3-c4aef35be5"><a href="#cb1-3-c4aef35be5"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">any</span>([]) <span class="co"># An empty collection has no True values!</span></span>
<span id="cb1-4-c4aef35be5"><a href="#cb1-4-c4aef35be5"></a><span class="va">False</span></span></code></pre></div>
<p>This might not seem useful by itself, but remember that we can use comprehensions to transform one collection of data into another. For example, suppose are given a set of strings <span class="math inline">\(S\)</span> and wish to determine whether any of them start with the letter <code>'D'</code>. In predicate logic, we could write this as the statement <span class="math inline">\(\exists s \in S,~ s[0] = \text{D&#39;}\)</span>. And in Python, we could do the following:</p>
<div class="sourceCode" id="cb2-c4aef35be5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-c4aef35be5"><a href="#cb2-1-c4aef35be5"></a><span class="op">&gt;&gt;&gt;</span> strings <span class="op">=</span> [<span class="st">&#39;Hello&#39;</span>, <span class="st">&#39;Goodbye&#39;</span>, <span class="st">&#39;David&#39;</span>]</span>
<span id="cb2-2-c4aef35be5"><a href="#cb2-2-c4aef35be5"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">any</span>([s[<span class="dv">0</span>] <span class="op">==</span> <span class="st">&#39;D&#39;</span> <span class="cf">for</span> s <span class="kw">in</span> strings])</span>
<span id="cb2-3-c4aef35be5"><a href="#cb2-3-c4aef35be5"></a><span class="va">True</span></span></code></pre></div>
<p>This example serves to highlight several elegant parallels between our mathematical statement and equivalent Python expression:</p>
<ul>
<li><span class="math inline">\(\exists\)</span> corresponds to calling the <code>any</code> function</li>
<li><span class="math inline">\(s \in S\)</span> corresponds to <code>for s in strings</code><label for="sn-3-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-c4aef35be5" class="margin-toggle"/><span class="sidenote"> The naming conventions are a bit different, however: in mathematics, we tend to represent collections using capital letters, whereas in Python all variables are lower-case words.</span></li>
<li><span class="math inline">\(s[0] = \text{D&#39;}\)</span> corresponds to <code>s[0] == 'D'</code></li>
</ul>
<p>Similar to <code>any</code>, Python includes another built-in function <code>all</code> that can be used as a universal quantifier. The <code>all</code> function is given a collection of values and evaluates to <code>True</code> when every element has the value <code>True</code>. For example, if we wanted to express <span class="math inline">\(\forall s \in S,~ s[0] = \text{D&#39;}\)</span> in Python, we could write:</p>
<div class="sourceCode" id="cb3-c4aef35be5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-c4aef35be5"><a href="#cb3-1-c4aef35be5"></a><span class="op">&gt;&gt;&gt;</span> strings <span class="op">=</span> [<span class="st">&#39;Hello&#39;</span>, <span class="st">&#39;Goodbye&#39;</span>, <span class="st">&#39;David&#39;</span>]</span>
<span id="cb3-2-c4aef35be5"><a href="#cb3-2-c4aef35be5"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">all</span>([s[<span class="dv">0</span>] <span class="op">==</span> <span class="st">&#39;D&#39;</span> <span class="cf">for</span> s <span class="kw">in</span> strings])</span>
<span id="cb3-3-c4aef35be5"><a href="#cb3-3-c4aef35be5"></a><span class="va">False</span></span></code></pre></div>
<p>Of course, Python is more limited than mathematics because there are limits on the size of the collections, and so we cannot easily express existential statement quantified over infinite domains like <span class="math inline">\(\N\)</span> or <span class="math inline">\(\R\)</span>. Well discuss this in more detail in a later section.</p>
<h2 id="writing-sentences-in-predicate-logic-c4aef35be5">Writing sentences in predicate logic</h2>
<p>Now that we have introduced the existential and universal quantifiers, we have a complete set of tools needed to represent all statements well see in this course. A general formula in predicate logic is built up using the existential and universal quantifiers, the propositional operators <span class="math inline">\(\lnot\)</span>, <span class="math inline">\(\land\)</span>, <span class="math inline">\(\lor\)</span>, <span class="math inline">\(\Rightarrow\)</span>, and <span class="math inline">\(\Leftrightarrow\)</span>, and arbitrary predicates. To ensure that the formula has a fixed truth value, we will require every variable in the formula to be quantified.<label for="sn-4-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-c4aef35be5" class="margin-toggle"/><span class="sidenote">Other texts will often refer to quantified variables as <em>bound variables</em>, and unquantified variables as <em>free variables</em>.</span> We call a formula with no unquantified variables a <strong>sentence</strong>. So for example, the formula <span class="math display">\[\forall x \in \N,~ x^2 &gt; y\]</span> is not a sentence: even though <span class="math inline">\(x\)</span> is quantified, <span class="math inline">\(y\)</span> is not, and so we cannot determine the truth value of this formula. If we quantify <span class="math inline">\(y\)</span> as well, we get a sentence: <span class="math display">\[\forall x, y \in \N,~ x^2 &gt; y.\]</span></p>
<p>However, dont confuse a formula being a sentence with a formula being True! As well see repeatedly throughout the course, it is quite possible to express both True and False sentences, and part of our job will be to determine whether a given sentence is True or False, and to prove it.</p>
<h3 id="commas-avoid-them-c4aef35be5">Commas: avoid them!</h3>
<p>Here is a common question from students who are first learning symbolic logic: “does the comma mean and or then?” As we discussed at the start of the course, we study to predicate logic to provide us with an unambiguous way of representing ideas. The English language is filled with ambiguities that can make it hard to express even relatively simple ideas, much less the complex definitions and concepts used in many fields of computer science. We have seen one example of this ambiguity in the English word “or,” which can be inclusive or exlusive, and often requires additional words of clarification to make precise. In everyday communication, these ambiguous aspects of the English language contribute to its richness of expression. But in a technical context, ambiguity is undesirable: it is much more useful to limit the possible meanings to make them unambiguous and precise.</p>
<p>There is another, more insidious example of ambiguity with which you are probably more familiar: the <em>comma</em>, a tiny, easily-glazed-over symbol that people often infuse with different meanings. Consider the following statements:</p>
<ol type="1">
<li>If it rains tomorrow, Ill be sad.</li>
<li>David is cool, Toniann is cool.</li>
</ol>
<p>Our intuitions tell us very different things about what the commas mean in each case. In the first, the comma means <em>then</em>, separating the hypothesis and conclusion of an implication. But in the second, the comma is used to mean <em>and</em>, the implicit joining of two separate sentences.<label for="sn-5-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-c4aef35be5" class="margin-toggle"/><span class="sidenote">Grammar-savvy folks will recognize this as a <em>comma splice</em>, which is often frowned upon but informs our reading nonetheless.</span> The fact that we are all fluent in English means that our prior intuition hides the ambiguity in this symbol, but it is quite obvious when we put this into the more unfamiliar context of predicate logic, as in the formula: <span class="math display">\[P(x), Q(x)\]</span></p>
<p>This, of course, is where the confusion lies, and is the origin of the question posed at the beginning of this section. Because of this ambiguity, <strong>never use the comma to connect propositions</strong>. We already have a rich enough set of symbols—including <span class="math inline">\(\land\)</span> and <span class="math inline">\(\Rightarrow\)</span>—that we do not need another one that is ambiguous and adds nothing new!</p>
<p>That said, keep in mind that commas do have two valid uses in predicate formulas:</p>
<ul>
<li>immediately after a variable quantification, or separating two variables with the same quantification</li>
<li>separating arguments to a predicate</li>
</ul>
<p>You can see both of these usages illustrated below, but please do remember that these are the <em>only</em> valid places for the comma within symbolic notation! <span class="math display">\[\forall x, y \in \N,~ \forall z \in \R,~ P(x, y) \Rightarrow Q(x, y, z)\]</span></p>
<h2 id="manipulating-negation-c4aef35be5">Manipulating negation</h2>
<p>We have already seen some equivalences among logical formulas, such as the equivalence of <span class="math inline">\(p \Rightarrow q\)</span> and <span class="math inline">\(\lnot p \lor q\)</span>. While there are many such equivalences, the only other major type that is important for this course are the ones used to simplify negated formulas. Taking the negation of a statement is extremely common, because often when we are trying to decide if a statement is True, it is useful to know exactly what its negation means and decide whether the negation is more plausible than the original.</p>
<p>Given any formula, we can state its negation simply by preceding it by a <span class="math inline">\(\lnot\)</span> symbol: <span class="math display">\[\lnot \big( \forall x \in \N,~ \exists y \in \N,~ x \geq 5 \lor x^2 - y \geq 30 \big).\]</span> However, such a statement is rather hard to understand if you try to transliterate each part separately: “Not for every natural number <span class="math inline">\(x\)</span>, there exists a natural number <span class="math inline">\(y\)</span>, such that <span class="math inline">\(x\)</span> is greater than or equal to <span class="math inline">\(5\)</span> or <span class="math inline">\(x^2 - y\)</span> is greater than or equal to 30.”</p>
<p>Instead, given a formula using negations, we apply some <em>simplification rules</em> to “push” the negation symbol to the right, closer the to individual predicates. Each simplification rule shows how to “move the negation inside” by one step, giving a pair of equivalent formulas, one with the negation applied to one of the logical operator or quantifiers, and one where the negation is applied to inner subexpressions.</p>
<ul>
<li><span class="math inline">\(\lnot (\lnot p)\)</span> becomes <span class="math inline">\(p\)</span>.</li>
<li><span class="math inline">\(\lnot (p \lor q)\)</span> becomes <span class="math inline">\((\lnot p) \land (\lnot q)\)</span>.<label for="sn-6-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-c4aef35be5" class="margin-toggle"/><span class="sidenote">The negation rules for AND and OR are known as <em>deMorgans laws</em>.</span></li>
<li><span class="math inline">\(\lnot (p \land q)\)</span> becomes <span class="math inline">\((\lnot p) \lor (\lnot q)\)</span>.</li>
<li><span class="math inline">\(\lnot (p \Rightarrow q)\)</span> becomes <span class="math inline">\(p \land (\lnot q)\)</span>.<label for="sn-7-c4aef35be5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7-c4aef35be5" class="margin-toggle"/><span class="sidenote">Since <span class="math inline">\(p \Rightarrow q\)</span> is equivalent to <span class="math inline">\(\lnot p \lor q\)</span>.</span></li>
<li><span class="math inline">\(\lnot (p \Leftrightarrow q)\)</span> becomes <span class="math inline">\((p \land (\lnot q)) \lor ((\lnot p) \land q))\)</span>.</li>
<li><span class="math inline">\(\lnot (\exists x \in S,~ P(x))\)</span> becomes <span class="math inline">\(\forall x \in S,~ \lnot P(x)\)</span>.</li>
<li><span class="math inline">\(\lnot (\forall x \in S,~ P(x))\)</span> becomes <span class="math inline">\(\exists x \in S,~ \lnot P(x)\)</span>.</li>
</ul>
<p>It is usually easy to remember the simplification rules for <span class="math inline">\(\land\)</span>, <span class="math inline">\(\lor\)</span>, <span class="math inline">\(\forall\)</span>, and <span class="math inline">\(\exists\)</span>, since you simply “flip” them when moving the negation inside. The intuition for the negation of <span class="math inline">\(p \Rightarrow q\)</span> is that there is only one case where this is False: when <span class="math inline">\(p\)</span> has occurred but <span class="math inline">\(q\)</span> does not. The intuition for the negation of <span class="math inline">\(p \Leftrightarrow q\)</span> is to remember that <span class="math inline">\(\Leftrightarrow\)</span> can be replaced with “have the same truth value,” so the negation is “have different truth values.”</p>
<p>What about the quantifiers? Consider a statement of the form <span class="math inline">\(\lnot (\exists x \in S,~ P(x))\)</span>, which says “there does not exist an element <span class="math inline">\(x\)</span> of <span class="math inline">\(S\)</span> that satisfies <span class="math inline">\(P\)</span>.” The only way this could be true is for every element of <span class="math inline">\(S\)</span> to <em>not</em> satisfy <span class="math inline">\(P\)</span>: “every element <span class="math inline">\(x\)</span> of <span class="math inline">\(S\)</span> does not satisfy <span class="math inline">\(P\)</span>.” A similar line of reasoning applies to <span class="math inline">\(\lnot (\forall x \in S,~ P(x))\)</span>.</p>
</section> <br/> <a id="anchor-03-03"></a>
<header id="title-block-header-da490a8b06">
<h1 class="title">3.3 Filtering Collections</h1>
</header>
<section>
<p>Now were going to take a look at one of the most common steps in expressing statements in predicate logic and in processing large collections of data. At first glance these two might not appear that related, after going through this section you should be able to appreciate this elegant connection between predicate logic and data processing.</p>
<h2 id="expressing-conditions-in-predicate-logic-da490a8b06">Expressing conditions in predicate logic</h2>
<p>We saw in the last section that the universal quantifier <span class="math inline">\(\forall\)</span> is used to express a statement of the form “every element of set <span class="math inline">\(S\)</span> satisfies ____”. This works well when we use a predefined set for <span class="math inline">\(S\)</span> (like the numeric sets <span class="math inline">\(\N\)</span> or <span class="math inline">\(\R\)</span>), but does not work well when we want to narrow the scope of our statement to a smaller set.</p>
<p>For example, consider the following statement: “Every natural number <span class="math inline">\(n\)</span> greater than 3 satisfies the inequality <span class="math inline">\(n^2 + n \geq 20\)</span>.” The phrase “greater than 3” is a <em>condition</em> that modifies the statement, limiting the original domain of <span class="math inline">\(n\)</span> (the natural numbers) to a smaller subset (the natural numbers greater than 3).</p>
<p>There are two ways we can represent such conditions in predicate logic. The first is to define a new set; for example, we could define a set <span class="math inline">\(S_1 = \{n \mid n \in \N \text{ and } n &gt; 3\}\)</span>, and then simply write <span class="math inline">\(\forall n \in S_1,~ n^2 + n \geq 20\)</span>.</p>
<p>The second approach is to use an implication to express the condition. To see how this works, first we can rewrite the original statement using an “if … then …” structure as follows: “For every natural number <span class="math inline">\(n\)</span>, if <span class="math inline">\(n\)</span> is greater than 3 then <span class="math inline">\(n\)</span> satisfies the inequality <span class="math inline">\(n^2 + n \geq 20\)</span>.” We can translate this into predicate logic as <span class="math inline">\(\forall n \in \N,~ n &gt; 3 \Rightarrow n^2 + n \geq 20\)</span>.</p>
<p>This works because the <span class="math inline">\(n &gt; 3 \Rightarrow\)</span> has a filtering effect, due to the <em>vacuous truth</em> case of implication. For the values <span class="math inline">\(n \in \{0, 1, 2\}\)</span>, the hypothesis of the implication, <span class="math inline">\(n &gt; 3\)</span> is False, and so for these values the implication itself is True. And then since the overall statement is universally quantified, these vacuous truth cases dont affect the truth value of the statement.</p>
<p>The “forall-implies” structure is one of the most common forms of statements well encounter in this course. They arise naturally any time a statement is universally quantified, but there are conditions that limit the domain that the statement applies to.</p>
<h2 id="filtering-collections-in-python-da490a8b06">Filtering collections in Python</h2>
<p>Now lets turn our attention back to Python. Last chapter, we learned about several aggregation functions (like <code>sum</code>, <code>max</code>), and weve just learned about two more, <code>any</code> and <code>all</code>. Sometimes, however, we want to limit the scope of one of these functions to certain values in the input collection. For example, “find the sum of only the even numbers in a collection of numbers”, or “find the length of the longest string in a collection that starts with a <code>'D'</code>”. For these problems, we can quickly identify which aggregation function is necessary, but the problem is in choosing the right argument to pass in.</p>
<p>This is where filtering appears. In programming, a <strong>filter operation</strong> is an operation that takes a collection of data and returns a new collection consisting of the elements in the original collection that satisfy some predicate (which can vary from one filter operation to the next).</p>
<p>There are different ways of accomplishing a filter operation in Python. The simplest one builds on what weve learned so far by adding a syntactic variation to comprehensions. Well use as our example a set comprehension here, but what well discuss applies to list and dictionary comprehensions as well.</p>
<div class="sourceCode" id="cb1-da490a8b06"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-da490a8b06"><a href="#cb1-1-da490a8b06"></a>{<span class="op">&lt;</span>expression<span class="op">&gt;</span> <span class="cf">for</span> <span class="op">&lt;</span>variable<span class="op">&gt;</span> <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span> <span class="cf">if</span> <span class="op">&lt;</span>condition<span class="op">&gt;</span>}</span></code></pre></div>
<p>The new part, <code>if &lt;condition&gt;</code>, is a boolean expression involving the <code>&lt;variable&gt;</code>. This form of set comprehension behaves the same way as the ones we studied last chapter, except that <code>&lt;expression&gt;</code> only gets evaluated for the values of the variable that make the condition evaluate to <code>True</code>. Here are some examples to illustrate this:</p>
<div class="sourceCode" id="cb2-da490a8b06"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-da490a8b06"><a href="#cb2-1-da490a8b06"></a><span class="op">&gt;&gt;&gt;</span> numbers <span class="op">=</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>} <span class="co"># Initial collection</span></span>
<span id="cb2-2-da490a8b06"><a href="#cb2-2-da490a8b06"></a><span class="op">&gt;&gt;&gt;</span> {n <span class="cf">for</span> n <span class="kw">in</span> numbers <span class="cf">if</span> n <span class="op">&gt;</span> <span class="dv">3</span>} <span class="co"># Pure filtering: only keep elements &gt; 3</span></span>
<span id="cb2-3-da490a8b06"><a href="#cb2-3-da490a8b06"></a>{<span class="dv">4</span>, <span class="dv">5</span>}</span>
<span id="cb2-4-da490a8b06"><a href="#cb2-4-da490a8b06"></a><span class="op">&gt;&gt;&gt;</span> {n <span class="op">*</span> n <span class="cf">for</span> n <span class="kw">in</span> numbers <span class="cf">if</span> n <span class="op">&gt;</span> <span class="dv">3</span>} <span class="co"># Filtering with a data transformation</span></span>
<span id="cb2-5-da490a8b06"><a href="#cb2-5-da490a8b06"></a>{<span class="dv">16</span>, <span class="dv">25</span>}</span></code></pre></div>
<p>By combining these filtering comprehensions with aggregation functions, we can now achieve our goal of limiting the scope of an aggregation.</p>
<div class="sourceCode" id="cb3-da490a8b06"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-da490a8b06"><a href="#cb3-1-da490a8b06"></a><span class="op">&gt;&gt;&gt;</span> numbers <span class="op">=</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>}</span>
<span id="cb3-2-da490a8b06"><a href="#cb3-2-da490a8b06"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sum</span>({n <span class="cf">for</span> n <span class="kw">in</span> numbers <span class="cf">if</span> n <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span>}) <span class="co"># Sum of only the even numbers</span></span>
<span id="cb3-3-da490a8b06"><a href="#cb3-3-da490a8b06"></a><span class="dv">6</span></span></code></pre></div>
<p>The keyword <code>if</code> used in this syntax for filtering comprehensions is directly connected to our use of implication above. Just as we used the hypothesis <span class="math inline">\(n &gt; 3 \Rightarrow\)</span> to limit the scope of the universal quantifier to a subset of the natural numbers, here we use <code>if n % 2 == 0</code> to limit the scope of the <code>sum</code> to just a subset of <code>numbers</code>.</p>
<p>Our final example in this section should make this connection even more explicit. Heres how we could translate the statement <span class="math inline">\(\forall n \in S,~ n &gt; 3 \Rightarrow n^2 + n \geq 20\)</span> into a Python expression:</p>
<div class="sourceCode" id="cb4-da490a8b06"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-da490a8b06"><a href="#cb4-1-da490a8b06"></a><span class="op">&gt;&gt;&gt;</span> numbers <span class="op">=</span> {<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>}</span>
<span id="cb4-2-da490a8b06"><a href="#cb4-2-da490a8b06"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">all</span>({n <span class="op">**</span> <span class="dv">2</span> <span class="op">+</span> n <span class="op">&gt;=</span> <span class="dv">20</span> <span class="cf">for</span> n <span class="kw">in</span> numbers <span class="cf">if</span> n <span class="op">&gt;</span> <span class="dv">3</span>})</span>
<span id="cb4-3-da490a8b06"><a href="#cb4-3-da490a8b06"></a><span class="va">True</span></span></code></pre></div>
</section>
<br/> <a id="anchor-03-04"></a>
<header id="title-block-header-560a2b96b6">
<h1 class="title">3.4 Conditional Execution</h1>
</header>
<section>
<p>So far, all of the function bodies weve written have consisted of a sequence of statements that always execute one after the other.<label for="sn-0-560a2b96b6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-560a2b96b6" class="margin-toggle"/><span class="sidenote"> This kind of code block is sometimes called a “straight line program”, since the statements form a linear path from one to the next.</span> But sometimes we want to execute a statement or block of statements only some of the time, based on some condition.</p>
<p>This is similar to the implication operator we saw when discussing propositional logic. The implication <span class="math inline">\(p \Rightarrow q\)</span> states that whenever <span class="math inline">\(p\)</span> is True, <span class="math inline">\(q\)</span> must also be True. In Python, what we would like to express is something of the form “Whenever <span class="math inline">\(p\)</span> is True, then the block of code <code>block1</code> must be executed”. To do so, well introduce a new type of Python statement that play a role analogous to <span class="math inline">\(\Rightarrow\)</span> in propositional logic.</p>
<h2 id="the-if-statement-560a2b96b6">The if statement</h2>
<p>Python uses the <strong>if statement</strong> to express conditional execution of code. An if statement is a <strong>compound statement</strong>, meaning it contains other statements within it.<label for="sn-1-560a2b96b6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-560a2b96b6" class="margin-toggle"/><span class="sidenote"> Analogously, a expression like <code>3 + 4</code> is a <em>compound expression</em>, since it consists of smaller expressions (<code>3</code> and <code>4</code>).</span> Here is our first syntax for an if statement:</p>
<div class="sourceCode" id="cb1-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-560a2b96b6"><a href="#cb1-1-560a2b96b6"></a><span class="cf">if</span> <span class="op">&lt;</span>condition<span class="op">&gt;</span>:</span>
<span id="cb1-2-560a2b96b6"><a href="#cb1-2-560a2b96b6"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb1-3-560a2b96b6"><a href="#cb1-3-560a2b96b6"></a> ...</span>
<span id="cb1-4-560a2b96b6"><a href="#cb1-4-560a2b96b6"></a><span class="cf">else</span>:</span>
<span id="cb1-5-560a2b96b6"><a href="#cb1-5-560a2b96b6"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb1-6-560a2b96b6"><a href="#cb1-6-560a2b96b6"></a> ...</span></code></pre></div>
<p>The if statement uses two keywords, <code>if</code> and <code>else</code>.<label for="sn-2-560a2b96b6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-560a2b96b6" class="margin-toggle"/><span class="sidenote"> Careful: we saw the <code>if</code> keyword used earlier to express conditions in comprehensions. The use of <code>if</code> here is logically similar, but quite different in how Python interprets it.</span> The <code>&lt;condition&gt;</code> following <code>if</code> must be an expression that evaluates to a boolean, called the <strong>if condition</strong>. This expression plays a role analogous to the hypothesis of an implication.</p>
<p>The statements on the lines after the <code>if</code> and <code>else</code> are indented to indicate that they are part of the <code>if</code> statement, similar to how a function docstring and body are indented relative to the function header. We call the statements under the <code>if</code> the <strong>if branch</strong> and the statements under the <code>else</code> the <strong>else branch</strong>.</p>
<p>When an <code>if</code> statement is executed, the following happens:</p>
<ol type="1">
<li>First, the if condition is evaluated, producing a boolean value.</li>
<li>If the condition evaluates to <code>True</code>, then the statements in the if branch are executed. If the condition evaluates to <code>False</code>, then the statements in the else branch are executed instead.</li>
</ol>
<p>Let us consider an example. Suppose Toronto Pearson Airport (YYZ) has hired us to develop some software. The first feature they want is to show their clients if a flight is on time or delayed. The airport will provide us with both the time a flight is scheduled to depart and an estimated departure time based on the planes current GPS location. Our task is to report a status (as a string) to display a string. Here is the function header and docstring:</p>
<div class="sourceCode" id="cb2-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-560a2b96b6"><a href="#cb2-1-560a2b96b6"></a><span class="kw">def</span> get_status(scheduled: <span class="bu">int</span>, estimated: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb2-2-560a2b96b6"><a href="#cb2-2-560a2b96b6"></a> <span class="co">&quot;&quot;&quot;Return the flight status for the given scheduled and estimated departure times.</span></span>
<span id="cb2-3-560a2b96b6"><a href="#cb2-3-560a2b96b6"></a></span>
<span id="cb2-4-560a2b96b6"><a href="#cb2-4-560a2b96b6"></a><span class="co"> The times are given as integers between 0 and 23 inclusive, representing</span></span>
<span id="cb2-5-560a2b96b6"><a href="#cb2-5-560a2b96b6"></a><span class="co"> the hour of the day.</span></span>
<span id="cb2-6-560a2b96b6"><a href="#cb2-6-560a2b96b6"></a></span>
<span id="cb2-7-560a2b96b6"><a href="#cb2-7-560a2b96b6"></a><span class="co"> The status is either &#39;On time&#39; or &#39;Delayed&#39;.</span></span>
<span id="cb2-8-560a2b96b6"><a href="#cb2-8-560a2b96b6"></a></span>
<span id="cb2-9-560a2b96b6"><a href="#cb2-9-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status(10, 10)</span></span>
<span id="cb2-10-560a2b96b6"><a href="#cb2-10-560a2b96b6"></a><span class="co"> &#39;On time&#39;</span></span>
<span id="cb2-11-560a2b96b6"><a href="#cb2-11-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status(10, 12)</span></span>
<span id="cb2-12-560a2b96b6"><a href="#cb2-12-560a2b96b6"></a><span class="co"> &#39;Delayed&#39;</span></span>
<span id="cb2-13-560a2b96b6"><a href="#cb2-13-560a2b96b6"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>Now, if we only needed to calculate a <code>bool</code> for whether the flight is delayed, this function would be very straightforward: simply return <code>estimated &lt;= scheduled</code>, i.e., whether the estimated departure time is before or at the scheduled departure time. Boolean expressions like this are often useful first steps in implementing functions to determine different “cases” of inputs, but they arent the only step.</p>
<p>Instead, we use if statements to execute different code based on these cases. Heres our implementation of <code>get_status</code>:</p>
<div class="sourceCode" id="cb3-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-560a2b96b6"><a href="#cb3-1-560a2b96b6"></a><span class="kw">def</span> get_status(scheduled: <span class="bu">int</span>, estimated: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb3-2-560a2b96b6"><a href="#cb3-2-560a2b96b6"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-3-560a2b96b6"><a href="#cb3-3-560a2b96b6"></a> <span class="cf">if</span> estimated <span class="op">&lt;=</span> scheduled:</span>
<span id="cb3-4-560a2b96b6"><a href="#cb3-4-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;On time&#39;</span></span>
<span id="cb3-5-560a2b96b6"><a href="#cb3-5-560a2b96b6"></a> <span class="cf">else</span>:</span>
<span id="cb3-6-560a2b96b6"><a href="#cb3-6-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;Delayed&#39;</span></span></code></pre></div>
<p>Our if statement uses the boolean expression we identified earlier (<code>estimated &lt;= scheduled</code>) to trigger different <code>return</code> statements to return the correct string.</p>
<h3 id="a-simple-control-flow-diagram-560a2b96b6">A simple control flow diagram</h3>
<p>One useful tool for understanding if statements is drawing <em>control flow diagrams</em> to visualize the order in which statements execute. For example, here is a simple diagram for our <code>get_status</code> function above:</p>
<p><img src="images/get-status.png" alt="get status control flow diagram" /><br />
</p>
<p>An <code>if</code> statement introduces a “fork in path” of a functions control flow, and this is why we use the term <em>branch</em> for each of the <code>if</code> and <code>else</code> blocks of code.</p>
<h2 id="code-with-more-than-two-cases-560a2b96b6">Code with more than two cases</h2>
<p>Now suppose Toronto Pearson Airport has changed the requirements of our feature. Theyve noticed that whenever a flight is delayed by more than four hours, the airline cancels the flight. They would like our <code>get_status</code> function to accommodate this change, so that the set of possible outputs is now <code>{'On time', 'Delayed', 'Cancelled'}</code>.</p>
<div class="sourceCode" id="cb4-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-560a2b96b6"><a href="#cb4-1-560a2b96b6"></a><span class="kw">def</span> get_status_v2(scheduled: <span class="bu">int</span>, estimated: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb4-2-560a2b96b6"><a href="#cb4-2-560a2b96b6"></a> <span class="co">&quot;&quot;&quot;Return the flight status for the given scheduled and estimated departure times.</span></span>
<span id="cb4-3-560a2b96b6"><a href="#cb4-3-560a2b96b6"></a></span>
<span id="cb4-4-560a2b96b6"><a href="#cb4-4-560a2b96b6"></a><span class="co"> The times are given as integers between 0 and 23 inclusive, representing</span></span>
<span id="cb4-5-560a2b96b6"><a href="#cb4-5-560a2b96b6"></a><span class="co"> the hour of the day.</span></span>
<span id="cb4-6-560a2b96b6"><a href="#cb4-6-560a2b96b6"></a></span>
<span id="cb4-7-560a2b96b6"><a href="#cb4-7-560a2b96b6"></a><span class="co"> The status is &#39;On time&#39;, &#39;Delayed&#39;, or &#39;Cancelled&#39;.</span></span>
<span id="cb4-8-560a2b96b6"><a href="#cb4-8-560a2b96b6"></a></span>
<span id="cb4-9-560a2b96b6"><a href="#cb4-9-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status_v2(10, 10)</span></span>
<span id="cb4-10-560a2b96b6"><a href="#cb4-10-560a2b96b6"></a><span class="co"> &#39;On time&#39;</span></span>
<span id="cb4-11-560a2b96b6"><a href="#cb4-11-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status_v2(10, 12)</span></span>
<span id="cb4-12-560a2b96b6"><a href="#cb4-12-560a2b96b6"></a><span class="co"> &#39;Delayed&#39;</span></span>
<span id="cb4-13-560a2b96b6"><a href="#cb4-13-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status_v2(10, 15)</span></span>
<span id="cb4-14-560a2b96b6"><a href="#cb4-14-560a2b96b6"></a><span class="co"> &#39;Cancelled&#39;</span></span>
<span id="cb4-15-560a2b96b6"><a href="#cb4-15-560a2b96b6"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>Lets consider whats changed between this version and our previous one. If the estimated time is before the scheduled time, nothings changed, and <code>'On time'</code> should still be returned. But when the estimated time is after the schedule time, we now need to distinguish between two separate subcases, based on the difference in time. We can express these subcases using nested if statements, i.e., one if statement contained in a branch of another:</p>
<div class="sourceCode" id="cb5-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-560a2b96b6"><a href="#cb5-1-560a2b96b6"></a><span class="kw">def</span> get_status_v2(scheduled: <span class="bu">int</span>, estimated: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb5-2-560a2b96b6"><a href="#cb5-2-560a2b96b6"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb5-3-560a2b96b6"><a href="#cb5-3-560a2b96b6"></a> <span class="cf">if</span> estimated <span class="op">&lt;=</span> scheduled:</span>
<span id="cb5-4-560a2b96b6"><a href="#cb5-4-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;On time&#39;</span></span>
<span id="cb5-5-560a2b96b6"><a href="#cb5-5-560a2b96b6"></a> <span class="cf">else</span>:</span>
<span id="cb5-6-560a2b96b6"><a href="#cb5-6-560a2b96b6"></a> <span class="cf">if</span> estimated <span class="op">-</span> scheduled <span class="op">&lt;=</span> <span class="dv">4</span>:</span>
<span id="cb5-7-560a2b96b6"><a href="#cb5-7-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;Delayed&#39;</span></span>
<span id="cb5-8-560a2b96b6"><a href="#cb5-8-560a2b96b6"></a> <span class="cf">else</span>:</span>
<span id="cb5-9-560a2b96b6"><a href="#cb5-9-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;Cancelled&#39;</span></span></code></pre></div>
<p>This function body is correct, but just like with expressions, excessive nesting of statements can make code difficult to read and understand. So instead of using a nested if statement, well introduce a new form of if statement that makes use of the <code>elif</code> keyword, which is short for “else if”.</p>
<div class="sourceCode" id="cb6-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-560a2b96b6"><a href="#cb6-1-560a2b96b6"></a><span class="cf">if</span> <span class="op">&lt;</span>condition1<span class="op">&gt;</span>:</span>
<span id="cb6-2-560a2b96b6"><a href="#cb6-2-560a2b96b6"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb6-3-560a2b96b6"><a href="#cb6-3-560a2b96b6"></a> ...</span>
<span id="cb6-4-560a2b96b6"><a href="#cb6-4-560a2b96b6"></a><span class="cf">elif</span> <span class="op">&lt;</span>condition2<span class="op">&gt;</span>:</span>
<span id="cb6-5-560a2b96b6"><a href="#cb6-5-560a2b96b6"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb6-6-560a2b96b6"><a href="#cb6-6-560a2b96b6"></a> ...</span>
<span id="cb6-7-560a2b96b6"><a href="#cb6-7-560a2b96b6"></a>... <span class="co"># [any number of elif conditions and branches]</span></span>
<span id="cb6-8-560a2b96b6"><a href="#cb6-8-560a2b96b6"></a><span class="cf">else</span>:</span>
<span id="cb6-9-560a2b96b6"><a href="#cb6-9-560a2b96b6"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb6-10-560a2b96b6"><a href="#cb6-10-560a2b96b6"></a> ...</span></code></pre></div>
<p>When this form of if statement is executed, the following happens.</p>
<ol type="1">
<li>First, the if condition (<code>&lt;condition1&gt;</code>) is evaluated, producing a boolean value.</li>
<li>If the condition evaluates to <code>True</code>, then the statements in the if branch are executed. If the condition evaluates to <code>False</code>, then next elif condition is evaluated, producing a boolean.</li>
<li>If that condition evaluates to <code>True</code>, then the statements in that elif branch are executed. If that condition evaluates to <code>False</code>, then the next elif condition is evaluated. This step repeats until either one of the elif conditions evaluate to <code>True</code>, or all of the elif conditions have evaluated to <code>False</code>.</li>
<li>If neither the if condition nor any of the elif conditions evaluate to <code>True</code>, then the else branch executes.</li>
</ol>
<p>Here is how we can use <code>elif</code> to rewrite <code>get_status</code> without nested if statements.</p>
<div class="sourceCode" id="cb7-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-560a2b96b6"><a href="#cb7-1-560a2b96b6"></a><span class="kw">def</span> get_status_v3(scheduled: <span class="bu">int</span>, estimated: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb7-2-560a2b96b6"><a href="#cb7-2-560a2b96b6"></a> <span class="co">&quot;&quot;&quot;Return the flight status for the given scheduled and estimated departure times.</span></span>
<span id="cb7-3-560a2b96b6"><a href="#cb7-3-560a2b96b6"></a></span>
<span id="cb7-4-560a2b96b6"><a href="#cb7-4-560a2b96b6"></a><span class="co"> The times are given as integers between 0 and 23 inclusive, representing</span></span>
<span id="cb7-5-560a2b96b6"><a href="#cb7-5-560a2b96b6"></a><span class="co"> the hour of the day.</span></span>
<span id="cb7-6-560a2b96b6"><a href="#cb7-6-560a2b96b6"></a></span>
<span id="cb7-7-560a2b96b6"><a href="#cb7-7-560a2b96b6"></a><span class="co"> The status is &#39;On time&#39;, &#39;Delayed&#39;, or &#39;Cancelled&#39;.</span></span>
<span id="cb7-8-560a2b96b6"><a href="#cb7-8-560a2b96b6"></a></span>
<span id="cb7-9-560a2b96b6"><a href="#cb7-9-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status_v3(10, 10)</span></span>
<span id="cb7-10-560a2b96b6"><a href="#cb7-10-560a2b96b6"></a><span class="co"> &#39;On time&#39;</span></span>
<span id="cb7-11-560a2b96b6"><a href="#cb7-11-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status_v3(10, 12)</span></span>
<span id="cb7-12-560a2b96b6"><a href="#cb7-12-560a2b96b6"></a><span class="co"> &#39;Delayed&#39;</span></span>
<span id="cb7-13-560a2b96b6"><a href="#cb7-13-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; get_status_v3(10, 15)</span></span>
<span id="cb7-14-560a2b96b6"><a href="#cb7-14-560a2b96b6"></a><span class="co"> &#39;Cancelled&#39;</span></span>
<span id="cb7-15-560a2b96b6"><a href="#cb7-15-560a2b96b6"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-16-560a2b96b6"><a href="#cb7-16-560a2b96b6"></a> <span class="cf">if</span> estimated <span class="op">&lt;=</span> scheduled:</span>
<span id="cb7-17-560a2b96b6"><a href="#cb7-17-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;On time&#39;</span></span>
<span id="cb7-18-560a2b96b6"><a href="#cb7-18-560a2b96b6"></a> <span class="cf">elif</span> estimated <span class="op">-</span> scheduled <span class="op">&lt;=</span> <span class="dv">4</span>:</span>
<span id="cb7-19-560a2b96b6"><a href="#cb7-19-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;Delayed&#39;</span></span>
<span id="cb7-20-560a2b96b6"><a href="#cb7-20-560a2b96b6"></a> <span class="cf">else</span>:</span>
<span id="cb7-21-560a2b96b6"><a href="#cb7-21-560a2b96b6"></a> <span class="cf">return</span> <span class="st">&#39;Cancelled&#39;</span></span></code></pre></div>
<p>This code is logically equivalent to the previous version, but its easier to read because theres no more nesting! Now, it is clear exactly what are the three possible branches of execution for this function.</p>
<!-- TODO: Add control flow diagram for get_status_v2 and get_status_v3 -->
<h2 id="testing-all-the-branches-560a2b96b6">Testing all the branches</h2>
<p>Adding branching to our control flow makes our functions more complex, and so we need to pay attention to how we test our code. With functions that contain if statements, any one particular input we give can only test one possible execution path, so we need to design our unit tests so that each possible execution path is used at least once. This form of test design is called <strong>white box</strong> testing, because we “see through the box” and therefore can design tests based on the source code itself. In contrast, <strong>black box</strong> testing are tests created without any knowledge of the source code (so no knowledge of the different paths the code can take).</p>
<p>In our doctests for <code>get_status_v3</code>, we chose three different examples, each corresponding to a different possible case of the if statement. This was pretty straightforward because the code is relatively simple, but well study later example of more complex control flow where it wont be so simple to design test cases to cover each branch. In fact, the percentage of lines of program code that are executed when a set of tests for that program is called <strong>code coverage</strong>, and is a metric used to assess the quality of tests. While a set of tests may strive for 100% code coverage, this does not always occur as our programs grow in complexity. The concept of code coverage and other metrics used to evaluate tests is something well only touch on in this course, but in future courses youll learn about this in more detail and even use some automated tools for calculating these metrics.<label for="sn-3-560a2b96b6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-560a2b96b6" class="margin-toggle"/><span class="sidenote"> In particular, even though code coverage is a commonly used metric, it is also criticized for giving a false sense of quality of a test suite. Just because all lines of code are executed at least once does not actually mean that the tests chosen cover all possible cases to consider for a program. Well see a simple example of this in the following section.</span></p>
<h2 id="building-on-our-example-560a2b96b6">Building on our example</h2>
<p>Toronto Pearson Airport is beginning to trust us with more data, and are requesting more complex features as a result. They now want us to write a function that determines how many flights are cancelled in a day. The airport will provide us with the data as a dictionary (i.e., <code>dict</code>), where the keys are unique flight numbers and the values for each flight number is a two-element list. The first element is the scheduled time and the second element is the estimated time. More succinctly, the data is a mapping of the form: <code>{ flight_number: [scheduled, estimated] }</code>.</p>
<p>Unlike earlier, when our function input was only two integers, we are now working with a collection of data. Before we start trying to solve the problem, lets create some example data in the Python console. Specifically, well create a dictionary with values for three different Air Canada flight numbers.</p>
<div class="sourceCode" id="cb8-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-560a2b96b6"><a href="#cb8-1-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> flights <span class="op">=</span> {<span class="st">&#39;AC110&#39;</span>: [<span class="dv">10</span>, <span class="dv">12</span>], <span class="st">&#39;AC321&#39;</span>: [<span class="dv">12</span>, <span class="dv">19</span>], <span class="st">&#39;AC999&#39;</span>: [<span class="dv">1</span>, <span class="dv">1</span>]}</span>
<span id="cb8-2-560a2b96b6"><a href="#cb8-2-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> flights[<span class="st">&#39;AC110&#39;</span>]</span>
<span id="cb8-3-560a2b96b6"><a href="#cb8-3-560a2b96b6"></a>[<span class="dv">10</span>, <span class="dv">12</span>]</span></code></pre></div>
<p>We know that we can query the dictionary by providing an existing key. The value associated with a key is a list of integers, and we can index the list to retrieve those integers. Index 0 of the list refers to the flight numbers scheduled time, while index 1 refers to the estimated time. Let us call our <code>get_status_v3</code> function for flight <code>'AC110'</code>:</p>
<div class="sourceCode" id="cb9-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-560a2b96b6"><a href="#cb9-1-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> flight_ac110 <span class="op">=</span> flights[<span class="st">&#39;AC110&#39;</span>]</span>
<span id="cb9-2-560a2b96b6"><a href="#cb9-2-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> get_status_v3(flight_ac110[<span class="dv">0</span>], flight_ac110[<span class="dv">1</span>])</span>
<span id="cb9-3-560a2b96b6"><a href="#cb9-3-560a2b96b6"></a><span class="co">&#39;Delayed&#39;</span></span></code></pre></div>
<p>Were making great progress! Instead of specifying the flight number ourselves (i.e., <code>'AC110'</code>), we would instead like to substitute in different flight numbers based on the data we receive from the airport. We can do that using comprehensions. Lets explore and see what we can get:</p>
<div class="sourceCode" id="cb10-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-560a2b96b6"><a href="#cb10-1-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> {k <span class="cf">for</span> k <span class="kw">in</span> flights}</span>
<span id="cb10-2-560a2b96b6"><a href="#cb10-2-560a2b96b6"></a>{<span class="st">&#39;AC999&#39;</span>, <span class="st">&#39;AC110&#39;</span>, <span class="st">&#39;AC321&#39;</span>}</span>
<span id="cb10-3-560a2b96b6"><a href="#cb10-3-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> {get_status_v3(flights[k][<span class="dv">0</span>], flights[k][<span class="dv">1</span>]) <span class="op">==</span> <span class="st">&#39;Cancelled&#39;</span> <span class="cf">for</span> k <span class="kw">in</span> flights}</span>
<span id="cb10-4-560a2b96b6"><a href="#cb10-4-560a2b96b6"></a>{<span class="va">False</span>, <span class="va">True</span>}</span>
<span id="cb10-5-560a2b96b6"><a href="#cb10-5-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> [get_status_v3(flights[k][<span class="dv">0</span>], flights[k][<span class="dv">1</span>]) <span class="op">==</span> <span class="st">&#39;Cancelled&#39;</span> <span class="cf">for</span> k <span class="kw">in</span> flights]</span>
<span id="cb10-6-560a2b96b6"><a href="#cb10-6-560a2b96b6"></a>[<span class="va">False</span>, <span class="va">True</span>, <span class="va">False</span>]</span></code></pre></div>
<p>Our first set comprehension can get us the set of flight numbers, but that doesnt tell us if the flight was cancelled or not. When we created our second set comprehension we could see that there was at least one flight cancelled. Remember that sets only contain unique elements, and this set consists of all possible boolean values. When we create a list comprehension, we can see that exactly one out of three flights were cancelled (there is one <code>True</code> value). But remember that the airport only wants to know how many flights were cancelled; a single integer value. Currently, we have a list of boolean values.</p>
<p>Let us now try to combine the first set comprehension with the second, using the filtering we learned in the last section.</p>
<div class="sourceCode" id="cb11-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-560a2b96b6"><a href="#cb11-1-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> {k <span class="cf">for</span> k <span class="kw">in</span> flights <span class="cf">if</span> get_status_v3(flights[k][<span class="dv">0</span>], flights[k][<span class="dv">1</span>]) <span class="op">==</span> <span class="st">&#39;Cancelled&#39;</span>}</span>
<span id="cb11-2-560a2b96b6"><a href="#cb11-2-560a2b96b6"></a>{<span class="st">&#39;AC321&#39;</span>}</span>
<span id="cb11-3-560a2b96b6"><a href="#cb11-3-560a2b96b6"></a><span class="op">&gt;&gt;&gt;</span> [k <span class="cf">for</span> k <span class="kw">in</span> flights <span class="cf">if</span> get_status_v3(flights[k][<span class="dv">0</span>], flights[k][<span class="dv">1</span>]) <span class="op">==</span> <span class="st">&#39;Cancelled&#39;</span>]</span>
<span id="cb11-4-560a2b96b6"><a href="#cb11-4-560a2b96b6"></a>[<span class="st">&#39;AC321&#39;</span>]</span></code></pre></div>
<p>Excellent! We now have a set of flight numbers that were cancelled. To convert this into an integer, we can use the built-in <code>len</code> function on the set.<label for="sn-4-560a2b96b6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-560a2b96b6" class="margin-toggle"/><span class="sidenote"> Something to think about: does it matter if we use the list or set comprehension here?</span> Lets see what all this looks like in a function:</p>
<div class="sourceCode" id="cb12-560a2b96b6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-560a2b96b6"><a href="#cb12-1-560a2b96b6"></a><span class="kw">def</span> count_cancelled(flights: <span class="bu">dict</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb12-2-560a2b96b6"><a href="#cb12-2-560a2b96b6"></a> <span class="co">&quot;&quot;&quot;Return the number of cancelled flights for the given flight data.</span></span>
<span id="cb12-3-560a2b96b6"><a href="#cb12-3-560a2b96b6"></a></span>
<span id="cb12-4-560a2b96b6"><a href="#cb12-4-560a2b96b6"></a><span class="co"> flights is a dictionary where each key is a flight ID,</span></span>
<span id="cb12-5-560a2b96b6"><a href="#cb12-5-560a2b96b6"></a><span class="co"> and whose corresponding value is a list of two numbers, where the first is</span></span>
<span id="cb12-6-560a2b96b6"><a href="#cb12-6-560a2b96b6"></a><span class="co"> the scheduled departure time and the second is the estimated departure time.</span></span>
<span id="cb12-7-560a2b96b6"><a href="#cb12-7-560a2b96b6"></a></span>
<span id="cb12-8-560a2b96b6"><a href="#cb12-8-560a2b96b6"></a><span class="co"> &gt;&gt;&gt; count_cancelled({&#39;AC110&#39;: [10, 12], &#39;AC321&#39;: [12, 19], &#39;AC999&#39;: [1, 1]})</span></span>
<span id="cb12-9-560a2b96b6"><a href="#cb12-9-560a2b96b6"></a><span class="co"> 1</span></span>
<span id="cb12-10-560a2b96b6"><a href="#cb12-10-560a2b96b6"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb12-11-560a2b96b6"><a href="#cb12-11-560a2b96b6"></a> cancelled_flights <span class="op">=</span> {k <span class="cf">for</span> k <span class="kw">in</span> flights</span>
<span id="cb12-12-560a2b96b6"><a href="#cb12-12-560a2b96b6"></a> <span class="cf">if</span> get_status_v3(flights[k][<span class="dv">0</span>], flights[k][<span class="dv">1</span>]) <span class="op">==</span> <span class="st">&#39;Cancelled&#39;</span>}</span>
<span id="cb12-13-560a2b96b6"><a href="#cb12-13-560a2b96b6"></a> <span class="cf">return</span> <span class="bu">len</span>(cancelled_flights)</span></code></pre></div>
<p>Lets review what we learned in this example:</p>
<ul>
<li>We can try to remember how we can use what weve learned by exploring in the Python console, well before starting to write the function. Here, we refreshed our memory on how we might look up values from dictionaries, index lists, call functions, create comprehensions, and filter collections.</li>
<li>We can substitute in different values for a functions input using comprehensions.</li>
<li>We can reuse functions weve already created and tested (like <code>get_status_v3</code>) to help implement other functions.</li>
</ul>
</section>
<br/> <a id="anchor-03-05"></a>
<header id="title-block-header-abca4702ed">
<h1 class="title">3.5 Simplifying If Statements</h1>
</header>
<section>
<p>In the last section we introduced if statements, a powerful Python structure that allowed us to perform conditional execution of blocks of code. But as well see again and again in this course, expressive power comes with a cost: as our toolkit gets larger and the programming language features we use get more advanced, our programs also get larger and more complex; harder to read and reason about.</p>
<p>So every time we introduce a new part of the Python programming language, well also take some time to discuss not just what it can do, but also how to use it in structured ways that minimize the complexity we create by using it, and how to reason about its behaviour formally using tools from mathematical logic.</p>
<h2 id="computing-booleans-when-if-statements-arent-necessary-abca4702ed">Computing booleans: when if statements arent necessary</h2>
<p>As our first example, consider the following function:</p>
<div class="sourceCode" id="cb1-abca4702ed"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-abca4702ed"><a href="#cb1-1-abca4702ed"></a><span class="kw">def</span> is_even(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-abca4702ed"><a href="#cb1-2-abca4702ed"></a> <span class="co">&quot;&quot;&quot;Return whether n is even (divisible by 2).&quot;&quot;&quot;</span></span>
<span id="cb1-3-abca4702ed"><a href="#cb1-3-abca4702ed"></a> <span class="cf">if</span> n <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb1-4-abca4702ed"><a href="#cb1-4-abca4702ed"></a> <span class="cf">return</span> <span class="va">True</span></span>
<span id="cb1-5-abca4702ed"><a href="#cb1-5-abca4702ed"></a> <span class="cf">else</span>:</span>
<span id="cb1-6-abca4702ed"><a href="#cb1-6-abca4702ed"></a> <span class="cf">return</span> <span class="va">False</span></span></code></pre></div>
<p>When we first learn about if statements, it is tempting to use them whenever we think of different “cases” of inputs, like even vs. odd numbers in this example. But remember that if statements are fundamentally about taking boolean values and conditionally executing code (usually to generate other values). In cases where all we need is a boolean value, <em>it is often simpler to write an expression to calculate the value directly, rather than using if statements</em>.</p>
<p>In our example, the if statement is redundant and can be simplified just by returning the value of the condition:</p>
<div class="sourceCode" id="cb2-abca4702ed"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-abca4702ed"><a href="#cb2-1-abca4702ed"></a><span class="kw">def</span> is_even(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-2-abca4702ed"><a href="#cb2-2-abca4702ed"></a> <span class="co">&quot;&quot;&quot;Return whether n is even (divisible by 2).&quot;&quot;&quot;</span></span>
<span id="cb2-3-abca4702ed"><a href="#cb2-3-abca4702ed"></a> <span class="cf">return</span> n <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
<p>Indeed, our earlier study of propositional logic should make us comfortable with the idea of treating booleans just like any other kind of value, and we should make full use of Pythons logical operators <code>and</code>, <code>or</code>, and <code>not</code> to combine them.</p>
<p>Consider this more complex example with nested if statements:</p>
<div class="sourceCode" id="cb3-abca4702ed"><pre class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb3-1-abca4702ed"><a href="#cb3-1-abca4702ed"></a><span class="kw">def</span> mystery(x: lst, y: lst) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb3-2-abca4702ed"><a href="#cb3-2-abca4702ed"></a> <span class="cf">if</span> x <span class="op">==</span> []:</span>
<span id="cb3-3-abca4702ed"><a href="#cb3-3-abca4702ed"></a> <span class="cf">if</span> y <span class="op">==</span> []:</span>
<span id="cb3-4-abca4702ed"><a href="#cb3-4-abca4702ed"></a> <span class="cf">return</span> <span class="va">True</span></span>
<span id="cb3-5-abca4702ed"><a href="#cb3-5-abca4702ed"></a> <span class="cf">else</span>:</span>
<span id="cb3-6-abca4702ed"><a href="#cb3-6-abca4702ed"></a> <span class="cf">return</span> <span class="va">False</span></span>
<span id="cb3-7-abca4702ed"><a href="#cb3-7-abca4702ed"></a> <span class="cf">else</span>:</span>
<span id="cb3-8-abca4702ed"><a href="#cb3-8-abca4702ed"></a> <span class="cf">if</span> y <span class="op">==</span> []:</span>
<span id="cb3-9-abca4702ed"><a href="#cb3-9-abca4702ed"></a> <span class="cf">return</span> <span class="va">False</span></span>
<span id="cb3-10-abca4702ed"><a href="#cb3-10-abca4702ed"></a> <span class="cf">else</span>:</span>
<span id="cb3-11-abca4702ed"><a href="#cb3-11-abca4702ed"></a> <span class="cf">return</span> <span class="va">True</span></span></code></pre></div>
<p>Here is a control flow diagram for this function, showing the four different possible execution paths.</p>
<p><img src="images/mystery.png" alt="mystery function control flow diagram" /><br />
</p>
<p>To simplify this, we start with the first inner if statement on lines 3-6. This follows the same structure as our first example, and can be simplified to just <code>return y == []</code>.</p>
<p>The second inner if statement on lines 8-11 follows a similar structure, except that now the boolean thats returned is the negation of the if condition. So we can simplify this as <code>return not y == []</code>, which we can simplify further using the <code>!=</code> operator: <code>return y != []</code>.</p>
<p>So now we have this simplification of the function body:</p>
<div class="sourceCode" id="cb4-abca4702ed"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-abca4702ed"><a href="#cb4-1-abca4702ed"></a><span class="kw">def</span> mystery(x: lst, y: lst) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb4-2-abca4702ed"><a href="#cb4-2-abca4702ed"></a> <span class="cf">if</span> x <span class="op">==</span> []:</span>
<span id="cb4-3-abca4702ed"><a href="#cb4-3-abca4702ed"></a> <span class="cf">return</span> y <span class="op">==</span> []</span>
<span id="cb4-4-abca4702ed"><a href="#cb4-4-abca4702ed"></a> <span class="cf">else</span>:</span>
<span id="cb4-5-abca4702ed"><a href="#cb4-5-abca4702ed"></a> <span class="cf">return</span> y <span class="op">!=</span> []</span></code></pre></div>
<p>But now how do we simplify this further? The idea here is to focus on the possible ways that <code>mystery</code> could return <code>True</code>. The if statement divides the inputs into two cases: when <code>x == []</code> and the if branch executes, and when <code>x != []</code> and the else branch executes. In the first case, when <code>x == []</code>, <code>mystery</code> returns the value of <code>y == []</code>. So one case for <code>mystery</code> returning <code>True</code> is when <code>x == [] and y == []</code>. Similarly, in the second case, when <code>x != []</code>, <code>mystery</code> returns <code>y != []</code>, and so the other case for <code>mystery</code> returning <code>True</code> is <code>x != [] and y != []</code>.</p>
<p>How should we combine these two cases? Because these are different cases, either one of them could occur, but we dont expect both of them to occur (since <code>x == []</code> and <code>x != []</code> cant both be true), and so we combine them using <code>or</code>:</p>
<div class="sourceCode" id="cb5-abca4702ed"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-abca4702ed"><a href="#cb5-1-abca4702ed"></a><span class="kw">def</span> mystery(x: lst, y: lst) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb5-2-abca4702ed"><a href="#cb5-2-abca4702ed"></a> <span class="cf">return</span> (x <span class="op">==</span> [] <span class="kw">and</span> y <span class="op">==</span> []) <span class="kw">or</span> (x <span class="op">!=</span> [] <span class="kw">and</span> y <span class="op">!=</span> [])</span></code></pre></div>
<p>This simplification took a bit of work, but as a result we have a clearer picture of what this function does. We can illustrate this further by breaking up the nested expression using local variables with meaningful names.</p>
<div class="sourceCode" id="cb6-abca4702ed"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-abca4702ed"><a href="#cb6-1-abca4702ed"></a><span class="kw">def</span> mystery(x: lst, y: lst) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb6-2-abca4702ed"><a href="#cb6-2-abca4702ed"></a> both_empty <span class="op">=</span> x <span class="op">==</span> [] <span class="kw">and</span> y <span class="op">==</span> []</span>
<span id="cb6-3-abca4702ed"><a href="#cb6-3-abca4702ed"></a> both_non_empty <span class="op">=</span> x <span class="op">!=</span> [] <span class="kw">and</span> y <span class="op">!=</span> []</span>
<span id="cb6-4-abca4702ed"><a href="#cb6-4-abca4702ed"></a> <span class="cf">return</span> both_empty <span class="kw">or</span> both_non_empty</span></code></pre></div>
<p>To check your understanding, try writing a docstring description for this function. Youll probably find it at least a little easier to do for this version than the original. And while this is still a relatively small example, the same principle will often apply in the future, and so be on the lookout for if statements that you can simplify in this way.<label for="sn-0-abca4702ed" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-abca4702ed" class="margin-toggle"/><span class="sidenote"> That said, this simplification wont always apply or be appropriate, depending on the complexity of the branches of the statement. Well discuss this in more detail later.</span></p>
<h2 id="using-if-statements-abca4702ed">Using if statements</h2>
<p><code>if</code> statements create branches in our code, allowing us to create more advanced functions. But more branches means more complexity because there are many possible paths that our function could take when called. To mitigate the complexity that comes with branching, we recommend two principles when working with if statements:</p>
<ol type="1">
<li>Prefer using a sequence of <code>elif</code>s rather than nested <code>if</code> statements. Overuse of nesting makes your code harder to understand, and can make the visual structure of your code more complex than necessary.</li>
<li>Write your conditions from most specific to most general. Order matters for these conditions, since they are checked one at a time in top-down order.</li>
</ol>
</section>
<br/> <a id="anchor-03-06"></a>
<header id="title-block-header-cd34d7ad7a">
<h1 class="title">3.6 <code>if __name__ == '__main__'</code></h1>
</header>
<section>
<p>One small application of if statements that weve already taken for granted in this course is writing certain “boilerplate” code for running certain libraries on our file. For example, we saw in <a href="../02-functions/06-testing-functions-1.html">2.6 Testing Functions I: <code>doctest</code> and <code>pytest</code></a> that we add the following code to our Python file to run the doctests in that file:</p>
<div class="sourceCode" id="cb1-cd34d7ad7a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-cd34d7ad7a"><a href="#cb1-1-cd34d7ad7a"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb1-2-cd34d7ad7a"><a href="#cb1-2-cd34d7ad7a"></a> <span class="im">import</span> doctest</span>
<span id="cb1-3-cd34d7ad7a"><a href="#cb1-3-cd34d7ad7a"></a> doctest.testmod()</span></code></pre></div>
<p>Now that weve learned about if statements, we are ready to understand that first line, <code>if __name__ == '__main__'</code>.</p>
<h2 id="import-statements-revisited-cd34d7ad7a">import statements revisited</h2>
<p>In <a href="../02-functions/04-importing-modules.html">2.4 Importing Modules</a>, we learned that an import statement is an instruction to the Python interpreter to find a Python module with a specified name and run it. This allows the program that executes the import statement to access the functions and data types defined within that module.</p>
<p>One consequence of this behaviour, though, is that by default <em>all</em> statements in the imported module are executed, not just function and data type definitions.</p>
<p>For example, suppose we had the following file <code>useful.py</code>:</p>
<div class="sourceCode" id="cb2-cd34d7ad7a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-cd34d7ad7a"><a href="#cb2-1-cd34d7ad7a"></a><span class="co"># useful.py</span></span>
<span id="cb2-2-cd34d7ad7a"><a href="#cb2-2-cd34d7ad7a"></a></span>
<span id="cb2-3-cd34d7ad7a"><a href="#cb2-3-cd34d7ad7a"></a><span class="kw">def</span> useful_function1(x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-4-cd34d7ad7a"><a href="#cb2-4-cd34d7ad7a"></a> <span class="co">&quot;&quot;&quot;...</span></span>
<span id="cb2-5-cd34d7ad7a"><a href="#cb2-5-cd34d7ad7a"></a></span>
<span id="cb2-6-cd34d7ad7a"><a href="#cb2-6-cd34d7ad7a"></a><span class="co"> &gt;&gt;&gt; useful_function1(1)</span></span>
<span id="cb2-7-cd34d7ad7a"><a href="#cb2-7-cd34d7ad7a"></a><span class="co"> 110</span></span>
<span id="cb2-8-cd34d7ad7a"><a href="#cb2-8-cd34d7ad7a"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-9-cd34d7ad7a"><a href="#cb2-9-cd34d7ad7a"></a> <span class="co"># Body omitted</span></span>
<span id="cb2-10-cd34d7ad7a"><a href="#cb2-10-cd34d7ad7a"></a></span>
<span id="cb2-11-cd34d7ad7a"><a href="#cb2-11-cd34d7ad7a"></a></span>
<span id="cb2-12-cd34d7ad7a"><a href="#cb2-12-cd34d7ad7a"></a><span class="kw">def</span> useful_function2(s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb2-13-cd34d7ad7a"><a href="#cb2-13-cd34d7ad7a"></a> <span class="co">&quot;&quot;&quot;...</span></span>
<span id="cb2-14-cd34d7ad7a"><a href="#cb2-14-cd34d7ad7a"></a></span>
<span id="cb2-15-cd34d7ad7a"><a href="#cb2-15-cd34d7ad7a"></a><span class="co"> &gt;&gt;&gt; useful_function1(&#39;Hello&#39;)</span></span>
<span id="cb2-16-cd34d7ad7a"><a href="#cb2-16-cd34d7ad7a"></a><span class="co"> &#39;Hello David&#39;</span></span>
<span id="cb2-17-cd34d7ad7a"><a href="#cb2-17-cd34d7ad7a"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-18-cd34d7ad7a"><a href="#cb2-18-cd34d7ad7a"></a> <span class="co"># Body omitted</span></span>
<span id="cb2-19-cd34d7ad7a"><a href="#cb2-19-cd34d7ad7a"></a></span>
<span id="cb2-20-cd34d7ad7a"><a href="#cb2-20-cd34d7ad7a"></a></span>
<span id="cb2-21-cd34d7ad7a"><a href="#cb2-21-cd34d7ad7a"></a><span class="im">import</span> doctest</span>
<span id="cb2-22-cd34d7ad7a"><a href="#cb2-22-cd34d7ad7a"></a>doctest.testmod()</span></code></pre></div>
<p>Note that here, the code to run <code>doctest</code> is not indented inside an if statement. It turns out that we can still run this file in the Python console, and the doctests will be run. However, these statements will also be executed every time <code>useful.py</code> is imported by another Python program. In other words, any time another program writes <code>import useful</code>, the doctests inside <code>useful.py</code> will be run, even though the doctests are not relevant for a program that just wants to use <code>useful.py</code>!</p>
<h2 id="enter-__name__-cd34d7ad7a">Enter <code>__name__</code></h2>
<p>To fix this problem, the Python interpreter creates a special variable called <code>__name__</code> for each module when a program is run.<label for="sn-0-cd34d7ad7a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-cd34d7ad7a" class="margin-toggle"/><span class="sidenote"> Python uses the “double underscore” naming convention to denote special variable or function names. Well encounter a few more of these throughout the course.</span> By default, the <code>__name__</code> variable is set to the name of the module: the <code>__name__</code> of <code>useful.py</code> is <code>'useful'</code>, and the <code>__name__</code> attribute of <code>math</code> is <code>'math'</code>.</p>
<div class="sourceCode" id="cb3-cd34d7ad7a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-cd34d7ad7a"><a href="#cb3-1-cd34d7ad7a"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> math</span>
<span id="cb3-2-cd34d7ad7a"><a href="#cb3-2-cd34d7ad7a"></a><span class="op">&gt;&gt;&gt;</span> math.<span class="va">__name__</span></span>
<span id="cb3-3-cd34d7ad7a"><a href="#cb3-3-cd34d7ad7a"></a><span class="co">&#39;math&#39;</span></span></code></pre></div>
<p>However, when you <em>run</em> a module (e.g., right-click and select “Run File in Python Console”), the Python interpreter overrides the default module <code>__name__</code> and instead sets it to the special string <code>'__main__'</code>. And so checking the <code>__name__</code> variable is a way to determine if the current module is being run, or whether its being imported by another module!</p>
<p>When we write <code>if __name__ == '__main__'</code>, we are really saying, “Execute the following code if this module is being run, and ignore the following code if this module is being imported by another module”. The boolean expression <code>__name__ == '__main__'</code> evaluates to <code>True</code> in the former case, and <code>False</code> in the latter, and the conditional execution happens because of the if statement.</p>
<h2 id="organizing-a-python-file-cd34d7ad7a">Organizing a Python file</h2>
<p>We call this if branch (all the code under <code>if __name__ == '__main__'</code>) the modules <strong>main block</strong>. Here are some important conventions to follow for organizing a Python file with a main block:</p>
<ol type="1">
<li>The only code that goes outside of the main block are import statements (<code>import ...</code>), constant definitions (<code>MY_CONSTANT = ...</code>), function definitions (<code>def ...</code>), and data type definitions (<code>class ...</code>), which we will see in the next chapter.</li>
<li>Other code, like code for running <code>doctest</code> or <code>pytest</code>, goes inside the main block so that it is only executed when the module is run, and not when it is imported.</li>
<li>The main block goes at the bottom of the module.</li>
</ol>
</section>
<br/> <a id="anchor-03-07"></a>
<header id="title-block-header-dc39e728e3">
<h1 class="title">3.7 Function Specifications</h1>
</header>
<section>
<p>One of the most central questions in software development is, “How do we know that the software we write is correct?” Certainly, writing test cases will ensure that our functions produce the expected output for specific situations. But as our programs increase in complexity, how confident can we be that our test cases are sufficient?</p>
<h2 id="function-specifications-and-correctness-dc39e728e3">Function specifications and correctness</h2>
<p>Before we address this question, we will formalize what it means for a program to be correct in the first place. Because functions are the primary way we organize programs, well focus on what it means for an individual function to be correct.</p>
<p>A <strong>specification</strong> for a function consists of two parts:</p>
<ol type="1">
<li>A description of what values the function takes as valid inputs. We can represent this description as a set of predicates, where a valid input must satisfy all these predicates. We call these predicates the <strong>preconditions</strong> of the function.</li>
<li>A description of what the function returns/does, in terms of its inputs.<label for="sn-0-dc39e728e3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-dc39e728e3" class="margin-toggle"/><span class="sidenote"> For now, all of our Python functions only return values, and do nothing else. Later on in the course, well study other kinds of function behaviour that could be included in a specification.</span> We can represent this description as a set of predicates as well, that must all be satisfied by the return value of the function. We call these predicates the <strong>postconditions</strong> of the function.</li>
</ol>
<p>With these two parts, a functions specification defines what we expect the function to do. The job of an implementation of the function is to provide the Python code in the function body that meets this specification. We say that a function implementation is <strong>correct</strong> when the following holds: <em>For all inputs that satisfy the specifications preconditions, the function implementations return value satisfies the specifications postconditions.</em></p>
<p>A function specification acts as a contract or agreement between the person who implements the function and the person who calls the function. For the person implementing the function, their responsibility is to make sure their code correctly returns or does what the specification says. When writing this code, they do not need to worry about exactly how the function is called and <em>assume</em> that the functions input is always valid.<label for="sn-1-dc39e728e3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-dc39e728e3" class="margin-toggle"/><span class="sidenote"> So in fact, we have already seen several preconditions in this course. Every time we had a function description that said “assume X about the input(s)”, that was a precondition.</span> For the person calling the function, their responsibility is to make sure they call the function with valid inputs. When they make this call, they do not need to worry about exactly how the function is implemented and <em>assume</em> that the function works correctly.</p>
<p>The concept of a function specification is a very powerful one, as it spreads the responsibility of function correctness across two parties that do their parts separately—as long as they both know what the function specification is. As a result, these specifications must be very precise. Outside of software, lawyers are hired to draft and review contracts to make sure that they are defensible in the eyes of the law. Similarly, programmers must behave as lawyers when designing software to write ironclad contracts that leave no ambiguity in what is expected of the user or how the software will behave. In this section, we introduce some new tools and terminology that can help our functions be more explicit in their requirements and behaviour.</p>
<h2 id="simple-specifications-dc39e728e3">Simple specifications</h2>
<p>Even though we havent formally introduced the notion of a function specification until this section, youve been writing specifications all along simply by following the Function Design Recipe. Lets take a look at an early example:</p>
<div class="sourceCode" id="cb1-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-dc39e728e3"><a href="#cb1-1-dc39e728e3"></a><span class="kw">def</span> is_even(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-dc39e728e3"><a href="#cb1-2-dc39e728e3"></a> <span class="co">&quot;&quot;&quot;Return whether n is even.</span></span>
<span id="cb1-3-dc39e728e3"><a href="#cb1-3-dc39e728e3"></a></span>
<span id="cb1-4-dc39e728e3"><a href="#cb1-4-dc39e728e3"></a><span class="co"> &gt;&gt;&gt; is_even(1)</span></span>
<span id="cb1-5-dc39e728e3"><a href="#cb1-5-dc39e728e3"></a><span class="co"> False</span></span>
<span id="cb1-6-dc39e728e3"><a href="#cb1-6-dc39e728e3"></a><span class="co"> &gt;&gt;&gt; is_even(2)</span></span>
<span id="cb1-7-dc39e728e3"><a href="#cb1-7-dc39e728e3"></a><span class="co"> True</span></span>
<span id="cb1-8-dc39e728e3"><a href="#cb1-8-dc39e728e3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-9-dc39e728e3"><a href="#cb1-9-dc39e728e3"></a> <span class="co"># Body omitted.</span></span></code></pre></div>
<p>Here, the <em>type contract</em> and <em>description</em> actually form a complete specification of this functions behaviour:</p>
<ol type="1">
<li>The type annotation of the parameter <code>n</code> tells us that the valid inputs to <code>is_even</code> are <code>int</code> values. The type annotation <code>int</code> is itself a <em>precondition</em> of the function.</li>
<li>Similarly, the type annotation for the return value tells us that the function will always return a <code>bool</code>. In addition, the description “Return whether n is even.” specifies the relationship between the functions return value and its input.<label for="sn-2-dc39e728e3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-dc39e728e3" class="margin-toggle"/><span class="sidenote"> The doctest examples aid understanding, but are not strictly required to specify what this function does.</span> The function description and return type annotation specify the <em>postconditions</em> of the function.</li>
</ol>
<p>From this alone, we know what it means for this function to be implemented correctly, even if we cant see the implementation.</p>
<blockquote>
<p><code>is_even</code> is implemented correctly when <em>for all <code>int</code>s <code>n</code>, <code>is_even(n)</code> returns a <code>bool</code> that is <code>True</code> when <code>n</code> is even, and <code>False</code> when <code>n</code> is not even</em>.</p>
</blockquote>
<p>For example, suppose David has implemented this function. Mario loads this function implementation into the Python console and calls it:</p>
<div class="sourceCode" id="cb2-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-dc39e728e3"><a href="#cb2-1-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> is_even(<span class="dv">4</span>)</span>
<span id="cb2-2-dc39e728e3"><a href="#cb2-2-dc39e728e3"></a><span class="va">False</span></span></code></pre></div>
<p>In this case, <code>4</code> is an <code>int</code>, so Mario held up his end of the contract when he called the function. But the <code>False</code> return value is inconsistent with the function description, and so we know there must be an error in the implementation—David is at fault, not Mario.</p>
<p>Suppose David fixes his implementation, and asks Mario to try another call. Mario types in:</p>
<div class="sourceCode" id="cb3-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-dc39e728e3"><a href="#cb3-1-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> is_even(<span class="dv">4</span>)</span>
<span id="cb3-2-dc39e728e3"><a href="#cb3-2-dc39e728e3"></a><span class="va">True</span></span></code></pre></div>
<p>Okay pretty good, and now Mario tries:</p>
<div class="sourceCode" id="cb4-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-dc39e728e3"><a href="#cb4-1-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> is_even([<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>])</span>
<span id="cb4-2-dc39e728e3"><a href="#cb4-2-dc39e728e3"></a>Traceback (most recent call last):</span>
<span id="cb4-3-dc39e728e3"><a href="#cb4-3-dc39e728e3"></a> File <span class="st">&quot;&lt;stdin&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb4-4-dc39e728e3"><a href="#cb4-4-dc39e728e3"></a> File <span class="st">&quot;&lt;stdin&gt;&quot;</span>, line <span class="dv">2</span>, <span class="kw">in</span> is_even</span>
<span id="cb4-5-dc39e728e3"><a href="#cb4-5-dc39e728e3"></a><span class="pp">TypeError</span>: unsupported operand <span class="bu">type</span>(s) <span class="cf">for</span> <span class="op">%</span>: <span class="st">&#39;list&#39;</span> <span class="kw">and</span> <span class="st">&#39;int&#39;</span></span></code></pre></div>
<p>In this case, the function did not produce a return value but rather an error (i.e., <code>TypeError</code>). Is David at fault again? <em>No!</em> Mario violated the functions precondition by passing in a <code>list</code> rather than an <code>int</code>, and so he should have no expectation that <code>is_even</code> will meet its postcondition. Therefore, Mario (the caller of the function) caused the error.</p>
<h2 id="preconditions-in-general-dc39e728e3">Preconditions in general</h2>
<p>All parameter type annotations are preconditions for a function. But often these type annotations are not precise enough to specify the exact set of valid inputs. Consider this function:</p>
<div class="sourceCode" id="cb5-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-dc39e728e3"><a href="#cb5-1-dc39e728e3"></a><span class="kw">def</span> max_length(strings: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb5-2-dc39e728e3"><a href="#cb5-2-dc39e728e3"></a> <span class="co">&quot;&quot;&quot;Return the maximum length of a string in the set of strings.</span></span>
<span id="cb5-3-dc39e728e3"><a href="#cb5-3-dc39e728e3"></a></span>
<span id="cb5-4-dc39e728e3"><a href="#cb5-4-dc39e728e3"></a><span class="co"> &gt;&gt;&gt; max_length({&#39;Hello&#39;, &#39;Mario&#39;, &#39;David Liu&#39;})</span></span>
<span id="cb5-5-dc39e728e3"><a href="#cb5-5-dc39e728e3"></a><span class="co"> 9</span></span>
<span id="cb5-6-dc39e728e3"><a href="#cb5-6-dc39e728e3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-7-dc39e728e3"><a href="#cb5-7-dc39e728e3"></a> <span class="cf">return</span> <span class="bu">max</span>({<span class="bu">len</span>(s) <span class="cf">for</span> s <span class="kw">in</span> strings})</span></code></pre></div>
<p>What happens when the set is empty? Lets try it out in the console:</p>
<div class="sourceCode" id="cb6-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-dc39e728e3"><a href="#cb6-1-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> empty_set <span class="op">=</span> <span class="bu">set</span>()</span>
<span id="cb6-2-dc39e728e3"><a href="#cb6-2-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> max_length(empty_set)</span>
<span id="cb6-3-dc39e728e3"><a href="#cb6-3-dc39e728e3"></a>Traceback (most recent call last):</span>
<span id="cb6-4-dc39e728e3"><a href="#cb6-4-dc39e728e3"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb6-5-dc39e728e3"><a href="#cb6-5-dc39e728e3"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">7</span>, <span class="kw">in</span> max_length</span>
<span id="cb6-6-dc39e728e3"><a href="#cb6-6-dc39e728e3"></a><span class="pp">ValueError</span>: <span class="bu">max</span>() arg <span class="kw">is</span> an empty sequence</span></code></pre></div>
<p>Weve obtained an error, rather than an <code>int</code>; this makes logical sense, because it is impossible to find the maximum value in a set that contains no values at all. But from a formal function specification sense, who is to blame: the functions caller or the functions implementer?</p>
<p>As it stands, the implementer is at fault because the only description of “valid inputs” given is the type annotation <code>set</code>; the empty set is still a <code>set</code>. So we need to update the specification to rule out this possibility, but how?<label for="sn-3-dc39e728e3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-dc39e728e3" class="margin-toggle"/><span class="sidenote"> You may recall that weve been adding extra “assumptions” on inputs for programming exercises in this course for the past few weeks already. What were learning here is how to formalize these assumptions into function docstrings.</span> We encountered this issue in <a href="03-filtering-collections.html">3.3 Filtering Collections</a>, when we wanted to restrict a statement to apply to a subset of our domain. Here were doing the same thing: making the set of valid function inputs more specific, because we only want to guarantee our implementation works correctly on those inputs. We add a precondition to the function docstring as follows:</p>
<div class="sourceCode" id="cb7-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-dc39e728e3"><a href="#cb7-1-dc39e728e3"></a><span class="kw">def</span> max_length(strings: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb7-2-dc39e728e3"><a href="#cb7-2-dc39e728e3"></a> <span class="co">&quot;&quot;&quot;Return the maximum length of a string in the set of strings.</span></span>
<span id="cb7-3-dc39e728e3"><a href="#cb7-3-dc39e728e3"></a></span>
<span id="cb7-4-dc39e728e3"><a href="#cb7-4-dc39e728e3"></a><span class="co"> Preconditions:</span></span>
<span id="cb7-5-dc39e728e3"><a href="#cb7-5-dc39e728e3"></a><span class="co"> - len(strings) &gt; 0</span></span>
<span id="cb7-6-dc39e728e3"><a href="#cb7-6-dc39e728e3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-7-dc39e728e3"><a href="#cb7-7-dc39e728e3"></a> <span class="cf">return</span> <span class="bu">max</span>({<span class="bu">len</span>(s) <span class="cf">for</span> s <span class="kw">in</span> strings})</span></code></pre></div>
<p>Whenever possible, well express these general preconditions as valid Python expressions involving the functions parameters.<label for="sn-4-dc39e728e3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-dc39e728e3" class="margin-toggle"/><span class="sidenote"> Sometimes well encounter a precondition that is extremely complex, in which case you can write them in English.</span> In English, we would say that the full specification of <code>max_length</code>s valid inputs is “<code>strings</code> is a <code>set</code>, and <code>len(strings) &gt; 0</code>”. As functions get more complex, we can add additional preconditions by listing them under the header <code>Preconditions:</code> in the docstring. <strong>A function input is valid when it satisfies the type annotations and <em>all</em> general precondition expressions</strong>.</p>
<p>Note that adding the precondition to the docstring does not change the behaviour of the function. If an empty set is passed into the function by the user, the function will still produce the <code>ValueError</code> we saw above. However, now that the precondition has been documented in the function specification, if we call <code>max_length(empty_set)</code>, we know that the error is entirely our fault because we violated a precondition.</p>
<h3 id="checking-preconditions-automatically-with-python_ta-dc39e728e3">Checking preconditions automatically with python_ta</h3>
<p>While our previous example illustrates how to document preconditions as part of a function specification, it has one drawback: it relies on whoever is calling the function to read the documentation! Of course, reading documentation is an important skill for any computer scientist, but despite our best intentions we sometimes miss things. It would be nice if we could turn our preconditions into executable Python code so that the Python interpreter checks them every time we call the function.</p>
<p>One way to do this is to use an <code>assert</code> statement, just like we do in unit tests. Because weve written the precondition as a Python expression, we can convert this to an assertion by copy-and-pasting it at the top of the function body.</p>
<div class="sourceCode" id="cb8-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-dc39e728e3"><a href="#cb8-1-dc39e728e3"></a><span class="kw">def</span> max_length(strings: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb8-2-dc39e728e3"><a href="#cb8-2-dc39e728e3"></a> <span class="co">&quot;&quot;&quot;Return the maximum length of a string in the set of strings.</span></span>
<span id="cb8-3-dc39e728e3"><a href="#cb8-3-dc39e728e3"></a></span>
<span id="cb8-4-dc39e728e3"><a href="#cb8-4-dc39e728e3"></a><span class="co"> Preconditions:</span></span>
<span id="cb8-5-dc39e728e3"><a href="#cb8-5-dc39e728e3"></a><span class="co"> - len(strings) &gt; 0</span></span>
<span id="cb8-6-dc39e728e3"><a href="#cb8-6-dc39e728e3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb8-7-dc39e728e3"><a href="#cb8-7-dc39e728e3"></a> <span class="cf">assert</span> <span class="bu">len</span>(strings) <span class="op">&gt;</span> <span class="dv">0</span>, <span class="st">&#39;Precondition violated: max_length called on an empty set.&#39;</span></span>
<span id="cb8-8-dc39e728e3"><a href="#cb8-8-dc39e728e3"></a> <span class="cf">return</span> <span class="bu">max</span>({<span class="bu">len</span>(s) <span class="cf">for</span> s <span class="kw">in</span> strings})</span></code></pre></div>
<p>Now, the precondition is checked every time the function is called, with a meaningful error message when the precondition is violated:</p>
<div class="sourceCode" id="cb9-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-dc39e728e3"><a href="#cb9-1-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> empty_set <span class="op">=</span> <span class="bu">set</span>()</span>
<span id="cb9-2-dc39e728e3"><a href="#cb9-2-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> max_length(empty_set)</span>
<span id="cb9-3-dc39e728e3"><a href="#cb9-3-dc39e728e3"></a>Traceback (most recent call last):</span>
<span id="cb9-4-dc39e728e3"><a href="#cb9-4-dc39e728e3"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb9-5-dc39e728e3"><a href="#cb9-5-dc39e728e3"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">7</span>, <span class="kw">in</span> max_length</span>
<span id="cb9-6-dc39e728e3"><a href="#cb9-6-dc39e728e3"></a><span class="pp">AssertionError</span>: Precondition violated: max_length called on an empty <span class="bu">set</span>.</span></code></pre></div>
<p>However, this approach is annoying and error-prone. First, we have to duplicate the precondition in two places. And second, we have increased the size of the function body with extra code. The <code>python_ta</code> library we use in this course has a way to automatically check preconditions for all functions in a given file. Here is an example:</p>
<div class="sourceCode" id="cb10-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-dc39e728e3"><a href="#cb10-1-dc39e728e3"></a><span class="kw">def</span> max_length(strings: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb10-2-dc39e728e3"><a href="#cb10-2-dc39e728e3"></a> <span class="co">&quot;&quot;&quot;Return the maximum length of a string in the set of strings.</span></span>
<span id="cb10-3-dc39e728e3"><a href="#cb10-3-dc39e728e3"></a></span>
<span id="cb10-4-dc39e728e3"><a href="#cb10-4-dc39e728e3"></a><span class="co"> Preconditions:</span></span>
<span id="cb10-5-dc39e728e3"><a href="#cb10-5-dc39e728e3"></a><span class="co"> - len(strings) &gt; 0</span></span>
<span id="cb10-6-dc39e728e3"><a href="#cb10-6-dc39e728e3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb10-7-dc39e728e3"><a href="#cb10-7-dc39e728e3"></a> <span class="cf">return</span> <span class="bu">max</span>({<span class="bu">len</span>(s) <span class="cf">for</span> s <span class="kw">in</span> strings})</span>
<span id="cb10-8-dc39e728e3"><a href="#cb10-8-dc39e728e3"></a></span>
<span id="cb10-9-dc39e728e3"><a href="#cb10-9-dc39e728e3"></a></span>
<span id="cb10-10-dc39e728e3"><a href="#cb10-10-dc39e728e3"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb10-11-dc39e728e3"><a href="#cb10-11-dc39e728e3"></a> <span class="im">import</span> python_ta.contracts</span>
<span id="cb10-12-dc39e728e3"><a href="#cb10-12-dc39e728e3"></a> python_ta.contracts.DEBUG_CONTRACTS <span class="op">=</span> <span class="va">False</span> <span class="co"># Disable contract debug messages</span></span>
<span id="cb10-13-dc39e728e3"><a href="#cb10-13-dc39e728e3"></a> python_ta.contracts.check_all_contracts()</span>
<span id="cb10-14-dc39e728e3"><a href="#cb10-14-dc39e728e3"></a></span>
<span id="cb10-15-dc39e728e3"><a href="#cb10-15-dc39e728e3"></a> max_length(<span class="bu">set</span>())</span></code></pre></div>
<p>Notice that weve kept the function docstring the same, but removed the assertion. The function we call, <code>python_ta.contracts.check_all_contracts</code>, modifies our <code>max_length</code> function. That is, <code>python_ta</code> takes the functions type contract and the preconditions it finds in the function docstring, and causes the function to check these preconditions every time the function is called! Lets see what happens when we run this file:</p>
<div class="sourceCode" id="cb11-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-dc39e728e3"><a href="#cb11-1-dc39e728e3"></a>Traceback (most recent call last):</span>
<span id="cb11-2-dc39e728e3"><a href="#cb11-2-dc39e728e3"></a>...</span>
<span id="cb11-3-dc39e728e3"><a href="#cb11-3-dc39e728e3"></a><span class="pp">AssertionError</span>: max_length precondition <span class="st">&quot;len(strings) &gt; 0&quot;</span> violated <span class="cf">for</span> arguments {<span class="st">&#39;strings&#39;</span>: <span class="bu">set</span>()}.</span></code></pre></div>
<p>Pretty cool! Well be using <code>check_all_contracts</code> for the rest of this course to help us make sure were sticking to the specifications weve written in our function header and docstrings when we call our functions. Moreover, <code>check_all_contracts</code> checks the return type of each function, so itll also work as a check when were implementing our functions to make sure the return value is of the correct type.</p>
<h2 id="preconditions-as-assumptions-and-restrictions-dc39e728e3">Preconditions as assumptions and restrictions</h2>
<p>Preconditions allow the implementer of a function to specify assumptions about the functions inputs, and so simplify the work of the implementer. On the other hand, preconditions place restrictions on the user of the function; the onus is on them to respect these preconditions every time the function is called. This often increases the complexity of the code that calls the function. For example, in our <code>max_length</code> function, the calling code might need an if statement to first check whether a set is empty before passing it to <code>max_length</code>.</p>
<p>When confronted with an “invalid input”, there is another strategy other than simply ruling out the invalid input with a precondition: explicitly defining some alternate function behaviour for this input. Here is another way we could define <code>max_length</code>:</p>
<div class="sourceCode" id="cb12-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-dc39e728e3"><a href="#cb12-1-dc39e728e3"></a><span class="kw">def</span> max_length(strings: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb12-2-dc39e728e3"><a href="#cb12-2-dc39e728e3"></a> <span class="co">&quot;&quot;&quot;Return the maximum length of a string in the set of strings.</span></span>
<span id="cb12-3-dc39e728e3"><a href="#cb12-3-dc39e728e3"></a></span>
<span id="cb12-4-dc39e728e3"><a href="#cb12-4-dc39e728e3"></a><span class="co"> Return 0 if strings is empty.</span></span>
<span id="cb12-5-dc39e728e3"><a href="#cb12-5-dc39e728e3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb12-6-dc39e728e3"><a href="#cb12-6-dc39e728e3"></a> <span class="cf">if</span> strings <span class="op">==</span> <span class="bu">set</span>():</span>
<span id="cb12-7-dc39e728e3"><a href="#cb12-7-dc39e728e3"></a> <span class="cf">return</span> <span class="dv">0</span></span>
<span id="cb12-8-dc39e728e3"><a href="#cb12-8-dc39e728e3"></a> <span class="cf">else</span>:</span>
<span id="cb12-9-dc39e728e3"><a href="#cb12-9-dc39e728e3"></a> <span class="cf">return</span> <span class="bu">max</span>({<span class="bu">len</span>(s) <span class="cf">for</span> s <span class="kw">in</span> strings})</span></code></pre></div>
<p>Here, we picked a reasonable default value for <code>max_length</code> when given an empty set,<label for="sn-5-dc39e728e3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-dc39e728e3" class="margin-toggle"/><span class="sidenote"> This is very similar to how we define empty sums and products by a mathematical convention.</span> and then handled that as an explicit case in our implementation by using an if statement. Our function implementation is more complex than before, but now another person can call our function on an empty set without producing an error:</p>
<div class="sourceCode" id="cb13-dc39e728e3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-dc39e728e3"><a href="#cb13-1-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> empty_set <span class="op">=</span> <span class="bu">set</span>()</span>
<span id="cb13-2-dc39e728e3"><a href="#cb13-2-dc39e728e3"></a><span class="op">&gt;&gt;&gt;</span> max_length(empty_set)</span>
<span id="cb13-3-dc39e728e3"><a href="#cb13-3-dc39e728e3"></a><span class="dv">0</span></span></code></pre></div>
<p>Youre probably wondering: is this version of <code>max_length</code> better or worse than our original one with the precondition? This version resulted in a longer description and function body, but it also removed a possible error we might encounter when calling the function. On the other hand, is 0 really a “reasonable” value for the behaviour of this function? Because this is ultimately a design decision, there is no clear “right answer”—there are always trade-offs to be made. Rather than sticking with a particular rule (i.e., “always/never use preconditions”), its better to use broader principles to evaluate different choices. How much complexity is added by handling an additional input in a function implementation? Are there “reasonable” behaviours defined for a larger set of inputs than what you originally intended? The trade-offs are rarely clear cut.</p>
<h2 id="thats-not-all-dc39e728e3">Thats not all!</h2>
<p>It turns out that with either of the “precondition” or “reasonable default” strategies, our specification of <code>max_length</code> is still incomplete. Before moving onto the next section, take a moment to study these implementations and try to guess what the gap might be!</p>
</section>
<!--
## The assert statement
TODO The outline currently introduces assertions, but this is done already in the Testing Functions I reading.
An `assert` statement looks very similar to an if statement.
But instead of branching into a specific path of the program, an `assert` statement instead raises an `AssertionError`.
Typically, these errors will terminate the program.
The syntax for an `assert` statement is:
```python
assert <expression>[, <message>]
```
The `assert` keyword must always be followed by a boolean expression.
When the expression evaluates to `False`, an `AssertionError` is raised.
We also have the option to include a message (i.e., a string) after the expression, separating the expression and the message with a comma.
The message is used to give the user additional information caused by a failure.
We can try this right inside the console:
```python
>>> assert 0 == 0
>>> assert 0 == 1
Traceback (most recent call last):
File "<input>", line 1, in <module>
AssertionError
>>> assert 0 == 1, 'Oops!'
Traceback (most recent call last):
File "<input>", line 1, in <module>
AssertionError: Oops!
```
Notice how when the expression evaluated to `True` (i.e., `0 == 0`), no error was raised and *nothing* was output on the console.
This is the main advantage of assertions: the only time an assertion will cause an issue is when the assertion fails.
Failed assertions also give us some information on where the failure occured.
Because our current example is done directly in the console, this information is not very useful.
But when our code is spread across multiple files with hundreds of lines of Python, this information becomes invaluable for tracking down issues.
-->
<!-- ## References
- [Appendix B.3 `python-ta`] -->
<br/> <a id="anchor-03-08"></a>
<header id="title-block-header-d996fdc65b">
<h1 class="title">3.8 Richer Type Annotations</h1>
</header>
<section>
<p>Recall our definition of <code>max_length</code> from the previous section:</p>
<div class="sourceCode" id="cb1-d996fdc65b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-d996fdc65b"><a href="#cb1-1-d996fdc65b"></a><span class="kw">def</span> max_length(strings: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb1-2-d996fdc65b"><a href="#cb1-2-d996fdc65b"></a> <span class="co">&quot;&quot;&quot;Return the maximum length of a string in the set of strings.</span></span>
<span id="cb1-3-d996fdc65b"><a href="#cb1-3-d996fdc65b"></a></span>
<span id="cb1-4-d996fdc65b"><a href="#cb1-4-d996fdc65b"></a><span class="co"> Preconditions:</span></span>
<span id="cb1-5-d996fdc65b"><a href="#cb1-5-d996fdc65b"></a><span class="co"> - len(strings) &gt; 0</span></span>
<span id="cb1-6-d996fdc65b"><a href="#cb1-6-d996fdc65b"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-7-d996fdc65b"><a href="#cb1-7-d996fdc65b"></a> <span class="cf">return</span> <span class="bu">max</span>({<span class="bu">len</span>(s) <span class="cf">for</span> s <span class="kw">in</span> strings})</span></code></pre></div>
<p>Let us introduce another issue:</p>
<div class="sourceCode" id="cb2-d996fdc65b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-d996fdc65b"><a href="#cb2-1-d996fdc65b"></a><span class="op">&gt;&gt;&gt;</span> max_length({<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>})</span>
<span id="cb2-2-d996fdc65b"><a href="#cb2-2-d996fdc65b"></a>Traceback (most recent call last):</span>
<span id="cb2-3-d996fdc65b"><a href="#cb2-3-d996fdc65b"></a> File <span class="st">&quot;&lt;stdin&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb2-4-d996fdc65b"><a href="#cb2-4-d996fdc65b"></a> File <span class="st">&quot;&lt;stdin&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>setcomp<span class="op">&gt;</span></span>
<span id="cb2-5-d996fdc65b"><a href="#cb2-5-d996fdc65b"></a><span class="pp">TypeError</span>: <span class="bu">object</span> of <span class="bu">type</span> <span class="st">&#39;int&#39;</span> has no <span class="bu">len</span>()</span></code></pre></div>
<p>Once again, our specification of valid inputs has failed us. The parameter type for <code>max_length</code> is <code>set</code>, and in Python <code>set</code>s can contain the values of many different types. It is not until the function description that we see that the parameter is not just <em>any</em> set, but specifically a set of strings. We could make this requirement more explicit by introducing another precondition, but there is a better approach. In this section, well learn how to use Pythons <code>typing</code> module to increase the specificity of our type annotations.</p>
<h2 id="the-types-in-a-collection-d996fdc65b">The types in a collection</h2>
<p>There are four collection types that have seen so far: <code>set</code>, <code>list</code>, <code>tuple</code>, and <code>dict</code>. These are analogous to the data types weve been using so far, with one key exception: we can specify the types of the values they can contained by writing them in square brackets. The table below shows these types and some examples; note that <code>T</code>, <code>T1</code>, etc. are variables that could be replaced with any data type.</p>
<div class="fullwidth" style="font-size: 0.9em;">
<table>
<colgroup>
<col style="width: 24%" />
<col style="width: 75%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>set[T]</code></td>
<td>A set whose elements all have type <code>T</code></td>
</tr>
<tr class="even">
<td><code>list[T]</code></td>
<td>A list whose elements all have type <code>T</code></td>
</tr>
<tr class="odd">
<td><code>tuple[T1, T2, ...]</code></td>
<td>A tuple whose first element has type <code>T1</code>, second element has type <code>T2</code>, etc.</td>
</tr>
<tr class="even">
<td><code>dict[T1, T2]</code></td>
<td>A dictionary whose keys are of type <code>T1</code> and whose values are of type <code>T2</code></td>
</tr>
</tbody>
</table>
</div>
<p>For example:</p>
<ul>
<li><code>{'hi', 'bye'}</code> has type <code>set[str]</code></li>
<li><code>[1, 2, 3]</code> has type <code>list[int]</code></li>
<li><code>('hello', True, 3.4)</code> has type <code>tuple[str, bool, float]</code></li>
<li><code>{'a': 1, 'b': 2, 'c': 3}</code> has type <code>dict[str, int]</code></li>
</ul>
<p>Here is how we can improve the type contract for <code>max_length</code>:</p>
<div class="sourceCode" id="cb3-d996fdc65b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-d996fdc65b"><a href="#cb3-1-d996fdc65b"></a><span class="kw">def</span> max_length(strings: <span class="bu">set</span>[<span class="bu">str</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-d996fdc65b"><a href="#cb3-2-d996fdc65b"></a> <span class="co">&quot;&quot;&quot;Return the maximum length of a string in the set of strings.</span></span>
<span id="cb3-3-d996fdc65b"><a href="#cb3-3-d996fdc65b"></a></span>
<span id="cb3-4-d996fdc65b"><a href="#cb3-4-d996fdc65b"></a><span class="co"> Preconditions:</span></span>
<span id="cb3-5-d996fdc65b"><a href="#cb3-5-d996fdc65b"></a><span class="co"> - len(strings) &gt; 0</span></span>
<span id="cb3-6-d996fdc65b"><a href="#cb3-6-d996fdc65b"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-7-d996fdc65b"><a href="#cb3-7-d996fdc65b"></a> <span class="cf">return</span> <span class="bu">max</span>({<span class="bu">len</span>(s) <span class="cf">for</span> s <span class="kw">in</span> strings})</span></code></pre></div>
<h3 id="general-collections-d996fdc65b">General collections</h3>
<p>Though indicating the type of the values inside a collection is useful, it is not always necessary. Sometimes we <em>want</em> to be flexible and say that a value must be a list, but we dont care whats in the list (could be a list of strings, a list of integers, or a list of strings mixed with integers). Or, we might want a list (or other collection) with elements of different types. In such cases, we will continue using the built-in types <code>set</code>, <code>list</code>, <code>tuple</code>, and <code>dict</code>, for these types annotations <em>without</em> additional information.</p>
<h2 id="applying-what-weve-learned-d996fdc65b">Applying what weve learned</h2>
<p>Let us revisit a function we designed when discussing if statements:</p>
<div class="sourceCode" id="cb4-d996fdc65b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-d996fdc65b"><a href="#cb4-1-d996fdc65b"></a><span class="kw">def</span> get_status_v3(scheduled: <span class="bu">int</span>, estimated: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb4-2-d996fdc65b"><a href="#cb4-2-d996fdc65b"></a> <span class="co">&quot;&quot;&quot;Return the flight status for the given scheduled and estimated departure times.</span></span>
<span id="cb4-3-d996fdc65b"><a href="#cb4-3-d996fdc65b"></a></span>
<span id="cb4-4-d996fdc65b"><a href="#cb4-4-d996fdc65b"></a><span class="co"> The times are given as integers between 0 and 23 inclusive, representing</span></span>
<span id="cb4-5-d996fdc65b"><a href="#cb4-5-d996fdc65b"></a><span class="co"> the hour of the day.</span></span>
<span id="cb4-6-d996fdc65b"><a href="#cb4-6-d996fdc65b"></a></span>
<span id="cb4-7-d996fdc65b"><a href="#cb4-7-d996fdc65b"></a><span class="co"> The status is &#39;On time&#39;, &#39;Delayed&#39;, or &#39;Cancelled&#39;.</span></span>
<span id="cb4-8-d996fdc65b"><a href="#cb4-8-d996fdc65b"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>How can we improve the specification of this function? Looking at the type annotations we see that, since none are collection types, we cannot make them any more specific than they already are. Next, looking at the docstring we see that there is the potential for some preconditions:<label for="sn-0-d996fdc65b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-d996fdc65b" class="margin-toggle"/><span class="sidenote"> We kept the English description of what the times represent, but moved the Python-checkable part into formal preconditions.</span></p>
<div class="sourceCode" id="cb5-d996fdc65b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-d996fdc65b"><a href="#cb5-1-d996fdc65b"></a><span class="kw">def</span> get_status_v3(scheduled: <span class="bu">int</span>, estimated: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb5-2-d996fdc65b"><a href="#cb5-2-d996fdc65b"></a> <span class="co">&quot;&quot;&quot;Return the flight status for the given scheduled and estimated departure times.</span></span>
<span id="cb5-3-d996fdc65b"><a href="#cb5-3-d996fdc65b"></a></span>
<span id="cb5-4-d996fdc65b"><a href="#cb5-4-d996fdc65b"></a><span class="co"> The times given represent the hour of the day.</span></span>
<span id="cb5-5-d996fdc65b"><a href="#cb5-5-d996fdc65b"></a></span>
<span id="cb5-6-d996fdc65b"><a href="#cb5-6-d996fdc65b"></a><span class="co"> Preconditions:</span></span>
<span id="cb5-7-d996fdc65b"><a href="#cb5-7-d996fdc65b"></a><span class="co"> - 0 &lt;= scheduled &lt;= 23</span></span>
<span id="cb5-8-d996fdc65b"><a href="#cb5-8-d996fdc65b"></a><span class="co"> - 0 &lt;= estimated &lt;= 23</span></span>
<span id="cb5-9-d996fdc65b"><a href="#cb5-9-d996fdc65b"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>Next let us revisit the <code>count_cancelled</code> function we designed:</p>
<div class="sourceCode" id="cb6-d996fdc65b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-d996fdc65b"><a href="#cb6-1-d996fdc65b"></a><span class="kw">def</span> count_cancelled(flights: <span class="bu">dict</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb6-2-d996fdc65b"><a href="#cb6-2-d996fdc65b"></a> <span class="co">&quot;&quot;&quot;Return the number of cancelled flights for the given flight data.</span></span>
<span id="cb6-3-d996fdc65b"><a href="#cb6-3-d996fdc65b"></a></span>
<span id="cb6-4-d996fdc65b"><a href="#cb6-4-d996fdc65b"></a><span class="co"> flights is a dictionary where each key is a flight ID,</span></span>
<span id="cb6-5-d996fdc65b"><a href="#cb6-5-d996fdc65b"></a><span class="co"> and whose corresponding value is a list of two numbers, where the first is</span></span>
<span id="cb6-6-d996fdc65b"><a href="#cb6-6-d996fdc65b"></a><span class="co"> the scheduled departure time and the second is the estimated departure time.</span></span>
<span id="cb6-7-d996fdc65b"><a href="#cb6-7-d996fdc65b"></a></span>
<span id="cb6-8-d996fdc65b"><a href="#cb6-8-d996fdc65b"></a><span class="co"> &gt;&gt;&gt; count_cancelled({&#39;AC110&#39;: [10, 12], &#39;AC321&#39;: [12, 19], &#39;AC999&#39;: [1, 1]})</span></span>
<span id="cb6-9-d996fdc65b"><a href="#cb6-9-d996fdc65b"></a><span class="co"> 1</span></span>
<span id="cb6-10-d996fdc65b"><a href="#cb6-10-d996fdc65b"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb6-11-d996fdc65b"><a href="#cb6-11-d996fdc65b"></a> cancelled_flights <span class="op">=</span> {<span class="bu">id</span> <span class="cf">for</span> <span class="bu">id</span> <span class="kw">in</span> flights</span>
<span id="cb6-12-d996fdc65b"><a href="#cb6-12-d996fdc65b"></a> <span class="cf">if</span> get_status2(flights[<span class="bu">id</span>][<span class="dv">0</span>], flights[<span class="bu">id</span>][<span class="dv">1</span>]) <span class="op">==</span> <span class="st">&#39;Cancelled&#39;</span>}</span>
<span id="cb6-13-d996fdc65b"><a href="#cb6-13-d996fdc65b"></a> <span class="cf">return</span> <span class="bu">len</span>(cancelled_flights)</span></code></pre></div>
<p>Here we can improve the type annotations. The first parameter is not just a <code>dict</code>, but a <code>dict[str, list[int]]</code>—that is, its keys are strings (the flight IDs), and the corresponding value is a list of integers. Does this type annotation mean that now the documentation describing the dictionary is irrelevant? No: while the type annotation gives some insight on the structure of the data, it does not provide domain-specific context, like the fact that the <code>str</code> keys represent flight IDs, or that the list values represent scheduled and estimated arrival departure times.</p>
<p>There is one more precondition that we can formalize, though: the length of each list in our dictionary. <em>Every</em> list should have length two, which translates naturally into a use of Pythons <code>all</code> function:</p>
<div class="sourceCode" id="cb7-d996fdc65b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-d996fdc65b"><a href="#cb7-1-d996fdc65b"></a><span class="kw">def</span> count_cancelled(flights: <span class="bu">dict</span>[<span class="bu">str</span>, <span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb7-2-d996fdc65b"><a href="#cb7-2-d996fdc65b"></a> <span class="co">&quot;&quot;&quot;Return the number of cancelled flights for the given flight data.</span></span>
<span id="cb7-3-d996fdc65b"><a href="#cb7-3-d996fdc65b"></a></span>
<span id="cb7-4-d996fdc65b"><a href="#cb7-4-d996fdc65b"></a><span class="co"> flights is a dictionary where each key is a flight ID,</span></span>
<span id="cb7-5-d996fdc65b"><a href="#cb7-5-d996fdc65b"></a><span class="co"> and whose corresponding value is a list of two numbers, where the first is</span></span>
<span id="cb7-6-d996fdc65b"><a href="#cb7-6-d996fdc65b"></a><span class="co"> the scheduled departure time and the second is the estimated departure time.</span></span>
<span id="cb7-7-d996fdc65b"><a href="#cb7-7-d996fdc65b"></a></span>
<span id="cb7-8-d996fdc65b"><a href="#cb7-8-d996fdc65b"></a><span class="co"> Precondition:</span></span>
<span id="cb7-9-d996fdc65b"><a href="#cb7-9-d996fdc65b"></a><span class="co"> - all(len(flights[k]) == 2 for k in flights)</span></span>
<span id="cb7-10-d996fdc65b"><a href="#cb7-10-d996fdc65b"></a></span>
<span id="cb7-11-d996fdc65b"><a href="#cb7-11-d996fdc65b"></a><span class="co"> &gt;&gt;&gt; count_cancelled({&#39;AC110&#39;: [10, 12], &#39;AC321&#39;: [12, 19], &#39;AC999&#39;: [1, 1]})</span></span>
<span id="cb7-12-d996fdc65b"><a href="#cb7-12-d996fdc65b"></a><span class="co"> 1</span></span>
<span id="cb7-13-d996fdc65b"><a href="#cb7-13-d996fdc65b"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-14-d996fdc65b"><a href="#cb7-14-d996fdc65b"></a> cancelled_flights <span class="op">=</span> {<span class="bu">id</span> <span class="cf">for</span> <span class="bu">id</span> <span class="kw">in</span> flights</span>
<span id="cb7-15-d996fdc65b"><a href="#cb7-15-d996fdc65b"></a> <span class="cf">if</span> get_status2(flights[<span class="bu">id</span>][<span class="dv">0</span>], flights[<span class="bu">id</span>][<span class="dv">1</span>]) <span class="op">==</span> <span class="st">&#39;Cancelled&#39;</span>}</span>
<span id="cb7-16-d996fdc65b"><a href="#cb7-16-d996fdc65b"></a> <span class="cf">return</span> <span class="bu">len</span>(cancelled_flights)</span></code></pre></div>
<h2 id="references-d996fdc65b">References</h2>
<ul>
<li><a href="../B-python-libraries/04-typing.html">B.4 <code>typing</code></a></li>
</ul>
</section>
<br/> <a id="anchor-03-09"></a>
<header id="title-block-header-1fae3bbe26">
<h1 class="title">3.9 Working with Definitions</h1>
</header>
<section>
<p>Throughout this course, we will study various mathematical objects that play key roles in computer science. As these objects become more complex, so too will our statements about them, to the point where if we try to write out everything using just basic set and arithmetic operations, our formulas wont fit on a single line! To avoid this problem, we create <em>definitions</em>, which we can use to express a long idea using a single term.<label for="sn-0-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-1fae3bbe26" class="margin-toggle"/><span class="sidenote">This is analogous to using local variables or helper functions in programming to express <em>part</em> of an overall value or computation.</span></p>
<p>In this section, well look at one extended example of defining our own predicates mathematically and in Python, and using them in our statements. Let us take some familiar terminology and make it precise using the languages of predicate logic and Python.</p>
<div class="definition" data-terms="divisibility">
<p>Let <span class="math inline">\(n, d \in \Z\)</span>.<label for="sn-1-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-1fae3bbe26" class="margin-toggle"/><span class="sidenote">You may be used to defining divisibility for just the natural numbers, but it will be helpful to allow for negative numbers in our work.</span> We say that <strong><span class="math inline">\(d\)</span> divides <span class="math inline">\(n\)</span></strong>, or <strong><span class="math inline">\(n\)</span> is divisible by <span class="math inline">\(d\)</span></strong>, when there exists a <span class="math inline">\(k \in \Z\)</span> such that <span class="math inline">\(n = dk\)</span>. In this case, we use the notation <span class="math inline">\(d \DIV n\)</span> to represent “<span class="math inline">\(d\)</span> divides <span class="math inline">\(n\)</span>.”</p>
<p>Note that just like the equals sign <span class="math inline">\(=\)</span> is a binary predicate, so too is <span class="math inline">\(\DIV\)</span>. For example, the statement <span class="math inline">\(3 \DIV 6\)</span> is True, while the statement <span class="math inline">\(4 \DIV 10\)</span> is False.<label for="sn-2-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-1fae3bbe26" class="margin-toggle"/><span class="sidenote">Students often confuse the divisibility predicate with the horizontal fraction bar. The former is a <em>predicate</em> that returns a boolean; the latter is a function that returns a number. So <span class="math inline">\(4 \DIV 10\)</span> is <span class="math inline">\(False\)</span>, while <span class="math inline">\(\frac{10}{4}\)</span> is <span class="math inline">\(2.5\)</span>.</span></p>
<p>This definition also permits <span class="math inline">\(d = 0\)</span>, which may be a bit surprising! According to this definition, <span class="math inline">\(0 \mid 0\)</span>, and for any non-zero <span class="math inline">\(n \in \Z\)</span>, <span class="math inline">\(0 \nmid n\)</span>.<label for="sn-3-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-1fae3bbe26" class="margin-toggle"/><span class="sidenote">Exercise: why are these two statements true?</span> In other words, when <span class="math inline">\(d = 0\)</span>, <span class="math inline">\(d \mid n\)</span> <em>if and only if</em> <span class="math inline">\(n = 0\)</span>.</p>
</div>
<div class="example">
<p>Lets express the statement “For every integer <span class="math inline">\(x\)</span>, if <span class="math inline">\(x\)</span> divides 10, then it also divides 100” in two ways: with the divisibility predicate <span class="math inline">\(d \DIV n\)</span>, and without it.</p>
<ul>
<li><p><strong>With the predicate</strong>: this is a universal quantification over all possible integers, and contains a logical implication. So we can write <span class="math display">\[\forall x \in \Z,~ x \DIV 10 \IMP x \DIV 100.\]</span></p></li>
<li><p><strong>Without the predicate</strong>: the same structure is there, except we <em>unpack the definition</em> of divisibility, replacing every instance of <span class="math inline">\(d \DIV n\)</span> with <span class="math inline">\(\exists k \in \Z,~ n = dk\)</span>. <span class="math display">\[\forall x \in \Z,~ \big(\exists k \in \Z,~ 10 = kx\big) \IMP \big(\exists k \in \Z,~ 100 = kx\big).\]</span></p>
<p>Note that each subformula in the parentheses has its own <span class="math inline">\(k\)</span> variable, whose scope is limited by the parentheses.<label for="sn-4-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-1fae3bbe26" class="margin-toggle"/><span class="sidenote">That is, the <span class="math inline">\(k\)</span> in the hypothesis of the implication is different from the <span class="math inline">\(k\)</span> in the conclusion: they can take on different values, though they can also take on the same value.</span> However, even though this technically correct, its often confusing for beginners. So instead, well tweak the variable names to emphasize their distinctness: <span class="math display">\[\forall x \in \Z,~ \big(\exists k_1 \in \Z,~ 10 = k_1x\big) \IMP \big(\exists k_2 \in \Z,~ 100 = k_2x\big).\]</span></p></li>
</ul>
</div>
<p>As you can see, using this new predicate makes our formula quite a bit more concise! But the usefulness of our definitions doesnt stop here: we can, of course, use our terms and predicates in further definitions.</p>
<div class="definition" data-terms="prime">
<p>Let <span class="math inline">\(p \in \Z\)</span>. We say <span class="math inline">\(p\)</span> is <strong>prime</strong> when it is greater than <span class="math inline">\(1\)</span> and the only natural numbers that divide it are <span class="math inline">\(1\)</span> and itself.</p>
</div>
<div class="example">
<p>Lets define a predicate <span class="math inline">\(IsPrime(p)\)</span> to express the statement that “<span class="math inline">\(p\)</span> is a prime number,” with and without using the divisibility predicate.</p>
<p>The first part of the definition, “greater than <span class="math inline">\(1\)</span>,” is straightforward. The second part is a bit trickier, but a good insight is that we can enforce constraints on values through implication: <em>if a number <span class="math inline">\(d\)</span> divides <span class="math inline">\(p\)</span>, then <span class="math inline">\(d = 1\)</span> or <span class="math inline">\(d = p\)</span></em>. We can put these two ideas together to create a formula: <span class="math display">\[IsPrime(p): p &gt; 1 \AND \big( \forall d \in \N,~ d \DIV p \IMP d = 1 \OR d = p \big), \qquad \text{where $p \in \Z$}.\]</span></p>
<p>To express this idea without using divisibility predicate, we substitute in the definition of divisibility. The underline shows the changed part. <span class="math display">\[IsPrime(p): p &gt; 1 \AND \big( \forall d \in \N,~ \underline{\left(\exists k \in \Z,~ p = kd\right)} \IMP d = 1 \OR d = p \big), \quad \text{where $p \in \Z$}.\]</span></p>
</div>
<h2 id="expressing-definitions-in-programs-1fae3bbe26">Expressing definitions in programs</h2>
<p>As we just saw, in mathematics we can often express definitions as predicates, where an element of the domain (e.g., an integer) satisfies the predicate if it fits the definition. Because predicates are just functions, we can express these in programs as well. For example, lets consider the divisibility predicate <span class="math inline">\(\mid\)</span>, where <span class="math inline">\(d \mid n\)</span> means <span class="math inline">\(\exists k \in \Z,~ n = kd\)</span> (for <span class="math inline">\(d, n \in \Z\)</span>). Here is the start of a function design in Python:</p>
<div class="sourceCode" id="cb1-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-1fae3bbe26"><a href="#cb1-1-1fae3bbe26"></a><span class="kw">def</span> divides(d: <span class="bu">int</span>, n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-1fae3bbe26"><a href="#cb1-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether d divides n.&quot;&quot;&quot;</span></span></code></pre></div>
<p>While we can use the modulo operator <code>%</code> to implement this function (more on this later), well stick to remaining faithful to the mathematical definition as much as possible. Unfortunately, there is one challenge with translating the mathematical definition of divisibility precisely into a Python function. In mathematics we have no trouble at all representing an infinite set of numbers with the symbol <span class="math inline">\(\Z\)</span>; but in a computer program, we cannot represent infinite sets in the same way. Instead, well use a <em>property</em> of divisibility to restrict the set of numbers to quantify over: when <span class="math inline">\(n \neq 0\)</span>, every number that divides <span class="math inline">\(n\)</span> must lie in the range <span class="math inline">\(\{-|n|, -|n| + 1, \dots, |n| - 1, |n|\}\)</span>.<label for="sn-5-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-1fae3bbe26" class="margin-toggle"/><span class="sidenote"> Well actually <em>prove</em> this property later on!</span></p>
<p>But the next question is, how do we represent the set <span class="math inline">\(\{-|n|, -|n| + 1, \dots, |n| - 1, |n|\}\)</span> in Python, when the <span class="math inline">\(n\)</span> is given as a parameter? We can use the <code>range</code> data type:<label for="sn-6-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-1fae3bbe26" class="margin-toggle"/><span class="sidenote"> Remember the asymmetry here: the <code>start</code> argument is inclusive, but the <code>end</code> argument is exclusive.</span></p>
<div class="sourceCode" id="cb2-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-1fae3bbe26"><a href="#cb2-1-1fae3bbe26"></a>possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="op">-</span><span class="bu">abs</span>(n), <span class="bu">abs</span>(n) <span class="op">+</span> <span class="dv">1</span>)</span></code></pre></div>
<p>And then we can replace <span class="math inline">\(\Z\)</span> by this variable in the definition of divisibility to obtain <span class="math inline">\(\exists k \in possible\_divisors,~ n = kd\)</span>. We can now translate this directly into Python code using what we learned earlier this chapter:</p>
<div class="sourceCode" id="cb3-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-1fae3bbe26"><a href="#cb3-1-1fae3bbe26"></a><span class="kw">def</span> divides(d: <span class="bu">int</span>, n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb3-2-1fae3bbe26"><a href="#cb3-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether d divides n.&quot;&quot;&quot;</span></span>
<span id="cb3-3-1fae3bbe26"><a href="#cb3-3-1fae3bbe26"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="op">-</span> <span class="bu">abs</span>(n), <span class="bu">abs</span>(n) <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb3-4-1fae3bbe26"><a href="#cb3-4-1fae3bbe26"></a> <span class="cf">return</span> <span class="bu">any</span>({n <span class="op">==</span> k <span class="op">*</span> d <span class="cf">for</span> k <span class="kw">in</span> possible_divisors})</span></code></pre></div>
<!-- TODO: Could ask the students, does this definition work when n = 0? When d = 0? -->
<p>Now lets turn our attention to the definition of <span class="math inline">\(\mathit{IsPrime}\)</span>:</p>
<p><span class="math display">\[\mathit{IsPrime}(p): p &gt; 1 \AND \big( \forall d \in \N,~ d \DIV p \IMP d = 1 \OR d = p \big), \qquad \text{where $p \in \Z$}.\]</span></p>
<p>Heres a start for translating this definition into a Python function:</p>
<div class="sourceCode" id="cb4-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-1fae3bbe26"><a href="#cb4-1-1fae3bbe26"></a><span class="kw">def</span> is_prime(p: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb4-2-1fae3bbe26"><a href="#cb4-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether p is prime.&quot;&quot;&quot;</span></span></code></pre></div>
<p>Once again, we have a problem of an infinite set: <span class="math inline">\(\forall d \in \N\)</span>. We can use the same property of divisibility as above and note that the possible natural numbers that are divisors of <code>p</code> are in the set <span class="math inline">\(\{1, 2, \dots, p\}\)</span>.<label for="sn-7-1fae3bbe26" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7-1fae3bbe26" class="margin-toggle"/><span class="sidenote"> This is simpler than the version above because <span class="math inline">\(p \geq 1\)</span>.</span> The quantified statement is a bit harder to translate because it contains an implication, so here we recall what we discussed in <a href="03-filtering-collections.html">3.3 Filtering Collections</a> to use the <code>if</code> keyword in a comprehension to model implications. Here is our complete implementation of <code>is_prime</code>:</p>
<div class="sourceCode" id="cb5-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-1fae3bbe26"><a href="#cb5-1-1fae3bbe26"></a><span class="kw">def</span> is_prime(p: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb5-2-1fae3bbe26"><a href="#cb5-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether p is prime.&quot;&quot;&quot;</span></span>
<span id="cb5-3-1fae3bbe26"><a href="#cb5-3-1fae3bbe26"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="dv">1</span>, p <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb5-4-1fae3bbe26"><a href="#cb5-4-1fae3bbe26"></a> <span class="cf">return</span> (</span>
<span id="cb5-5-1fae3bbe26"><a href="#cb5-5-1fae3bbe26"></a> p <span class="op">&gt;</span> <span class="dv">1</span> <span class="kw">and</span></span>
<span id="cb5-6-1fae3bbe26"><a href="#cb5-6-1fae3bbe26"></a> <span class="bu">all</span>({d <span class="op">==</span> <span class="dv">1</span> <span class="kw">or</span> d <span class="op">==</span> p <span class="cf">for</span> d <span class="kw">in</span> possible_divisors <span class="cf">if</span> divides(d, p)})</span>
<span id="cb5-7-1fae3bbe26"><a href="#cb5-7-1fae3bbe26"></a> )</span></code></pre></div>
<p>Notice that just like the mathematical definition, in Python our implementation of <code>is_prime</code> uses the <code>divides</code> function. This is a great example of how useful it can be to divide our work into functions that build on each other, rather than writing all of our code in a single function. As we learn about more complex domains in this course, well see this pattern repeat itself: definitions will build on top of one another, and you should expect that your functions will build on one another as well.</p>
<h2 id="divisibility-and-the-remainder-operation-1fae3bbe26">Divisibility and the remainder operation</h2>
<p>You might have noticed that our definition of <code>divides</code>, though faithful to the mathematical definition, is not the same as how weve previously determined whether a number is divisible by 2 (i.e., is even).</p>
<div class="sourceCode" id="cb6-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-1fae3bbe26"><a href="#cb6-1-1fae3bbe26"></a><span class="kw">def</span> is_even(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb6-2-1fae3bbe26"><a href="#cb6-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether n is even.&quot;&quot;&quot;</span></span>
<span id="cb6-3-1fae3bbe26"><a href="#cb6-3-1fae3bbe26"></a> <span class="cf">return</span> n <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
<p>In this case, we check whether <code>n</code> is divisible by 2 by checking whether the remainder when <code>n</code> is divided by 2 is 0 or not. It turns out that for <em>non-zero</em> <span class="math inline">\(d \in Z\)</span>, checking remainders is equivalent to the original definition of divisibility:</p>
<p><span class="math display">\[\forall n, d \in \Z,~ d \neq 0 \Rightarrow (d \mid n \Leftrightarrow n~\%~d = 0).\]</span></p>
<p>Note that when <span class="math inline">\(d = 0\)</span>, the remainder <span class="math inline">\(n~\%~d\)</span> is undefined, and so we really do need the <span class="math inline">\(d \neq 0\)</span> condition in the above statement.</p>
<p>We can use this observation to write an alternate implementation of the <code>divides</code> function:</p>
<div class="sourceCode" id="cb7-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-1fae3bbe26"><a href="#cb7-1-1fae3bbe26"></a><span class="kw">def</span> divides2(d: <span class="bu">int</span>, n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb7-2-1fae3bbe26"><a href="#cb7-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether d divides n.&quot;&quot;&quot;</span></span>
<span id="cb7-3-1fae3bbe26"><a href="#cb7-3-1fae3bbe26"></a> <span class="cf">if</span> d <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb7-4-1fae3bbe26"><a href="#cb7-4-1fae3bbe26"></a> <span class="co"># This is the original definition.</span></span>
<span id="cb7-5-1fae3bbe26"><a href="#cb7-5-1fae3bbe26"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="op">-</span><span class="bu">abs</span>(n), <span class="bu">abs</span>(n) <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb7-6-1fae3bbe26"><a href="#cb7-6-1fae3bbe26"></a> <span class="cf">return</span> <span class="bu">any</span>({n <span class="op">==</span> k <span class="op">*</span> d <span class="cf">for</span> k <span class="kw">in</span> possible_divisors})</span>
<span id="cb7-7-1fae3bbe26"><a href="#cb7-7-1fae3bbe26"></a> <span class="cf">else</span>:</span>
<span id="cb7-8-1fae3bbe26"><a href="#cb7-8-1fae3bbe26"></a> <span class="co"># This is a new but equivalent check.</span></span>
<span id="cb7-9-1fae3bbe26"><a href="#cb7-9-1fae3bbe26"></a> <span class="cf">return</span> n <span class="op">%</span> d <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
<p>You might also notice that the <code>d == 0</code> case is quite special: according to our definition of divisibility, when <code>d == 0</code> we know that <code>d</code> divides <code>n</code> if and only if <code>n == 0</code>:</p>
<p><span class="math display">\[\forall n, d \in \Z,~ d = 0 \Rightarrow (d \mid n \Leftrightarrow n = 0)\]</span></p>
<p>We can use this to greatly simplify the if branch in our <code>divides2</code> function:</p>
<div class="sourceCode" id="cb8-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-1fae3bbe26"><a href="#cb8-1-1fae3bbe26"></a><span class="kw">def</span> divides3(d: <span class="bu">int</span>, n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb8-2-1fae3bbe26"><a href="#cb8-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether d divides n.&quot;&quot;&quot;</span></span>
<span id="cb8-3-1fae3bbe26"><a href="#cb8-3-1fae3bbe26"></a> <span class="cf">if</span> d <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb8-4-1fae3bbe26"><a href="#cb8-4-1fae3bbe26"></a> <span class="co"># This is another new, equivalent check.</span></span>
<span id="cb8-5-1fae3bbe26"><a href="#cb8-5-1fae3bbe26"></a> <span class="cf">return</span> n <span class="op">==</span> <span class="dv">0</span></span>
<span id="cb8-6-1fae3bbe26"><a href="#cb8-6-1fae3bbe26"></a> <span class="cf">else</span>:</span>
<span id="cb8-7-1fae3bbe26"><a href="#cb8-7-1fae3bbe26"></a> <span class="co"># This is a new but equivalent check.</span></span>
<span id="cb8-8-1fae3bbe26"><a href="#cb8-8-1fae3bbe26"></a> <span class="cf">return</span> n <span class="op">%</span> d <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
<p>Our implementation in <code>divides3</code> meets the same function specification as the original <code>divides</code>, but has a much simpler implementation! It is also much more <em>efficient</em> than the original <code>divides</code>, meaning it performs fewer calculations (or computational “steps”) and takes less time to compute its result. Intuitively, this is because the original <code>divides</code> function used the value <code>range(-abs(n), abs(n) + 1)</code> in a comprehension, and so the number of expressions evaluated gets larger as <code>n</code> grows. This is not the case for <code>divides3</code>, which does not use a single <code>range</code> or comprehension in its body!</p>
<p>What this also means is that we can speed up our implementation of <code>is_prime</code> simply by calling <code>divides3</code> instead of <code>divides</code>:</p>
<div class="sourceCode" id="cb9-1fae3bbe26"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-1fae3bbe26"><a href="#cb9-1-1fae3bbe26"></a><span class="kw">def</span> is_prime(p: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb9-2-1fae3bbe26"><a href="#cb9-2-1fae3bbe26"></a> <span class="co">&quot;&quot;&quot;Return whether p is prime.&quot;&quot;&quot;</span></span>
<span id="cb9-3-1fae3bbe26"><a href="#cb9-3-1fae3bbe26"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="dv">1</span>, p <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb9-4-1fae3bbe26"><a href="#cb9-4-1fae3bbe26"></a> <span class="cf">return</span> (</span>
<span id="cb9-5-1fae3bbe26"><a href="#cb9-5-1fae3bbe26"></a> p <span class="op">&gt;</span> <span class="dv">1</span> <span class="kw">and</span></span>
<span id="cb9-6-1fae3bbe26"><a href="#cb9-6-1fae3bbe26"></a> <span class="bu">all</span>({d <span class="op">==</span> <span class="dv">1</span> <span class="kw">or</span> d <span class="op">==</span> p <span class="cf">for</span> d <span class="kw">in</span> possible_divisors <span class="cf">if</span> divides3(d, p)}) <span class="co"># &lt;-- Note the &quot;divides3&quot;</span></span>
<span id="cb9-7-1fae3bbe26"><a href="#cb9-7-1fae3bbe26"></a> )</span></code></pre></div>
<p>This is a very powerful idea: we started out with one implementation of the divisibility predicate (<code>divides</code>), and then through some mathematical reasoning wrote a second implementation (<code>divides3</code>) that was logically equivalent to the first, but simpler and faster. But because <code>divides</code> and <code>divides3</code> were logically equivalent, we could safe replace <code>divides</code> with <code>divides3</code> in the implementation of <code>is_prime</code> to make it run faster, without worrying about introducing new errors!</p>
<p>The idea of <em>swapping out implementations</em> will come up again and again in this course. As the functions and programs you write grows larger, efficiency will be an important consideration for your code, and so it will be common to start with one function implementation and eventually replace it with another. Were only touching on these idea here with a relatively simple example, but we will talk formally about program efficiency in a later chapter.</p>
<!-- ### A note about efficiency
The combination of our `is_prime` and `divides` code is actually extremely inefficient.
To understand why, let us use the example function call `is_prime(5)`.
How many `possible_divisors` will we have?
```python
>>> p = 5
>>> possible_divisors = range(1, p + 1)
>>> list(possible_divisors)
[1, 2, 3, 4, 5]
```
Now let's consider the set comprehension in `is_prime`.
The filtering condition, `if divides(d, p)`, will check every integer in `possible_divisors`.
This means that our `divides` function will be called five times (`len(possible_divisors)`).
But `divides` has its own set of `possible_divisors`, too!^[
Remember: `range(- abs(n), abs(n) + 1)`.
]
Let's track this with a table:
`is_prime` calls to `divides` `possible_divisors` in `divides`
----------------------------- --------------------------------
`divides(1, 5)` `range(-abs(5), abs(5) + 1)`
`divides(2, 5)` `range(-abs(5), abs(5) + 1)`
`divides(3, 5)` `range(-abs(5), abs(5) + 1)`
`divides(4, 5)` `range(-abs(5), abs(5) + 1)`
`divides(5, 5)` `range(-abs(5), abs(5) + 1)`
There are two take-aways from this table.
First, the number of rows in the table is equal to the integer (i.e., $p$) we pass to `is_prime` (here, we showed `5`, but imagine if we checked `143512`).
Second, the range of `possible_divisors` in `divides` is roughly twice the integer we past to `is_prime`.
Together, this means that Python is performing around $p \times 2 \times p$ calculations for any prime number we want to check.
As a comparison, how many calculations would you need to do without Python to see if $5$ is prime?
Is it less than $5 \times 2 \times 5 = 50$?
Efficiency is an important part of computer science that we will talk about formally in a later chapter. -->
</section>
<br/> <a id="anchor-03-10"></a>
<header id="title-block-header-dce9897ac4">
<h1 class="title">3.10 Testing Functions II: <code>hypothesis</code></h1>
</header>
<section>
<p>When we introduced if statements in <a href="04-if-statements.html">Section 3.4</a>, we discussed how unit tests could be used to perform <em>white box testing</em>, where the goal is to “cover” all possible execution paths with unit tests. Unit tests really excel in this scenario because we can determine what the inputs of a function should be to reach a particular branch.</p>
<p>But choosing unit test inputs also imposes challenges on the programmer writing those tests. How do we know we have “enough” inputs? What properties of the inputs should we consider? For example, if our function takes a <code>list[int]</code>, how long should our input lists be, should they contain duplicates, and what should the values inside the list be? For each choice of answers to these questions, we then need to choose a specific input and calculate the expected output to write a unit test.</p>
<p>In this section, we introduce a different form of testing called <em>property-based testing</em>, using the Python module <code>hypothesis</code>. The main advantage of property-based testing with <code>hypothesis</code> is that we can write one test case that calls the function being tested <em>multiple inputs</em> that the <code>hypothesis</code> library chooses for us automatically. Property-based tests are not intended to replace unit tests—both have their role in testing and both are important.</p>
<h2 id="property-based-testing-dce9897ac4">Property-based testing</h2>
<p>The kinds of tests weve discussed so far involve defining <em>input-output pairs</em>: for each test, we write a specific input to the function were testing, and then use <code>assert</code> statements to verify the correctness of the corresponding output. These tests have the advantage that writing any one individual test is usually straightforward, but the disadvantage that choosing and implementing test cases can be challenging and time-consuming.</p>
<p>There is another way of constructing tests that we will explore here: <em>property-based testing</em>, in which a single test typically consists of a large set of possible inputs that is generated in a programmatic way. Such tests have the advantage that it is usually straightforward to cover a broad range of inputs in a short amount of code; but it isnt always easy to specify exactly what the corresponding outputs should be. If we were to write code to compute the correct answer, how would we know that <em>that</em> code is correct?</p>
<p>So instead, property-based tests use <code>assert</code> statements to check for <em>properties</em> that the function being tested should satisfy. In the simplest case, these are properties that every output of the function should satisfy, regardless of what the input was. For example:</p>
<ul>
<li>The <em>type</em> of the output: “the function <code>str</code> should always return a string.”</li>
<li><em>Allowed values</em> of the output: “the function <code>len</code> should always return an integer that is greater than or equal to zero.”</li>
<li><em>Relationships</em> between the input and output: “the function <code>max(x, y)</code> should return something that is greater than or equal to both <code>x</code> and <code>y</code>.”</li>
<li><em>Relationships</em> between two (or more) input-output pairs: "for any two lists of numbers <code>nums1</code> and <code>nums2</code>, we know that <code>sum(nums1 + nums2) == sum(nums1) + sum(nums2)</code>.</li>
</ul>
<p>These properties may seem a little strange, because they do not capture precisely what each function does; for example, <code>str</code> should not just return any string, but a string that represents its input. This is the trade-off that comes with property-based testing: in exchange for being able to run our code on a much larger range of inputs, we write tests which are imprecise characterizations of the functions inputs. The challenge, then, with property-based testing is to come up with good properties that narrow down as much as possible the behaviour of the function being tested.</p>
<h2 id="using-hypothesis-dce9897ac4">Using <code>hypothesis</code></h2>
<p>As a first example, lets consider our familiar <code>is_even</code> function, which we define in a file called <code>my_functions.py</code>:<label for="sn-0-dce9897ac4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-dce9897ac4" class="margin-toggle"/><span class="sidenote">You can follow along in this section by creating your own files!</span></p>
<div class="sourceCode" id="cb1-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-dce9897ac4"><a href="#cb1-1-dce9897ac4"></a><span class="co"># Suppose we&#39;ve saved this in my_functions.py</span></span>
<span id="cb1-2-dce9897ac4"><a href="#cb1-2-dce9897ac4"></a></span>
<span id="cb1-3-dce9897ac4"><a href="#cb1-3-dce9897ac4"></a><span class="kw">def</span> is_even(value: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-4-dce9897ac4"><a href="#cb1-4-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Return whether value is divisible by 2.</span></span>
<span id="cb1-5-dce9897ac4"><a href="#cb1-5-dce9897ac4"></a></span>
<span id="cb1-6-dce9897ac4"><a href="#cb1-6-dce9897ac4"></a><span class="co"> &gt;&gt;&gt; is_even(2)</span></span>
<span id="cb1-7-dce9897ac4"><a href="#cb1-7-dce9897ac4"></a><span class="co"> True</span></span>
<span id="cb1-8-dce9897ac4"><a href="#cb1-8-dce9897ac4"></a><span class="co"> &gt;&gt;&gt; is_even(17)</span></span>
<span id="cb1-9-dce9897ac4"><a href="#cb1-9-dce9897ac4"></a><span class="co"> False</span></span>
<span id="cb1-10-dce9897ac4"><a href="#cb1-10-dce9897ac4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-11-dce9897ac4"><a href="#cb1-11-dce9897ac4"></a> <span class="cf">return</span> value <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
<p>Rather than choosing specific inputs to test <code>is_even</code> on, were going to test the following two <em>properties</em>:</p>
<ul>
<li><code>is_even</code> always returns <code>True</code> when given an <code>int</code> of the form <code>2 * x</code> (where <code>x</code> is an <code>int</code>)</li>
<li><code>is_even</code> always returns <code>False</code> when given an <code>int</code> of the form <code>2 * x + 1</code> (where <code>x</code> is an <code>int</code>)</li>
</ul>
<p>One of the benefits of our previous study of predicate logic is that we can express both of these properties clearly and unambiguously using symbolic notation:</p>
<p><span class="math display">\[\begin{align*}
\forall x \in \Z,~ \text{is_even}(2x) \\
\forall x \in \Z,~ \lnot \text{is_even}(2x + 1)
\end{align*}\]</span></p>
<p>Now lets see how to express these properties as test cases using <code>hypothesis</code>. First, we create a new file called <code>test_my_functions.py</code>, and include the following “test” function:<label for="sn-1-dce9897ac4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-dce9897ac4" class="margin-toggle"/><span class="sidenote"> Make sure that <code>my_functions.py</code> and <code>test_my_functions.py</code> are in the same directory.</span></p>
<div class="sourceCode" id="cb2-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-dce9897ac4"><a href="#cb2-1-dce9897ac4"></a><span class="co"># In file test_my_functions.py</span></span>
<span id="cb2-2-dce9897ac4"><a href="#cb2-2-dce9897ac4"></a><span class="im">from</span> my_functions <span class="im">import</span> is_even</span>
<span id="cb2-3-dce9897ac4"><a href="#cb2-3-dce9897ac4"></a></span>
<span id="cb2-4-dce9897ac4"><a href="#cb2-4-dce9897ac4"></a></span>
<span id="cb2-5-dce9897ac4"><a href="#cb2-5-dce9897ac4"></a><span class="kw">def</span> test_is_even_2x(x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-6-dce9897ac4"><a href="#cb2-6-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test that is_even returns True when given a number of the form 2*x.&quot;&quot;&quot;</span></span>
<span id="cb2-7-dce9897ac4"><a href="#cb2-7-dce9897ac4"></a> <span class="cf">assert</span> is_even(<span class="dv">2</span> <span class="op">*</span> x)</span></code></pre></div>
<p>Note that unlike previous tests weve written, we have not chosen a specific input value for <code>is_even</code>! Instead, our test function <code>test_is_even_2x</code> takes an an integer for <code>x</code>, and calls <code>is_even</code> on <code>2 * x</code>. This is a more general form of test because now <code>x</code> could be any integer.</p>
<p>So now the question is, how do we actually call <code>test_is_even_2x</code> on many different integer values?<label for="sn-2-dce9897ac4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-dce9897ac4" class="margin-toggle"/><span class="sidenote"> You could run this file in the Python console and call it manually on different arguments, but there must be a better way!</span> This is where <code>hypothesis</code> comes in. In order to generate a range of inputs, the <code>hypothesis</code> module offers a set of <em>strategies</em> that we can use. These strategies are able to generate several values of a specific type of input. For example, to generate <code>int</code> data types, we can use the <code>integers</code> strategy. To start, we add these two lines to the top of our test file:</p>
<div class="sourceCode" id="cb3-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-dce9897ac4"><a href="#cb3-1-dce9897ac4"></a><span class="co"># In file test_my_functions.py</span></span>
<span id="cb3-2-dce9897ac4"><a href="#cb3-2-dce9897ac4"></a><span class="im">from</span> hypothesis <span class="im">import</span> given <span class="co"># NEW</span></span>
<span id="cb3-3-dce9897ac4"><a href="#cb3-3-dce9897ac4"></a><span class="im">from</span> hypothesis.strategies <span class="im">import</span> integers <span class="co"># NEW</span></span>
<span id="cb3-4-dce9897ac4"><a href="#cb3-4-dce9897ac4"></a></span>
<span id="cb3-5-dce9897ac4"><a href="#cb3-5-dce9897ac4"></a><span class="im">from</span> my_functions <span class="im">import</span> is_even</span>
<span id="cb3-6-dce9897ac4"><a href="#cb3-6-dce9897ac4"></a></span>
<span id="cb3-7-dce9897ac4"><a href="#cb3-7-dce9897ac4"></a></span>
<span id="cb3-8-dce9897ac4"><a href="#cb3-8-dce9897ac4"></a><span class="kw">def</span> test_is_even_2x(x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-9-dce9897ac4"><a href="#cb3-9-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test that is_even returns True when given a number of the form 2*x.&quot;&quot;&quot;</span></span>
<span id="cb3-10-dce9897ac4"><a href="#cb3-10-dce9897ac4"></a> <span class="cf">assert</span> is_even(<span class="dv">2</span> <span class="op">*</span> x)</span></code></pre></div>
<p>Just importing <code>given</code> and <code>integers</code> isnt enough, of course. We need to somehow “attach” them to our test function so that <code>hypothesis</code> knows to generate integer inputs for the test. To do so, we use a new piece of Python syntax called a <strong>decorator</strong>, which is specified by using the <code>@</code> symbol with an expression in the line immediately before a function definition. Here is the use of a decorator in action:</p>
<div class="sourceCode" id="cb4-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-dce9897ac4"><a href="#cb4-1-dce9897ac4"></a><span class="co"># In file test_my_functions.py</span></span>
<span id="cb4-2-dce9897ac4"><a href="#cb4-2-dce9897ac4"></a><span class="im">from</span> hypothesis <span class="im">import</span> given</span>
<span id="cb4-3-dce9897ac4"><a href="#cb4-3-dce9897ac4"></a><span class="im">from</span> hypothesis.strategies <span class="im">import</span> integers</span>
<span id="cb4-4-dce9897ac4"><a href="#cb4-4-dce9897ac4"></a></span>
<span id="cb4-5-dce9897ac4"><a href="#cb4-5-dce9897ac4"></a><span class="im">from</span> my_functions <span class="im">import</span> is_even</span>
<span id="cb4-6-dce9897ac4"><a href="#cb4-6-dce9897ac4"></a></span>
<span id="cb4-7-dce9897ac4"><a href="#cb4-7-dce9897ac4"></a></span>
<span id="cb4-8-dce9897ac4"><a href="#cb4-8-dce9897ac4"></a><span class="at">@given</span>(x<span class="op">=</span>integers()) <span class="co"># NEW</span></span>
<span id="cb4-9-dce9897ac4"><a href="#cb4-9-dce9897ac4"></a><span class="kw">def</span> test_is_even_2x(x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb4-10-dce9897ac4"><a href="#cb4-10-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test that is_even returns True when given a number of the form 2*x.&quot;&quot;&quot;</span></span>
<span id="cb4-11-dce9897ac4"><a href="#cb4-11-dce9897ac4"></a> <span class="cf">assert</span> is_even(<span class="dv">2</span> <span class="op">*</span> x)</span></code></pre></div>
<p>The line <code>@given(x=integers())</code> is a bit tricky, so lets unpack it. First, <code>integers</code> is a <code>hypothesis</code> function that returns a special data type called a <strong>strategy</strong>, which is what <code>hypothesis</code> uses to generate a range of possible inputs. In this case, calling <code>integers()</code> returns a strategy that simply generates <code>int</code>s.</p>
<p>Second, <code>given</code> is a <code>hypothesis</code> function that takes in arguments in the form <code>&lt;param&gt;=&lt;strategy&gt;</code>, which acts as a mapping for the test parameter name to a strategy that <code>hypothesis</code> should use for generating arguments for that parameter.</p>
<p>We say that the line <code>@given(x=integers())</code> <em>decorates</em> the test function, so that when we run the test function, <code>hypothesis</code> will call the test several times, using <code>int</code> values for <code>x</code> as specified by the strategy <code>integers()</code>. Essentially, <code>@given</code> helps automate the process of “run the test on different <code>int</code> values” for us!</p>
<p>And finally, To actually run the test, we use <code>pytest</code>, just like before:</p>
<div class="sourceCode" id="cb5-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-dce9897ac4"><a href="#cb5-1-dce9897ac4"></a><span class="co"># In file test_my_functions.py</span></span>
<span id="cb5-2-dce9897ac4"><a href="#cb5-2-dce9897ac4"></a><span class="im">from</span> hypothesis <span class="im">import</span> given</span>
<span id="cb5-3-dce9897ac4"><a href="#cb5-3-dce9897ac4"></a><span class="im">from</span> hypothesis.strategies <span class="im">import</span> integers</span>
<span id="cb5-4-dce9897ac4"><a href="#cb5-4-dce9897ac4"></a></span>
<span id="cb5-5-dce9897ac4"><a href="#cb5-5-dce9897ac4"></a><span class="im">from</span> my_functions <span class="im">import</span> is_even</span>
<span id="cb5-6-dce9897ac4"><a href="#cb5-6-dce9897ac4"></a></span>
<span id="cb5-7-dce9897ac4"><a href="#cb5-7-dce9897ac4"></a></span>
<span id="cb5-8-dce9897ac4"><a href="#cb5-8-dce9897ac4"></a><span class="at">@given</span>(x<span class="op">=</span>integers())</span>
<span id="cb5-9-dce9897ac4"><a href="#cb5-9-dce9897ac4"></a><span class="kw">def</span> test_is_even_2x(x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb5-10-dce9897ac4"><a href="#cb5-10-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test that is_even returns True when given a number of the form 2*x.&quot;&quot;&quot;</span></span>
<span id="cb5-11-dce9897ac4"><a href="#cb5-11-dce9897ac4"></a> <span class="cf">assert</span> is_even(<span class="dv">2</span> <span class="op">*</span> x)</span>
<span id="cb5-12-dce9897ac4"><a href="#cb5-12-dce9897ac4"></a></span>
<span id="cb5-13-dce9897ac4"><a href="#cb5-13-dce9897ac4"></a></span>
<span id="cb5-14-dce9897ac4"><a href="#cb5-14-dce9897ac4"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb5-15-dce9897ac4"><a href="#cb5-15-dce9897ac4"></a> <span class="im">import</span> pytest</span>
<span id="cb5-16-dce9897ac4"><a href="#cb5-16-dce9897ac4"></a> pytest.main([<span class="st">&#39;test_my_functions.py&#39;</span>, <span class="st">&#39;-v&#39;</span>])</span></code></pre></div>
<h3 id="testing-odd-values-dce9897ac4">Testing odd values</h3>
<p>Just like with unit tests, we can write multiple property-based tests in the same file and have <code>pytest</code> run each of them. Here is our final version of <code>test_my_functions.py</code> for this example, which adds a second test for numbers of the form <span class="math inline">\(2x + 1\)</span>.</p>
<div class="sourceCode" id="cb6-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-dce9897ac4"><a href="#cb6-1-dce9897ac4"></a><span class="co"># In file test_my_functions.py</span></span>
<span id="cb6-2-dce9897ac4"><a href="#cb6-2-dce9897ac4"></a><span class="im">from</span> hypothesis <span class="im">import</span> given</span>
<span id="cb6-3-dce9897ac4"><a href="#cb6-3-dce9897ac4"></a><span class="im">from</span> hypothesis.strategies <span class="im">import</span> integers</span>
<span id="cb6-4-dce9897ac4"><a href="#cb6-4-dce9897ac4"></a></span>
<span id="cb6-5-dce9897ac4"><a href="#cb6-5-dce9897ac4"></a><span class="im">from</span> my_functions <span class="im">import</span> is_even</span>
<span id="cb6-6-dce9897ac4"><a href="#cb6-6-dce9897ac4"></a></span>
<span id="cb6-7-dce9897ac4"><a href="#cb6-7-dce9897ac4"></a></span>
<span id="cb6-8-dce9897ac4"><a href="#cb6-8-dce9897ac4"></a><span class="at">@given</span>(x<span class="op">=</span>integers())</span>
<span id="cb6-9-dce9897ac4"><a href="#cb6-9-dce9897ac4"></a><span class="kw">def</span> test_is_even_2x(x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-10-dce9897ac4"><a href="#cb6-10-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test that is_even returns True when given a number of the form 2*x.&quot;&quot;&quot;</span></span>
<span id="cb6-11-dce9897ac4"><a href="#cb6-11-dce9897ac4"></a> <span class="cf">assert</span> is_even(<span class="dv">2</span> <span class="op">*</span> x)</span>
<span id="cb6-12-dce9897ac4"><a href="#cb6-12-dce9897ac4"></a></span>
<span id="cb6-13-dce9897ac4"><a href="#cb6-13-dce9897ac4"></a></span>
<span id="cb6-14-dce9897ac4"><a href="#cb6-14-dce9897ac4"></a><span class="at">@given</span>(x<span class="op">=</span>integers())</span>
<span id="cb6-15-dce9897ac4"><a href="#cb6-15-dce9897ac4"></a><span class="kw">def</span> test_is_even_2x_plus_1(x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-16-dce9897ac4"><a href="#cb6-16-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test that is_even returns False when given a number of the form 2*x + 1.&quot;&quot;&quot;</span></span>
<span id="cb6-17-dce9897ac4"><a href="#cb6-17-dce9897ac4"></a> <span class="cf">assert</span> <span class="kw">not</span> is_even(<span class="dv">2</span> <span class="op">*</span> x <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb6-18-dce9897ac4"><a href="#cb6-18-dce9897ac4"></a></span>
<span id="cb6-19-dce9897ac4"><a href="#cb6-19-dce9897ac4"></a></span>
<span id="cb6-20-dce9897ac4"><a href="#cb6-20-dce9897ac4"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb6-21-dce9897ac4"><a href="#cb6-21-dce9897ac4"></a> <span class="im">import</span> pytest</span>
<span id="cb6-22-dce9897ac4"><a href="#cb6-22-dce9897ac4"></a> pytest.main([<span class="st">&#39;test_my_functions.py&#39;</span>, <span class="st">&#39;-v&#39;</span>])</span></code></pre></div>
<!--
We would also expect `is_even` to evaluate to `False` whenever an odd number is passed as an argument.
But how can we turn the number generated by the `integers` strategy into an odd number?
We could use a similar mathematical trick (e.g., multiply by two and add one), but instead we will use this opportunity to introduce a new hypothesis feature: `hypothesis.assume`.
With `assume`, we can communicate to `hypothesis` that the value generated by a strategy should not be tested:
```python
# Note the change: we also import assume
from hypothesis import given, assume
from hypothesis.strategies import integers
from my_functions import is_even
@given(integers())
def test_is_even_on_odd_number(value: int):
assume(value % 2 == 1)
assert is_even(value) == False
```
If we did not include `assume(value % 2 == 1)`, then the `integers` strategy may produce an even number, causing our assertion to fail even for a correct implementation of `is_even`.
However, by including the `assume` statement, we ensure that `hypothesis` skips the assertion when `value` is even (in other words, we assume that `value` is odd). -->
<h2 id="using-hypothesis-with-collections-dce9897ac4">Using <code>hypothesis</code> with collections</h2>
<p>Now lets consider a more complicated example, this time involving lists of integers. Lets add the following function to <code>my_functions.py</code>:</p>
<div class="sourceCode" id="cb7-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-dce9897ac4"><a href="#cb7-1-dce9897ac4"></a><span class="co"># In my_functions.py</span></span>
<span id="cb7-2-dce9897ac4"><a href="#cb7-2-dce9897ac4"></a></span>
<span id="cb7-3-dce9897ac4"><a href="#cb7-3-dce9897ac4"></a></span>
<span id="cb7-4-dce9897ac4"><a href="#cb7-4-dce9897ac4"></a><span class="kw">def</span> num_evens(nums: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb7-5-dce9897ac4"><a href="#cb7-5-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Return the number of even elements in nums.&quot;&quot;&quot;</span></span>
<span id="cb7-6-dce9897ac4"><a href="#cb7-6-dce9897ac4"></a> <span class="cf">return</span> <span class="bu">len</span>([n <span class="cf">for</span> n <span class="kw">in</span> nums <span class="cf">if</span> is_even(n)])</span></code></pre></div>
<p>Lets look at one example of a property-based test for <code>num_evens</code>. For practice, well express this property in predicate logic first. Let <span class="math inline">\(\mathcal{L}_{int}\)</span> be the set of lists of integers. The property well express is:</p>
<p><span class="math display">\[
\forall \text{nums} \in \mathcal{L}_{\text{int}},~ \forall x \in \Z,~ \text{num_evens}(\text{nums} + [2x]) = \text{num_evens}(\text{nums}) + 1
\]</span></p>
<p>Translated into English: for any list of integers <span class="math inline">\(nums\)</span> and any integer <span class="math inline">\(x\)</span>, the number of even elements of <code>nums + [2 * x]</code> is one more than the number of even elements of <code>nums</code>.</p>
<p>We can start using the same idea as our <code>is_even</code> example, by writing the test function in <code>test_my_functions.py</code>.</p>
<div class="sourceCode" id="cb8-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-dce9897ac4"><a href="#cb8-1-dce9897ac4"></a><span class="co"># In test_my_functions.py</span></span>
<span id="cb8-2-dce9897ac4"><a href="#cb8-2-dce9897ac4"></a><span class="kw">def</span> test_num_evens_one_more_even(nums: <span class="bu">list</span>[<span class="bu">int</span>], x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb8-3-dce9897ac4"><a href="#cb8-3-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test num_evens when you add one more even element.&quot;&quot;&quot;</span></span>
<span id="cb8-4-dce9897ac4"><a href="#cb8-4-dce9897ac4"></a> <span class="cf">assert</span> num_evens(nums <span class="op">+</span> [<span class="dv">2</span> <span class="op">*</span> x]) <span class="op">==</span> num_evens(nums) <span class="op">+</span> <span class="dv">1</span></span></code></pre></div>
<p>Now we need to use <code>@given</code> again to tell <code>hypothesis</code> to generate inputs for this test function. Because this function takes two arguments, we know that well need a decorator expression of the form</p>
<div class="sourceCode" id="cb9-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-dce9897ac4"><a href="#cb9-1-dce9897ac4"></a><span class="at">@given</span>(nums<span class="op">=</span>..., x<span class="op">=</span>...)</span></code></pre></div>
<p>We can reuse the same <code>integers()</code> strategy for <code>x</code>, but what about <code>nums</code>? Not surprisingly, we can import the <code>lists</code> function from <code>hypothesis.strategies</code> to create strategies for generating lists! The <code>lists</code> function takes in a single argument, which is a strategy for generating the elements of the list. In our example, we can use <code>lists(integers())</code> to return a strategy for generating lists of integers.</p>
<p>Here is our full test file (with the <code>is_even</code> tests omitted):</p>
<div class="sourceCode" id="cb10-dce9897ac4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-dce9897ac4"><a href="#cb10-1-dce9897ac4"></a><span class="co"># In file test_my_functions.py</span></span>
<span id="cb10-2-dce9897ac4"><a href="#cb10-2-dce9897ac4"></a><span class="im">from</span> hypothesis <span class="im">import</span> given</span>
<span id="cb10-3-dce9897ac4"><a href="#cb10-3-dce9897ac4"></a><span class="im">from</span> hypothesis.strategies <span class="im">import</span> integers, lists <span class="co"># NEW lists import</span></span>
<span id="cb10-4-dce9897ac4"><a href="#cb10-4-dce9897ac4"></a></span>
<span id="cb10-5-dce9897ac4"><a href="#cb10-5-dce9897ac4"></a><span class="im">from</span> my_functions <span class="im">import</span> is_even, num_evens</span>
<span id="cb10-6-dce9897ac4"><a href="#cb10-6-dce9897ac4"></a></span>
<span id="cb10-7-dce9897ac4"><a href="#cb10-7-dce9897ac4"></a></span>
<span id="cb10-8-dce9897ac4"><a href="#cb10-8-dce9897ac4"></a><span class="at">@given</span>(nums<span class="op">=</span>lists(integers()), x<span class="op">=</span>integers()) <span class="co"># NEW given call</span></span>
<span id="cb10-9-dce9897ac4"><a href="#cb10-9-dce9897ac4"></a><span class="kw">def</span> test_num_evens_one_more_even(nums: <span class="bu">list</span>[<span class="bu">int</span>], x: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb10-10-dce9897ac4"><a href="#cb10-10-dce9897ac4"></a> <span class="co">&quot;&quot;&quot;Test num_evens when you add one more even element.&quot;&quot;&quot;</span></span>
<span id="cb10-11-dce9897ac4"><a href="#cb10-11-dce9897ac4"></a> <span class="cf">assert</span> num_evens(nums <span class="op">+</span> [<span class="dv">2</span> <span class="op">*</span> x]) <span class="op">==</span> num_evens(nums) <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb10-12-dce9897ac4"><a href="#cb10-12-dce9897ac4"></a></span>
<span id="cb10-13-dce9897ac4"><a href="#cb10-13-dce9897ac4"></a></span>
<span id="cb10-14-dce9897ac4"><a href="#cb10-14-dce9897ac4"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb10-15-dce9897ac4"><a href="#cb10-15-dce9897ac4"></a> <span class="im">import</span> pytest</span>
<span id="cb10-16-dce9897ac4"><a href="#cb10-16-dce9897ac4"></a> pytest.main([<span class="st">&#39;test_my_functions.py&#39;</span>, <span class="st">&#39;-v&#39;</span>])</span></code></pre></div>
<h3 id="choosing-enough-properties-dce9897ac4">Choosing “enough” properties</h3>
<p>The property test expressed in <code>test_num_evens_one_more_even</code> is pretty neat, but it by itself is not sufficient to verify the correctness of the <code>num_evens</code> function. For example, this property would also hold true if <code>num_evens</code> simply returned the length of the list, rather than the number of even elements.</p>
<p>This is drawback with property-based tests: even though we can now check some property for very many inputs automatically, a single property alone does not guarantee that a function is correct. The ideal goal of property-based testing, then, is <em>choosing properties to verify</em>, so that if all of the properties are verified, then the function must be correct. This sounds too good to be true, and it often is—as functions get more complex, it is challenging or even impossible to find such a set of properties.</p>
<p>But for <code>num_evens</code>, a relatively simple function, it is actually possible to <em>formally prove</em> the following statement, which tells us exactly which properties we need to check.</p>
<div class="framed fullwidth">
<p><strong>Theorem (correctness for <code>num_evens</code>).</strong> An implementation for <code>num_evens</code> is correct (i.e., returns the number of even elements for any list of numbers) <em>if and only if</em> it satisfies all three of the following:</p>
<ol type="1">
<li><span class="math inline">\(\text{num_evens}(\text{[]}) = 0\)</span></li>
<li><span class="math inline">\(\forall \text{nums} \in \mathcal{L}_{\text{int}},~ \forall x \in \Z,~ \text{num_evens}(\text{nums} + [2x]) = \text{num_evens}(\text{nums}) + 1\)</span></li>
<li><span class="math inline">\(\forall \text{nums} \in \mathcal{L}_{\text{int}},~ \forall x \in \Z,~ \text{num_evens}(\text{nums} + [2x + 1]) = \text{num_evens}(\text{nums})\)</span></li>
</ol>
</div>
<p>Proving such a statement is beyond the scope of this chapter, but if youre curious it is closely related to the proof technique of <em>induction</em>, which we will cover formally later this year. But the actual statement is pretty amazing: it tells us that with just one unit test (for <code>nums = []</code>) and two property tests, we can be certain that our <code>num_evens</code> function is correct!</p>
<!--
Let us consider a more complicated example, this time involving sets rather than integers.
Let A and B be two arbitrary sets, and define for any set X, n(X) = "the number of elements in X".
From this we can recall the following property:
$n(A \cup B) = n(A) + n(B) - n(A \cap B)$.
Let's add two functions to our `my_functions.py` file:
```python
def union(set1: set, set2: set) -> set:
"""Return a new set that is the union of set1 and set2.
>>> union({1, 2, 3}, set())
{1, 2, 3}
>>> union({4, 5, 6}, {4, 5, 6})
{4, 5, 6}
"""
union_set = set1
for item in set2:
if item not in union_set:
union_set.add(item)
return union_set
def intersection(set1: set, set2: set) -> set:
"""Return a new set that is the intersection of set1 and set2.
>>> intersection(set(), {7, 8, 9})
set()
>>> intersection({1, 2, 3, 'four'}, {2, 3, 4, 'four'})
{2, 3, 'four'}
"""
intersection_set = set()
for item in set1:
if item in set2:
intersection_set.add(item)
return intersection_set
```
Next, we will import these functions and test the earlier property by generating sets with hypothesis.
The elements in the sets don't actually matter, so without loss of generality we will use integers in the sets:
```python
from hypothesis import given
# Note the change: we also import sets
from hypothesis.strategies import integers, sets
from my_functions import union, intersection
@given(sets(integers()), sets(integers()))
def test_intersection_formula(A: set, B: set):
assert len(union(A, B)) == len(A) + len(B) - len(intersection(A, B))
```
Note that our `@given` decorator has two arguments matching the two arguments of `test_intersection_formula`.
Also notice that the `sets` strategy takes an argument itself.
In this case, we have used `sets(integers())` to indicate that we want a set of integers for both `A` and `B`.
The assertion will test to see that our property holds for all each `A` and `B`.
Because we are using the `@given` decorator, the `hypothesis` module will test many different sets of integers to ensure that the property holds.
The `hypothesis` module has many strategies that can be used to generate different types of data.
See the appendix for more information. -->
</section>
<br/> <a id="anchor-03-11"></a>
<header id="title-block-header-6c23cb9602">
<h1 class="title">3.11 Working with Multiple Quantifiers</h1>
</header>
<section>
<p>Expressions in predicate logic with a single quantifier can generally be translated into English as either “there exists an element <span class="math inline">\(x\)</span> of set <span class="math inline">\(S\)</span> that satisfies <span class="math inline">\(P(x)\)</span>” (existential quantifier) or “every element <span class="math inline">\(x\)</span> of set <span class="math inline">\(S\)</span> satisfies <span class="math inline">\(P(x)\)</span>” (universal quantifier). However, there are situations where multiple variables are quantified, and we need to pay special attention to what such statements are actually saying. Let us revisit our <span class="math inline">\(Loves\)</span> predicate from earlier this chapter. In particular, recall the following relationships regarding who loves whom:</p>
<table>
<thead>
<tr class="header">
<th></th>
<th style="text-align: left;">Sophia</th>
<th style="text-align: left;">Thelonious</th>
<th style="text-align: left;">Stanley</th>
<th style="text-align: left;">Laura</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Breanna</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">False</td>
</tr>
<tr class="even">
<td>Malena</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
</tr>
<tr class="odd">
<td>Patrick</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">False</td>
</tr>
<tr class="even">
<td>Ella</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
</tr>
</tbody>
</table>
<p>Remember that our <span class="math inline">\(Loves\)</span> predicate is binary—what if we wanted to quantify <em>both</em> of its inputs? Consider the formula: <span class="math display">\[\forall a \in A,~\forall b \in B,~Loves(a,b).\]</span></p>
<p>We translate this as “for every person <span class="math inline">\(a\)</span> in <span class="math inline">\(A\)</span>, for every person <span class="math inline">\(b\)</span> in <span class="math inline">\(B\)</span>, <span class="math inline">\(a\)</span> loves <span class="math inline">\(b\)</span>.” After some thought, we notice that the order in which we quantified <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> doesnt matter; the statement “for every person <span class="math inline">\(b\)</span> in <span class="math inline">\(B\)</span>, for every person <span class="math inline">\(a\)</span> in <span class="math inline">\(A\)</span>, <span class="math inline">\(a\)</span> loves <span class="math inline">\(b\)</span>” means exactly the same thing! In both cases, we are considering all possible pairs of people (one from <span class="math inline">\(A\)</span> and one from <span class="math inline">\(B\)</span>).</p>
<p>In general, when we have two consecutive universal quantifiers the order does <em>not</em> matter. That is, the following two formulas are equivalent:<label for="sn-0-6c23cb9602" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-6c23cb9602" class="margin-toggle"/><span class="sidenote">Tip: when the domains of the two variables are the same, we typically combine the quantifications, e.g., <span class="math inline">\(\forall x \in S,~ \forall y \in S,~ P(x, y)\)</span> into <span class="math inline">\(\forall x,y \in S,~ P(x, y)\)</span>.</span></p>
<ul>
<li><span class="math inline">\(\forall x \in S_1,~ \forall y \in S_2,~ P(x, y)\)</span></li>
<li><span class="math inline">\(\forall y \in S_2,~ \forall x \in S_1,~ P(x, y)\)</span></li>
</ul>
<p>The same is true of two consecutive existential quantifiers. Consider the statements “there exist an <span class="math inline">\(a\)</span> in <span class="math inline">\(A\)</span> and <span class="math inline">\(b\)</span> in <span class="math inline">\(B\)</span> such that <span class="math inline">\(a\)</span> loves <span class="math inline">\(b\)</span>” and “there exist a <span class="math inline">\(b\)</span> in <span class="math inline">\(B\)</span> and <span class="math inline">\(a\)</span> in <span class="math inline">\(A\)</span> such that <span class="math inline">\(a\)</span> loves <span class="math inline">\(b\)</span>.” Again, they mean the same thing: in this case, we only care about one particular pair of people (one from <span class="math inline">\(A\)</span> and one from <span class="math inline">\(B\)</span>), so the order in which we pick the particular <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> doesnt matter. In general, the following two formulas are equivalent:</p>
<ul>
<li><span class="math inline">\(\exists x \in S_1,~ \exists y \in S_2,~ P(x, y)\)</span></li>
<li><span class="math inline">\(\exists y \in S_2,~ \exists x \in S_1,~ P(x, y)\)</span></li>
</ul>
<p>But even though consecutive quantifiers of the same type behave very nicely, this is <strong>not</strong> the case for a pair of alternating quantifiers. First, consider <span class="math display">\[\forall a \in A,~ \exists b \in B,~ Loves(a,b).\]</span> This can be translated as “For every person <span class="math inline">\(a\)</span> in <span class="math inline">\(A\)</span>, there exists a person <span class="math inline">\(b\)</span> in <span class="math inline">\(B\)</span>, such that <span class="math inline">\(a\)</span> loves <span class="math inline">\(b\)</span>.”<label for="sn-1-6c23cb9602" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-6c23cb9602" class="margin-toggle"/><span class="sidenote"> Or put a bit more naturally, “For every person <span class="math inline">\(a\)</span> in <span class="math inline">\(A\)</span>, <span class="math inline">\(a\)</span> loves someone in <span class="math inline">\(B\)</span>,” which can be shortened even further to “Everyone in <span class="math inline">\(A\)</span> loves someone in <span class="math inline">\(B\)</span>.”</span> This is true: every person in <span class="math inline">\(A\)</span> loves at least one person.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;"><span class="math inline">\(a\)</span> (from <span class="math inline">\(A\)</span>)</th>
<th style="text-align: left;"><span class="math inline">\(b\)</span> (a person in <span class="math inline">\(B\)</span> who <span class="math inline">\(a\)</span> loves)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Breanna</td>
<td style="text-align: left;">Thelonious</td>
</tr>
<tr class="even">
<td style="text-align: left;">Malena</td>
<td style="text-align: left;">Laura</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Patrick</td>
<td style="text-align: left;">Stanley</td>
</tr>
<tr class="even">
<td style="text-align: left;">Ella</td>
<td style="text-align: left;">Stanley</td>
</tr>
</tbody>
</table>
<p>Note that the choice of person who <span class="math inline">\(a\)</span> loves depends on <span class="math inline">\(a\)</span>: this is consistent with the latter part of the English translation, “<span class="math inline">\(a\)</span> loves someone in <span class="math inline">\(B\)</span>.”</p>
<p>Let us contrast this with the similar-looking formula, where the order of the quantifiers has changed: <span class="math display">\[\exists b \in B,~ \forall a \in A,~ Loves(a,b).\]</span> This formulas meaning is quite different: “there exists a person <span class="math inline">\(b\)</span> in <span class="math inline">\(B\)</span>, where for every person <span class="math inline">\(a\)</span> in <span class="math inline">\(A\)</span>, <span class="math inline">\(a\)</span> loves <span class="math inline">\(b\)</span>.” Put more naturally, “there is a person <span class="math inline">\(b\)</span> in <span class="math inline">\(B\)</span> who is loved by everyone in <span class="math inline">\(A\)</span>” or “someone in <span class="math inline">\(B\)</span> is loved by everyone in <span class="math inline">\(A\)</span>”.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;"><span class="math inline">\(b\)</span> (from <span class="math inline">\(B\)</span>)</th>
<th style="text-align: left;">Loved by everyone in <span class="math inline">\(A\)</span>?</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Sophia</td>
<td style="text-align: left;">No</td>
</tr>
<tr class="even">
<td style="text-align: left;">Thelonious</td>
<td style="text-align: left;">No</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Stanley</td>
<td style="text-align: left;">Yes</td>
</tr>
<tr class="even">
<td style="text-align: left;">Laura</td>
<td style="text-align: left;">No</td>
</tr>
</tbody>
</table>
<p>This happens to be True because everyone in <span class="math inline">\(A\)</span> loves Stanley. But it would <em>not</em> be True if we, for example, removed the love connection between Malena and Stanley. In this case, Stanley would no longer be loved by everyone, and so <em>no one</em> in <span class="math inline">\(B\)</span> is loved by everyone in <span class="math inline">\(A\)</span>. But notice that even if Malena no longer loves Stanley, the previous statement (“everyone in <span class="math inline">\(A\)</span> loves someone”) remains True!</p>
<p>So we would have a case where switching the order of quantifiers changes the meaning of a formula! In both cases, the existential quantifier <span class="math inline">\(\exists b \in B\)</span> involves making a <em>choice</em> of person from <span class="math inline">\(B\)</span>. But in the first case, this quantifier occurs after <span class="math inline">\(a\)</span> is quantified, so the choice of <span class="math inline">\(b\)</span> is allowed to depend on the choice of <span class="math inline">\(a\)</span>. In the second case, this quantifier occurs before <span class="math inline">\(a\)</span>, and so the choice of <span class="math inline">\(b\)</span> must be <em>independent</em> of the choice of <span class="math inline">\(a\)</span>.</p>
<p>When reading a nested quantified expression, you should read it from left to right, and pay attention to the order of the quantifiers. In order to see if the statement is True, whenever you come across a universal quantifier, you must verify the statement for every single value that this variable can take on. Whenever you see an existential quantifier, you only need to exhibit <em>one</em> value for that variable such that the statement is True, and this value can depend on the variables to the left of it, but not on the variables to the right of it.</p>
<h2 id="translating-multiple-quantifiers-into-python-code-6c23cb9602">Translating multiple quantifiers into Python code</h2>
<p>Now lets see how we could represent this example in Python. First, recall the table of who loves whom from above:</p>
<table>
<thead>
<tr class="header">
<th></th>
<th style="text-align: left;">Sophia</th>
<th style="text-align: left;">Thelonious</th>
<th style="text-align: left;">Stanley</th>
<th style="text-align: left;">Laura</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Breanna</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">False</td>
</tr>
<tr class="even">
<td>Malena</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
</tr>
<tr class="odd">
<td>Patrick</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">False</td>
</tr>
<tr class="even">
<td>Ella</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">False</td>
<td style="text-align: left;">True</td>
<td style="text-align: left;">True</td>
</tr>
</tbody>
</table>
<p>And we can represent this table of who loves whom in Python as a <em>list of lists</em> or, more precisely, using a <code>list[list[bool]]</code>.</p>
<div class="sourceCode" id="cb1-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-6c23cb9602"><a href="#cb1-1-6c23cb9602"></a>[</span>
<span id="cb1-2-6c23cb9602"><a href="#cb1-2-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb1-3-6c23cb9602"><a href="#cb1-3-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">True</span>],</span>
<span id="cb1-4-6c23cb9602"><a href="#cb1-4-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb1-5-6c23cb9602"><a href="#cb1-5-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>]</span>
<span id="cb1-6-6c23cb9602"><a href="#cb1-6-6c23cb9602"></a>]</span></code></pre></div>
<p>Our list is the same as the table above, except with the peoples names removed. Each <em>row</em> of the table represents a person from set <span class="math inline">\(A\)</span>, while each <em>column</em> in the table represents a person from set <span class="math inline">\(B\)</span>. Weve kept the order the same; so the first row represents <span class="math inline">\(Breanna\)</span>, while the third column represents <span class="math inline">\(Stanley\)</span>.</p>
<p>Now, how are we going to access the data from this table? For this section were going to put all of our work into a new file called <code>loves.py</code>, and so well start by defining a new variable in this file:</p>
<div class="sourceCode" id="cb2-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-6c23cb9602"><a href="#cb2-1-6c23cb9602"></a><span class="co"># In loves.py</span></span>
<span id="cb2-2-6c23cb9602"><a href="#cb2-2-6c23cb9602"></a>LOVES_TABLE <span class="op">=</span> [</span>
<span id="cb2-3-6c23cb9602"><a href="#cb2-3-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb2-4-6c23cb9602"><a href="#cb2-4-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">True</span>],</span>
<span id="cb2-5-6c23cb9602"><a href="#cb2-5-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb2-6-6c23cb9602"><a href="#cb2-6-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>]</span>
<span id="cb2-7-6c23cb9602"><a href="#cb2-7-6c23cb9602"></a>]</span></code></pre></div>
<p>This is the first time weve defined a variable within a Python file (rather than the Python console) that is <em>not</em> in a function definition. Variables defined in this way are called <em>global constants</em>, to distinguish them from the local variables defined within functions.<label for="sn-2-6c23cb9602" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-6c23cb9602" class="margin-toggle"/><span class="sidenote"> The term “constant” is not important right now, but will become important later in the course.</span> Global constants are called “global” because their <em>scope</em> is the entire Python module in which they are defined: they can be accessed anywhere in the file, including all function bodies. They can also be imported and used in other Python modules, and are available when we run the file in the Python console.</p>
<h3 id="exploring-loves_table-6c23cb9602">Exploring <code>LOVES_TABLE</code></h3>
<p>To start, lets run our <code>loves.py</code> file in the Python console so we can play around with the <code>LOVES_TABLE</code> value. Because <code>LOVES_TABLE</code> is a list of lists, where each inner list represents a row of the table, its easy to access a single row with list indexing:</p>
<div class="sourceCode" id="cb3-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-6c23cb9602"><a href="#cb3-1-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> LOVES_TABLE[<span class="dv">0</span>] <span class="co"># This is the first row of the table</span></span>
<span id="cb3-2-6c23cb9602"><a href="#cb3-2-6c23cb9602"></a>[<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">False</span>]</span></code></pre></div>
<p>From here, we can access individual elements of the table, which represent an individual value of the <span class="math inline">\(Loves(a, b)\)</span> predicate.</p>
<div class="sourceCode" id="cb4-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-6c23cb9602"><a href="#cb4-1-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> LOVES_TABLE[<span class="dv">0</span>][<span class="dv">1</span>] <span class="co"># This is the (0, 1) entry in the table</span></span>
<span id="cb4-2-6c23cb9602"><a href="#cb4-2-6c23cb9602"></a><span class="va">True</span></span>
<span id="cb4-3-6c23cb9602"><a href="#cb4-3-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> LOVES_TABLE[<span class="dv">2</span>][<span class="dv">3</span>] <span class="co"># This is the (2, 3) entry in the table</span></span>
<span id="cb4-4-6c23cb9602"><a href="#cb4-4-6c23cb9602"></a><span class="va">False</span></span></code></pre></div>
<p>In general, <code>LOVES_TABLE[i][j]</code> evaluates to the entry in row <code>i</code> and column <code>j</code> of the table. Finally, since the data is stored by rows, accessing columns is a little more work. To access column <code>j</code>, we can use a list comprehension to access the <code>j</code>-th element in each row:</p>
<div class="sourceCode" id="cb5-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-6c23cb9602"><a href="#cb5-1-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> [LOVES_TABLE[i][<span class="dv">0</span>] <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">4</span>)]</span>
<span id="cb5-2-6c23cb9602"><a href="#cb5-2-6c23cb9602"></a>[<span class="va">False</span>, <span class="va">False</span>, <span class="va">False</span>, <span class="va">False</span>]</span></code></pre></div>
<p>Now, lets return to our Python file <code>loves.py</code> and define a version of our <span class="math inline">\(Loves\)</span> predicate. First, we add two more constants to represent the sets <span class="math inline">\(A\)</span> and <span class="math inline">\(B\)</span>, but using a dictionary to map names to their corresponding indices in <code>LOVES_TABLE</code>.</p>
<div class="sourceCode" id="cb6-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-6c23cb9602"><a href="#cb6-1-6c23cb9602"></a><span class="co"># In loves.py</span></span>
<span id="cb6-2-6c23cb9602"><a href="#cb6-2-6c23cb9602"></a>LOVES_TABLE <span class="op">=</span> [</span>
<span id="cb6-3-6c23cb9602"><a href="#cb6-3-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb6-4-6c23cb9602"><a href="#cb6-4-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">True</span>],</span>
<span id="cb6-5-6c23cb9602"><a href="#cb6-5-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb6-6-6c23cb9602"><a href="#cb6-6-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>]</span>
<span id="cb6-7-6c23cb9602"><a href="#cb6-7-6c23cb9602"></a>]</span>
<span id="cb6-8-6c23cb9602"><a href="#cb6-8-6c23cb9602"></a></span>
<span id="cb6-9-6c23cb9602"><a href="#cb6-9-6c23cb9602"></a>A <span class="op">=</span> {</span>
<span id="cb6-10-6c23cb9602"><a href="#cb6-10-6c23cb9602"></a> <span class="st">&#39;Breanna&#39;</span>: <span class="dv">0</span>,</span>
<span id="cb6-11-6c23cb9602"><a href="#cb6-11-6c23cb9602"></a> <span class="st">&#39;Malena&#39;</span>: <span class="dv">1</span>,</span>
<span id="cb6-12-6c23cb9602"><a href="#cb6-12-6c23cb9602"></a> <span class="st">&#39;Patrick&#39;</span>: <span class="dv">2</span>,</span>
<span id="cb6-13-6c23cb9602"><a href="#cb6-13-6c23cb9602"></a> <span class="st">&#39;Ella&#39;</span>: <span class="dv">3</span></span>
<span id="cb6-14-6c23cb9602"><a href="#cb6-14-6c23cb9602"></a>}</span>
<span id="cb6-15-6c23cb9602"><a href="#cb6-15-6c23cb9602"></a></span>
<span id="cb6-16-6c23cb9602"><a href="#cb6-16-6c23cb9602"></a>B <span class="op">=</span> {</span>
<span id="cb6-17-6c23cb9602"><a href="#cb6-17-6c23cb9602"></a> <span class="st">&#39;Sophia&#39;</span>: <span class="dv">0</span>,</span>
<span id="cb6-18-6c23cb9602"><a href="#cb6-18-6c23cb9602"></a> <span class="st">&#39;Thelonius&#39;</span>: <span class="dv">1</span>,</span>
<span id="cb6-19-6c23cb9602"><a href="#cb6-19-6c23cb9602"></a> <span class="st">&#39;Stanley&#39;</span>: <span class="dv">2</span>,</span>
<span id="cb6-20-6c23cb9602"><a href="#cb6-20-6c23cb9602"></a> <span class="st">&#39;Laura&#39;</span>: <span class="dv">3</span>,</span>
<span id="cb6-21-6c23cb9602"><a href="#cb6-21-6c23cb9602"></a>}</span></code></pre></div>
<p>Next, we define a <code>loves</code> predicate, which take in two strings (note the preconditions) and returns whether person <code>a</code> loves person <code>b</code>.<label for="sn-3-6c23cb9602" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-6c23cb9602" class="margin-toggle"/><span class="sidenote"> Note that because this function is defined in the same file as <code>LOVES_TABLE</code>, it can access that global constant in its body.</span></p>
<div class="sourceCode" id="cb7-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-6c23cb9602"><a href="#cb7-1-6c23cb9602"></a><span class="kw">def</span> loves(a: <span class="bu">str</span>, b: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb7-2-6c23cb9602"><a href="#cb7-2-6c23cb9602"></a> <span class="co">&quot;&quot;&quot;Return whether the person at index a loves the person at index b.</span></span>
<span id="cb7-3-6c23cb9602"><a href="#cb7-3-6c23cb9602"></a></span>
<span id="cb7-4-6c23cb9602"><a href="#cb7-4-6c23cb9602"></a><span class="co"> Preconditions:</span></span>
<span id="cb7-5-6c23cb9602"><a href="#cb7-5-6c23cb9602"></a><span class="co"> - a in A</span></span>
<span id="cb7-6-6c23cb9602"><a href="#cb7-6-6c23cb9602"></a><span class="co"> - b in B</span></span>
<span id="cb7-7-6c23cb9602"><a href="#cb7-7-6c23cb9602"></a></span>
<span id="cb7-8-6c23cb9602"><a href="#cb7-8-6c23cb9602"></a><span class="co"> &gt;&gt;&gt; loves(&#39;Breanna&#39;, &#39;Sophia&#39;)</span></span>
<span id="cb7-9-6c23cb9602"><a href="#cb7-9-6c23cb9602"></a><span class="co"> False</span></span>
<span id="cb7-10-6c23cb9602"><a href="#cb7-10-6c23cb9602"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-11-6c23cb9602"><a href="#cb7-11-6c23cb9602"></a> a_index <span class="op">=</span> A[a]</span>
<span id="cb7-12-6c23cb9602"><a href="#cb7-12-6c23cb9602"></a> b_index <span class="op">=</span> B[b]</span>
<span id="cb7-13-6c23cb9602"><a href="#cb7-13-6c23cb9602"></a> <span class="cf">return</span> LOVES_TABLE[a_index][b_index]</span></code></pre></div>
<p>Now that weve seen how to access individual entries, rows, and columns from the table, lets turn to how we would represent the statements in predicate logic weve written in this section. First, we can express <span class="math inline">\(\forall a \in A,~ \forall b \in B,~ Loves(a, b)\)</span> as the expression:</p>
<div class="sourceCode" id="cb8-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-6c23cb9602"><a href="#cb8-1-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">all</span>({loves(a, b) <span class="cf">for</span> a <span class="kw">in</span> A <span class="cf">for</span> b <span class="kw">in</span> B})</span>
<span id="cb8-2-6c23cb9602"><a href="#cb8-2-6c23cb9602"></a><span class="va">False</span></span></code></pre></div>
<p>And similarly, we can express <span class="math inline">\(\exists a \in A,~ \exists b \in B,~ Loves(a, b)\)</span> as the expression:</p>
<div class="sourceCode" id="cb9-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-6c23cb9602"><a href="#cb9-1-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">any</span>({loves(a, b) <span class="cf">for</span> a <span class="kw">in</span> A <span class="cf">for</span> b <span class="kw">in</span> B})</span>
<span id="cb9-2-6c23cb9602"><a href="#cb9-2-6c23cb9602"></a><span class="va">True</span></span></code></pre></div>
<p>These two examples illustrate how Pythons <code>all</code> and <code>any</code> functions naturally enable us to express multiple quantifiers of the same type. But what about the expressions we looked at with alternating quantifiers? Consider <span class="math inline">\(\forall a \in A,~ \exists b \in B,~ Loves(a,b)\)</span>. It is possible to construct a nested expression that represents this one as well:</p>
<div class="sourceCode" id="cb10-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-6c23cb9602"><a href="#cb10-1-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">all</span>({<span class="bu">any</span>({loves(a, b) <span class="cf">for</span> b <span class="kw">in</span> B}) <span class="cf">for</span> a <span class="kw">in</span> A})</span>
<span id="cb10-2-6c23cb9602"><a href="#cb10-2-6c23cb9602"></a><span class="va">True</span></span></code></pre></div>
<p>Though this is structurally equivalent to the statement in predicate logic, its syntactically longer and a bit harder to read. In general we try to avoid lots of nesting in expressions in programming, and a rule of thumb well try to follow in this course is to <em>never nest <code>all</code>/<code>any</code> calls</em>. Instead, we can pull out the inner <code>any</code> into its own function, which not only reduces the nesting but makes it clearer whats going on:</p>
<div class="sourceCode" id="cb11-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-6c23cb9602"><a href="#cb11-1-6c23cb9602"></a><span class="kw">def</span> loves_someone(a: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb11-2-6c23cb9602"><a href="#cb11-2-6c23cb9602"></a> <span class="co">&quot;&quot;&quot;Return whether a loves at least one person in B.</span></span>
<span id="cb11-3-6c23cb9602"><a href="#cb11-3-6c23cb9602"></a></span>
<span id="cb11-4-6c23cb9602"><a href="#cb11-4-6c23cb9602"></a><span class="co"> Preconditions:</span></span>
<span id="cb11-5-6c23cb9602"><a href="#cb11-5-6c23cb9602"></a><span class="co"> - a in A</span></span>
<span id="cb11-6-6c23cb9602"><a href="#cb11-6-6c23cb9602"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb11-7-6c23cb9602"><a href="#cb11-7-6c23cb9602"></a> <span class="cf">return</span> <span class="bu">any</span>({loves(a, b) <span class="cf">for</span> b <span class="kw">in</span> B})</span>
<span id="cb11-8-6c23cb9602"><a href="#cb11-8-6c23cb9602"></a></span>
<span id="cb11-9-6c23cb9602"><a href="#cb11-9-6c23cb9602"></a></span>
<span id="cb11-10-6c23cb9602"><a href="#cb11-10-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">all</span>({loves_someone(a) <span class="cf">for</span> a <span class="kw">in</span> A})</span>
<span id="cb11-11-6c23cb9602"><a href="#cb11-11-6c23cb9602"></a><span class="va">True</span></span></code></pre></div>
<p>Similarly, we can express the statement <span class="math inline">\(\exists b \in B,~ \forall a \in A,~ Loves(a,b)\)</span> in two different ways. With a nested <code>any</code>/<code>all</code>:</p>
<div class="sourceCode" id="cb12-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-6c23cb9602"><a href="#cb12-1-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">any</span>({<span class="bu">all</span>({loves(a, b)} <span class="cf">for</span> a <span class="kw">in</span> A) <span class="cf">for</span> b <span class="kw">in</span> B})</span>
<span id="cb12-2-6c23cb9602"><a href="#cb12-2-6c23cb9602"></a><span class="va">True</span></span></code></pre></div>
<p>And by pulling out the inner <code>all</code> expression into a named function:</p>
<div class="sourceCode" id="cb13-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-6c23cb9602"><a href="#cb13-1-6c23cb9602"></a><span class="kw">def</span> loved_by_everyone(b: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb13-2-6c23cb9602"><a href="#cb13-2-6c23cb9602"></a> <span class="co">&quot;&quot;&quot;Return whether b is loved by everyone in A.</span></span>
<span id="cb13-3-6c23cb9602"><a href="#cb13-3-6c23cb9602"></a></span>
<span id="cb13-4-6c23cb9602"><a href="#cb13-4-6c23cb9602"></a><span class="co"> Preconditions:</span></span>
<span id="cb13-5-6c23cb9602"><a href="#cb13-5-6c23cb9602"></a><span class="co"> - b in B</span></span>
<span id="cb13-6-6c23cb9602"><a href="#cb13-6-6c23cb9602"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-7-6c23cb9602"><a href="#cb13-7-6c23cb9602"></a> <span class="cf">return</span> <span class="bu">all</span>({loves(a, b)} <span class="cf">for</span> a <span class="kw">in</span> A)</span>
<span id="cb13-8-6c23cb9602"><a href="#cb13-8-6c23cb9602"></a></span>
<span id="cb13-9-6c23cb9602"><a href="#cb13-9-6c23cb9602"></a></span>
<span id="cb13-10-6c23cb9602"><a href="#cb13-10-6c23cb9602"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">any</span>({loved_by_everyone(b) <span class="cf">for</span> b <span class="kw">in</span> B})</span>
<span id="cb13-11-6c23cb9602"><a href="#cb13-11-6c23cb9602"></a><span class="va">True</span></span></code></pre></div>
<p>Here is our final <code>loves.py</code> file, for you to play around with:</p>
<div class="sourceCode" id="cb14-6c23cb9602"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-6c23cb9602"><a href="#cb14-1-6c23cb9602"></a><span class="co"># In loves.py</span></span>
<span id="cb14-2-6c23cb9602"><a href="#cb14-2-6c23cb9602"></a>LOVES_TABLE <span class="op">=</span> [</span>
<span id="cb14-3-6c23cb9602"><a href="#cb14-3-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb14-4-6c23cb9602"><a href="#cb14-4-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>, <span class="va">True</span>],</span>
<span id="cb14-5-6c23cb9602"><a href="#cb14-5-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">False</span>],</span>
<span id="cb14-6-6c23cb9602"><a href="#cb14-6-6c23cb9602"></a> [<span class="va">False</span>, <span class="va">False</span>, <span class="va">True</span>, <span class="va">True</span>]</span>
<span id="cb14-7-6c23cb9602"><a href="#cb14-7-6c23cb9602"></a>]</span>
<span id="cb14-8-6c23cb9602"><a href="#cb14-8-6c23cb9602"></a></span>
<span id="cb14-9-6c23cb9602"><a href="#cb14-9-6c23cb9602"></a>A <span class="op">=</span> {</span>
<span id="cb14-10-6c23cb9602"><a href="#cb14-10-6c23cb9602"></a> <span class="st">&#39;Breanna&#39;</span>: <span class="dv">0</span>,</span>
<span id="cb14-11-6c23cb9602"><a href="#cb14-11-6c23cb9602"></a> <span class="st">&#39;Malena&#39;</span>: <span class="dv">1</span>,</span>
<span id="cb14-12-6c23cb9602"><a href="#cb14-12-6c23cb9602"></a> <span class="st">&#39;Patrick&#39;</span>: <span class="dv">2</span>,</span>
<span id="cb14-13-6c23cb9602"><a href="#cb14-13-6c23cb9602"></a> <span class="st">&#39;Ella&#39;</span>: <span class="dv">3</span></span>
<span id="cb14-14-6c23cb9602"><a href="#cb14-14-6c23cb9602"></a>}</span>
<span id="cb14-15-6c23cb9602"><a href="#cb14-15-6c23cb9602"></a></span>
<span id="cb14-16-6c23cb9602"><a href="#cb14-16-6c23cb9602"></a>B <span class="op">=</span> {</span>
<span id="cb14-17-6c23cb9602"><a href="#cb14-17-6c23cb9602"></a> <span class="st">&#39;Sophia&#39;</span>: <span class="dv">0</span>,</span>
<span id="cb14-18-6c23cb9602"><a href="#cb14-18-6c23cb9602"></a> <span class="st">&#39;Thelonius&#39;</span>: <span class="dv">1</span>,</span>
<span id="cb14-19-6c23cb9602"><a href="#cb14-19-6c23cb9602"></a> <span class="st">&#39;Stanley&#39;</span>: <span class="dv">2</span>,</span>
<span id="cb14-20-6c23cb9602"><a href="#cb14-20-6c23cb9602"></a> <span class="st">&#39;Laura&#39;</span>: <span class="dv">3</span>,</span>
<span id="cb14-21-6c23cb9602"><a href="#cb14-21-6c23cb9602"></a>}</span>
<span id="cb14-22-6c23cb9602"><a href="#cb14-22-6c23cb9602"></a></span>
<span id="cb14-23-6c23cb9602"><a href="#cb14-23-6c23cb9602"></a><span class="kw">def</span> loves(a: <span class="bu">str</span>, b: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb14-24-6c23cb9602"><a href="#cb14-24-6c23cb9602"></a> <span class="co">&quot;&quot;&quot;Return whether the person at index a loves the person at index b.</span></span>
<span id="cb14-25-6c23cb9602"><a href="#cb14-25-6c23cb9602"></a></span>
<span id="cb14-26-6c23cb9602"><a href="#cb14-26-6c23cb9602"></a><span class="co"> Preconditions:</span></span>
<span id="cb14-27-6c23cb9602"><a href="#cb14-27-6c23cb9602"></a><span class="co"> - a in A</span></span>
<span id="cb14-28-6c23cb9602"><a href="#cb14-28-6c23cb9602"></a><span class="co"> - b in B</span></span>
<span id="cb14-29-6c23cb9602"><a href="#cb14-29-6c23cb9602"></a></span>
<span id="cb14-30-6c23cb9602"><a href="#cb14-30-6c23cb9602"></a><span class="co"> &gt;&gt;&gt; loves(&#39;Breanna&#39;, &#39;Sophia&#39;)</span></span>
<span id="cb14-31-6c23cb9602"><a href="#cb14-31-6c23cb9602"></a><span class="co"> False</span></span>
<span id="cb14-32-6c23cb9602"><a href="#cb14-32-6c23cb9602"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb14-33-6c23cb9602"><a href="#cb14-33-6c23cb9602"></a> a_index <span class="op">=</span> A[a]</span>
<span id="cb14-34-6c23cb9602"><a href="#cb14-34-6c23cb9602"></a> b_index <span class="op">=</span> B[b]</span>
<span id="cb14-35-6c23cb9602"><a href="#cb14-35-6c23cb9602"></a> <span class="cf">return</span> LOVES_TABLE[a_index][b_index]</span>
<span id="cb14-36-6c23cb9602"><a href="#cb14-36-6c23cb9602"></a></span>
<span id="cb14-37-6c23cb9602"><a href="#cb14-37-6c23cb9602"></a></span>
<span id="cb14-38-6c23cb9602"><a href="#cb14-38-6c23cb9602"></a><span class="kw">def</span> loves_someone(a: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb14-39-6c23cb9602"><a href="#cb14-39-6c23cb9602"></a> <span class="co">&quot;&quot;&quot;Return whether a loves at least one person in B.</span></span>
<span id="cb14-40-6c23cb9602"><a href="#cb14-40-6c23cb9602"></a></span>
<span id="cb14-41-6c23cb9602"><a href="#cb14-41-6c23cb9602"></a><span class="co"> Preconditions:</span></span>
<span id="cb14-42-6c23cb9602"><a href="#cb14-42-6c23cb9602"></a><span class="co"> - a in A</span></span>
<span id="cb14-43-6c23cb9602"><a href="#cb14-43-6c23cb9602"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb14-44-6c23cb9602"><a href="#cb14-44-6c23cb9602"></a> <span class="cf">return</span> <span class="bu">any</span>({loves(a, b) <span class="cf">for</span> b <span class="kw">in</span> B})</span>
<span id="cb14-45-6c23cb9602"><a href="#cb14-45-6c23cb9602"></a></span>
<span id="cb14-46-6c23cb9602"><a href="#cb14-46-6c23cb9602"></a></span>
<span id="cb14-47-6c23cb9602"><a href="#cb14-47-6c23cb9602"></a><span class="kw">def</span> loved_by_everyone(b: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb14-48-6c23cb9602"><a href="#cb14-48-6c23cb9602"></a> <span class="co">&quot;&quot;&quot;Return whether b is loved by everyone in A.</span></span>
<span id="cb14-49-6c23cb9602"><a href="#cb14-49-6c23cb9602"></a></span>
<span id="cb14-50-6c23cb9602"><a href="#cb14-50-6c23cb9602"></a><span class="co"> Preconditions:</span></span>
<span id="cb14-51-6c23cb9602"><a href="#cb14-51-6c23cb9602"></a><span class="co"> - b in B</span></span>
<span id="cb14-52-6c23cb9602"><a href="#cb14-52-6c23cb9602"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb14-53-6c23cb9602"><a href="#cb14-53-6c23cb9602"></a> <span class="cf">return</span> <span class="bu">all</span>({loves(a, b)} <span class="cf">for</span> a <span class="kw">in</span> A)</span></code></pre></div>
<h2 id="a-famous-logical-statement-6c23cb9602">A famous logical statement</h2>
<p>Before we wrap up, let us use our understanding of multiple quantifiers to express one of the more famous properties about prime numbers: “there are infinitely many primes.”<label for="sn-4-6c23cb9602" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-6c23cb9602" class="margin-toggle"/><span class="sidenote"> Later on, well actually prove this statement! </span></p>
<p>In <a href="09-working-with-definitions.html">Section 2.9</a>, we saw how to express the fact that a single number <span class="math inline">\(p\)</span> is a prime number, but how do we capture “infinitely many”? The key idea is that because primes are natural numbers, if there are infinitely many of them, then they have to keep growing bigger and bigger.<label for="sn-5-6c23cb9602" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-6c23cb9602" class="margin-toggle"/><span class="sidenote"> Another way to think about this is to consider the statement “every prime number is less than 9000. If this statement were True, then there could only be at most 8999 primes.” </span> So we can express the original statement as “every natural number has a prime number larger than it,” or in the symbolic notation: <span class="math display">\[\forall n \in \N,~ \exists p \in \N,~ p &gt; n \land IsPrime(p).\]</span></p>
<p>If we wanted to express this statement without either the <span class="math inline">\(IsPrime\)</span> or divisibility predicates, we would end up with an extremely cumbersome statement: <span class="math display">\[\forall n \in \N,~ \exists p \IN \N,~
p &gt; n \land
p &gt; 1 \land \Big( \forall d \in \N,~ \left(\exists k \in \Z,~ p = kd\right) \Rightarrow d = 1 \OR d = p \Big).\]</span></p>
<p>This statement is terribly ugly, which is why we define our own predicates! Keep this in mind throughout the course: when you are given a statement to express, make sure you are aware of all of the relevant definitions, and make use of them to simplify your expression.</p>
<h2 id="looking-ahead-6c23cb9602">Looking Ahead</h2>
<p>In this section, weve introduced the notion of lists within lists to represent tables of values for binary predicates. In the next chapter, well start looking at tabular data and other forms of nested collections of data in more detail, and see how these more complex structures can be used to represent real-world data for our programs.</p>
</section>
<br/>
<h2 class="unnumbered" id="working-with-complex-data">4. Working with Complex Data</h2>
<a id="anchor-04-01"></a>
<header id="title-block-header-8714485ec8">
<h1 class="title">4.1 Tabular Data</h1>
</header>
<section>
<p>Weve seen how Python can store collections of data, such as lists, sets, and dictionaries. Mostly, weve focused on collections of integers or strings. But what about collections of collections? Weve actually encountered this already: our <a href="../03-logic/04-if-statements.html"><code>count_cancelled</code> function</a> had a parameter <code>flights</code> that was a dictionary whose values were lists, and we represented the <span class="math inline">\(Loves\)</span> predicate as a <a href="../03-logic/11-multiple-quantifiers.html">list of lists</a>, storing a two-dimensional table of booleans. In this section, well look at using list of lists to store more complex forms of tabular data, like a table from a spreadsheet, and writing functions to perform computations on this data.</p>
<h2 id="toronto-getting-married-8714485ec8">Toronto getting married</h2>
<p>Lets consider a <a href="https://open.toronto.ca/dataset/marriage-licence-statistics/">real data set</a> from the city of Toronto. This data shows information about how many marriage licenses were issued in Toronto at a particular location and month. The data is in a tabular format with four columns: id, civic centre, number of marriage licenses issued, and time period. Each row of the table tells us how many marriage licenses were issued by a civic centre in a specific time period; the id is simply a unique numerical identifier for each row. Suppose we wanted to answer the following question: What is the average number of marriage licenses issued by each civic centre?</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><strong>ID</strong></th>
<th style="text-align: center;"><strong>Civic Centre</strong></th>
<th style="text-align: center;"><strong>Marriage Licenses Issued</strong></th>
<th style="text-align: center;"><strong>Time Period</strong></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">1657</td>
<td style="text-align: center;">ET</td>
<td style="text-align: center;">80</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1658</td>
<td style="text-align: center;">NY</td>
<td style="text-align: center;">136</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="odd">
<td style="text-align: center;">1659</td>
<td style="text-align: center;">SC</td>
<td style="text-align: center;">159</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1660</td>
<td style="text-align: center;">TO</td>
<td style="text-align: center;">367</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="odd">
<td style="text-align: center;">1661</td>
<td style="text-align: center;">ET</td>
<td style="text-align: center;">109</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1662</td>
<td style="text-align: center;">NY</td>
<td style="text-align: center;">150</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
<tr class="odd">
<td style="text-align: center;">1663</td>
<td style="text-align: center;">SC</td>
<td style="text-align: center;">154</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1664</td>
<td style="text-align: center;">TO</td>
<td style="text-align: center;">383</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
</tbody>
</table>
<p>To write a program that uses this data, we must first decide on a way to store it. As we did with our <span class="math inline">\(Loves\)</span> table of values, well store this table as a list of lists, where each inner list represents one row of the table. Unlike our previous example, these lists wont just store boolean values, so we need to determine what data type to use for each column, based on the sample data we have.</p>
<ul>
<li>The ids and number of marriage licenses are natural numbers, so well use the <code>int</code> data type for them.</li>
<li>The civic centre is a two-letter code, and so well store it as a <code>str</code>.</li>
<li>The time period is a year-month combination; well represent these as dates using the <code>datetime</code> module.<label for="sn-0-8714485ec8" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-8714485ec8" class="margin-toggle"/><span class="sidenote"> To review this <code>date</code> data type, check out <a href="../02-functions/04-importing-modules.html">2.4 Importing Modules</a>.</span></li>
</ul>
<p>With this in mind, let us see how we can store our data as a nested list<label for="sn-1-8714485ec8" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-8714485ec8" class="margin-toggle"/><span class="sidenote"> In tutorial, you will explore how to load the data from a file into a nested list.</span>:</p>
<div class="sourceCode" id="cb1-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-8714485ec8"><a href="#cb1-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> datetime</span>
<span id="cb1-2-8714485ec8"><a href="#cb1-2-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> marriage_data <span class="op">=</span> [</span>
<span id="cb1-3-8714485ec8"><a href="#cb1-3-8714485ec8"></a>... [<span class="dv">1657</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">80</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb1-4-8714485ec8"><a href="#cb1-4-8714485ec8"></a>... [<span class="dv">1658</span>, <span class="st">&#39;NY&#39;</span>, <span class="dv">136</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb1-5-8714485ec8"><a href="#cb1-5-8714485ec8"></a>... [<span class="dv">1659</span>, <span class="st">&#39;SC&#39;</span>, <span class="dv">159</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb1-6-8714485ec8"><a href="#cb1-6-8714485ec8"></a>... [<span class="dv">1660</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">367</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb1-7-8714485ec8"><a href="#cb1-7-8714485ec8"></a>... [<span class="dv">1661</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">109</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)],</span>
<span id="cb1-8-8714485ec8"><a href="#cb1-8-8714485ec8"></a>... [<span class="dv">1662</span>, <span class="st">&#39;NY&#39;</span>, <span class="dv">150</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)],</span>
<span id="cb1-9-8714485ec8"><a href="#cb1-9-8714485ec8"></a>... [<span class="dv">1663</span>, <span class="st">&#39;SC&#39;</span>, <span class="dv">154</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)],</span>
<span id="cb1-10-8714485ec8"><a href="#cb1-10-8714485ec8"></a>... [<span class="dv">1664</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">383</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)]</span>
<span id="cb1-11-8714485ec8"><a href="#cb1-11-8714485ec8"></a>... ]</span>
<span id="cb1-12-8714485ec8"><a href="#cb1-12-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">len</span>(marriage_data) <span class="co"># There are eight rows of data</span></span>
<span id="cb1-13-8714485ec8"><a href="#cb1-13-8714485ec8"></a><span class="dv">8</span></span>
<span id="cb1-14-8714485ec8"><a href="#cb1-14-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">len</span>(marriage_data[<span class="dv">0</span>]) <span class="co"># The first row has four elements</span></span>
<span id="cb1-15-8714485ec8"><a href="#cb1-15-8714485ec8"></a><span class="dv">4</span></span>
<span id="cb1-16-8714485ec8"><a href="#cb1-16-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> [<span class="bu">len</span>(row) <span class="cf">for</span> row <span class="kw">in</span> marriage_data] <span class="co"># Every row has four elements</span></span>
<span id="cb1-17-8714485ec8"><a href="#cb1-17-8714485ec8"></a>[<span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">4</span>]</span>
<span id="cb1-18-8714485ec8"><a href="#cb1-18-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> marriage_data[<span class="dv">0</span>]</span>
<span id="cb1-19-8714485ec8"><a href="#cb1-19-8714485ec8"></a>[<span class="dv">1657</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">80</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)]</span>
<span id="cb1-20-8714485ec8"><a href="#cb1-20-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> marriage_data[<span class="dv">1</span>]</span>
<span id="cb1-21-8714485ec8"><a href="#cb1-21-8714485ec8"></a>[<span class="dv">1658</span>, <span class="st">&#39;NY&#39;</span>, <span class="dv">136</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)]</span></code></pre></div>
<p>We can see that by indexing the nested list <code>marriage_data</code>, a list is returned. Specifically, this list represents a row from our table. For each row, we can then access its id via index 0, its civic centre via index 1, and so on.</p>
<div class="sourceCode" id="cb2-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-8714485ec8"><a href="#cb2-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> marriage_data[<span class="dv">0</span>][<span class="dv">0</span>]</span>
<span id="cb2-2-8714485ec8"><a href="#cb2-2-8714485ec8"></a><span class="dv">1657</span></span>
<span id="cb2-3-8714485ec8"><a href="#cb2-3-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> marriage_data[<span class="dv">0</span>][<span class="dv">1</span>]</span>
<span id="cb2-4-8714485ec8"><a href="#cb2-4-8714485ec8"></a><span class="co">&#39;ET&#39;</span></span>
<span id="cb2-5-8714485ec8"><a href="#cb2-5-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> marriage_data[<span class="dv">0</span>][<span class="dv">2</span>]</span>
<span id="cb2-6-8714485ec8"><a href="#cb2-6-8714485ec8"></a><span class="dv">80</span></span>
<span id="cb2-7-8714485ec8"><a href="#cb2-7-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> marriage_data[<span class="dv">0</span>][<span class="dv">3</span>]</span>
<span id="cb2-8-8714485ec8"><a href="#cb2-8-8714485ec8"></a>datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)</span></code></pre></div>
<h2 id="accessing-columns-and-filtering-rows-8714485ec8">Accessing columns and filtering rows</h2>
<p>Suppose we want to see all of the different values from a single column of this table (e.g., all civic centres or marriage license numbers). We can retrieve a column by using a list comprehension:</p>
<div class="sourceCode" id="cb3-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-8714485ec8"><a href="#cb3-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> [row[<span class="dv">1</span>] <span class="cf">for</span> row <span class="kw">in</span> marriage_data] <span class="co"># The civic centre column</span></span>
<span id="cb3-2-8714485ec8"><a href="#cb3-2-8714485ec8"></a>[<span class="st">&#39;ET&#39;</span>, <span class="st">&#39;NY&#39;</span>, <span class="st">&#39;SC&#39;</span>, <span class="st">&#39;TO&#39;</span>, <span class="st">&#39;ET&#39;</span>, <span class="st">&#39;NY&#39;</span>, <span class="st">&#39;SC&#39;</span>, <span class="st">&#39;TO&#39;</span>]</span></code></pre></div>
<p>Or, using an identically-structured set comprehension, we can obtain all unique values in a column.</p>
<div class="sourceCode" id="cb4-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-8714485ec8"><a href="#cb4-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> {row[<span class="dv">1</span>] <span class="cf">for</span> row <span class="kw">in</span> marriage_data}</span>
<span id="cb4-2-8714485ec8"><a href="#cb4-2-8714485ec8"></a>{<span class="st">&#39;NY&#39;</span>, <span class="st">&#39;TO&#39;</span>, <span class="st">&#39;ET&#39;</span>, <span class="st">&#39;SC&#39;</span>}</span></code></pre></div>
<p>Using our knowledge of filtering using if conditions in comprehensions, we can retrieve all rows corresponding to a specific civic centre.</p>
<div class="sourceCode" id="cb5-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-8714485ec8"><a href="#cb5-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> [row <span class="cf">for</span> row <span class="kw">in</span> marriage_data <span class="cf">if</span> row[<span class="dv">1</span>] <span class="op">==</span> <span class="st">&#39;TO&#39;</span>]</span>
<span id="cb5-2-8714485ec8"><a href="#cb5-2-8714485ec8"></a>[[<span class="dv">1660</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">367</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)], [<span class="dv">1664</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">383</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)]]</span></code></pre></div>
<p>Or we can filter rows based on a threshold for the number of marriage licenses issued:</p>
<div class="sourceCode" id="cb6-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-8714485ec8"><a href="#cb6-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> [row <span class="cf">for</span> row <span class="kw">in</span> marriage_data <span class="cf">if</span> row[<span class="dv">2</span>] <span class="op">&gt;</span> <span class="dv">380</span>]</span>
<span id="cb6-2-8714485ec8"><a href="#cb6-2-8714485ec8"></a>[[<span class="dv">1664</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">383</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)]]</span></code></pre></div>
<h2 id="a-worked-example-8714485ec8">A worked example</h2>
<p>Earlier, we asked the question: What is the average number of marriage licenses issued by each civic centre? The question implies a mapping of civic centre names to numbers (i.e., the average). This means we need to create a dictionary comprehension. Lets start exploring in the Python console. Remember, we saw earlier that we can get all unique civic centre names in the data through a set comprehension.</p>
<div class="sourceCode" id="cb7-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-8714485ec8"><a href="#cb7-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> names <span class="op">=</span> {row[<span class="dv">1</span>] <span class="cf">for</span> row <span class="kw">in</span> marriage_data}</span>
<span id="cb7-2-8714485ec8"><a href="#cb7-2-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> names</span>
<span id="cb7-3-8714485ec8"><a href="#cb7-3-8714485ec8"></a>{<span class="st">&#39;NY&#39;</span>, <span class="st">&#39;TO&#39;</span>, <span class="st">&#39;ET&#39;</span>, <span class="st">&#39;SC&#39;</span>}</span>
<span id="cb7-4-8714485ec8"><a href="#cb7-4-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> {key: <span class="dv">0</span> <span class="cf">for</span> key <span class="kw">in</span> names}</span>
<span id="cb7-5-8714485ec8"><a href="#cb7-5-8714485ec8"></a>{<span class="st">&#39;NY&#39;</span>: <span class="dv">0</span>, <span class="st">&#39;TO&#39;</span>: <span class="dv">0</span>, <span class="st">&#39;ET&#39;</span>: <span class="dv">0</span>, <span class="st">&#39;SC&#39;</span>: <span class="dv">0</span>}</span></code></pre></div>
<p>So far, weve created a dictionary where each key is a civic centre name and they all map to the value 0. To proceed, we need to be able to calculate the average number of marriage licenses issued per month by each civic centre.</p>
<p>Lets try to do this just for the <code>'TO'</code> civic centre first. We saw earlier how to get all rows for a specific civic centre, and to extract the values for a specific column. Well first combine these two operations to retrieve the number of marriage licenses issued by <code>'TO'</code> each month.</p>
<div class="sourceCode" id="cb8-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-8714485ec8"><a href="#cb8-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> [row <span class="cf">for</span> row <span class="kw">in</span> marriage_data <span class="cf">if</span> row[<span class="dv">1</span>] <span class="op">==</span> <span class="st">&#39;TO&#39;</span>] <span class="co"># The &#39;TO&#39; rows</span></span>
<span id="cb8-2-8714485ec8"><a href="#cb8-2-8714485ec8"></a>[[<span class="dv">1660</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">367</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)], [<span class="dv">1664</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">383</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)]]</span>
<span id="cb8-3-8714485ec8"><a href="#cb8-3-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> [row[<span class="dv">2</span>] <span class="cf">for</span> row <span class="kw">in</span> marriage_data <span class="cf">if</span> row[<span class="dv">1</span>] <span class="op">==</span> <span class="st">&#39;TO&#39;</span>] <span class="co"># The &#39;TO&#39; marriages issued</span></span>
<span id="cb8-4-8714485ec8"><a href="#cb8-4-8714485ec8"></a>[<span class="dv">367</span>, <span class="dv">383</span>]</span>
<span id="cb8-5-8714485ec8"><a href="#cb8-5-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> issued_by_TO <span class="op">=</span> [row[<span class="dv">2</span>] <span class="cf">for</span> row <span class="kw">in</span> marriage_data <span class="cf">if</span> row[<span class="dv">1</span>] <span class="op">==</span> <span class="st">&#39;TO&#39;</span>]</span></code></pre></div>
<p>So <code>issued_by_TO</code> is now a list containing the number of marriage licenses issued by the <code>'TO'</code> civic centre. We can now calculate their average by dividing its sum by its length:</p>
<div class="sourceCode" id="cb9-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-8714485ec8"><a href="#cb9-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">sum</span>(issued_by_TO) <span class="op">/</span> <span class="bu">len</span>(issued_by_TO)</span>
<span id="cb9-2-8714485ec8"><a href="#cb9-2-8714485ec8"></a><span class="fl">375.0</span></span></code></pre></div>
<p>Excellent! Through our exploration, we managed to find the average number of marriage licenses issued by one specific civic centre. How can we merge this with our earlier dictionary comprehension? Its quite a bit to keep in our head at once, and looks like it will quickly get messy. At this point, we should design a function to help us. Specifically, lets design a function that calculates the average for only one civic centre. As input, we will need the dataset as well as the name of the civic centre we are querying.</p>
<div class="sourceCode" id="cb10-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-8714485ec8"><a href="#cb10-1-8714485ec8"></a><span class="kw">def</span> average_licenses_issued(data: <span class="bu">list</span>[<span class="bu">list</span>], civic_centre: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb10-2-8714485ec8"><a href="#cb10-2-8714485ec8"></a> <span class="co">&quot;&quot;&quot;Return the average number of marriage licenses issued by civic_centre in data.</span></span>
<span id="cb10-3-8714485ec8"><a href="#cb10-3-8714485ec8"></a></span>
<span id="cb10-4-8714485ec8"><a href="#cb10-4-8714485ec8"></a><span class="co"> Return 0.0 if civic_centre does not appear in the given data.</span></span>
<span id="cb10-5-8714485ec8"><a href="#cb10-5-8714485ec8"></a></span>
<span id="cb10-6-8714485ec8"><a href="#cb10-6-8714485ec8"></a><span class="co"> Preconditions:</span></span>
<span id="cb10-7-8714485ec8"><a href="#cb10-7-8714485ec8"></a><span class="co"> - all({len(row) == 4 for row in data})</span></span>
<span id="cb10-8-8714485ec8"><a href="#cb10-8-8714485ec8"></a><span class="co"> - data is in the format described in Section 4.1</span></span>
<span id="cb10-9-8714485ec8"><a href="#cb10-9-8714485ec8"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb10-10-8714485ec8"><a href="#cb10-10-8714485ec8"></a> issued_by_civic_centre <span class="op">=</span> [row[<span class="dv">2</span>] <span class="cf">for</span> row <span class="kw">in</span> data <span class="cf">if</span> row[<span class="dv">1</span>] <span class="op">==</span> civic_centre]</span>
<span id="cb10-11-8714485ec8"><a href="#cb10-11-8714485ec8"></a></span>
<span id="cb10-12-8714485ec8"><a href="#cb10-12-8714485ec8"></a> <span class="cf">if</span> issued_by_civic_centre <span class="op">==</span> []:</span>
<span id="cb10-13-8714485ec8"><a href="#cb10-13-8714485ec8"></a> <span class="cf">return</span> <span class="fl">0.0</span></span>
<span id="cb10-14-8714485ec8"><a href="#cb10-14-8714485ec8"></a> <span class="cf">else</span>:</span>
<span id="cb10-15-8714485ec8"><a href="#cb10-15-8714485ec8"></a> total <span class="op">=</span> <span class="bu">sum</span>(issued_by_civic_centre)</span>
<span id="cb10-16-8714485ec8"><a href="#cb10-16-8714485ec8"></a> count <span class="op">=</span> <span class="bu">len</span>(issued_by_civic_centre)</span>
<span id="cb10-17-8714485ec8"><a href="#cb10-17-8714485ec8"></a></span>
<span id="cb10-18-8714485ec8"><a href="#cb10-18-8714485ec8"></a> <span class="cf">return</span> total <span class="op">/</span> count</span></code></pre></div>
<p>Lets test it to make sure we get the same result as before:</p>
<div class="sourceCode" id="cb11-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-8714485ec8"><a href="#cb11-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> average_licenses_issued(marriage_data, <span class="st">&#39;TO&#39;</span>)</span>
<span id="cb11-2-8714485ec8"><a href="#cb11-2-8714485ec8"></a><span class="fl">375.0</span></span></code></pre></div>
<p>Finally, we can combine it with our previous dictionary comprehension by observing that <code>'TO'</code> can be replaced with the <code>key</code> that is changing:</p>
<div class="sourceCode" id="cb12-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-8714485ec8"><a href="#cb12-1-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> {key: <span class="dv">0</span> <span class="cf">for</span> key <span class="kw">in</span> names}</span>
<span id="cb12-2-8714485ec8"><a href="#cb12-2-8714485ec8"></a>{<span class="st">&#39;NY&#39;</span>: <span class="dv">0</span>, <span class="st">&#39;TO&#39;</span>: <span class="dv">0</span>, <span class="st">&#39;ET&#39;</span>: <span class="dv">0</span>, <span class="st">&#39;SC&#39;</span>: <span class="dv">0</span>}</span>
<span id="cb12-3-8714485ec8"><a href="#cb12-3-8714485ec8"></a><span class="op">&gt;&gt;&gt;</span> {key: average_licenses_issued(marriage_data, key) <span class="cf">for</span> key <span class="kw">in</span> names}</span>
<span id="cb12-4-8714485ec8"><a href="#cb12-4-8714485ec8"></a>{<span class="st">&#39;NY&#39;</span>: <span class="fl">143.0</span>, <span class="st">&#39;TO&#39;</span>: <span class="fl">375.0</span>, <span class="st">&#39;ET&#39;</span>: <span class="fl">94.5</span>, <span class="st">&#39;SC&#39;</span>: <span class="fl">156.5</span>}</span></code></pre></div>
<p>Now that weve done this exploration in the Python console, we can save our work by writing this as a function:</p>
<div class="sourceCode" id="cb13-8714485ec8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-8714485ec8"><a href="#cb13-1-8714485ec8"></a><span class="kw">def</span> average_licenses_by_centre(marriage_data: <span class="bu">list</span>[<span class="bu">list</span>]) <span class="op">-&gt;</span> Dict[<span class="bu">str</span>, <span class="bu">float</span>]:</span>
<span id="cb13-2-8714485ec8"><a href="#cb13-2-8714485ec8"></a> <span class="co">&quot;&quot;&quot;Return a mapping of the average number of marriage licenses issued at each civic centre.</span></span>
<span id="cb13-3-8714485ec8"><a href="#cb13-3-8714485ec8"></a></span>
<span id="cb13-4-8714485ec8"><a href="#cb13-4-8714485ec8"></a><span class="co"> In the returned mapping:</span></span>
<span id="cb13-5-8714485ec8"><a href="#cb13-5-8714485ec8"></a><span class="co"> - Each key is the name of a civic centre</span></span>
<span id="cb13-6-8714485ec8"><a href="#cb13-6-8714485ec8"></a><span class="co"> - Each corresponding value is the average number of marriage licenses issued at</span></span>
<span id="cb13-7-8714485ec8"><a href="#cb13-7-8714485ec8"></a><span class="co"> that centre.</span></span>
<span id="cb13-8-8714485ec8"><a href="#cb13-8-8714485ec8"></a></span>
<span id="cb13-9-8714485ec8"><a href="#cb13-9-8714485ec8"></a><span class="co"> Preconditions:</span></span>
<span id="cb13-10-8714485ec8"><a href="#cb13-10-8714485ec8"></a><span class="co"> - marriage_data is in the format described in Section 4.1</span></span>
<span id="cb13-11-8714485ec8"><a href="#cb13-11-8714485ec8"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-12-8714485ec8"><a href="#cb13-12-8714485ec8"></a> names <span class="op">=</span> {<span class="st">&#39;TO&#39;</span>, <span class="st">&#39;NY&#39;</span>, <span class="st">&#39;ET&#39;</span>, <span class="st">&#39;SC&#39;</span>}</span>
<span id="cb13-13-8714485ec8"><a href="#cb13-13-8714485ec8"></a> <span class="cf">return</span> {key: average_licenses_issued(marriage_data, key) <span class="cf">for</span> key <span class="kw">in</span> names}</span></code></pre></div>
</section>
<br/> <a id="anchor-04-02"></a>
<header id="title-block-header-ed7f2f831d">
<h1 class="title">4.2 Defining Our Own Data Types, Part 1</h1>
</header>
<section>
<p>Up to this point, all the data weve worked with in Python have been stored in objects that are instances of the built-in types that come with Python, like <code>int</code>s and <code>list</code>s. Pythons built-in data types are powerful, but are not always the most intuitive way to store data. For example, we saw in <a href="01-tabular-data.html">4.1 Tabular Data</a> that we could use a list of lists to represent tabular data. One of the downsides of this approach is that when working with this data, the onus is on us to remember which list element corresponds to which component of the data.</p>
<div class="sourceCode" id="cb1-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-ed7f2f831d"><a href="#cb1-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> datetime</span>
<span id="cb1-2-ed7f2f831d"><a href="#cb1-2-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> row <span class="op">=</span> [<span class="dv">1657</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">80</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)]</span>
<span id="cb1-3-ed7f2f831d"><a href="#cb1-3-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> row[<span class="dv">0</span>] <span class="co"># The id</span></span>
<span id="cb1-4-ed7f2f831d"><a href="#cb1-4-ed7f2f831d"></a><span class="dv">1657</span></span>
<span id="cb1-5-ed7f2f831d"><a href="#cb1-5-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> row[<span class="dv">1</span>] <span class="co"># The name of the civic centre</span></span>
<span id="cb1-6-ed7f2f831d"><a href="#cb1-6-ed7f2f831d"></a><span class="co">&#39;ET&#39;</span></span>
<span id="cb1-7-ed7f2f831d"><a href="#cb1-7-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> row[<span class="dv">2</span>] <span class="co"># The number of marriage licenses issued</span></span>
<span id="cb1-8-ed7f2f831d"><a href="#cb1-8-ed7f2f831d"></a><span class="dv">80</span></span>
<span id="cb1-9-ed7f2f831d"><a href="#cb1-9-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> row[<span class="dv">3</span>] <span class="co"># The time period</span></span>
<span id="cb1-10-ed7f2f831d"><a href="#cb1-10-ed7f2f831d"></a>datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)</span></code></pre></div>
<p>You can imagine how error prone this might be. A simple “off by one” error for an index might retrieve a completely different data type. It also makes our code difficult to read; the reader must know what each index of the list represents. And, as more experienced programmers will tell you, readable code is crucial.<label for="sn-0-ed7f2f831d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-ed7f2f831d" class="margin-toggle"/><span class="sidenote"> “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” Martin Fowler</span></p>
<p>So a row in our marriage license data set is made up of four data elements. It would be nice if, instead of indices, we could use a name that was reflective of each element. Certainly, we could use a dictionary (instead of a list) where the keys are strings. But there is a more robust option well learn about in this section: creating our <em>own</em> data types.</p>
<h2 id="defining-a-data-class-ed7f2f831d">Defining a data class</h2>
<p>You might remember from Chapter 1 that in Python, another term for data type is a <strong>class</strong>.<label for="sn-1-ed7f2f831d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-ed7f2f831d" class="margin-toggle"/><span class="sidenote"> This is why <code>type(3)</code> evaluates to <code>&lt;class 'int'&gt;</code> in Python.</span> The built-in data types weve studied so far illustrate how rich and complex data types can be. So for creating our own data types, we will first learn about the simplest kind of data type: a <strong>data class</strong>, which is a kind of class whose purpose is to bundle individual pieces of data into a single Python object.</p>
<p>For example, suppose we want to represent a “person” consisting of a given name, family name, age, and home address. We already know how to represent each individual piece of data: the given name, family name, and address could be strings, and the age could be a natural number. To bundle these values together, we could use a list or other built-in collection data type, but that approach would run into the issues we discussed above.</p>
<p>So instead, we define our own data class to create a new data type consisting of these four values. Here is the way to create a data class in Python:</p>
<div class="sourceCode" id="cb2-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-ed7f2f831d"><a href="#cb2-1-ed7f2f831d"></a><span class="im">from</span> dataclasses <span class="im">import</span> dataclass</span>
<span id="cb2-2-ed7f2f831d"><a href="#cb2-2-ed7f2f831d"></a></span>
<span id="cb2-3-ed7f2f831d"><a href="#cb2-3-ed7f2f831d"></a></span>
<span id="cb2-4-ed7f2f831d"><a href="#cb2-4-ed7f2f831d"></a><span class="at">@dataclass</span></span>
<span id="cb2-5-ed7f2f831d"><a href="#cb2-5-ed7f2f831d"></a><span class="kw">class</span> Person:</span>
<span id="cb2-6-ed7f2f831d"><a href="#cb2-6-ed7f2f831d"></a> <span class="co">&quot;&quot;&quot;A custom data type that represents data for a person.&quot;&quot;&quot;</span></span>
<span id="cb2-7-ed7f2f831d"><a href="#cb2-7-ed7f2f831d"></a> given_name: <span class="bu">str</span></span>
<span id="cb2-8-ed7f2f831d"><a href="#cb2-8-ed7f2f831d"></a> family_name: <span class="bu">str</span></span>
<span id="cb2-9-ed7f2f831d"><a href="#cb2-9-ed7f2f831d"></a> age: <span class="bu">int</span></span>
<span id="cb2-10-ed7f2f831d"><a href="#cb2-10-ed7f2f831d"></a> address: <span class="bu">str</span></span></code></pre></div>
<p>Lets unpack this definition.</p>
<ol type="1">
<li><p><code>from dataclasses import dataclass</code> is a Python import statement that lets us use <code>dataclass</code> below.</p></li>
<li><p><code>@dataclass</code> is a Python <em>decorator</em>. Weve seen decorators before for function definitions; a decorator for a class definition works in the same way, acting as a modifier for our definition. In this case, <code>@dataclass</code> tells Python that the data type were defining is a data class, which well explore the benefits of down below.</p></li>
<li><p><code>class Person:</code>, signals the start of a <em>class definition</em>.<label for="sn-2-ed7f2f831d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-ed7f2f831d" class="margin-toggle"/><span class="sidenote"> This is similar to function definitions, except we use the <code>class</code> keyword instead of <code>def</code>. </span> The name of the class is <code>Person</code>.</p>
<p>The rest of the code is indented to put it inside of the class body.</p></li>
<li><p>The next line is a docstring that describes the purpose of the class.</p></li>
<li><p>Each remaining line (starting with <code>given_name: str</code>) defines a piece of data associated with the class; each piece of data is called an <strong>instance attribute</strong> of the class.</p>
<p>For each instance attribute, we write a name and a type annotation.<label for="sn-3-ed7f2f831d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-ed7f2f831d" class="margin-toggle"/><span class="sidenote"> This is similar to defining parameter names and types for functions, though of course the purposes are different. </span></p></li>
</ol>
<h3 id="general-data-class-definition-syntax-ed7f2f831d">General data class definition syntax</h3>
<p>In general, a data class definition in Python has the following syntax:</p>
<div class="sourceCode" id="cb3-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-ed7f2f831d"><a href="#cb3-1-ed7f2f831d"></a><span class="at">@dataclass</span></span>
<span id="cb3-2-ed7f2f831d"><a href="#cb3-2-ed7f2f831d"></a><span class="kw">class</span> <span class="op">&lt;</span>ClassName<span class="op">&gt;</span>:</span>
<span id="cb3-3-ed7f2f831d"><a href="#cb3-3-ed7f2f831d"></a> <span class="co">&quot;&quot;&quot;Description of data class.</span></span>
<span id="cb3-4-ed7f2f831d"><a href="#cb3-4-ed7f2f831d"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-5-ed7f2f831d"><a href="#cb3-5-ed7f2f831d"></a> <span class="op">&lt;</span>attribute1<span class="op">&gt;</span>: <span class="op">&lt;</span>type1<span class="op">&gt;</span></span>
<span id="cb3-6-ed7f2f831d"><a href="#cb3-6-ed7f2f831d"></a> <span class="op">&lt;</span>attribute2<span class="op">&gt;</span>: <span class="op">&lt;</span>type2<span class="op">&gt;</span></span>
<span id="cb3-7-ed7f2f831d"><a href="#cb3-7-ed7f2f831d"></a> ...</span></code></pre></div>
<h2 id="using-data-classes-ed7f2f831d">Using data classes</h2>
<p>Now that weve seen how to define a data class, we now are ready to actually put it to use. To create an instance of our <code>Person</code> data class, we write a Python expression that calls the data class, passing in as arguments the values for each instance attribute:</p>
<div class="sourceCode" id="cb4-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-ed7f2f831d"><a href="#cb4-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Liu&#39;</span>, <span class="dv">100</span>, <span class="st">&#39;40 St. George Street&#39;</span>)</span></code></pre></div>
<p>Pretty cool! That line of code creates a new <code>Person</code> object whose given name is <code>'David'</code>, family name is <code>'Liu'</code>, age is <code>100</code>, and address is <code>'40 St. George Street'</code>, and stores the object in the variable <code>david</code>. The <em>type</em> of this new value is, as wed expect, <code>Person</code>:</p>
<div class="sourceCode" id="cb5-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-ed7f2f831d"><a href="#cb5-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(david)</span>
<span id="cb5-2-ed7f2f831d"><a href="#cb5-2-ed7f2f831d"></a><span class="op">&lt;</span><span class="kw">class</span> Person<span class="op">&gt;</span></span></code></pre></div>
<p>If we ask Python to evaluate the <code>Person</code> object, we see the different pieces of data that have been bundled together:</p>
<div class="sourceCode" id="cb6-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-ed7f2f831d"><a href="#cb6-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david</span>
<span id="cb6-2-ed7f2f831d"><a href="#cb6-2-ed7f2f831d"></a>Person(given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>, family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>, age<span class="op">=</span><span class="dv">100</span>, address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>)</span></code></pre></div>
<p>But from a <code>Person</code> object, how do we extract the individual values we bundled together? If we were using lists, wed simply do list indexing: <code>david[0]</code>, <code>david[1]</code>, etc. The syntax for Python classes improves this because we can use the names of the instance attributes together with <strong>dot notation</strong> to access these values:</p>
<div class="sourceCode" id="cb7-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-ed7f2f831d"><a href="#cb7-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david.given_name</span>
<span id="cb7-2-ed7f2f831d"><a href="#cb7-2-ed7f2f831d"></a><span class="co">&#39;David&#39;</span></span>
<span id="cb7-3-ed7f2f831d"><a href="#cb7-3-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david.family_name</span>
<span id="cb7-4-ed7f2f831d"><a href="#cb7-4-ed7f2f831d"></a><span class="co">&#39;Liu&#39;</span></span>
<span id="cb7-5-ed7f2f831d"><a href="#cb7-5-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david.age</span>
<span id="cb7-6-ed7f2f831d"><a href="#cb7-6-ed7f2f831d"></a><span class="dv">100</span></span>
<span id="cb7-7-ed7f2f831d"><a href="#cb7-7-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david.address</span>
<span id="cb7-8-ed7f2f831d"><a href="#cb7-8-ed7f2f831d"></a><span class="co">&#39;40 St. George Street&#39;</span></span></code></pre></div>
<p>This is much more readable than list indexing, and this is one of the major advantages of using data classes over lists to represent custom data in Python.</p>
<h2 id="tip-naming-attributes-when-creating-data-class-instances-ed7f2f831d">Tip: naming attributes when creating data class instances</h2>
<p>One challenge when creating instances of our data classes is keeping track of which arguments correspond to which instance attributes. In the expression <code>Person('David', 'Liu', 100, '40 St. George Street')</code>, the order of the arguments must match the order the instance attributes are listed in the definition of the data class—and its our responsibility to remember this order. Think about how easy it would be for us to write <code>Person('Liu', 'David', 100, '40 St. George Street')</code>, only to discover much later in our program that we accidentally switched this poor fellows given and family names!</p>
<p>To solve this issue, Python enables us to create data class instances using <em>keyword arguments</em> to explicitly name which argument corresponds to which instance attribute, using the exact same format as the <code>Person</code> representation we saw above:</p>
<div class="sourceCode" id="cb8-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-ed7f2f831d"><a href="#cb8-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>, family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>, age<span class="op">=</span><span class="dv">100</span>, address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>)</span></code></pre></div>
<p>Not only is this more explicit, but using keyword arguments allows us to pass the values in any order we want:</p>
<div class="sourceCode" id="cb9-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-ed7f2f831d"><a href="#cb9-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>, given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>, address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>, age<span class="op">=</span><span class="dv">100</span>)</span></code></pre></div>
<p>This is a great improvement for the readability of our code when we use data classes, especially as they grow larger. One potential downside that comes with this (and in general when being more explicit) is that this requires a bit more typing, and makes our code a little longer. You can get around the first issue by using auto-completion features (e.g., in PyCharm), and for the second issue you can put the different arguments on separate lines:</p>
<div class="sourceCode" id="cb10-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-ed7f2f831d"><a href="#cb10-1-ed7f2f831d"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(</span>
<span id="cb10-2-ed7f2f831d"><a href="#cb10-2-ed7f2f831d"></a>... family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>,</span>
<span id="cb10-3-ed7f2f831d"><a href="#cb10-3-ed7f2f831d"></a>... given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>,</span>
<span id="cb10-4-ed7f2f831d"><a href="#cb10-4-ed7f2f831d"></a>... address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>,</span>
<span id="cb10-5-ed7f2f831d"><a href="#cb10-5-ed7f2f831d"></a>... age<span class="op">=</span><span class="dv">100</span></span>
<span id="cb10-6-ed7f2f831d"><a href="#cb10-6-ed7f2f831d"></a>... )</span></code></pre></div>
<h3 id="representing-data-classes-in-the-memory-model-ed7f2f831d">Representing data classes in the memory model</h3>
<p>Now that we have the ability to define our own data types, we need to decide how these data types will fit into our memory model. Well do this by using the representation that Python displays, formatted to show each instance attribute on a new line. For example, we would represent the <code>david</code> variable in a memory model as follows:</p>
<div class="memory-model-values" style="width:65%">
<table style="width:69%;">
<colgroup>
<col style="width: 15%" />
<col style="width: 54%" />
</colgroup>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>david</code></td>
<td><div class="sourceCode" id="cb11-ed7f2f831d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-ed7f2f831d"><a href="#cb11-1-ed7f2f831d"></a>Person(</span>
<span id="cb11-2-ed7f2f831d"><a href="#cb11-2-ed7f2f831d"></a> family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>,</span>
<span id="cb11-3-ed7f2f831d"><a href="#cb11-3-ed7f2f831d"></a> given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>,</span>
<span id="cb11-4-ed7f2f831d"><a href="#cb11-4-ed7f2f831d"></a> address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>,</span>
<span id="cb11-5-ed7f2f831d"><a href="#cb11-5-ed7f2f831d"></a> age<span class="op">=</span><span class="dv">100</span></span>
<span id="cb11-6-ed7f2f831d"><a href="#cb11-6-ed7f2f831d"></a>)</span></code></pre></div>
 </td>
</tr>
</tbody>
</table>
</div>
</section>
<!--
In Python, a **class** defines a data type.
The data types we've been working with so far (e.g., `int`, `dict`) are classes.
When we create, for example, a list, we have created an **object**.
Careful, an object and a class are two different things.
While a class defines the data type and you can think of it like a template or form.
An object is the template with all the blank spaces filled out.
We say that an **object** is an **instance** of a **class**.
-->
<br/> <a id="anchor-04-03"></a>
<header id="title-block-header-f0ff4a06d4">
<h1 class="title">4.3 Defining Our Own Data Types, Part 2</h1>
</header>
<section>
<p>In the previous section, we learned about <em>data classes</em>, a way to define our own data types in Python. In this section, were going to learn study some more details about defining and designing data classes in our programs, and apply what weve learned to simplify some of work we did with tabular data in <a href="01-tabular-data.html">4.1 Tabular Data</a>.</p>
<p>Before we begin, please take a moment to review the <code>Person</code> data class we developed in the previous section.</p>
<div class="sourceCode" id="cb1-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-f0ff4a06d4"><a href="#cb1-1-f0ff4a06d4"></a><span class="im">from</span> dataclasses <span class="im">import</span> dataclass</span>
<span id="cb1-2-f0ff4a06d4"><a href="#cb1-2-f0ff4a06d4"></a></span>
<span id="cb1-3-f0ff4a06d4"><a href="#cb1-3-f0ff4a06d4"></a></span>
<span id="cb1-4-f0ff4a06d4"><a href="#cb1-4-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb1-5-f0ff4a06d4"><a href="#cb1-5-f0ff4a06d4"></a><span class="kw">class</span> Person:</span>
<span id="cb1-6-f0ff4a06d4"><a href="#cb1-6-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;A custom data type that represents data for a person.&quot;&quot;&quot;</span></span>
<span id="cb1-7-f0ff4a06d4"><a href="#cb1-7-f0ff4a06d4"></a> given_name: <span class="bu">str</span></span>
<span id="cb1-8-f0ff4a06d4"><a href="#cb1-8-f0ff4a06d4"></a> family_name: <span class="bu">str</span></span>
<span id="cb1-9-f0ff4a06d4"><a href="#cb1-9-f0ff4a06d4"></a> age: <span class="bu">int</span></span>
<span id="cb1-10-f0ff4a06d4"><a href="#cb1-10-f0ff4a06d4"></a> address: <span class="bu">str</span></span></code></pre></div>
<h2 id="constraining-data-class-values-representation-invariants-f0ff4a06d4">Constraining data class values: representation invariants</h2>
<p>In our <code>Person</code> data class definition, we specify the type of each instance attribute. By doing so, we constrain the possible values can be stored for these attributes. However, just as we saw with function type contracts, we dont always want to allow every possible value of a given type for an attribute value.</p>
<p>For example, the <code>age</code> attribute for <code>Person</code> has a type annotation <code>int</code>, but we certainly would not allow negative integers to be stored here! Somehow, wed like to record a second piece of information about this attribute: that <code>age &gt;= 0</code>. This kind of constraint is called a <strong>representation invariant</strong>, since it is a predicate describing a condition on how we <em>represent</em> a person that must always be true—this condition never varies.<label for="sn-0-f0ff4a06d4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-f0ff4a06d4" class="margin-toggle"/><span class="sidenote"> The term <em>invariant</em> is used in a few different contexts in computer science; well explore one other kind of invariant a bit later in this chapter.</span> All attribute type annotations, like <code>age: int</code>, are representation invariants. However, we can express general representation invariants as well, by adding them to the class docstring. Whenever possible, we write this as Python expressions rather than English, for a reason well see in the next section.</p>
<p>Here is how we add non-type-annotation representation invariants in a class docstring:</p>
<div class="sourceCode" id="cb2-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-f0ff4a06d4"><a href="#cb2-1-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb2-2-f0ff4a06d4"><a href="#cb2-2-f0ff4a06d4"></a><span class="kw">class</span> Person:</span>
<span id="cb2-3-f0ff4a06d4"><a href="#cb2-3-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;A custom data type that represents data for a person.</span></span>
<span id="cb2-4-f0ff4a06d4"><a href="#cb2-4-f0ff4a06d4"></a></span>
<span id="cb2-5-f0ff4a06d4"><a href="#cb2-5-f0ff4a06d4"></a><span class="co"> Representation Invariants:</span></span>
<span id="cb2-6-f0ff4a06d4"><a href="#cb2-6-f0ff4a06d4"></a><span class="co"> - self.age &gt;= 0</span></span>
<span id="cb2-7-f0ff4a06d4"><a href="#cb2-7-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-8-f0ff4a06d4"><a href="#cb2-8-f0ff4a06d4"></a> given_name: <span class="bu">str</span></span>
<span id="cb2-9-f0ff4a06d4"><a href="#cb2-9-f0ff4a06d4"></a> family_name: <span class="bu">str</span></span>
<span id="cb2-10-f0ff4a06d4"><a href="#cb2-10-f0ff4a06d4"></a> age: <span class="bu">int</span></span>
<span id="cb2-11-f0ff4a06d4"><a href="#cb2-11-f0ff4a06d4"></a> address: <span class="bu">str</span></span></code></pre></div>
<p>One oddity with this definition is that we use <code>self.age</code> instead of <code>age</code> to refer to the instance attribute. This mimics how we access data type attributes using dot notation:</p>
<div class="sourceCode" id="cb3-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-f0ff4a06d4"><a href="#cb3-1-f0ff4a06d4"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Liu&#39;</span>, <span class="dv">100</span>, <span class="st">&#39;40 St. George Street&#39;</span>)</span>
<span id="cb3-2-f0ff4a06d4"><a href="#cb3-2-f0ff4a06d4"></a><span class="op">&gt;&gt;&gt;</span> david.age</span>
<span id="cb3-3-f0ff4a06d4"><a href="#cb3-3-f0ff4a06d4"></a><span class="dv">100</span></span></code></pre></div>
<p>In the class docstring, we use the variable name <code>self</code> to refer to a generic instance of the data class.<label for="sn-1-f0ff4a06d4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-f0ff4a06d4" class="margin-toggle"/><span class="sidenote"> Keep in mind that <code>self</code> here is used just in the class docstring. In the above example, the variable <code>david</code> would appear in our memory model, but <code>self</code> would not.</span> This use of <code>self</code> is a strong Python convention, and well return to other uses of <code>self</code> later on in this course.</p>
<h3 id="checking-representation-invariants-automatically-with-python_ta-f0ff4a06d4">Checking representation invariants automatically with <code>python_ta</code></h3>
<p>Just as we saw with preconditions in <a href="../03-logic/07-function-specification.html">3.7 Function Specification</a>, representation invariants are useful pieces of documentation for how a data class should be used. Like preconditions, representation invariants are <em>assumptions</em> that we make about values of a data type; for example, we can assume that every <code>Person</code> instance has an <code>age</code> thats greater than or equal to zero.</p>
<p>Representation invariants are also <em>constraints</em> on how we can create a data class instance. Because it can be easy to miss or ignore a representation invariant buried in a class docstring, <code>python_ta.contracts</code> supposts checking all representation invariants, just like it does with preconditions! Lets add a <code>check_all_contracts</code> call to our <code>Person</code> example:</p>
<div class="sourceCode" id="cb4-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-f0ff4a06d4"><a href="#cb4-1-f0ff4a06d4"></a><span class="im">from</span> dataclasses <span class="im">import</span> dataclass</span>
<span id="cb4-2-f0ff4a06d4"><a href="#cb4-2-f0ff4a06d4"></a></span>
<span id="cb4-3-f0ff4a06d4"><a href="#cb4-3-f0ff4a06d4"></a></span>
<span id="cb4-4-f0ff4a06d4"><a href="#cb4-4-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb4-5-f0ff4a06d4"><a href="#cb4-5-f0ff4a06d4"></a><span class="kw">class</span> Person:</span>
<span id="cb4-6-f0ff4a06d4"><a href="#cb4-6-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;A person with some basic demographic information.</span></span>
<span id="cb4-7-f0ff4a06d4"><a href="#cb4-7-f0ff4a06d4"></a></span>
<span id="cb4-8-f0ff4a06d4"><a href="#cb4-8-f0ff4a06d4"></a><span class="co"> Representation Invariants:</span></span>
<span id="cb4-9-f0ff4a06d4"><a href="#cb4-9-f0ff4a06d4"></a><span class="co"> - self.age &gt;= 0</span></span>
<span id="cb4-10-f0ff4a06d4"><a href="#cb4-10-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-11-f0ff4a06d4"><a href="#cb4-11-f0ff4a06d4"></a> given_name: <span class="bu">str</span></span>
<span id="cb4-12-f0ff4a06d4"><a href="#cb4-12-f0ff4a06d4"></a> family_name: <span class="bu">str</span></span>
<span id="cb4-13-f0ff4a06d4"><a href="#cb4-13-f0ff4a06d4"></a> age: <span class="bu">int</span></span>
<span id="cb4-14-f0ff4a06d4"><a href="#cb4-14-f0ff4a06d4"></a> address: <span class="bu">str</span></span>
<span id="cb4-15-f0ff4a06d4"><a href="#cb4-15-f0ff4a06d4"></a></span>
<span id="cb4-16-f0ff4a06d4"><a href="#cb4-16-f0ff4a06d4"></a></span>
<span id="cb4-17-f0ff4a06d4"><a href="#cb4-17-f0ff4a06d4"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb4-18-f0ff4a06d4"><a href="#cb4-18-f0ff4a06d4"></a> <span class="im">import</span> python_ta.contracts</span>
<span id="cb4-19-f0ff4a06d4"><a href="#cb4-19-f0ff4a06d4"></a> python_ta.contracts.DEBUG_CONTRACTS <span class="op">=</span> <span class="va">False</span></span>
<span id="cb4-20-f0ff4a06d4"><a href="#cb4-20-f0ff4a06d4"></a> python_ta.contracts.check_all_contracts()</span></code></pre></div>
<p>If we run the above file in the Python console, well obtain an error whenever we attempt to instantiate a <code>Person</code> with invalid attributes.</p>
<div class="sourceCode" id="cb5-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-f0ff4a06d4"><a href="#cb5-1-f0ff4a06d4"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(</span>
<span id="cb5-2-f0ff4a06d4"><a href="#cb5-2-f0ff4a06d4"></a>... given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>,</span>
<span id="cb5-3-f0ff4a06d4"><a href="#cb5-3-f0ff4a06d4"></a>... family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>,</span>
<span id="cb5-4-f0ff4a06d4"><a href="#cb5-4-f0ff4a06d4"></a>... age<span class="op">=-</span><span class="dv">100</span>,</span>
<span id="cb5-5-f0ff4a06d4"><a href="#cb5-5-f0ff4a06d4"></a>... address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>)</span>
<span id="cb5-6-f0ff4a06d4"><a href="#cb5-6-f0ff4a06d4"></a>Traceback (most recent call last):</span>
<span id="cb5-7-f0ff4a06d4"><a href="#cb5-7-f0ff4a06d4"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb5-8-f0ff4a06d4"><a href="#cb5-8-f0ff4a06d4"></a> ...</span>
<span id="cb5-9-f0ff4a06d4"><a href="#cb5-9-f0ff4a06d4"></a><span class="pp">AssertionError</span>: Representation invariant <span class="st">&quot;self.age &gt;= 0&quot;</span> violated.</span></code></pre></div>
<p><strong>Note</strong>: currently, <code>python_ta</code> is strict with the header <code>Representation Invariants:</code>. In particular, both the “<code>Representation</code>” and “<code>Invariants</code>” must be capitalized (and spelled correctly). Please watch out for this, as otherwise any representation invariants you add will not be checked!</p>
<h2 id="the-data-class-design-recipe-f0ff4a06d4">The data class design recipe</h2>
<p>Just as how functions give us a way of organizing blocks of code to represent a computation, data classes give us a way of organizing pieces of data to represent an entity. In <a href="../02-functions/05-the-function-design-recipe.html">2.5 The Function Design Recipe</a>, we learned a structured approach to designing and implementing functions. There is an analogous <strong>Data Class Design Recipe</strong>, which you should use every time you want to create a new data type for a program.<label for="sn-2-f0ff4a06d4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-f0ff4a06d4" class="margin-toggle"/><span class="sidenote"> Note the similarities between the two recipes, such as the importance of naming and documentation.</span></p>
<div class="fullwidth">
<table>
<colgroup>
<col style="width: 59%" />
<col style="width: 40%" />
</colgroup>
<tbody>
<tr class="odd">
<td><p><strong>1. Write the class header.</strong></p>
<p>The class header consists of three parts: the <code>@dataclass</code> decorator (dont forget to import from <code>dataclasses</code>), the keyword <code>class</code>, and the name of the data class. Pick a short noun or noun phrase as the name of the class. The name of the class should use the “CamelCase” naming convention: capitalize every word of the class name, and do <em>not</em> separate the words with underscores.</p></td>
<td><div class="sourceCode" id="cb6-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-f0ff4a06d4"><a href="#cb6-1-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb6-2-f0ff4a06d4"><a href="#cb6-2-f0ff4a06d4"></a><span class="kw">class</span> Person:</span></code></pre></div>
 </td>
</tr>
<tr class="even">
<td><p><strong>2. Write the instance attributes for the data class.</strong></p>
<p>Decide on what attributes you want the data class to bundle together. Remember that every instance of the data class will have <em>all</em> of these attributes.</p>
<p>Each attribute name should be a short noun or noun phrase, using “snake_case” (like function and variable names). Write each annotation name and its type indented within the data class body. |</p></td>
<td><div class="sourceCode" id="cb7-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-f0ff4a06d4"><a href="#cb7-1-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb7-2-f0ff4a06d4"><a href="#cb7-2-f0ff4a06d4"></a><span class="kw">class</span> Person:</span>
<span id="cb7-3-f0ff4a06d4"><a href="#cb7-3-f0ff4a06d4"></a> given_name: <span class="bu">str</span></span>
<span id="cb7-4-f0ff4a06d4"><a href="#cb7-4-f0ff4a06d4"></a> family_name: <span class="bu">str</span></span>
<span id="cb7-5-f0ff4a06d4"><a href="#cb7-5-f0ff4a06d4"></a> age: <span class="bu">int</span></span>
<span id="cb7-6-f0ff4a06d4"><a href="#cb7-6-f0ff4a06d4"></a> address: <span class="bu">str</span></span></code></pre></div>
 </td>
</tr>
<tr class="odd">
<td><p><strong>3. Write the data class docstring.</strong></p>
<p>Create a class docstring using triple-quotes, using the same format as function docstrings. Inside the docstring, write a description of the class and a description for every instance attribute. The class description should start with a one-line summary, and you can add a longer description underneath if necessary.</p>
<p>Use the header “Instance Attributes:” to mark the beginning of the attribute descriptions.</p></td>
<td><div class="sourceCode" id="cb8-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-f0ff4a06d4"><a href="#cb8-1-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb8-2-f0ff4a06d4"><a href="#cb8-2-f0ff4a06d4"></a><span class="kw">class</span> Person:</span>
<span id="cb8-3-f0ff4a06d4"><a href="#cb8-3-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;A data class representing a person.</span></span>
<span id="cb8-4-f0ff4a06d4"><a href="#cb8-4-f0ff4a06d4"></a></span>
<span id="cb8-5-f0ff4a06d4"><a href="#cb8-5-f0ff4a06d4"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb8-6-f0ff4a06d4"><a href="#cb8-6-f0ff4a06d4"></a><span class="co"> - given_name: the person&#39;s given name</span></span>
<span id="cb8-7-f0ff4a06d4"><a href="#cb8-7-f0ff4a06d4"></a><span class="co"> - family_name: the person&#39;s family name</span></span>
<span id="cb8-8-f0ff4a06d4"><a href="#cb8-8-f0ff4a06d4"></a><span class="co"> - age: the person&#39;s age</span></span>
<span id="cb8-9-f0ff4a06d4"><a href="#cb8-9-f0ff4a06d4"></a><span class="co"> - address: the person&#39;s address</span></span>
<span id="cb8-10-f0ff4a06d4"><a href="#cb8-10-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb8-11-f0ff4a06d4"><a href="#cb8-11-f0ff4a06d4"></a> given_name: <span class="bu">str</span></span>
<span id="cb8-12-f0ff4a06d4"><a href="#cb8-12-f0ff4a06d4"></a> family_name: <span class="bu">str</span></span>
<span id="cb8-13-f0ff4a06d4"><a href="#cb8-13-f0ff4a06d4"></a> age: <span class="bu">int</span></span>
<span id="cb8-14-f0ff4a06d4"><a href="#cb8-14-f0ff4a06d4"></a> address: <span class="bu">str</span></span></code></pre></div>
 </td>
</tr>
<tr class="even">
<td><p><strong>4. Write an example instance (optional).</strong></p>
<p>At the bottom of the class docstring, write a doctest example of a typical instance of the data class. This should be used to illustrate all of the instance attributes, which is especially important when the instance attributes are complex types.</p></td>
<td><div class="sourceCode" id="cb9-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-f0ff4a06d4"><a href="#cb9-1-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb9-2-f0ff4a06d4"><a href="#cb9-2-f0ff4a06d4"></a><span class="kw">class</span> Person:</span>
<span id="cb9-3-f0ff4a06d4"><a href="#cb9-3-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;A data class representing a person.</span></span>
<span id="cb9-4-f0ff4a06d4"><a href="#cb9-4-f0ff4a06d4"></a></span>
<span id="cb9-5-f0ff4a06d4"><a href="#cb9-5-f0ff4a06d4"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb9-6-f0ff4a06d4"><a href="#cb9-6-f0ff4a06d4"></a><span class="co"> - given_name: the person&#39;s given name</span></span>
<span id="cb9-7-f0ff4a06d4"><a href="#cb9-7-f0ff4a06d4"></a><span class="co"> - family_name: the person&#39;s family name</span></span>
<span id="cb9-8-f0ff4a06d4"><a href="#cb9-8-f0ff4a06d4"></a><span class="co"> - age: the person&#39;s age</span></span>
<span id="cb9-9-f0ff4a06d4"><a href="#cb9-9-f0ff4a06d4"></a><span class="co"> - address: the person&#39;s address</span></span>
<span id="cb9-10-f0ff4a06d4"><a href="#cb9-10-f0ff4a06d4"></a></span>
<span id="cb9-11-f0ff4a06d4"><a href="#cb9-11-f0ff4a06d4"></a><span class="co"> &gt;&gt;&gt; david = Person(</span></span>
<span id="cb9-12-f0ff4a06d4"><a href="#cb9-12-f0ff4a06d4"></a><span class="co"> ... &#39;David&#39;,</span></span>
<span id="cb9-13-f0ff4a06d4"><a href="#cb9-13-f0ff4a06d4"></a><span class="co"> ... &#39;Liu&#39;,</span></span>
<span id="cb9-14-f0ff4a06d4"><a href="#cb9-14-f0ff4a06d4"></a><span class="co"> ... 40,</span></span>
<span id="cb9-15-f0ff4a06d4"><a href="#cb9-15-f0ff4a06d4"></a><span class="co"> ... &#39;40 St. George Street&#39;</span></span>
<span id="cb9-16-f0ff4a06d4"><a href="#cb9-16-f0ff4a06d4"></a><span class="co"> ... )</span></span>
<span id="cb9-17-f0ff4a06d4"><a href="#cb9-17-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb9-18-f0ff4a06d4"><a href="#cb9-18-f0ff4a06d4"></a> given_name: <span class="bu">str</span></span>
<span id="cb9-19-f0ff4a06d4"><a href="#cb9-19-f0ff4a06d4"></a> family_name: <span class="bu">str</span></span>
<span id="cb9-20-f0ff4a06d4"><a href="#cb9-20-f0ff4a06d4"></a> age: <span class="bu">int</span></span>
<span id="cb9-21-f0ff4a06d4"><a href="#cb9-21-f0ff4a06d4"></a> address: <span class="bu">str</span></span></code></pre></div>
 </td>
</tr>
<tr class="odd">
<td><p><strong>5. Document any additional representation invariants.</strong></p>
<p>If there are representation invariants for the instance attributes beyond the type annotations, include them in the class docstring under a separate section “Representation Invariants:” in between the instance attribute descriptions and sample instance.</p>
<p>Just as with function preconditions, each representation invariant should be a boolean expression in Python. Use <code>self.&lt;attribute&gt;</code> to refer to an instance attribute within a representation invariant.</p></td>
<td><div class="sourceCode" id="cb10-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-f0ff4a06d4"><a href="#cb10-1-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb10-2-f0ff4a06d4"><a href="#cb10-2-f0ff4a06d4"></a><span class="kw">class</span> Person:</span>
<span id="cb10-3-f0ff4a06d4"><a href="#cb10-3-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;A data class representing a person.</span></span>
<span id="cb10-4-f0ff4a06d4"><a href="#cb10-4-f0ff4a06d4"></a></span>
<span id="cb10-5-f0ff4a06d4"><a href="#cb10-5-f0ff4a06d4"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb10-6-f0ff4a06d4"><a href="#cb10-6-f0ff4a06d4"></a><span class="co"> - given_name: the person&#39;s given name</span></span>
<span id="cb10-7-f0ff4a06d4"><a href="#cb10-7-f0ff4a06d4"></a><span class="co"> - family_name: the person&#39;s family name</span></span>
<span id="cb10-8-f0ff4a06d4"><a href="#cb10-8-f0ff4a06d4"></a><span class="co"> - age: the person&#39;s age</span></span>
<span id="cb10-9-f0ff4a06d4"><a href="#cb10-9-f0ff4a06d4"></a><span class="co"> - address: the person&#39;s address</span></span>
<span id="cb10-10-f0ff4a06d4"><a href="#cb10-10-f0ff4a06d4"></a></span>
<span id="cb10-11-f0ff4a06d4"><a href="#cb10-11-f0ff4a06d4"></a><span class="co"> Representation Invariants:</span></span>
<span id="cb10-12-f0ff4a06d4"><a href="#cb10-12-f0ff4a06d4"></a><span class="co"> - self.age &gt;= 0</span></span>
<span id="cb10-13-f0ff4a06d4"><a href="#cb10-13-f0ff4a06d4"></a></span>
<span id="cb10-14-f0ff4a06d4"><a href="#cb10-14-f0ff4a06d4"></a><span class="co"> &gt;&gt;&gt; david = Person(</span></span>
<span id="cb10-15-f0ff4a06d4"><a href="#cb10-15-f0ff4a06d4"></a><span class="co"> ... &#39;David&#39;,</span></span>
<span id="cb10-16-f0ff4a06d4"><a href="#cb10-16-f0ff4a06d4"></a><span class="co"> ... &#39;Liu&#39;,</span></span>
<span id="cb10-17-f0ff4a06d4"><a href="#cb10-17-f0ff4a06d4"></a><span class="co"> ... 40,</span></span>
<span id="cb10-18-f0ff4a06d4"><a href="#cb10-18-f0ff4a06d4"></a><span class="co"> ... &#39;40 St. George Street&#39;</span></span>
<span id="cb10-19-f0ff4a06d4"><a href="#cb10-19-f0ff4a06d4"></a><span class="co"> ... )</span></span>
<span id="cb10-20-f0ff4a06d4"><a href="#cb10-20-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb10-21-f0ff4a06d4"><a href="#cb10-21-f0ff4a06d4"></a> given_name: <span class="bu">str</span></span>
<span id="cb10-22-f0ff4a06d4"><a href="#cb10-22-f0ff4a06d4"></a> family_name: <span class="bu">str</span></span>
<span id="cb10-23-f0ff4a06d4"><a href="#cb10-23-f0ff4a06d4"></a> age: <span class="bu">int</span></span>
<span id="cb10-24-f0ff4a06d4"><a href="#cb10-24-f0ff4a06d4"></a> address: <span class="bu">str</span></span></code></pre></div>
 </td>
</tr>
</tbody>
</table>
</div>
<h2 id="a-worked-example-f0ff4a06d4">A worked example</h2>
<p>To wrap up our introduction of data classes, lets see how to apply data classes to the marriage license data set we studied in <a href="01-tabular-data.html">4.1 Tabular Data</a>.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;"><strong>ID</strong></th>
<th style="text-align: center;"><strong>Civic Centre</strong></th>
<th style="text-align: center;"><strong>Marriage Licenses Issued</strong></th>
<th style="text-align: center;"><strong>Time Period</strong></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">1657</td>
<td style="text-align: center;">ET</td>
<td style="text-align: center;">80</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1658</td>
<td style="text-align: center;">NY</td>
<td style="text-align: center;">136</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="odd">
<td style="text-align: center;">1659</td>
<td style="text-align: center;">SC</td>
<td style="text-align: center;">159</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1660</td>
<td style="text-align: center;">TO</td>
<td style="text-align: center;">367</td>
<td style="text-align: center;">January 1, 2011</td>
</tr>
<tr class="odd">
<td style="text-align: center;">1661</td>
<td style="text-align: center;">ET</td>
<td style="text-align: center;">109</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1662</td>
<td style="text-align: center;">NY</td>
<td style="text-align: center;">150</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
<tr class="odd">
<td style="text-align: center;">1663</td>
<td style="text-align: center;">SC</td>
<td style="text-align: center;">154</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
<tr class="even">
<td style="text-align: center;">1664</td>
<td style="text-align: center;">TO</td>
<td style="text-align: center;">383</td>
<td style="text-align: center;">February 1, 2011</td>
</tr>
</tbody>
</table>
<p>Recall that we represented the data as a list of lists:</p>
<div class="sourceCode" id="cb11-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-f0ff4a06d4"><a href="#cb11-1-f0ff4a06d4"></a><span class="op">&gt;&gt;&gt;</span> marriage_data <span class="op">=</span> [</span>
<span id="cb11-2-f0ff4a06d4"><a href="#cb11-2-f0ff4a06d4"></a>... [<span class="dv">1657</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">80</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb11-3-f0ff4a06d4"><a href="#cb11-3-f0ff4a06d4"></a>... [<span class="dv">1658</span>, <span class="st">&#39;NY&#39;</span>, <span class="dv">136</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb11-4-f0ff4a06d4"><a href="#cb11-4-f0ff4a06d4"></a>... [<span class="dv">1659</span>, <span class="st">&#39;SC&#39;</span>, <span class="dv">159</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb11-5-f0ff4a06d4"><a href="#cb11-5-f0ff4a06d4"></a>... [<span class="dv">1660</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">367</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)],</span>
<span id="cb11-6-f0ff4a06d4"><a href="#cb11-6-f0ff4a06d4"></a>... [<span class="dv">1661</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">109</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)],</span>
<span id="cb11-7-f0ff4a06d4"><a href="#cb11-7-f0ff4a06d4"></a>... [<span class="dv">1662</span>, <span class="st">&#39;NY&#39;</span>, <span class="dv">150</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)],</span>
<span id="cb11-8-f0ff4a06d4"><a href="#cb11-8-f0ff4a06d4"></a>... [<span class="dv">1663</span>, <span class="st">&#39;SC&#39;</span>, <span class="dv">154</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)],</span>
<span id="cb11-9-f0ff4a06d4"><a href="#cb11-9-f0ff4a06d4"></a>... [<span class="dv">1664</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">383</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)]</span>
<span id="cb11-10-f0ff4a06d4"><a href="#cb11-10-f0ff4a06d4"></a>... ]</span></code></pre></div>
<p>We implemented the following function to calculate the average number of marriage licenses issued by a particular civic centre:</p>
<div class="sourceCode" id="cb12-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-f0ff4a06d4"><a href="#cb12-1-f0ff4a06d4"></a><span class="kw">def</span> average_licenses_issued(data: <span class="bu">list</span>[<span class="bu">list</span>], civic_centre: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb12-2-f0ff4a06d4"><a href="#cb12-2-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;Return the average number of marriage licenses issued by civic_centre in data.</span></span>
<span id="cb12-3-f0ff4a06d4"><a href="#cb12-3-f0ff4a06d4"></a></span>
<span id="cb12-4-f0ff4a06d4"><a href="#cb12-4-f0ff4a06d4"></a><span class="co"> Precondition:</span></span>
<span id="cb12-5-f0ff4a06d4"><a href="#cb12-5-f0ff4a06d4"></a><span class="co"> - all({len(row) == 4 for row in data})</span></span>
<span id="cb12-6-f0ff4a06d4"><a href="#cb12-6-f0ff4a06d4"></a><span class="co"> - any({row[1] == civic_centre for row in data})</span></span>
<span id="cb12-7-f0ff4a06d4"><a href="#cb12-7-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb12-8-f0ff4a06d4"><a href="#cb12-8-f0ff4a06d4"></a> issued_by_civic_centre <span class="op">=</span> [row[<span class="dv">2</span>] <span class="cf">for</span> row <span class="kw">in</span> data <span class="cf">if</span> row[<span class="dv">1</span>] <span class="op">==</span> civic_centre]</span>
<span id="cb12-9-f0ff4a06d4"><a href="#cb12-9-f0ff4a06d4"></a></span>
<span id="cb12-10-f0ff4a06d4"><a href="#cb12-10-f0ff4a06d4"></a> total <span class="op">=</span> <span class="bu">sum</span>(issued_by_civic_centre)</span>
<span id="cb12-11-f0ff4a06d4"><a href="#cb12-11-f0ff4a06d4"></a> count <span class="op">=</span> <span class="bu">len</span>(issued_by_civic_centre)</span>
<span id="cb12-12-f0ff4a06d4"><a href="#cb12-12-f0ff4a06d4"></a></span>
<span id="cb12-13-f0ff4a06d4"><a href="#cb12-13-f0ff4a06d4"></a> <span class="cf">return</span> total <span class="op">/</span> count</span></code></pre></div>
<p>Here is how we will use data classes to simplify this approach. Rather than storing each row in the table as a list, we can instead introduce a new data class to store this information:</p>
<div class="sourceCode" id="cb13-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-f0ff4a06d4"><a href="#cb13-1-f0ff4a06d4"></a><span class="im">from</span> dataclasses <span class="im">import</span> dataclass</span>
<span id="cb13-2-f0ff4a06d4"><a href="#cb13-2-f0ff4a06d4"></a><span class="im">from</span> datetime <span class="im">import</span> date</span>
<span id="cb13-3-f0ff4a06d4"><a href="#cb13-3-f0ff4a06d4"></a></span>
<span id="cb13-4-f0ff4a06d4"><a href="#cb13-4-f0ff4a06d4"></a></span>
<span id="cb13-5-f0ff4a06d4"><a href="#cb13-5-f0ff4a06d4"></a><span class="at">@dataclass</span></span>
<span id="cb13-6-f0ff4a06d4"><a href="#cb13-6-f0ff4a06d4"></a><span class="kw">class</span> MarriageData:</span>
<span id="cb13-7-f0ff4a06d4"><a href="#cb13-7-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;A record of the number of marriage licenses issued in a civic centre in a given month.</span></span>
<span id="cb13-8-f0ff4a06d4"><a href="#cb13-8-f0ff4a06d4"></a></span>
<span id="cb13-9-f0ff4a06d4"><a href="#cb13-9-f0ff4a06d4"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb13-10-f0ff4a06d4"><a href="#cb13-10-f0ff4a06d4"></a><span class="co"> - id: a unique identifier for the record</span></span>
<span id="cb13-11-f0ff4a06d4"><a href="#cb13-11-f0ff4a06d4"></a><span class="co"> - civic_centre: the name of the civic centre</span></span>
<span id="cb13-12-f0ff4a06d4"><a href="#cb13-12-f0ff4a06d4"></a><span class="co"> - num_licenses: the number of licenses issued</span></span>
<span id="cb13-13-f0ff4a06d4"><a href="#cb13-13-f0ff4a06d4"></a><span class="co"> - month: the month these licenses were issued</span></span>
<span id="cb13-14-f0ff4a06d4"><a href="#cb13-14-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-15-f0ff4a06d4"><a href="#cb13-15-f0ff4a06d4"></a> <span class="bu">id</span>: <span class="bu">int</span></span>
<span id="cb13-16-f0ff4a06d4"><a href="#cb13-16-f0ff4a06d4"></a> civic_centre: <span class="bu">str</span></span>
<span id="cb13-17-f0ff4a06d4"><a href="#cb13-17-f0ff4a06d4"></a> num_licenses: <span class="bu">int</span></span>
<span id="cb13-18-f0ff4a06d4"><a href="#cb13-18-f0ff4a06d4"></a> month: date</span></code></pre></div>
<p>Then using this data class, we can represent tabular data as a list of <code>MarriageData</code> instances rather than a list of lists. Not much has changed! The values representing each entry in the table are the same, but how we “bundle” each row of data into a single entity is different.</p>
<div class="sourceCode" id="cb14-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-f0ff4a06d4"><a href="#cb14-1-f0ff4a06d4"></a><span class="op">&gt;&gt;&gt;</span> marriage_data <span class="op">=</span> [</span>
<span id="cb14-2-f0ff4a06d4"><a href="#cb14-2-f0ff4a06d4"></a>... MarriageData(<span class="dv">1657</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">80</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)),</span>
<span id="cb14-3-f0ff4a06d4"><a href="#cb14-3-f0ff4a06d4"></a>... MarriageData(<span class="dv">1658</span>, <span class="st">&#39;NY&#39;</span>, <span class="dv">136</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)),</span>
<span id="cb14-4-f0ff4a06d4"><a href="#cb14-4-f0ff4a06d4"></a>... MarriageData(<span class="dv">1659</span>, <span class="st">&#39;SC&#39;</span>, <span class="dv">159</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)),</span>
<span id="cb14-5-f0ff4a06d4"><a href="#cb14-5-f0ff4a06d4"></a>... MarriageData(<span class="dv">1660</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">367</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">1</span>, <span class="dv">1</span>)),</span>
<span id="cb14-6-f0ff4a06d4"><a href="#cb14-6-f0ff4a06d4"></a>... MarriageData(<span class="dv">1661</span>, <span class="st">&#39;ET&#39;</span>, <span class="dv">109</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)),</span>
<span id="cb14-7-f0ff4a06d4"><a href="#cb14-7-f0ff4a06d4"></a>... MarriageData(<span class="dv">1662</span>, <span class="st">&#39;NY&#39;</span>, <span class="dv">150</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)),</span>
<span id="cb14-8-f0ff4a06d4"><a href="#cb14-8-f0ff4a06d4"></a>... MarriageData(<span class="dv">1663</span>, <span class="st">&#39;SC&#39;</span>, <span class="dv">154</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>)),</span>
<span id="cb14-9-f0ff4a06d4"><a href="#cb14-9-f0ff4a06d4"></a>... MarriageData(<span class="dv">1664</span>, <span class="st">&#39;TO&#39;</span>, <span class="dv">383</span>, datetime.date(<span class="dv">2011</span>, <span class="dv">2</span>, <span class="dv">1</span>))</span>
<span id="cb14-10-f0ff4a06d4"><a href="#cb14-10-f0ff4a06d4"></a>... ]</span></code></pre></div>
<p>And here is how we could modify our <code>average_licenses_issued</code> function.</p>
<div class="sourceCode" id="cb15-f0ff4a06d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-f0ff4a06d4"><a href="#cb15-1-f0ff4a06d4"></a><span class="kw">def</span> average_licenses_issued(data: <span class="bu">list</span>[MarriageData], civic_centre: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb15-2-f0ff4a06d4"><a href="#cb15-2-f0ff4a06d4"></a> <span class="co">&quot;&quot;&quot;Return the average number of marriage licenses issued by civic_centre in data.</span></span>
<span id="cb15-3-f0ff4a06d4"><a href="#cb15-3-f0ff4a06d4"></a></span>
<span id="cb15-4-f0ff4a06d4"><a href="#cb15-4-f0ff4a06d4"></a><span class="co"> Precondition:</span></span>
<span id="cb15-5-f0ff4a06d4"><a href="#cb15-5-f0ff4a06d4"></a><span class="co"> - any({row.civic_centre == civic_centre for row in data})</span></span>
<span id="cb15-6-f0ff4a06d4"><a href="#cb15-6-f0ff4a06d4"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb15-7-f0ff4a06d4"><a href="#cb15-7-f0ff4a06d4"></a> issued_by_civic_centre <span class="op">=</span> [</span>
<span id="cb15-8-f0ff4a06d4"><a href="#cb15-8-f0ff4a06d4"></a> row.num_licenses <span class="cf">for</span> row <span class="kw">in</span> data <span class="cf">if</span> row.civic_centre <span class="op">==</span> civic_centre</span>
<span id="cb15-9-f0ff4a06d4"><a href="#cb15-9-f0ff4a06d4"></a> ]</span>
<span id="cb15-10-f0ff4a06d4"><a href="#cb15-10-f0ff4a06d4"></a></span>
<span id="cb15-11-f0ff4a06d4"><a href="#cb15-11-f0ff4a06d4"></a> total <span class="op">=</span> <span class="bu">sum</span>(issued_by_civic_centre)</span>
<span id="cb15-12-f0ff4a06d4"><a href="#cb15-12-f0ff4a06d4"></a> count <span class="op">=</span> <span class="bu">len</span>(issued_by_civic_centre)</span>
<span id="cb15-13-f0ff4a06d4"><a href="#cb15-13-f0ff4a06d4"></a></span>
<span id="cb15-14-f0ff4a06d4"><a href="#cb15-14-f0ff4a06d4"></a> <span class="cf">return</span> total <span class="op">/</span> count</span></code></pre></div>
<p>Again, not much has changed: instead of writing <code>row[1]</code> and <code>row[2]</code>, we instead write <code>row.civic_centre</code> and <code>row.num_licenses</code>. This is longer to write, but also more explicit in what attributes of the data are accessed. And to quote from the <a href="https://www.python.org/dev/peps/pep-0020/">Zen of Python</a>, <em>explicit is better than implicit</em>.</p>
<h2 id="summary-why-data-classes-f0ff4a06d4">Summary: why data classes?</h2>
<p>Earlier, we claimed that a <code>dataclass</code> is a better way of representing a bundle of data than a list. Lets review a few reasons why:</p>
<ol type="1">
<li>We now access the different attributes by name rather than index in the list, which is easier to remember and understand if youre reading the code.</li>
<li>Similarly, software like PyCharm and <code>python_ta</code> understand data class definitions, and will warn us if we try to create <em>malformed person values</em> (e.g., wrong arguments to <code>Person</code>), or access invalid attributes.</li>
<li>Lists are designed to be a very flexible and general data type, and support many operations (e.g. list concatenation and “element of”) that we dont want to do for actual people or rows of marriage data. Now that we use a separate data class, we eliminate the possibility of using these list operations on a “marriage data row”, even accidentally.</li>
</ol>
</section>
<br/> <a id="anchor-04-04"></a>
<header id="title-block-header-de893942be">
<h1 class="title">4.4 Repeated Execution: For Loops</h1>
</header>
<section>
<p>Collections in Python can be used in many ways. We have already seen how we can use built-in aggregation functions (e.g., <code>any</code>, <code>all</code>, <code>max</code>) to perform computations across all elements of a collection (e.g., <code>list</code>, <code>set</code>).</p>
<p>But right now, were limited by what aggregation functions Python makes available to us: for example, theres a built-in <code>sum</code> function, but no <code>product</code> function.<label for="sn-0-de893942be" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-de893942be" class="margin-toggle"/><span class="sidenote"> Thats not exactly true: there is a <code>math.product</code> function, but lets ignore that here. :)</span> So in this section, well learn about the <code>for</code> loop, a compound statement that will allow us to implement our own custom aggregation functions across different types of collection data.</p>
<h2 id="introducing-the-problem-repeating-code-de893942be">Introducing the problem: repeating code</h2>
<p>Suppose we wanted to write a function that computes the sum of a list of numbers, without using the built-in <code>sum</code> function.</p>
<div class="sourceCode" id="cb1-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-de893942be"><a href="#cb1-1-de893942be"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb1-2-de893942be"><a href="#cb1-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.</span></span>
<span id="cb1-3-de893942be"><a href="#cb1-3-de893942be"></a></span>
<span id="cb1-4-de893942be"><a href="#cb1-4-de893942be"></a><span class="co"> &gt;&gt;&gt; my_sum([10, 20, 30])</span></span>
<span id="cb1-5-de893942be"><a href="#cb1-5-de893942be"></a><span class="co"> 60</span></span>
<span id="cb1-6-de893942be"><a href="#cb1-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>If we knew the size of <code>numbers</code> in advance, we could write a single expression to do this. For example, here is how we could implement <code>my_sum</code> if we knew that <code>numbers</code> always contained three elements:</p>
<div class="sourceCode" id="cb2-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-de893942be"><a href="#cb2-1-de893942be"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-2-de893942be"><a href="#cb2-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.</span></span>
<span id="cb2-3-de893942be"><a href="#cb2-3-de893942be"></a></span>
<span id="cb2-4-de893942be"><a href="#cb2-4-de893942be"></a><span class="co"> &gt;&gt;&gt; my_sum([10, 20, 30])</span></span>
<span id="cb2-5-de893942be"><a href="#cb2-5-de893942be"></a><span class="co"> 60</span></span>
<span id="cb2-6-de893942be"><a href="#cb2-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-7-de893942be"><a href="#cb2-7-de893942be"></a> <span class="cf">return</span> numbers[<span class="dv">0</span>] <span class="op">+</span> numbers[<span class="dv">1</span>] <span class="op">+</span> numbers[<span class="dv">2</span>]</span></code></pre></div>
<p>But of course, this approach doesnt work for general lists, when we dont know ahead of time how many elements the input will have. We need a way to repeat the “<code>+ numbers[_]</code>” for an arbitrary number of list elements. Here is another way of writing our three-element code to pull out the exact statement that is repeated.</p>
<div class="sourceCode" id="cb3-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-de893942be"><a href="#cb3-1-de893942be"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-de893942be"><a href="#cb3-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.</span></span>
<span id="cb3-3-de893942be"><a href="#cb3-3-de893942be"></a></span>
<span id="cb3-4-de893942be"><a href="#cb3-4-de893942be"></a><span class="co"> &gt;&gt;&gt; my_sum([10, 20, 30])</span></span>
<span id="cb3-5-de893942be"><a href="#cb3-5-de893942be"></a><span class="co"> 60</span></span>
<span id="cb3-6-de893942be"><a href="#cb3-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-7-de893942be"><a href="#cb3-7-de893942be"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb3-8-de893942be"><a href="#cb3-8-de893942be"></a></span>
<span id="cb3-9-de893942be"><a href="#cb3-9-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">0</span>]</span>
<span id="cb3-10-de893942be"><a href="#cb3-10-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">1</span>]</span>
<span id="cb3-11-de893942be"><a href="#cb3-11-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">2</span>]</span>
<span id="cb3-12-de893942be"><a href="#cb3-12-de893942be"></a></span>
<span id="cb3-13-de893942be"><a href="#cb3-13-de893942be"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>This implementation follows how a human might add up the numbers in the list. First, we start a counter a 0 (using a variable called <code>sum_so_far</code>). Then, we use three assignment statements to update the value of <code>sum_so_far</code> by adding another element of <code>numbers</code>. Lets look at the first such statement:</p>
<div class="sourceCode" id="cb4-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-de893942be"><a href="#cb4-1-de893942be"></a>sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">0</span>]</span></code></pre></div>
<p>This looks fairly straightforward, but is actually a big leap from the assignment statements weve studied before! Whats unusual about it is that for the first time, we are assigning a value to a variable that has <em>already</em> been given a value. This type of assignment statement is called a <strong>variable reassignment statement</strong>. This statement is especially tricky because the variable <code>sum_so_far</code> appears on both sides of the <code>=</code>. We can make sense of this statement by reviewing the evaluation order that Python follows when executing an assignment statement:</p>
<ul>
<li>First, the right-hand side of the assignment statement (<code>sum_so_far + numbers[0]</code>) is evaluated.</li>
<li>Second, the value produced by evaluating the right-hand side is stored in the variable on the left-hand side (<code>sum_so_far</code>).</li>
</ul>
<p>We can visualize how the three assignment statements work by tracing through an example. Lets consider calling our doctest example, <code>my_sum([10, 20, 30])</code>. What happens to the value of <code>sum_so_far</code>?</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 39%" />
<col style="width: 22%" />
<col style="width: 38%" />
</colgroup>
<thead>
<tr class="header">
<th>Statement</th>
<th><code>sum_so_far</code> <em>after</em> executing statement</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>sum_so_far = 0</code></td>
<td><code>0</code></td>
<td></td>
</tr>
<tr class="even">
<td><code>sum_so_far = sum_so_far + numbers[0]</code></td>
<td><code>10</code> (<code>0 + 10</code>)</td>
<td>When evaluating the right-hand side, <code>sum_so_far</code> is <code>0</code> and <code>numbers[0]</code> is <code>10</code>.</td>
</tr>
<tr class="odd">
<td><code>sum_so_far = sum_so_far + numbers[1]</code></td>
<td><code>30</code> (<code>10 + 20</code>)</td>
<td>When evaluating the right-hand side, <code>sum_so_far</code> is <code>10</code> and <code>numbers[1]</code> is <code>20</code>.</td>
</tr>
<tr class="even">
<td><code>sum_so_far = sum_so_far + numbers[2]</code></td>
<td><code>60</code> (<code>30 + 30</code>)</td>
<td>When evaluating the right-hand side, <code>sum_so_far</code> is <code>30</code> and <code>numbers[2]</code> is <code>30</code>.</td>
</tr>
</tbody>
</table>
</div>
<p>Now that we understand this implementation, we can see that the statement <code>sum_so_far = sum_so_far + numbers[_]</code> is exactly what needs to be repeated for every element of the input list. So now, lets learn how to perform <em>repeated execution</em> of Python statements.</p>
<h2 id="the-for-loop-de893942be">The for loop</h2>
<p>In Python, the <strong>for loop</strong> is a compound statement that repeats a block of code once for element in a collection. Here is the syntax of a for loop:<label for="sn-1-de893942be" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-de893942be" class="margin-toggle"/><span class="sidenote"> Notice that the syntax is very similar to a comprehension. The key difference is that a comprehension evaluates an <em>expression</em> once for each element in a collection, but a for loop evaluates a <em>sequence of statements</em> once per element.</span></p>
<div class="sourceCode" id="cb5-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-de893942be"><a href="#cb5-1-de893942be"></a><span class="cf">for</span> <span class="op">&lt;</span>loop_variable<span class="op">&gt;</span> <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span>:</span>
<span id="cb5-2-de893942be"><a href="#cb5-2-de893942be"></a> <span class="op">&lt;</span>body<span class="op">&gt;</span></span></code></pre></div>
<p>There are three parts:</p>
<ol type="1">
<li><p><code>&lt;collection&gt;</code> is an expression for a Python collection (e.g., a <code>list</code> or <code>set</code>).</p></li>
<li><p><code>&lt;loop_variable&gt;</code> is a name for the <em>loop variable</em> that will refer to an element in the colleciton.</p></li>
<li><p><code>&lt;body&gt;</code> is a sequence of one or more statements that will be repeatedly executed. This is called the <em>body</em> of the for loop. The statements within the loop body may refer to the loop variable to access the “current” element in the collection.</p>
<p>Just as we saw with if statements, the body of a for loop <em>must</em> be indented relative to the <code>for</code> keyword.</p></li>
</ol>
<p>When a for loop is executed, the following happens:</p>
<ol type="1">
<li><p>The loop variable is assigned to the first element in the collection.</p></li>
<li><p>The loop body is executed, using the current value of the loop variable.</p></li>
<li><p>Steps 1 and 2 repeat for the second element of the collection, then the third, etc. until all elements of the collection have been assigned to the loop variable exactly once.</p>
<p>Each individual execution of the loop body is called a <strong>loop iteration</strong>.</p></li>
</ol>
<p>As with if statements, for loops are a control flow structure in Python because they modify the order in which statements are executed—in this case, by repeating a block of code multiple times. The reason we use the term <em>loop</em> is because after the last statement in the loop body is executed, the Python interpreter “loops back” to the beginning of the for loop, assigning the loop variable to the next element in the collection.</p>
<!-- TODO: Add general control flow diagram for for loops -->
<h2 id="my_sum-and-the-accumulator-pattern-de893942be"><code>my_sum</code> and the accumulator pattern</h2>
<p>Now let us see how to use a for loop to implement <code>my_sum</code>. We left off with the following block of repeated code:</p>
<div class="sourceCode" id="cb6-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-de893942be"><a href="#cb6-1-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">0</span>]</span>
<span id="cb6-2-de893942be"><a href="#cb6-2-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">1</span>]</span>
<span id="cb6-3-de893942be"><a href="#cb6-3-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">2</span>]</span></code></pre></div>
<p>We can now move the repeated <code>sum_so_far = sum_so_far + _</code> part into a <code>for</code> loop as follows:<label for="sn-2-de893942be" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-de893942be" class="margin-toggle"/><span class="sidenote"> Notice our loop variable name! A good convention to follow is that collections have a pluralized name (<code>numbers</code>), and loop variables have the singular version of that name (<code>number</code>).</span></p>
<div class="sourceCode" id="cb7-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-de893942be"><a href="#cb7-1-de893942be"></a><span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb7-2-de893942be"><a href="#cb7-2-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> number</span></code></pre></div>
<p>One important thing to note is that we no longer need to use list indexing (<code>numbers[_]</code>) to access individual list elements. The for loop in Python handles the extracing of individual elements for us, so that our loop body can focus just on what to do with each element.</p>
<p>With this, we can now write our complete implementation of <code>my_sum</code>.</p>
<div class="sourceCode" id="cb8-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-de893942be"><a href="#cb8-1-de893942be"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb8-2-de893942be"><a href="#cb8-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.</span></span>
<span id="cb8-3-de893942be"><a href="#cb8-3-de893942be"></a></span>
<span id="cb8-4-de893942be"><a href="#cb8-4-de893942be"></a><span class="co"> &gt;&gt;&gt; my_sum([10, 20, 30])</span></span>
<span id="cb8-5-de893942be"><a href="#cb8-5-de893942be"></a><span class="co"> 60</span></span>
<span id="cb8-6-de893942be"><a href="#cb8-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb8-7-de893942be"><a href="#cb8-7-de893942be"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb8-8-de893942be"><a href="#cb8-8-de893942be"></a></span>
<span id="cb8-9-de893942be"><a href="#cb8-9-de893942be"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb8-10-de893942be"><a href="#cb8-10-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> number</span>
<span id="cb8-11-de893942be"><a href="#cb8-11-de893942be"></a></span>
<span id="cb8-12-de893942be"><a href="#cb8-12-de893942be"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>Now, no matter how many elements <code>numbers</code> has, the loop body <code>sum_so_far = sum_so_far + number</code> will repeat once for each element. The ability to write a small amount of code that processes an arbitrary amount of data is one of the truly remarkable feats of computer science.</p>
<h3 id="accumulators-and-tracing-through-loops-de893942be">Accumulators and tracing through loops</h3>
<p>Because of the variable reassignment, <code>sum_so_far</code> is more complex than every other variable we have used so far in this course. And because this reassignment happens inside the loop body, it happens once for each element in the collection, not just once or twice. This frequent reassignment can make loops hard to reason about, especially as our loop bodies grow more complex, and so we will take some time now to introduce a formal process you can use to reason about loops in your code.</p>
<p>First, some terminology. We call the variable <code>sum_so_far</code> the <strong>loop accumulator</strong>. The purpose of a loop accumulator is to store an aggregated result based on the elements of the collection that have been previously visited by the loop. In the case of <code>my_sum</code>, the loop accumulator <code>sum_so_far</code> stores, well, the sum of the elements that we have seen so far in the loop. We can keep track of the execution of the different iterations of the loop in a tracing table consisting of three columms: how many iterations have occurred so far, the value of the loop variable for that iteration, and the value of the loop accumulator at the <em>end</em> of that iteration. We call this table a <strong>loop accumulation table</strong>. Here is the loop accumulation table for a call to <code>my_sum([10, 20, 30])</code>:</p>
<div class="reference-table">
<table>
<thead>
<tr class="header">
<th>Iteration</th>
<th>Loop variable (<code>number</code>)</th>
<th>Loop accumulator (<code>sum_so_far</code>)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>N/A</td>
<td>0</td>
</tr>
<tr class="even">
<td>1</td>
<td>10</td>
<td>10</td>
</tr>
<tr class="odd">
<td>2</td>
<td>20</td>
<td>30</td>
</tr>
<tr class="even">
<td>3</td>
<td>30</td>
<td>60</td>
</tr>
</tbody>
</table>
</div>
<p>Almost every for loop has an accumulator variable.<label for="sn-3-de893942be" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-de893942be" class="margin-toggle"/><span class="sidenote"> Later, some might even have more than one.</span> To distinguish these from other variables, we recommend using the <code>_so_far</code> suffix in the variable name, and optionally adding a comment in your code explaining the purpose of the variable.</p>
<div class="sourceCode" id="cb9-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-de893942be"><a href="#cb9-1-de893942be"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb9-2-de893942be"><a href="#cb9-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the sum of the numbers in numbers.</span></span>
<span id="cb9-3-de893942be"><a href="#cb9-3-de893942be"></a></span>
<span id="cb9-4-de893942be"><a href="#cb9-4-de893942be"></a><span class="co"> &gt;&gt;&gt; my_sum([10, 20, 30])</span></span>
<span id="cb9-5-de893942be"><a href="#cb9-5-de893942be"></a><span class="co"> 60</span></span>
<span id="cb9-6-de893942be"><a href="#cb9-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb9-7-de893942be"><a href="#cb9-7-de893942be"></a> <span class="co"># ACCUMULATOR sum_so_far: keep track of the running sum of the elements in numbers.</span></span>
<span id="cb9-8-de893942be"><a href="#cb9-8-de893942be"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb9-9-de893942be"><a href="#cb9-9-de893942be"></a></span>
<span id="cb9-10-de893942be"><a href="#cb9-10-de893942be"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb9-11-de893942be"><a href="#cb9-11-de893942be"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> number</span>
<span id="cb9-12-de893942be"><a href="#cb9-12-de893942be"></a></span>
<span id="cb9-13-de893942be"><a href="#cb9-13-de893942be"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<h3 id="when-the-collection-is-empty-de893942be">When the collection is empty</h3>
<p>What happens if we call <code>my_sum</code> on an empty list?</p>
<div class="sourceCode" id="cb10-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-de893942be"><a href="#cb10-1-de893942be"></a><span class="op">&gt;&gt;&gt;</span> my_sum([])</span>
<span id="cb10-2-de893942be"><a href="#cb10-2-de893942be"></a><span class="dv">0</span></span></code></pre></div>
<p>Why does this happen? The key to understanding this is that when we loop over an empty collection, zero iterations occur and the loop body never executes. So when we call <code>my_sum([])</code>, first <code>sum_so_far</code> is assigned to <code>0</code>, and then the for loop does not execute any code, and so <code>0</code> is returned. A key observation here is that <em>when the collection is empty, the initial value of <code>sum_so_far</code> is returned</em>.</p>
<h2 id="designing-loops-using-the-accumulator-pattern-de893942be">Designing loops using the accumulator pattern</h2>
<p>Our implementation of <code>my_sum</code> illustrates a more general pattern that well employ when we use loops to perform an aggregation computation. Here is the <strong>accumulator pattern</strong>:</p>
<ol type="1">
<li>Choose a meaningful name for an accumulator variable based on what youre computing. Use the suffix <code>_so_far</code> to remind yourself that this is an accumulator.</li>
<li>Pick an initial value for the accumulator. This value is usually what should be returned if the collection is empty.</li>
<li>In the loop body, update the accumulator variable based on the current value of the loop variable.</li>
<li>After the loop ends, return the accumulator.</li>
</ol>
<p>Here is a <em>code template</em> to illustrate this pattern.</p>
<div class="sourceCode" id="cb11-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-de893942be"><a href="#cb11-1-de893942be"></a><span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far <span class="op">=</span> <span class="op">&lt;</span>default_value<span class="op">&gt;</span></span>
<span id="cb11-2-de893942be"><a href="#cb11-2-de893942be"></a></span>
<span id="cb11-3-de893942be"><a href="#cb11-3-de893942be"></a><span class="cf">for</span> element <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span>:</span>
<span id="cb11-4-de893942be"><a href="#cb11-4-de893942be"></a> <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far <span class="op">=</span> ... <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far ... element ... <span class="co"># Somehow combine loop variable and accumulator</span></span>
<span id="cb11-5-de893942be"><a href="#cb11-5-de893942be"></a></span>
<span id="cb11-6-de893942be"><a href="#cb11-6-de893942be"></a><span class="cf">return</span> <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far</span></code></pre></div>
<p>Code templates are helpful when learning about programming techniques, as they give you a natural starting point in your code with “places to fill in”. However, as well see over the next few sections, we should not blindly follow code templates either. Part of mastering a code template is deciding when to use it and when to modify it to solve the problem at hand.</p>
<h3 id="accumulating-the-product-de893942be">Accumulating the product</h3>
<p>Lets use the accumulator pattern to implement the function <code>product</code>:</p>
<div class="sourceCode" id="cb12-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-de893942be"><a href="#cb12-1-de893942be"></a><span class="kw">def</span> product(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb12-2-de893942be"><a href="#cb12-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the product of the given numbers.</span></span>
<span id="cb12-3-de893942be"><a href="#cb12-3-de893942be"></a></span>
<span id="cb12-4-de893942be"><a href="#cb12-4-de893942be"></a><span class="co"> &gt;&gt;&gt; product([10, 20])</span></span>
<span id="cb12-5-de893942be"><a href="#cb12-5-de893942be"></a><span class="co"> 200</span></span>
<span id="cb12-6-de893942be"><a href="#cb12-6-de893942be"></a><span class="co"> &gt;&gt;&gt; product([-5, 4])</span></span>
<span id="cb12-7-de893942be"><a href="#cb12-7-de893942be"></a><span class="co"> -20</span></span>
<span id="cb12-8-de893942be"><a href="#cb12-8-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb12-9-de893942be"><a href="#cb12-9-de893942be"></a> <span class="co"># ACCUMULATOR product_so_far: keep track of the product of the</span></span>
<span id="cb12-10-de893942be"><a href="#cb12-10-de893942be"></a> <span class="co"># elements in numbers seen so far in the loop.</span></span>
<span id="cb12-11-de893942be"><a href="#cb12-11-de893942be"></a> product_so_far <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb12-12-de893942be"><a href="#cb12-12-de893942be"></a></span>
<span id="cb12-13-de893942be"><a href="#cb12-13-de893942be"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb12-14-de893942be"><a href="#cb12-14-de893942be"></a> product_so_far <span class="op">=</span> product_so_far <span class="op">*</span> number</span>
<span id="cb12-15-de893942be"><a href="#cb12-15-de893942be"></a></span>
<span id="cb12-16-de893942be"><a href="#cb12-16-de893942be"></a> <span class="cf">return</span> product_so_far</span></code></pre></div>
<p>Notice how similar the code for <code>product</code> is to <code>my_sum</code>. In fact, disregarding the changes in variable names, the only changes are:</p>
<ul>
<li>the initial value of the accumulator (<code>0</code> versus <code>1</code>)</li>
<li>the “update” operation inside the loop body (<code>+</code> versus <code>*</code>)</li>
</ul>
<h2 id="looping-over-sets-de893942be">Looping over sets</h2>
<p>Because sets are collections, we can use for loops to iterate through the elements of a set as well. However, because sets are unordered, we cannot assume a particular order that the for loop will visit the elements in. So for loops over sets should only be used when <em>the same result would be obtained regardless of the order of the elements</em>. The aggregation functions weve looked at so far like <code>sum</code> satisfy this property.</p>
<h2 id="looping-over-strings-de893942be">Looping over strings</h2>
<p>Strings are very similar to lists because they are considered ordered sequences of data. Python treats a string as an ordered collection of characters (strings of length one), and so we can use for loops with strings to iterate over its characters one at a time.</p>
<p>Here is an example of using a for loop to count the number of characters in a string.</p>
<div class="sourceCode" id="cb13-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-de893942be"><a href="#cb13-1-de893942be"></a><span class="kw">def</span> my_len(s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb13-2-de893942be"><a href="#cb13-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the number of characters in s.</span></span>
<span id="cb13-3-de893942be"><a href="#cb13-3-de893942be"></a></span>
<span id="cb13-4-de893942be"><a href="#cb13-4-de893942be"></a><span class="co"> &gt;&gt;&gt; my_len(&#39;David&#39;)</span></span>
<span id="cb13-5-de893942be"><a href="#cb13-5-de893942be"></a><span class="co"> 5</span></span>
<span id="cb13-6-de893942be"><a href="#cb13-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-7-de893942be"><a href="#cb13-7-de893942be"></a> <span class="co"># ACCUMULATOR len_so_far: keep track of the number of</span></span>
<span id="cb13-8-de893942be"><a href="#cb13-8-de893942be"></a> <span class="co"># characters in s seen so far in the loop.</span></span>
<span id="cb13-9-de893942be"><a href="#cb13-9-de893942be"></a> len_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb13-10-de893942be"><a href="#cb13-10-de893942be"></a></span>
<span id="cb13-11-de893942be"><a href="#cb13-11-de893942be"></a> <span class="cf">for</span> character <span class="kw">in</span> s:</span>
<span id="cb13-12-de893942be"><a href="#cb13-12-de893942be"></a> len_so_far <span class="op">=</span> len_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb13-13-de893942be"><a href="#cb13-13-de893942be"></a></span>
<span id="cb13-14-de893942be"><a href="#cb13-14-de893942be"></a> <span class="cf">return</span> len_so_far</span></code></pre></div>
<p>Unlike <code>my_sum</code>, here we do not use the loop variable to update the accumulator <code>len_so_far</code>. This is because we dont care what the actual value character is, we are only counting iterations. In these scenarios, we can use an underscore <code>_</code> in place of the name for the loop variable to communicate that the loop variable is not used in the body of the for loop:</p>
<div class="sourceCode" id="cb14-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-de893942be"><a href="#cb14-1-de893942be"></a><span class="kw">def</span> my_len(s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb14-2-de893942be"><a href="#cb14-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the number of characters in s.</span></span>
<span id="cb14-3-de893942be"><a href="#cb14-3-de893942be"></a></span>
<span id="cb14-4-de893942be"><a href="#cb14-4-de893942be"></a><span class="co"> &gt;&gt;&gt; my_len(&#39;David&#39;)</span></span>
<span id="cb14-5-de893942be"><a href="#cb14-5-de893942be"></a><span class="co"> 5</span></span>
<span id="cb14-6-de893942be"><a href="#cb14-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb14-7-de893942be"><a href="#cb14-7-de893942be"></a> <span class="co"># ACCUMULATOR len_so_far: keep track of the number of</span></span>
<span id="cb14-8-de893942be"><a href="#cb14-8-de893942be"></a> <span class="co"># characters in s seen so far in the loop.</span></span>
<span id="cb14-9-de893942be"><a href="#cb14-9-de893942be"></a> len_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb14-10-de893942be"><a href="#cb14-10-de893942be"></a></span>
<span id="cb14-11-de893942be"><a href="#cb14-11-de893942be"></a> <span class="cf">for</span> _ <span class="kw">in</span> s:</span>
<span id="cb14-12-de893942be"><a href="#cb14-12-de893942be"></a> len_so_far <span class="op">=</span> len_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb14-13-de893942be"><a href="#cb14-13-de893942be"></a></span>
<span id="cb14-14-de893942be"><a href="#cb14-14-de893942be"></a> <span class="cf">return</span> len_so_far</span></code></pre></div>
<h2 id="looping-over-dictionaries-de893942be">Looping over dictionaries</h2>
<p>Python dictionaries are also iterable. Just like we saw with comprehensions, when we iterate over a dictionary, the loop variable refers to the <em>key</em> of each key-value pair. But of course, we can use the key to lookup its corresponding value in the dictionary.</p>
<p>For example, suppose we are given a dictionary mapping restaurant menu items (as strings) to their prices (as floats). Here is how we could calculate the sum of all the prices on the menu.</p>
<div class="sourceCode" id="cb15-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-de893942be"><a href="#cb15-1-de893942be"></a><span class="kw">def</span> total_menu_price(menu: <span class="bu">dict</span>[<span class="bu">str</span>, <span class="bu">float</span>]) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb15-2-de893942be"><a href="#cb15-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the total price of the given menu items.</span></span>
<span id="cb15-3-de893942be"><a href="#cb15-3-de893942be"></a></span>
<span id="cb15-4-de893942be"><a href="#cb15-4-de893942be"></a><span class="co"> &gt;&gt;&gt; total_menu_price({&#39;fries&#39;: 3.5, &#39;hamburger&#39;: 6.5})</span></span>
<span id="cb15-5-de893942be"><a href="#cb15-5-de893942be"></a><span class="co"> 10.0</span></span>
<span id="cb15-6-de893942be"><a href="#cb15-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb15-7-de893942be"><a href="#cb15-7-de893942be"></a> <span class="co"># ACCUMULATOR total_so_far: keep track of the total cost of</span></span>
<span id="cb15-8-de893942be"><a href="#cb15-8-de893942be"></a> <span class="co"># all items in the menu seen so far in the loop.</span></span>
<span id="cb15-9-de893942be"><a href="#cb15-9-de893942be"></a> total_so_far <span class="op">=</span> <span class="fl">0.0</span></span>
<span id="cb15-10-de893942be"><a href="#cb15-10-de893942be"></a></span>
<span id="cb15-11-de893942be"><a href="#cb15-11-de893942be"></a> <span class="cf">for</span> item <span class="kw">in</span> menu:</span>
<span id="cb15-12-de893942be"><a href="#cb15-12-de893942be"></a> total_so_far <span class="op">=</span> total_so_far <span class="op">+</span> menu[item]</span>
<span id="cb15-13-de893942be"><a href="#cb15-13-de893942be"></a></span>
<span id="cb15-14-de893942be"><a href="#cb15-14-de893942be"></a> <span class="cf">return</span> total_so_far</span></code></pre></div>
<p>The loop variable <code>item</code> refers to the <em>keys</em> in the dictionary, so to access the corresponding prices we need to use a key lookup expression, <code>menu[item]</code>. Here is how we can visualize this using a loop accumulation table:</p>
<div class="reference-table">
<table>
<colgroup>
<col style="width: 16%" />
<col style="width: 34%" />
<col style="width: 49%" />
</colgroup>
<thead>
<tr class="header">
<th>Iteration</th>
<th>Loop variable (<code>item</code>)</th>
<th>Loop accumulator (<code>total_so_far</code>)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td></td>
<td><code>0.0</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>'fries'</code></td>
<td><code>6.5</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>'hamburger'</code></td>
<td><code>10.0</code></td>
</tr>
</tbody>
</table>
</div>
<p>One final note: like sets, dictionaries are unordered. We chose a particular order of keys for the loop accumulation table just to understand the loop behaviour, but we should not assume that this is the guaranteed order the keys would be visited. Just as with sets, only loop over dictionaries when your computation does <em>not</em> depend on the iteration order.</p>
<h2 id="a-new-type-annotation-iterable-de893942be">A new type annotation: <code>Iterable</code></h2>
<p>Something you might notice about the two functions <code>my_len</code> and <code>my_sum</code> weve developed so far is that actually work on more types than currently specified by their parameter type annotation. For example, <code>my_len</code> works just as well on lists, sets, and other collections. If we look at the function body, we dont use the fact that <code>s</code> is a string at all—just that it can be iterated over. It would be nice if we could relax our type contract to allow for any collection argument value.</p>
<p>We say that a Python data type is <strong>iterable</strong> when its values can be used as the “collection” of a for loop, and that a Python object is iterable when it is an instance of an iterable data type.<label for="sn-4-de893942be" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-de893942be" class="margin-toggle"/><span class="sidenote"> You might wonder why Python doesnt just call these “collections” instead. There is a technical reason that is beyond the scope of this course, but for our purposes, well treat “iterable” and “collection” as synonymous.</span> This is equivalent to when a value can be used as the “collection” of a comprehension. We can import the <code>Iterable</code> type from <code>typing</code> to indicate that a value must be any data type that is iterable. Heres how we would write a more general <code>my_len</code>:</p>
<div class="sourceCode" id="cb16-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1-de893942be"><a href="#cb16-1-de893942be"></a><span class="im">from</span> typing <span class="im">import</span> Iterable</span>
<span id="cb16-2-de893942be"><a href="#cb16-2-de893942be"></a></span>
<span id="cb16-3-de893942be"><a href="#cb16-3-de893942be"></a></span>
<span id="cb16-4-de893942be"><a href="#cb16-4-de893942be"></a><span class="kw">def</span> my_len(collection: Iterable) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb16-5-de893942be"><a href="#cb16-5-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the number of elements in collection.</span></span>
<span id="cb16-6-de893942be"><a href="#cb16-6-de893942be"></a></span>
<span id="cb16-7-de893942be"><a href="#cb16-7-de893942be"></a><span class="co"> &gt;&gt;&gt; my_len(&#39;David&#39;)</span></span>
<span id="cb16-8-de893942be"><a href="#cb16-8-de893942be"></a><span class="co"> 5</span></span>
<span id="cb16-9-de893942be"><a href="#cb16-9-de893942be"></a><span class="co"> &gt;&gt;&gt; my_len([1, 2, 3])</span></span>
<span id="cb16-10-de893942be"><a href="#cb16-10-de893942be"></a><span class="co"> 3</span></span>
<span id="cb16-11-de893942be"><a href="#cb16-11-de893942be"></a><span class="co"> &gt;&gt;&gt; my_len({&#39;a&#39;: 1000})</span></span>
<span id="cb16-12-de893942be"><a href="#cb16-12-de893942be"></a><span class="co"> 1</span></span>
<span id="cb16-13-de893942be"><a href="#cb16-13-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb16-14-de893942be"><a href="#cb16-14-de893942be"></a> len_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb16-15-de893942be"><a href="#cb16-15-de893942be"></a></span>
<span id="cb16-16-de893942be"><a href="#cb16-16-de893942be"></a> <span class="cf">for</span> _ <span class="kw">in</span> collection:</span>
<span id="cb16-17-de893942be"><a href="#cb16-17-de893942be"></a> len_so_far <span class="op">=</span> len_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb16-18-de893942be"><a href="#cb16-18-de893942be"></a></span>
<span id="cb16-19-de893942be"><a href="#cb16-19-de893942be"></a> <span class="cf">return</span> len_so_far</span></code></pre></div>
<p>Notice that other than renaming a variable, we did not change the function body at all! This demonstrates how powerful the accumulator pattern can be; accumulators can work with any iterable object.</p>
<h3 id="alternatives-to-for-loops-de893942be">Alternatives to for loops</h3>
<p>You may feel that several of the examples in this section are contrived. You are not wrong; we are trying to leverage your familiarity with the built-in functions to help introduce a new concept. You may also have noticed that there are other ways to solve some of the problems weve presented. For example, <code>average_menu_price</code> can be solved using comprehensions rather than loops:</p>
<div class="sourceCode" id="cb17-de893942be"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1-de893942be"><a href="#cb17-1-de893942be"></a><span class="kw">def</span> average_menu_price_v2(menu: <span class="bu">dict</span>[<span class="bu">str</span>, <span class="bu">float</span>]) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb17-2-de893942be"><a href="#cb17-2-de893942be"></a> <span class="co">&quot;&quot;&quot;Return the average price of an item from the menu.</span></span>
<span id="cb17-3-de893942be"><a href="#cb17-3-de893942be"></a></span>
<span id="cb17-4-de893942be"><a href="#cb17-4-de893942be"></a><span class="co"> &gt;&gt;&gt; average_menu_price({&#39;fries&#39;: 4.0, &#39;hamburger&#39;: 6.0})</span></span>
<span id="cb17-5-de893942be"><a href="#cb17-5-de893942be"></a><span class="co"> 5.0</span></span>
<span id="cb17-6-de893942be"><a href="#cb17-6-de893942be"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb17-7-de893942be"><a href="#cb17-7-de893942be"></a> prices <span class="op">=</span> [menu[item] <span class="cf">for</span> item <span class="kw">in</span> menu]</span>
<span id="cb17-8-de893942be"><a href="#cb17-8-de893942be"></a> <span class="cf">return</span> <span class="bu">sum</span>(prices) <span class="op">/</span> <span class="bu">len</span>(prices)</span></code></pre></div>
<p>Indeed, you have performed remarkably complex computations up to this point using just comprehensions to filter and transform data, and Pythons built-in functions to aggregate this data. For loops provide an alternate approach to these comprehensions that offer a trade-off of <em>code complexity</em> vs. <em>flexibility</em>. Comprehensions and built-in functions are often shorter and more direct translations of a computation than for loops, but for loops allow us to customize exactly how filtering and aggregation occurs.<label for="sn-5-de893942be" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-de893942be" class="margin-toggle"/><span class="sidenote"> A good rule of thumb to follow in this course is to use comprehensions and built-in functions when possible, and use loops when you really need a custom aggregation.</span></p>
<p>Of course, on your journey to learning programming it is important that you learn and master both of these techniques, and be able to translate between them when possible! Just as there are many ways to visualize a sunset (a painting, a photograph, a drawing, pixel art), so too are there many ways to implement a function. So whenever you see some code for a function involving comprehensions or loops, remember that you can always turn it into an additional learning opportunity by trying to rewrite it with a different approach.</p>
<h2 id="references-de893942be">References</h2>
<ul>
<li>CSC108 videos: For loop over str (<a href="https://youtu.be/4OGtBt_VNCg">Part 1</a>, <a href="https://youtu.be/WRVDP152GEI">Part 2</a>, <a href="https://youtu.be/WRVDP152GEI">Part 3</a>)</li>
</ul>
</section>
<!--
(from outline)
Now let's see this in action in the PyCharm debugger.
We've now seen two ways to trace through this loop: writing (in English) what happens at each loop iteration, and tracing through with the PyCharm debugger.
The writing has the benefit that we can scan through to find each step and forces us to be very precise and detailed about analysing the code that's run, while the PyCharm debugger makes it very clear exactly what the values of the variables `sum_so_far` and `number` are and how they change over time, but we can only see one variable at a time (can't see history), and can only go forwards instead of backwards.
So we introduce a third approach that combines some of the key strengths of these two approaches (but also has some limitations): the *loop accumulation table*.
-->
<br/> <a id="anchor-04-05"></a>
<header id="title-block-header-95faf7e65d">
<h1 class="title">4.5 For Loop Variations</h1>
</header>
<section>
<p>In the last section we introduced for loops and the accumulator pattern. The examples we used all had very similar code, with some differences in the type of collection we iterated over and how we initialized and updated our accumulator variable. In this section, well study two variations of the basic loop accumulator pattern: having multiple accumulator variables for the same loop, and using if statements to perform a <em>conditional update</em> of loop accumulators.</p>
<p>Before proceeding, please take moment to review the loop accumulator pattern:</p>
<div class="sourceCode" id="cb1-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-95faf7e65d"><a href="#cb1-1-95faf7e65d"></a><span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far <span class="op">=</span> <span class="op">&lt;</span>default_value<span class="op">&gt;</span></span>
<span id="cb1-2-95faf7e65d"><a href="#cb1-2-95faf7e65d"></a></span>
<span id="cb1-3-95faf7e65d"><a href="#cb1-3-95faf7e65d"></a><span class="cf">for</span> element <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span>:</span>
<span id="cb1-4-95faf7e65d"><a href="#cb1-4-95faf7e65d"></a> <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far <span class="op">=</span> ... <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far ... element ... <span class="co"># Somehow combine loop variable and accumulator</span></span>
<span id="cb1-5-95faf7e65d"><a href="#cb1-5-95faf7e65d"></a></span>
<span id="cb1-6-95faf7e65d"><a href="#cb1-6-95faf7e65d"></a><span class="cf">return</span> <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far</span></code></pre></div>
<h2 id="multiple-accumulators-95faf7e65d">Multiple accumulators</h2>
<p>In each example from the last section we used only one accumulator. The pattern can be extended to use multiple accumulators. For example, given a dictionary mapping menu items to prices, how can we get the average price? Remember that an average requires both the sum and the number of elements. We can create two accumulators to accomplish this:</p>
<div class="sourceCode" id="cb2-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-95faf7e65d"><a href="#cb2-1-95faf7e65d"></a><span class="kw">def</span> average_menu_price(menu: <span class="bu">dict</span>[<span class="bu">str</span>, <span class="bu">float</span>]) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb2-2-95faf7e65d"><a href="#cb2-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;Return the average price of an item from the menu.</span></span>
<span id="cb2-3-95faf7e65d"><a href="#cb2-3-95faf7e65d"></a></span>
<span id="cb2-4-95faf7e65d"><a href="#cb2-4-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; average_menu_price({&#39;fries&#39;: 3.5, &#39;hamburger&#39;: 6.5})</span></span>
<span id="cb2-5-95faf7e65d"><a href="#cb2-5-95faf7e65d"></a><span class="co"> 5.0</span></span>
<span id="cb2-6-95faf7e65d"><a href="#cb2-6-95faf7e65d"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-7-95faf7e65d"><a href="#cb2-7-95faf7e65d"></a> <span class="co"># ACCUMULATOR len_so_far: keep track of the number of</span></span>
<span id="cb2-8-95faf7e65d"><a href="#cb2-8-95faf7e65d"></a> <span class="co"># items in the menu seen so far in the loop.</span></span>
<span id="cb2-9-95faf7e65d"><a href="#cb2-9-95faf7e65d"></a> len_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb2-10-95faf7e65d"><a href="#cb2-10-95faf7e65d"></a> <span class="co"># ACCUMULATOR total_so_far: keep track of the cost of</span></span>
<span id="cb2-11-95faf7e65d"><a href="#cb2-11-95faf7e65d"></a> <span class="co"># all items in the menu seen so far in the loop.</span></span>
<span id="cb2-12-95faf7e65d"><a href="#cb2-12-95faf7e65d"></a> total_so_far <span class="op">=</span> <span class="fl">0.0</span></span>
<span id="cb2-13-95faf7e65d"><a href="#cb2-13-95faf7e65d"></a></span>
<span id="cb2-14-95faf7e65d"><a href="#cb2-14-95faf7e65d"></a> <span class="cf">for</span> item <span class="kw">in</span> menu:</span>
<span id="cb2-15-95faf7e65d"><a href="#cb2-15-95faf7e65d"></a> len_so_far <span class="op">=</span> len_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb2-16-95faf7e65d"><a href="#cb2-16-95faf7e65d"></a> total_so_far <span class="op">=</span> total_so_far <span class="op">+</span> menu[item]</span>
<span id="cb2-17-95faf7e65d"><a href="#cb2-17-95faf7e65d"></a></span>
<span id="cb2-18-95faf7e65d"><a href="#cb2-18-95faf7e65d"></a> <span class="cf">return</span> total_so_far <span class="op">/</span> len_so_far</span></code></pre></div>
<p>Here is how we could write a loop accumulation table for this example:</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 12%" />
<col style="width: 26%" />
<col style="width: 29%" />
<col style="width: 31%" />
</colgroup>
<thead>
<tr class="header">
<th>Iteration</th>
<th>Loop variable (<code>item</code>)</th>
<th>Accumulator <code>len_so_far</code></th>
<th>Accumulator <code>total_so_far</code></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td></td>
<td><code>0</code></td>
<td><code>0.0</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>'fries'</code></td>
<td><code>1</code></td>
<td><code>6.5</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>'hamburger'</code></td>
<td><code>2</code></td>
<td><code>10.0</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="conditional-execution-of-the-accumulator-95faf7e65d">Conditional execution of the accumulator</h2>
<p>Consider the following problem: given a string, count the number of vowels in the string.</p>
<div class="sourceCode" id="cb3-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-95faf7e65d"><a href="#cb3-1-95faf7e65d"></a><span class="kw">def</span> count_vowels(s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-95faf7e65d"><a href="#cb3-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;Return the number of vowels in s.</span></span>
<span id="cb3-3-95faf7e65d"><a href="#cb3-3-95faf7e65d"></a></span>
<span id="cb3-4-95faf7e65d"><a href="#cb3-4-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; count_vowels(&#39;aeiou&#39;)</span></span>
<span id="cb3-5-95faf7e65d"><a href="#cb3-5-95faf7e65d"></a><span class="co"> 5</span></span>
<span id="cb3-6-95faf7e65d"><a href="#cb3-6-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; count_vowels(&#39;David&#39;)</span></span>
<span id="cb3-7-95faf7e65d"><a href="#cb3-7-95faf7e65d"></a><span class="co"> 2</span></span>
<span id="cb3-8-95faf7e65d"><a href="#cb3-8-95faf7e65d"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>We saw in <a href="04-for-loops.html">4.4 Repeated Execution: For Loops</a> that we could count <em>every</em> character in a given string by using an accumulator that increased by 1 for every loop iteration. We can use the same idea for counting just vowels, but we need to increase the accumulator only when the current character is a vowel.</p>
<p>In Chapter 3, we learned how to control execution of whole blocks of code using if statements. By nesting an if statement inside a for loop, we can adapt our accumulator pattern to only update the accumulator when certain conditions are met.</p>
<div class="sourceCode" id="cb4-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-95faf7e65d"><a href="#cb4-1-95faf7e65d"></a><span class="kw">def</span> count_vowels(s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb4-2-95faf7e65d"><a href="#cb4-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;Return the number of vowels in s.</span></span>
<span id="cb4-3-95faf7e65d"><a href="#cb4-3-95faf7e65d"></a></span>
<span id="cb4-4-95faf7e65d"><a href="#cb4-4-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; count_vowels(&#39;aeiou&#39;)</span></span>
<span id="cb4-5-95faf7e65d"><a href="#cb4-5-95faf7e65d"></a><span class="co"> 5</span></span>
<span id="cb4-6-95faf7e65d"><a href="#cb4-6-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; count_vowels(&#39;David&#39;)</span></span>
<span id="cb4-7-95faf7e65d"><a href="#cb4-7-95faf7e65d"></a><span class="co"> 2</span></span>
<span id="cb4-8-95faf7e65d"><a href="#cb4-8-95faf7e65d"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-9-95faf7e65d"><a href="#cb4-9-95faf7e65d"></a> <span class="co"># ACCUMULATOR vowels_so_far: keep track of the number of vowels</span></span>
<span id="cb4-10-95faf7e65d"><a href="#cb4-10-95faf7e65d"></a> <span class="co"># seen so far in the loop.</span></span>
<span id="cb4-11-95faf7e65d"><a href="#cb4-11-95faf7e65d"></a> vowels_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb4-12-95faf7e65d"><a href="#cb4-12-95faf7e65d"></a></span>
<span id="cb4-13-95faf7e65d"><a href="#cb4-13-95faf7e65d"></a> <span class="cf">for</span> letter <span class="kw">in</span> s:</span>
<span id="cb4-14-95faf7e65d"><a href="#cb4-14-95faf7e65d"></a> <span class="cf">if</span> letter <span class="kw">in</span> <span class="st">&#39;aeiou&#39;</span>:</span>
<span id="cb4-15-95faf7e65d"><a href="#cb4-15-95faf7e65d"></a> vowels_so_far <span class="op">=</span> vowels_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb4-16-95faf7e65d"><a href="#cb4-16-95faf7e65d"></a></span>
<span id="cb4-17-95faf7e65d"><a href="#cb4-17-95faf7e65d"></a> <span class="cf">return</span> vowels_so_far</span></code></pre></div>
<p>If <code>word</code> is the empty string, the for loop will not iterate once and the value 0 is returned. This tells us that we have initialized our accumulator correctly. What about the loop body? There are two cases to consider:</p>
<ol type="1">
<li>When <code>letter</code> is a vowel, the reassignment <code>vowels_so_far = vowels_so_far + 1</code> increases the number of vowels seen so far by 1.</li>
<li>When <code>letter</code> is not a vowel, nothing else happens in the current iteration because this if statement has no else branch. The vowel count remains the same.</li>
</ol>
<p>Heres our loop accumulation table for <code>count_vowels('David')</code>. At each iteration, the accumulator either stays the same (when <code>letter</code> is not a vowel) or increases by 1 (when <code>letter</code> is a vowel).</p>
<div class="reference-table">
<table>
<colgroup>
<col style="width: 23%" />
<col style="width: 34%" />
<col style="width: 41%" />
</colgroup>
<thead>
<tr class="header">
<th>Loop Iteration</th>
<th>Loop Variable <code>letter</code></th>
<th>Accumulator <code>vowels_so_far</code></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td></td>
<td><code>0</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>'D'</code></td>
<td><code>0</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>'a'</code></td>
<td><code>1</code></td>
</tr>
<tr class="even">
<td>3</td>
<td><code>'v'</code></td>
<td><code>1</code></td>
</tr>
<tr class="odd">
<td>4</td>
<td><code>'i'</code></td>
<td><code>2</code></td>
</tr>
<tr class="even">
<td>5</td>
<td><code>'d'</code></td>
<td><code>2</code></td>
</tr>
</tbody>
</table>
</div>
<!-- TODO: Add general control flow diagram of `count_vowels`-->
<p>We can also contrast this function to an equivalent implementation using a filtering comprehension:</p>
<div class="sourceCode" id="cb5-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-95faf7e65d"><a href="#cb5-1-95faf7e65d"></a><span class="kw">def</span> count_vowels(s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb5-2-95faf7e65d"><a href="#cb5-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;Return the number of vowels in s.</span></span>
<span id="cb5-3-95faf7e65d"><a href="#cb5-3-95faf7e65d"></a></span>
<span id="cb5-4-95faf7e65d"><a href="#cb5-4-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; count_vowels(&#39;aeiou&#39;)</span></span>
<span id="cb5-5-95faf7e65d"><a href="#cb5-5-95faf7e65d"></a><span class="co"> 5</span></span>
<span id="cb5-6-95faf7e65d"><a href="#cb5-6-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; count_vowels(&#39;David&#39;)</span></span>
<span id="cb5-7-95faf7e65d"><a href="#cb5-7-95faf7e65d"></a><span class="co"> 2</span></span>
<span id="cb5-8-95faf7e65d"><a href="#cb5-8-95faf7e65d"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-9-95faf7e65d"><a href="#cb5-9-95faf7e65d"></a> <span class="cf">return</span> <span class="bu">len</span>([letter <span class="cf">for</span> letter <span class="kw">in</span> s <span class="cf">if</span> letter <span class="kw">in</span> <span class="st">&#39;aeiou&#39;</span>])</span></code></pre></div>
<p>This version hopefully makes clear that the <code>if letter in 'aeiou</code> in the loop version acts as a <em>filter</em> on the string <code>s</code>, causing the loop accumulator to only be updated for the vowels. In this version, the actual accumulation (<code>vowels_so_far = vowels_so_far + 1</code>) is handled by the call to <code>len</code>.</p>
<h3 id="implementing-max-95faf7e65d">Implementing <code>max</code></h3>
<p>Now lets consider implementing another built-in aggregation function: <code>max</code>. Well require that the input be non-empty, as we cannot compute the maximum element of an empty collection. This allows us to set the initial value of our accumulator based on the input.</p>
<div class="sourceCode" id="cb6-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-95faf7e65d"><a href="#cb6-1-95faf7e65d"></a><span class="kw">def</span> my_max(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb6-2-95faf7e65d"><a href="#cb6-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;Return the maximum value of the numbers in numbers.</span></span>
<span id="cb6-3-95faf7e65d"><a href="#cb6-3-95faf7e65d"></a></span>
<span id="cb6-4-95faf7e65d"><a href="#cb6-4-95faf7e65d"></a><span class="co"> Preconditions:</span></span>
<span id="cb6-5-95faf7e65d"><a href="#cb6-5-95faf7e65d"></a><span class="co"> - numbers != []</span></span>
<span id="cb6-6-95faf7e65d"><a href="#cb6-6-95faf7e65d"></a></span>
<span id="cb6-7-95faf7e65d"><a href="#cb6-7-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; my_max([10, 20])</span></span>
<span id="cb6-8-95faf7e65d"><a href="#cb6-8-95faf7e65d"></a><span class="co"> 20</span></span>
<span id="cb6-9-95faf7e65d"><a href="#cb6-9-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; my_max([-5, -4])</span></span>
<span id="cb6-10-95faf7e65d"><a href="#cb6-10-95faf7e65d"></a><span class="co"> -4</span></span>
<span id="cb6-11-95faf7e65d"><a href="#cb6-11-95faf7e65d"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb6-12-95faf7e65d"><a href="#cb6-12-95faf7e65d"></a> <span class="co"># ACCUMULATOR max_so_far: keep track of the maximum value</span></span>
<span id="cb6-13-95faf7e65d"><a href="#cb6-13-95faf7e65d"></a> <span class="co"># of the elements in numbers seen so far in the loop.</span></span>
<span id="cb6-14-95faf7e65d"><a href="#cb6-14-95faf7e65d"></a> max_so_far <span class="op">=</span> numbers[<span class="dv">0</span>]</span>
<span id="cb6-15-95faf7e65d"><a href="#cb6-15-95faf7e65d"></a></span>
<span id="cb6-16-95faf7e65d"><a href="#cb6-16-95faf7e65d"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb6-17-95faf7e65d"><a href="#cb6-17-95faf7e65d"></a> <span class="cf">if</span> number <span class="op">&gt;</span> max_so_far:</span>
<span id="cb6-18-95faf7e65d"><a href="#cb6-18-95faf7e65d"></a> max_so_far <span class="op">=</span> number</span>
<span id="cb6-19-95faf7e65d"><a href="#cb6-19-95faf7e65d"></a></span>
<span id="cb6-20-95faf7e65d"><a href="#cb6-20-95faf7e65d"></a> <span class="cf">return</span> max_so_far</span></code></pre></div>
<p>Because we can <em>assume</em> that the precondition holds when implementing <code>my_max</code>, we can access <code>numbers[0]</code> to set the initial value of <code>max_so_far</code> without worrying about getting an <code>IndexError</code>. In the loop, the accumulator <code>max_so_far</code> is updated only when a larger number is encountered (<code>if number &gt; max_so_far</code>). Note that here, the term <em>accumulator</em> diverges from its normal English meaning. At any point during the loop, <code>max_so_far</code> is assigned to a single list element, not some “accumulation” of all list elements see so far. Instead, <code>max_so_far</code> represents the <em>maximum of the elements seen so far</em>, and so what is being accumulated is a set of facts: “the elements seen so far all <code>&lt;= max_so_far</code>”.</p>
<h3 id="existential-search-95faf7e65d">Existential search</h3>
<p>In <a href="../03-logic/02-predicate-logic.html">3.2 Predicate Logic</a>, we saw how to use <code>any</code> to check whether there exists a string in a collection that starts with the letter <code>'D'</code>:</p>
<div class="sourceCode" id="cb7-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-95faf7e65d"><a href="#cb7-1-95faf7e65d"></a><span class="kw">def</span> starts_with(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb7-2-95faf7e65d"><a href="#cb7-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;Return whether one of the given strings starts with the character char.</span></span>
<span id="cb7-3-95faf7e65d"><a href="#cb7-3-95faf7e65d"></a></span>
<span id="cb7-4-95faf7e65d"><a href="#cb7-4-95faf7e65d"></a><span class="co"> Precondition:</span></span>
<span id="cb7-5-95faf7e65d"><a href="#cb7-5-95faf7e65d"></a><span class="co"> - all({s != &#39;&#39; for s in strings})</span></span>
<span id="cb7-6-95faf7e65d"><a href="#cb7-6-95faf7e65d"></a><span class="co"> - len(char) == 1</span></span>
<span id="cb7-7-95faf7e65d"><a href="#cb7-7-95faf7e65d"></a></span>
<span id="cb7-8-95faf7e65d"><a href="#cb7-8-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; starts_with([&#39;Hello&#39;, &#39;Goodbye&#39;, &#39;David&#39;, &#39;Dario&#39;], &#39;D&#39;)</span></span>
<span id="cb7-9-95faf7e65d"><a href="#cb7-9-95faf7e65d"></a><span class="co"> True</span></span>
<span id="cb7-10-95faf7e65d"><a href="#cb7-10-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; starts_with([&#39;Hello&#39;, &#39;Goodbye&#39;, &#39;David&#39;, &#39;Dario&#39;], &#39;A&#39;)</span></span>
<span id="cb7-11-95faf7e65d"><a href="#cb7-11-95faf7e65d"></a><span class="co"> False</span></span>
<span id="cb7-12-95faf7e65d"><a href="#cb7-12-95faf7e65d"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-13-95faf7e65d"><a href="#cb7-13-95faf7e65d"></a> <span class="cf">return</span> <span class="bu">any</span>({s[<span class="dv">0</span>] <span class="op">==</span> char <span class="cf">for</span> s <span class="kw">in</span> words})</span></code></pre></div>
<p>Our next goal is to implement this function <em>without</em> using the <code>any</code> function, replacing it for loops and if statements. If we take a look at the argument to <code>any</code> above, we see some pretty big hints on how to do this:</p>
<ol type="1">
<li>The syntax <code>for s in words</code> can be used to create a for loop.</li>
<li>The expression <code>s[0] == char</code> can be used as a condition for an if statement.</li>
</ol>
<p>Lets give it a shot using our existing accumulator pattern. Because the result of the function is a <code>bool</code>, our accumulator will also be a <code>bool</code>. Its initial value will be <code>False</code>, which is the correct return value when <code>strings</code> is empty.</p>
<div class="sourceCode" id="cb8-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-95faf7e65d"><a href="#cb8-1-95faf7e65d"></a><span class="kw">def</span> starts_with_v2(words: <span class="bu">list</span>[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb8-2-95faf7e65d"><a href="#cb8-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb8-3-95faf7e65d"><a href="#cb8-3-95faf7e65d"></a> <span class="co"># ACCUMULATOR starts_with_so_far: keep track of whether</span></span>
<span id="cb8-4-95faf7e65d"><a href="#cb8-4-95faf7e65d"></a> <span class="co"># any of the words seen by the loop so far starts with char.</span></span>
<span id="cb8-5-95faf7e65d"><a href="#cb8-5-95faf7e65d"></a> starts_with_so_far <span class="op">=</span> <span class="va">False</span></span>
<span id="cb8-6-95faf7e65d"><a href="#cb8-6-95faf7e65d"></a></span>
<span id="cb8-7-95faf7e65d"><a href="#cb8-7-95faf7e65d"></a> <span class="cf">for</span> s <span class="kw">in</span> words:</span>
<span id="cb8-8-95faf7e65d"><a href="#cb8-8-95faf7e65d"></a> ...</span>
<span id="cb8-9-95faf7e65d"><a href="#cb8-9-95faf7e65d"></a></span>
<span id="cb8-10-95faf7e65d"><a href="#cb8-10-95faf7e65d"></a> <span class="cf">return</span> starts_with_so_far</span></code></pre></div>
<p>How do we update the accumulator? We set it to <code>True</code> when the current string <code>s</code> starts with <code>char</code>, which is exactly the condition from the comprehension.</p>
<div class="sourceCode" id="cb9-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-95faf7e65d"><a href="#cb9-1-95faf7e65d"></a><span class="kw">def</span> starts_with_v2(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb9-2-95faf7e65d"><a href="#cb9-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb9-3-95faf7e65d"><a href="#cb9-3-95faf7e65d"></a> <span class="co"># ACCUMULATOR starts_with_so_far: keep track of whether</span></span>
<span id="cb9-4-95faf7e65d"><a href="#cb9-4-95faf7e65d"></a> <span class="co"># any of the strings seen by the loop so far starts with char.</span></span>
<span id="cb9-5-95faf7e65d"><a href="#cb9-5-95faf7e65d"></a> starts_with_so_far <span class="op">=</span> <span class="va">False</span></span>
<span id="cb9-6-95faf7e65d"><a href="#cb9-6-95faf7e65d"></a></span>
<span id="cb9-7-95faf7e65d"><a href="#cb9-7-95faf7e65d"></a> <span class="cf">for</span> s <span class="kw">in</span> strings:</span>
<span id="cb9-8-95faf7e65d"><a href="#cb9-8-95faf7e65d"></a> <span class="cf">if</span> s[<span class="dv">0</span>] <span class="op">==</span> char:</span>
<span id="cb9-9-95faf7e65d"><a href="#cb9-9-95faf7e65d"></a> starts_with_so_far <span class="op">=</span> <span class="va">True</span></span>
<span id="cb9-10-95faf7e65d"><a href="#cb9-10-95faf7e65d"></a></span>
<span id="cb9-11-95faf7e65d"><a href="#cb9-11-95faf7e65d"></a> <span class="cf">return</span> starts_with_so_far</span></code></pre></div>
<p>Here is a loop accumulation table for <code>starts_with(['Hello', 'Goodbye', 'David', 'Mario'], 'D')</code>. The third iteration assigns <code>starts_with_so_far</code> to <code>True</code>, while in the other iterations nothing occurs.</p>
<div class="reference-table">
<table style="width:93%;">
<colgroup>
<col style="width: 16%" />
<col style="width: 27%" />
<col style="width: 48%" />
</colgroup>
<thead>
<tr class="header">
<th>Iteration</th>
<th>Loop variable <code>s</code></th>
<th>Accumulator <code>starts_with_so_far</code></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td></td>
<td><code>False</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>'Hello'</code></td>
<td><code>False</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>'Goodbye'</code></td>
<td><code>False</code></td>
</tr>
<tr class="even">
<td>3</td>
<td><code>'David'</code></td>
<td><code>True</code></td>
</tr>
<tr class="odd">
<td>4</td>
<td><code>'Mario'</code></td>
<td><code>True</code></td>
</tr>
</tbody>
</table>
</div>
<h3 id="early-returns-95faf7e65d">Early returns</h3>
<p>The function <code>starts_with_v2</code> is correct and fits our accumulator pattern well. But you might have noticed that it performs unnecessary work because it must loop through every element of the collection before returning a result. Why is this unnecessary? Because we are interested only in whether <em>there exists</em> a string that starts with the given letter! As soon as the condition <code>s[0] == char</code> evaluates to <code>True</code>, we know that the answer is <em>Yes</em> without checking any of the remaining strings.</p>
<p>So the question is, how do we take advantage of this observation to make our code more efficient? We can use a return statement inside the body of the loop. Lets revisit how we described the execution of a return statement in Chapter 2 (new emphasis in <strong>bold</strong>):</p>
<blockquote>
<p>When a return statement is executed, the following happens:</p>
</blockquote>
<blockquote>
<ol type="1">
<li>The <code>&lt;expression&gt;</code> is evaluated, producing a value.</li>
<li>That value is then returned to wherever the function was called. <strong>No more code in the function body is executed after this point.</strong>"</li>
</ol>
</blockquote>
<p>In all our functions so far, we have written return statements only at the end of our function bodies or branches of an if statement. This should make sense based on the behaviour described above: any code after a return statement will not execute!</p>
<div class="sourceCode" id="cb10-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-95faf7e65d"><a href="#cb10-1-95faf7e65d"></a><span class="cf">return</span> <span class="dv">5</span></span>
<span id="cb10-2-95faf7e65d"><a href="#cb10-2-95faf7e65d"></a>x <span class="op">=</span> <span class="dv">10</span> <span class="co"># This statement doesn&#39;t execute!</span></span></code></pre></div>
<p>But we can combine return statements with if statements to conditionally stop executing any more code in the function body. This is called <em>short-circuiting</em> or <em>early returning</em>.</p>
<p>So our first attempt at making a more efficient <code>starts_with</code> is to use an early return inside the if branch:</p>
<div class="sourceCode" id="cb11-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-95faf7e65d"><a href="#cb11-1-95faf7e65d"></a><span class="kw">def</span> starts_with_v3(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb11-2-95faf7e65d"><a href="#cb11-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb11-3-95faf7e65d"><a href="#cb11-3-95faf7e65d"></a> <span class="cf">for</span> s <span class="kw">in</span> strings:</span>
<span id="cb11-4-95faf7e65d"><a href="#cb11-4-95faf7e65d"></a> <span class="cf">if</span> s[<span class="dv">0</span>] <span class="op">==</span> char:</span>
<span id="cb11-5-95faf7e65d"><a href="#cb11-5-95faf7e65d"></a> <span class="cf">return</span> <span class="va">True</span></span></code></pre></div>
<!-- TODO: Add control flow diagram of `starts_with_v3`, showing that there is a path from the for loop to no return statement (or a path from the for loop to the default return statement: return None)-->
<p>This for loop is strange: it seems we no longer have an accumulator variable! This is actually fairly common for functions that return booleans. Rather than accumulating a <code>True</code>/<code>False</code> value, it is often possible to directly return the literals <code>True</code> or <code>False</code>.</p>
<p>The <code>starts_with_v3</code> implementation does successfully return <code>True</code> on our first doctest example during the <em>third</em> loop iteration (when <code>s = 'David'</code>), skipping the fourth iteration. However, this implementation will fail the second doctest example (when there are no strings that start with the given character in the collection). We have not explicitly stated what to return when <em>none</em> of the strings in <code>words</code> starts with <code>char</code>. Actually, we have <em>violated our own type contract</em> because the function will implicitly return <code>None</code> in this scenario.</p>
<p>To fix it, we need to specify what to return if the loop stops without retuning early—this occurs only when there are no strings that start with the given character, and so we return <code>False</code>.</p>
<div class="sourceCode" id="cb12-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-95faf7e65d"><a href="#cb12-1-95faf7e65d"></a><span class="kw">def</span> starts_with_v4(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb12-2-95faf7e65d"><a href="#cb12-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb12-3-95faf7e65d"><a href="#cb12-3-95faf7e65d"></a> <span class="cf">for</span> s <span class="kw">in</span> strings:</span>
<span id="cb12-4-95faf7e65d"><a href="#cb12-4-95faf7e65d"></a> <span class="cf">if</span> s[<span class="dv">0</span>] <span class="op">==</span> char:</span>
<span id="cb12-5-95faf7e65d"><a href="#cb12-5-95faf7e65d"></a> <span class="cf">return</span> <span class="va">True</span></span>
<span id="cb12-6-95faf7e65d"><a href="#cb12-6-95faf7e65d"></a></span>
<span id="cb12-7-95faf7e65d"><a href="#cb12-7-95faf7e65d"></a> <span class="cf">return</span> <span class="va">False</span></span></code></pre></div>
<!-- TODO: Add control flow diagram of `starts_with_v4`.-->
<h3 id="one-common-error-95faf7e65d">One common error</h3>
<p>When working with early returns inside loops, students often have a tendency to write symmetric if-else branches, like the following:</p>
<div class="sourceCode" id="cb13-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-95faf7e65d"><a href="#cb13-1-95faf7e65d"></a><span class="kw">def</span> starts_with_v5(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb13-2-95faf7e65d"><a href="#cb13-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb13-3-95faf7e65d"><a href="#cb13-3-95faf7e65d"></a> <span class="cf">for</span> s <span class="kw">in</span> strings:</span>
<span id="cb13-4-95faf7e65d"><a href="#cb13-4-95faf7e65d"></a> <span class="cf">if</span> s[<span class="dv">0</span>] <span class="op">==</span> char:</span>
<span id="cb13-5-95faf7e65d"><a href="#cb13-5-95faf7e65d"></a> <span class="cf">return</span> <span class="va">True</span></span>
<span id="cb13-6-95faf7e65d"><a href="#cb13-6-95faf7e65d"></a> <span class="cf">else</span>:</span>
<span id="cb13-7-95faf7e65d"><a href="#cb13-7-95faf7e65d"></a> <span class="cf">return</span> <span class="va">False</span></span></code></pre></div>
<p>Unfortunately, while we emphasized symmetry earlier when writing functions with if statements, here symmetry is <em>not</em> desirable! With both the if and else branches containing an early return, the loop will only ever perform one iteration. That is, <code>starts_with_v5</code> makes a decision about whether to return <code>True</code> or <code>False</code> just by examining the first string in the collection, regardless of what the other strings are. So if we consider <code>starts_with_v5(['Hello', 'Goodbye', 'David', 'Mario'], 'D')</code>, the only string to be visited in the loop is <code>'Hello'</code>, and <code>False</code> would be returned!</p>
<p>The lesson here is that existential searches are fundamentally asymmetric: your function can return <code>True</code> early as soon as it has found an element of the collection meeting the desired criterion, but to return <code>False</code> it must check <em>every</em> element of the collection.</p>
<!-- TODO: Add control flow diagram of `starts_with_v5`, showing that there is no way to loop.-->
<h3 id="universal-search-95faf7e65d">Universal search</h3>
<p>Now lets consider a dual problem to the previous one: given a collection of strings and a character, return whether <em>all</em> strings in the collect start with that letter. If we use the comprehension version of <code>starts_with</code>, this change is as simple as swapping the <code>any</code> for <code>all</code>:</p>
<div class="sourceCode" id="cb14-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-95faf7e65d"><a href="#cb14-1-95faf7e65d"></a><span class="kw">def</span> all_start_with(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb14-2-95faf7e65d"><a href="#cb14-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;Return whether all of the given strings starts with the character char.</span></span>
<span id="cb14-3-95faf7e65d"><a href="#cb14-3-95faf7e65d"></a></span>
<span id="cb14-4-95faf7e65d"><a href="#cb14-4-95faf7e65d"></a><span class="co"> Precondition:</span></span>
<span id="cb14-5-95faf7e65d"><a href="#cb14-5-95faf7e65d"></a><span class="co"> - all({s != &#39;&#39; for s in strings})</span></span>
<span id="cb14-6-95faf7e65d"><a href="#cb14-6-95faf7e65d"></a><span class="co"> - len(char) == 1</span></span>
<span id="cb14-7-95faf7e65d"><a href="#cb14-7-95faf7e65d"></a></span>
<span id="cb14-8-95faf7e65d"><a href="#cb14-8-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; all_starts_with([&#39;Hello&#39;, &#39;Goodbye&#39;, &#39;David&#39;, &#39;Dario&#39;], &#39;D&#39;)</span></span>
<span id="cb14-9-95faf7e65d"><a href="#cb14-9-95faf7e65d"></a><span class="co"> False</span></span>
<span id="cb14-10-95faf7e65d"><a href="#cb14-10-95faf7e65d"></a><span class="co"> &gt;&gt;&gt; all_starts_with([&#39;Drip&#39;, &#39;Drop&#39;, &#39;Dangle&#39;], &#39;D&#39;)</span></span>
<span id="cb14-11-95faf7e65d"><a href="#cb14-11-95faf7e65d"></a><span class="co"> True</span></span>
<span id="cb14-12-95faf7e65d"><a href="#cb14-12-95faf7e65d"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb14-13-95faf7e65d"><a href="#cb14-13-95faf7e65d"></a> <span class="cf">return</span> <span class="bu">all</span>({s[<span class="dv">0</span>] <span class="op">==</span> char <span class="cf">for</span> s <span class="kw">in</span> strings})</span></code></pre></div>
<p>We can also use the accumulator pattern from <code>starts_with_v2</code> to check every string. Now, our accumulator starts with the default value of <code>True</code>, and changes to <code>False</code> when the loop encounters a string that does <em>not</em> start with the given letter.<label for="sn-0-95faf7e65d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-95faf7e65d" class="margin-toggle"/><span class="sidenote"> Such a string acts as a <em>counterexample</em> to the statement “every string starts with the given character”.</span></p>
<div class="sourceCode" id="cb15-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-95faf7e65d"><a href="#cb15-1-95faf7e65d"></a><span class="kw">def</span> all_starts_with_v2(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb15-2-95faf7e65d"><a href="#cb15-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb15-3-95faf7e65d"><a href="#cb15-3-95faf7e65d"></a> <span class="co"># ACCUMULATOR starts_with_so_far: keep track of whether</span></span>
<span id="cb15-4-95faf7e65d"><a href="#cb15-4-95faf7e65d"></a> <span class="co"># all of the strings seen by the loop so far starts with char.</span></span>
<span id="cb15-5-95faf7e65d"><a href="#cb15-5-95faf7e65d"></a> starts_with_so_far <span class="op">=</span> <span class="va">True</span></span>
<span id="cb15-6-95faf7e65d"><a href="#cb15-6-95faf7e65d"></a></span>
<span id="cb15-7-95faf7e65d"><a href="#cb15-7-95faf7e65d"></a> <span class="cf">for</span> s <span class="kw">in</span> strings:</span>
<span id="cb15-8-95faf7e65d"><a href="#cb15-8-95faf7e65d"></a> <span class="cf">if</span> s[<span class="dv">0</span>] <span class="op">!=</span> char:</span>
<span id="cb15-9-95faf7e65d"><a href="#cb15-9-95faf7e65d"></a> starts_with_so_far <span class="op">=</span> <span class="va">False</span></span>
<span id="cb15-10-95faf7e65d"><a href="#cb15-10-95faf7e65d"></a></span>
<span id="cb15-11-95faf7e65d"><a href="#cb15-11-95faf7e65d"></a> <span class="cf">return</span> starts_with_so_far</span></code></pre></div>
<p>And as before, we can also write this function using an early return, since we can return <code>False</code> as soon as a counterexample is found:</p>
<div class="sourceCode" id="cb16-95faf7e65d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1-95faf7e65d"><a href="#cb16-1-95faf7e65d"></a><span class="kw">def</span> all_starts_with_v3(strings: Iterable[<span class="bu">str</span>], char: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb16-2-95faf7e65d"><a href="#cb16-2-95faf7e65d"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb16-3-95faf7e65d"><a href="#cb16-3-95faf7e65d"></a> <span class="cf">for</span> s <span class="kw">in</span> words:</span>
<span id="cb16-4-95faf7e65d"><a href="#cb16-4-95faf7e65d"></a> <span class="cf">if</span> s[<span class="dv">0</span>] <span class="op">!=</span> char:</span>
<span id="cb16-5-95faf7e65d"><a href="#cb16-5-95faf7e65d"></a> <span class="cf">return</span> <span class="va">False</span></span>
<span id="cb16-6-95faf7e65d"><a href="#cb16-6-95faf7e65d"></a></span>
<span id="cb16-7-95faf7e65d"><a href="#cb16-7-95faf7e65d"></a> <span class="cf">return</span> <span class="va">True</span></span></code></pre></div>
<p>Note that this code is very similar to <code>starts_with_v4</code>, except the condition has been negated and the <code>True</code> and <code>False</code> swapped. Existential and universal search are very closely related, and this is borne out by the similarities in these two functions. However, this also illustrates the fact that loops are more complex than using built-in functions and comprehensions: before, we could just swap <code>any</code> for <code>all</code>, but with loops we have to change a few different areas of the code to make this change.</p>
</section>
<!--
We've seen short-circuiting before.
For example, when performing an `and` operation and the left-hand value evaluates to `False`, there is no need to test the right-hand value.
Similarly, the built-in functions `any` and `all` don't need to test all the values in a collection.
For example, as soon as the condition given to `any` evaluates to `True` for some element in the collection, the remaining elements do not need to be tested.
Let's look at how to implement our own, simplified versions of `any` and `all` using for loops, if statements, and return statements.
-->
<br/> <a id="anchor-04-06"></a>
<header id="title-block-header-6e597f6381">
<h1 class="title">4.6 Index-Based For Loops</h1>
</header>
<section>
<p>We have learned a lot about collections so far:</p>
<ol type="1">
<li>We can access the elements of a collection via indexing (e.g., for lists and strings) or key lookups (e.g., for dictionaries).</li>
<li>We can evaluate an expression for each element of a collection with comprehensions to produce a new collection.</li>
<li>We can execute a set of statements for each element of a collection with a for loop.</li>
</ol>
<p>The loops we have worked with so far are element-based, meaning the loop variable refers to a specific element in the collection. Though these loops are powerful, they have one limitation: they process each element of the collection independent of where they appear in the collection. In this section, well see how we can loop through elements of index-based collections while keeping track of the current index. Looping by index enables us to solve more problems than looping by element alone, because well be able to take into account <em>where</em> a particular element is in a collection in the loop body.</p>
<p>As in the previous section, before proceeding please take a moment to review the basic loop accumulator pattern:</p>
<div class="sourceCode" id="cb1-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-6e597f6381"><a href="#cb1-1-6e597f6381"></a><span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far <span class="op">=</span> <span class="op">&lt;</span>default_value<span class="op">&gt;</span></span>
<span id="cb1-2-6e597f6381"><a href="#cb1-2-6e597f6381"></a></span>
<span id="cb1-3-6e597f6381"><a href="#cb1-3-6e597f6381"></a><span class="cf">for</span> element <span class="kw">in</span> <span class="op">&lt;</span>collection<span class="op">&gt;</span>:</span>
<span id="cb1-4-6e597f6381"><a href="#cb1-4-6e597f6381"></a> <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far <span class="op">=</span> ... <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far ... element ... <span class="co"># Somehow combine loop variable and accumulator</span></span>
<span id="cb1-5-6e597f6381"><a href="#cb1-5-6e597f6381"></a></span>
<span id="cb1-6-6e597f6381"><a href="#cb1-6-6e597f6381"></a><span class="cf">return</span> <span class="op">&lt;</span>x<span class="op">&gt;</span>_so_far</span></code></pre></div>
<h2 id="remembering-the-problem-repeating-code-6e597f6381">Remembering the problem: repeating code</h2>
<p>When we introduced for loops, we presented a <code>my_sum</code> implementation that showed the exact statement that is repeated:</p>
<div class="sourceCode" id="cb2-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-6e597f6381"><a href="#cb2-1-6e597f6381"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-2-6e597f6381"><a href="#cb2-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.</span></span>
<span id="cb2-3-6e597f6381"><a href="#cb2-3-6e597f6381"></a></span>
<span id="cb2-4-6e597f6381"><a href="#cb2-4-6e597f6381"></a><span class="co"> &gt;&gt;&gt; my_sum([10, 20, 30])</span></span>
<span id="cb2-5-6e597f6381"><a href="#cb2-5-6e597f6381"></a><span class="co"> 60</span></span>
<span id="cb2-6-6e597f6381"><a href="#cb2-6-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-7-6e597f6381"><a href="#cb2-7-6e597f6381"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb2-8-6e597f6381"><a href="#cb2-8-6e597f6381"></a></span>
<span id="cb2-9-6e597f6381"><a href="#cb2-9-6e597f6381"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">0</span>]</span>
<span id="cb2-10-6e597f6381"><a href="#cb2-10-6e597f6381"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">1</span>]</span>
<span id="cb2-11-6e597f6381"><a href="#cb2-11-6e597f6381"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[<span class="dv">2</span>]</span>
<span id="cb2-12-6e597f6381"><a href="#cb2-12-6e597f6381"></a></span>
<span id="cb2-13-6e597f6381"><a href="#cb2-13-6e597f6381"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>Our eventual solution to the <code>my_sum</code> function used a loop variable, <code>number</code>, in place of the <code>numbers[_]</code> in the body. There is another solution if we observe that the indexes being used start at <code>0</code> and increase by one on each iteration of the loop. On the last iteration, the index should be: <code>len(numbers) - 1</code>. This sequence of numbers can be expressed using the <code>range</code> data type: <code>range(0, len(numbers))</code> Based on this, let us use a different kind of for loop to implement <code>my_sum</code>:</p>
<div class="sourceCode" id="cb3-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-6e597f6381"><a href="#cb3-1-6e597f6381"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-6e597f6381"><a href="#cb3-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.</span></span>
<span id="cb3-3-6e597f6381"><a href="#cb3-3-6e597f6381"></a></span>
<span id="cb3-4-6e597f6381"><a href="#cb3-4-6e597f6381"></a><span class="co"> &gt;&gt;&gt; my_sum([10, 20, 30])</span></span>
<span id="cb3-5-6e597f6381"><a href="#cb3-5-6e597f6381"></a><span class="co"> 60</span></span>
<span id="cb3-6-6e597f6381"><a href="#cb3-6-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-7-6e597f6381"><a href="#cb3-7-6e597f6381"></a> <span class="co"># ACCUMULATOR sum_so_far: keep track of the running sum of the elements in numbers.</span></span>
<span id="cb3-8-6e597f6381"><a href="#cb3-8-6e597f6381"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb3-9-6e597f6381"><a href="#cb3-9-6e597f6381"></a></span>
<span id="cb3-10-6e597f6381"><a href="#cb3-10-6e597f6381"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb3-11-6e597f6381"><a href="#cb3-11-6e597f6381"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> number</span>
<span id="cb3-12-6e597f6381"><a href="#cb3-12-6e597f6381"></a></span>
<span id="cb3-13-6e597f6381"><a href="#cb3-13-6e597f6381"></a> <span class="cf">return</span> sum_so_far</span>
<span id="cb3-14-6e597f6381"><a href="#cb3-14-6e597f6381"></a></span>
<span id="cb3-15-6e597f6381"><a href="#cb3-15-6e597f6381"></a></span>
<span id="cb3-16-6e597f6381"><a href="#cb3-16-6e597f6381"></a><span class="kw">def</span> my_sum_v2(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-17-6e597f6381"><a href="#cb3-17-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.</span></span>
<span id="cb3-18-6e597f6381"><a href="#cb3-18-6e597f6381"></a></span>
<span id="cb3-19-6e597f6381"><a href="#cb3-19-6e597f6381"></a><span class="co"> &gt;&gt;&gt; my_sum_v2([10, 20, 30])</span></span>
<span id="cb3-20-6e597f6381"><a href="#cb3-20-6e597f6381"></a><span class="co"> 60</span></span>
<span id="cb3-21-6e597f6381"><a href="#cb3-21-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-22-6e597f6381"><a href="#cb3-22-6e597f6381"></a> <span class="co"># ACCUMULATOR sum_so_far: keep track of the running sum of the elements in numbers.</span></span>
<span id="cb3-23-6e597f6381"><a href="#cb3-23-6e597f6381"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb3-24-6e597f6381"><a href="#cb3-24-6e597f6381"></a></span>
<span id="cb3-25-6e597f6381"><a href="#cb3-25-6e597f6381"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(numbers)):</span>
<span id="cb3-26-6e597f6381"><a href="#cb3-26-6e597f6381"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[i]</span>
<span id="cb3-27-6e597f6381"><a href="#cb3-27-6e597f6381"></a></span>
<span id="cb3-28-6e597f6381"><a href="#cb3-28-6e597f6381"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>Both <code>my_sum</code> and <code>my_sum_v2</code> use the accumulator pattern, and in fact initialize and update the accumulator in the exact same way. But there are some key differences in how their loops are structured:</p>
<ul>
<li>Loop variable <code>number</code> vs. <code>i</code>: <code>number</code> refers to an element of the list <code>numbers</code> (starting with the first element); <code>i</code> refers to an integer (starting at 0).</li>
<li>Looping over a <code>list</code> vs. a <code>range</code>: <code>for number in numbers</code> causes the loop body to execute once for each element in <code>numbers</code>. <code>for i in range(0, len(numbers))</code> causes the loop body to execute once for each integer in <code>range(0, len(numbers))</code>.<label for="sn-0-6e597f6381" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-6e597f6381" class="margin-toggle"/><span class="sidenote"> Because the range “stop” argument is exclusive, these two versions both cause the same number of iterations, equal to the number of elements in <code>numbers</code>.</span></li>
<li>Updating the accumulator: since <code>number</code> refers to a list element, we can add it directly to the accumulator. Since <code>i</code> refers to <em>where</em> we are in the list, we access the corresponding list element using list indexing to add it to the accumulator.</li>
</ul>
<p>In the case of <code>my_sum</code>, both our element-based and index-based implementations are correct. However, our next example illustrates a situation where the loop <em>must</em> know the index of the current element in order to solve the given problem.</p>
<h2 id="when-location-matters-6e597f6381">When location matters</h2>
<p>Consider the following problem: given a string, count the number of times in the string two adjacent characters are equal. For example, the string <code>'look'</code> has two adjacent <code>'o'</code>s, and the string <code>'David'</code> has no repeated adjacent characters. The location of the characters matters; even though the string <code>'canal'</code> has two <code>'a'</code> characters, they are not adjacent</p>
<p>Lets use these examples to design our function:</p>
<div class="sourceCode" id="cb4-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-6e597f6381"><a href="#cb4-1-6e597f6381"></a><span class="kw">def</span> count_adjacent_repeats(string: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb4-2-6e597f6381"><a href="#cb4-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the number of times in the given string that two adjacent characters are equal.</span></span>
<span id="cb4-3-6e597f6381"><a href="#cb4-3-6e597f6381"></a></span>
<span id="cb4-4-6e597f6381"><a href="#cb4-4-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;look&#39;)</span></span>
<span id="cb4-5-6e597f6381"><a href="#cb4-5-6e597f6381"></a><span class="co"> 1</span></span>
<span id="cb4-6-6e597f6381"><a href="#cb4-6-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;David&#39;)</span></span>
<span id="cb4-7-6e597f6381"><a href="#cb4-7-6e597f6381"></a><span class="co"> 0</span></span>
<span id="cb4-8-6e597f6381"><a href="#cb4-8-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;canal&#39;)</span></span>
<span id="cb4-9-6e597f6381"><a href="#cb4-9-6e597f6381"></a><span class="co"> 0</span></span>
<span id="cb4-10-6e597f6381"><a href="#cb4-10-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>Before we try to implement this function, lets reason about how we might approach the problem. First, as this is a “counting” problem, a natural fit would be to use an accumulator variable <code>repeats_so_far</code> that starts at 0 and increases by 1 every time two adjacent repeated characters are found. We dont know where the characters in the string may be repeated, so we must start at the beginning and continue to the end. In addition, we are comparing adjacent characters, so we need two indices every loop iteration:</p>
<table>
<thead>
<tr class="header">
<th>Comparison</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>string[0] == string[1]</code></td>
</tr>
<tr class="even">
<td><code>string[1] == string[2]</code></td>
</tr>
<tr class="odd">
<td><code>string[2] == string[3]</code></td>
</tr>
<tr class="even">
<td>…</td>
</tr>
</tbody>
</table>
<p>Notice that the indices to the left of the <code>==</code> operator start at 0 and increase by 1. Similarly, the indices to the right of the <code>==</code> operator start at 1 and increase by 1. Does this mean we need to use two for loops and two <code>range</code>s? No. We should also notice that the index to the right of <code>==</code> is always larger than the left by 1, so we have a way of calculating the right index from the left index. Here is out first attempt.</p>
<div class="sourceCode" id="cb5-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-6e597f6381"><a href="#cb5-1-6e597f6381"></a><span class="kw">def</span> count_adjacent_repeats(string: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb5-2-6e597f6381"><a href="#cb5-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the number of repeated adjacent characters in string.</span></span>
<span id="cb5-3-6e597f6381"><a href="#cb5-3-6e597f6381"></a></span>
<span id="cb5-4-6e597f6381"><a href="#cb5-4-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;look&#39;)</span></span>
<span id="cb5-5-6e597f6381"><a href="#cb5-5-6e597f6381"></a><span class="co"> 1</span></span>
<span id="cb5-6-6e597f6381"><a href="#cb5-6-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;David&#39;)</span></span>
<span id="cb5-7-6e597f6381"><a href="#cb5-7-6e597f6381"></a><span class="co"> 0</span></span>
<span id="cb5-8-6e597f6381"><a href="#cb5-8-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;canal&#39;)</span></span>
<span id="cb5-9-6e597f6381"><a href="#cb5-9-6e597f6381"></a><span class="co"> 0</span></span>
<span id="cb5-10-6e597f6381"><a href="#cb5-10-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-11-6e597f6381"><a href="#cb5-11-6e597f6381"></a> <span class="co"># ACCUMULATOR repeats_so_far: keep track of the number of adjacent</span></span>
<span id="cb5-12-6e597f6381"><a href="#cb5-12-6e597f6381"></a> <span class="co"># characters that are identical</span></span>
<span id="cb5-13-6e597f6381"><a href="#cb5-13-6e597f6381"></a> repeats_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb5-14-6e597f6381"><a href="#cb5-14-6e597f6381"></a></span>
<span id="cb5-15-6e597f6381"><a href="#cb5-15-6e597f6381"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(string)):</span>
<span id="cb5-16-6e597f6381"><a href="#cb5-16-6e597f6381"></a> <span class="cf">if</span> string[i] <span class="op">==</span> string[i <span class="op">+</span> <span class="dv">1</span>]:</span>
<span id="cb5-17-6e597f6381"><a href="#cb5-17-6e597f6381"></a> repeats_so_far <span class="op">=</span> repeats_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb5-18-6e597f6381"><a href="#cb5-18-6e597f6381"></a></span>
<span id="cb5-19-6e597f6381"><a href="#cb5-19-6e597f6381"></a> <span class="cf">return</span> repeats_so_far</span></code></pre></div>
<p>Unfortunately, if we attempt to run our doctest examples above, we dont get the expected values. Instead, we get 3 <code>IndexError</code>s, one for each example. Here is the error for the first failed example:</p>
<pre><code>Failed example:
count_adjacent_repeats(&#39;look&#39;)
Exception raised:
Traceback (most recent call last):
File &quot;path\to\Python\Python38\lib\doctest.py&quot;, line 1329, in __run
exec(compile(example.source, filename, &quot;single&quot;,
File &quot;&lt;doctest __main__.count_adjacent_repeats[0]&gt;&quot;, line 1, in &lt;module&gt;
count_adjacent_repeats(&#39;look&#39;)
File &quot;path/to/functions.py&quot;, line 74, in count_adjacent_repeats
if string[i] == string[i + 1]:
IndexError: string index out of range</code></pre>
<p>Conveniently, the error tells us what the problem is (<code>'string index out of range'</code>). It even tells us the line where the error occurs: <code>if string[i] == string[i + 1]:</code>. It is now our job to figure out why the line is causing an <code>IndexError</code>. The line indexes the parameter <code>string</code> using <code>i</code> and <code>i + 1</code>, so one of them must be causing the error.</p>
<p>Remember that given a string of length <code>n</code>, the valid indices are from <code>0</code> to <code>n - 1</code>. Now lets look at our use of <code>range</code>: <code>for i in range(0, len(string))</code>. This means that <code>i</code> can take on the values <code>0</code> to <code>n - 1</code>, which seems to be in the correct bounds. But dont forget, we also are indexing using <code>i + 1</code>! This is the problem: <code>i + 1</code> can take on the values <code>1</code> to <code>n</code>, and <code>n</code> is not a valid index.</p>
<p>We can solve this bug by remembering our goal: to compare adjacent pairs of characters. For a string of length <code>n</code>, the last pair of characters is <code>(string[n - 2], string[n - 1])</code>, so our loop variable <code>i</code> only needs to go up to <code>n - 2</code>, not <code>n - 1</code>. Lets look at the final solution:</p>
<div class="sourceCode" id="cb7-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-6e597f6381"><a href="#cb7-1-6e597f6381"></a><span class="kw">def</span> count_adjacent_repeats(string: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb7-2-6e597f6381"><a href="#cb7-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the number of repeated adjacent characters in string.</span></span>
<span id="cb7-3-6e597f6381"><a href="#cb7-3-6e597f6381"></a></span>
<span id="cb7-4-6e597f6381"><a href="#cb7-4-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;look&#39;)</span></span>
<span id="cb7-5-6e597f6381"><a href="#cb7-5-6e597f6381"></a><span class="co"> 1</span></span>
<span id="cb7-6-6e597f6381"><a href="#cb7-6-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;David&#39;)</span></span>
<span id="cb7-7-6e597f6381"><a href="#cb7-7-6e597f6381"></a><span class="co"> 0</span></span>
<span id="cb7-8-6e597f6381"><a href="#cb7-8-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_adjacent_repeats(&#39;canal&#39;)</span></span>
<span id="cb7-9-6e597f6381"><a href="#cb7-9-6e597f6381"></a><span class="co"> 0</span></span>
<span id="cb7-10-6e597f6381"><a href="#cb7-10-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-11-6e597f6381"><a href="#cb7-11-6e597f6381"></a> <span class="co"># ACCUMULATOR repeats_so_far: keep track of the number of adjacent</span></span>
<span id="cb7-12-6e597f6381"><a href="#cb7-12-6e597f6381"></a> <span class="co"># characters that are identical</span></span>
<span id="cb7-13-6e597f6381"><a href="#cb7-13-6e597f6381"></a> repeats_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb7-14-6e597f6381"><a href="#cb7-14-6e597f6381"></a></span>
<span id="cb7-15-6e597f6381"><a href="#cb7-15-6e597f6381"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(string) <span class="op">-</span> <span class="dv">1</span>):</span>
<span id="cb7-16-6e597f6381"><a href="#cb7-16-6e597f6381"></a> <span class="cf">if</span> string[i] <span class="op">==</span> string[i <span class="op">+</span> <span class="dv">1</span>]:</span>
<span id="cb7-17-6e597f6381"><a href="#cb7-17-6e597f6381"></a> repeats_so_far <span class="op">=</span> repeats_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb7-18-6e597f6381"><a href="#cb7-18-6e597f6381"></a></span>
<span id="cb7-19-6e597f6381"><a href="#cb7-19-6e597f6381"></a> <span class="cf">return</span> repeats_so_far</span></code></pre></div>
<p>Notice that we could not have implemented this function using an element-based for loop. Having <code>for char in string</code> would let us access the current character (<code>char</code>), but <em>not</em> the next character adjacent to <code>char</code>. To summarize, when we want to write a loop body that compares the current element with another based on their positions, we must use an index-based loop to keep track of the current index in the loop.</p>
<h2 id="two-lists-one-loop-6e597f6381">Two lists, one loop</h2>
<p>Index-based for loops can also be used to iterate over two collections in parallel using a single for loop. Consider the common mathematical problem: sum of products.<label for="sn-1-6e597f6381" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-6e597f6381" class="margin-toggle"/><span class="sidenote"> In your linear algebra course youll learn about the <em>inner product</em> operation, which formalizes this idea.</span></p>
<p>For example, suppose we have two nickels, four dimes, and three quarters in our pocket. How much money do we have in total? To solve this, we must know the value of nickels, dimes, and quarters. Then we can use sum of products:</p>
<div class="sourceCode" id="cb8-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-6e597f6381"><a href="#cb8-1-6e597f6381"></a><span class="op">&gt;&gt;&gt;</span> money_so_far <span class="op">=</span> <span class="fl">0.0</span></span>
<span id="cb8-2-6e597f6381"><a href="#cb8-2-6e597f6381"></a><span class="op">&gt;&gt;&gt;</span> money_so_far <span class="op">=</span> money_so_far <span class="op">+</span> <span class="dv">2</span> <span class="op">*</span> <span class="fl">0.05</span> <span class="co"># Two nickels</span></span>
<span id="cb8-3-6e597f6381"><a href="#cb8-3-6e597f6381"></a><span class="op">&gt;&gt;&gt;</span> money_so_far <span class="op">=</span> money_so_far <span class="op">+</span> <span class="dv">4</span> <span class="op">*</span> <span class="fl">0.10</span> <span class="co"># Four dimes</span></span>
<span id="cb8-4-6e597f6381"><a href="#cb8-4-6e597f6381"></a><span class="op">&gt;&gt;&gt;</span> money_so_far <span class="op">=</span> money_so_far <span class="op">+</span> <span class="dv">3</span> <span class="op">*</span> <span class="fl">0.25</span> <span class="co"># Three quarters</span></span>
<span id="cb8-5-6e597f6381"><a href="#cb8-5-6e597f6381"></a><span class="op">&gt;&gt;&gt;</span> money_so_far</span>
<span id="cb8-6-6e597f6381"><a href="#cb8-6-6e597f6381"></a><span class="fl">1.25</span></span></code></pre></div>
<p>This looks very similar to our <code>sum_so_far</code> exploration from earlier. The main difference is that this time we are accumulating products using the <code>*</code> operator. To the left of the <code>*</code> operator, we have a count (e.g., the number of nickels, an <code>int</code>). To the right of the <code>*</code> operator, we have a cent value (e.g., how much a nickel is worth in cents, a <code>float</code>). We can store this information in two same-sized lists. Lets design a function that uses these two lists to tell us how much money we have:</p>
<div class="sourceCode" id="cb9-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-6e597f6381"><a href="#cb9-1-6e597f6381"></a><span class="kw">def</span> count_money(counts: <span class="bu">list</span>[<span class="bu">int</span>], denoms: <span class="bu">list</span>[<span class="bu">float</span>]) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb9-2-6e597f6381"><a href="#cb9-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the total amount of money for the given coin counts and denominations.</span></span>
<span id="cb9-3-6e597f6381"><a href="#cb9-3-6e597f6381"></a></span>
<span id="cb9-4-6e597f6381"><a href="#cb9-4-6e597f6381"></a><span class="co"> counts stores the number of coins of each type, and denominations stores the</span></span>
<span id="cb9-5-6e597f6381"><a href="#cb9-5-6e597f6381"></a><span class="co"> value of each coin type. Each element in counts corresponds to the element at</span></span>
<span id="cb9-6-6e597f6381"><a href="#cb9-6-6e597f6381"></a><span class="co"> the same index in denoms.</span></span>
<span id="cb9-7-6e597f6381"><a href="#cb9-7-6e597f6381"></a></span>
<span id="cb9-8-6e597f6381"><a href="#cb9-8-6e597f6381"></a><span class="co"> Preconditions:</span></span>
<span id="cb9-9-6e597f6381"><a href="#cb9-9-6e597f6381"></a><span class="co"> - len(counts) == len(values)</span></span>
<span id="cb9-10-6e597f6381"><a href="#cb9-10-6e597f6381"></a></span>
<span id="cb9-11-6e597f6381"><a href="#cb9-11-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_money([2, 4, 3], [0.05, 0.10, 0.25])</span></span>
<span id="cb9-12-6e597f6381"><a href="#cb9-12-6e597f6381"></a><span class="co"> 1.25</span></span>
<span id="cb9-13-6e597f6381"><a href="#cb9-13-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>Before using a loop, lets investigate how we would implement this using a comprehension. We need to multiply each corresponding element of <code>counts</code> and <code>denoms</code>, and add the results:</p>
<div class="sourceCode" id="cb10-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-6e597f6381"><a href="#cb10-1-6e597f6381"></a>(counts[<span class="dv">0</span>] <span class="op">*</span> denoms[<span class="dv">0</span>]) <span class="op">+</span> (counts[<span class="dv">1</span>] <span class="op">*</span> denoms[<span class="dv">1</span>]) <span class="op">+</span> (counts[<span class="dv">2</span>] <span class="op">*</span> denoms[<span class="dv">2</span>]) <span class="op">+</span> ...</span></code></pre></div>
<p>We can generate each of these products by using <code>range</code>:<label for="sn-2-6e597f6381" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-6e597f6381" class="margin-toggle"/><span class="sidenote"> We used <code>len(counts)</code>, but could have used <code>len(denoms)</code> as well because of the functions precondition.</span></p>
<div class="sourceCode" id="cb11-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-6e597f6381"><a href="#cb11-1-6e597f6381"></a>[counts[i] <span class="op">*</span> denoms[i] <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(counts))]</span></code></pre></div>
<p>And we can then compute the sum of this expression by using the builtin Python function:</p>
<div class="sourceCode" id="cb12-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-6e597f6381"><a href="#cb12-1-6e597f6381"></a><span class="kw">def</span> count_money(counts: <span class="bu">list</span>[<span class="bu">int</span>], denoms: <span class="bu">list</span>[<span class="bu">float</span>]) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb12-2-6e597f6381"><a href="#cb12-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;Return the total amount of money for the given coin counts and denominations.</span></span>
<span id="cb12-3-6e597f6381"><a href="#cb12-3-6e597f6381"></a></span>
<span id="cb12-4-6e597f6381"><a href="#cb12-4-6e597f6381"></a><span class="co"> counts stores the number of coins of each type, and denominations stores the</span></span>
<span id="cb12-5-6e597f6381"><a href="#cb12-5-6e597f6381"></a><span class="co"> value of each coin type. Each element in counts corresponds to the element at</span></span>
<span id="cb12-6-6e597f6381"><a href="#cb12-6-6e597f6381"></a><span class="co"> the same index in denoms.</span></span>
<span id="cb12-7-6e597f6381"><a href="#cb12-7-6e597f6381"></a></span>
<span id="cb12-8-6e597f6381"><a href="#cb12-8-6e597f6381"></a><span class="co"> Preconditions:</span></span>
<span id="cb12-9-6e597f6381"><a href="#cb12-9-6e597f6381"></a><span class="co"> - len(counts) == len(values)</span></span>
<span id="cb12-10-6e597f6381"><a href="#cb12-10-6e597f6381"></a></span>
<span id="cb12-11-6e597f6381"><a href="#cb12-11-6e597f6381"></a><span class="co"> &gt;&gt;&gt; count_money([2, 4, 3], [0.05, 0.10, 0.25])</span></span>
<span id="cb12-12-6e597f6381"><a href="#cb12-12-6e597f6381"></a><span class="co"> 1.25</span></span>
<span id="cb12-13-6e597f6381"><a href="#cb12-13-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb12-14-6e597f6381"><a href="#cb12-14-6e597f6381"></a> <span class="cf">return</span> <span class="bu">sum</span>([counts[i] <span class="op">*</span> denoms[i] <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(counts))])</span></code></pre></div>
<p>This implementation of <code>count_money</code> has all the necessary ingredients that would appear in an equivalent for loop. Here is our alternate implementation of <code>count_money</code> using a for loop, but the same structure as <code>my_sum</code> from <a href="04-for-loops.html">4.4 Repeated Execution: For Loops</a>.</p>
<div class="sourceCode" id="cb13-6e597f6381"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-6e597f6381"><a href="#cb13-1-6e597f6381"></a><span class="kw">def</span> count_money(counts: <span class="bu">list</span>[<span class="bu">int</span>], values: <span class="bu">list</span>[<span class="bu">float</span>]) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb13-2-6e597f6381"><a href="#cb13-2-6e597f6381"></a> <span class="co">&quot;&quot;&quot;...</span></span>
<span id="cb13-3-6e597f6381"><a href="#cb13-3-6e597f6381"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-4-6e597f6381"><a href="#cb13-4-6e597f6381"></a> <span class="co"># ACCUMULATOR money_so_far: keep track of the total money so far.</span></span>
<span id="cb13-5-6e597f6381"><a href="#cb13-5-6e597f6381"></a> money_so_far <span class="op">=</span> <span class="fl">0.0</span></span>
<span id="cb13-6-6e597f6381"><a href="#cb13-6-6e597f6381"></a></span>
<span id="cb13-7-6e597f6381"><a href="#cb13-7-6e597f6381"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(counts)):</span>
<span id="cb13-8-6e597f6381"><a href="#cb13-8-6e597f6381"></a> money_so_far <span class="op">=</span> money_so_far <span class="op">+</span> counts[i] <span class="op">*</span> values[i]</span>
<span id="cb13-9-6e597f6381"><a href="#cb13-9-6e597f6381"></a></span>
<span id="cb13-10-6e597f6381"><a href="#cb13-10-6e597f6381"></a> <span class="cf">return</span> money_so_far</span></code></pre></div>
<h2 id="choosing-the-right-for-loop-6e597f6381">Choosing the right for loop</h2>
<p>We have seen two forms of for loops. The first version, the element-based for loop, takes the form <code>for &lt;loop_variable&gt; in &lt;collection&gt;</code>. This is useful when we want to process each element in the collection without knowing about its position in the collection. The second version, the index-based for loops, takes the form <code>for &lt;loop_variable&gt; in &lt;range&gt;</code>. In index-based for loops, the <code>range</code> must belong to the set of valid indices for the collection we wish to loop over. We have seen two situations where this is useful:<label for="sn-3-6e597f6381" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-6e597f6381" class="margin-toggle"/><span class="sidenote"> Well see one more example use of index-based loops later this chapter.</span></p>
<ol type="1">
<li>When the location of elements in the collection matters (as in <code>count_adjacent_repeats</code>).</li>
<li>When we want to loop through more than one list at a time (as in <code>count_money</code>), using the same index for both lists.</li>
</ol>
<p>You might have noticed from our <code>my_sum</code> example that index-based for loops are <em>more powerful</em> than element-based for loops: given the current index, we can always access the current collection element, but not vice versa. So why dont we just always use index-based for loops? Two reasons: first, not all collections can be indexed (think <code>set</code> and <code>dict</code>); and second, index-based for loops introduce a level of <em>indirection</em> to our code. In our <code>my_sum_v2</code> example, we had to access the current element using list indexing (<code>numbers[i]</code>), while in <code>my_sum</code>, we could directly access the element by using the loop variable (<code>number</code>)`. So its important to understand when we can use element-based for loops vs. index-based for loops, as the former makes our code easier to write and understand.</p>
<h1 id="references-6e597f6381">References</h1>
<ul>
<li>CSC108 videos: For loops over indices (<a href="https://youtu.be/tLnWFnnZ6sA">Part 1</a> only)</li>
<li>CSC108 videos: Parallel Lists and Strings (<a href="https://youtu.be/RpWIaXNiob0">Part 1</a>, <a href="https://youtu.be/t7RWk6VygwE">Part 2</a>)</li>
</ul>
</section>
<br/> <a id="anchor-04-07"></a>
<header id="title-block-header-f02d52a916">
<h1 class="title">4.7 Nested For Loops</h1>
</header>
<section>
<p>When we introduced for loops, we said that the loop body consists of one of more statements. We saw in <a href="05-more-for-loops.html">4.5 For Loop Variations</a> that we could put if statements inside loop bodies. In this section, well see that a for loop body can itself contain another for loop, since for loops are themselves statements. Well study uses of these <em>nested for loops</em>, and also draw comparisons between them and comprehensions from the previous chapter.</p>
<h2 id="nested-loops-and-nested-data-f02d52a916">Nested loops and nested data</h2>
<p>Nested loops are particularly useful when dealing with nested data. As a first example, suppose we have a list of lists of integers:</p>
<div class="sourceCode" id="cb1-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-f02d52a916"><a href="#cb1-1-f02d52a916"></a><span class="op">&gt;&gt;&gt;</span> lists_of_numbers <span class="op">=</span> [[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>], [<span class="dv">10</span>, <span class="op">-</span><span class="dv">5</span>], [<span class="dv">100</span>]]</span></code></pre></div>
<p>Our goal is to compute the sum of all of the elements of this list:</p>
<div class="sourceCode" id="cb2-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-f02d52a916"><a href="#cb2-1-f02d52a916"></a><span class="kw">def</span> sum_all(lists_of_numbers: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-2-f02d52a916"><a href="#cb2-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;Return the sum of all the numbers in the given lists_of_numbers.</span></span>
<span id="cb2-3-f02d52a916"><a href="#cb2-3-f02d52a916"></a></span>
<span id="cb2-4-f02d52a916"><a href="#cb2-4-f02d52a916"></a><span class="co"> &gt;&gt;&gt; sum_all([[1, 2, 3], [10, -5], [100]])</span></span>
<span id="cb2-5-f02d52a916"><a href="#cb2-5-f02d52a916"></a><span class="co"> 111</span></span>
<span id="cb2-6-f02d52a916"><a href="#cb2-6-f02d52a916"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>We can start with our basic loop accumulator pattern:</p>
<div class="sourceCode" id="cb3-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-f02d52a916"><a href="#cb3-1-f02d52a916"></a><span class="kw">def</span> sum_all(lists_of_numbers: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-f02d52a916"><a href="#cb3-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-3-f02d52a916"><a href="#cb3-3-f02d52a916"></a> <span class="co"># ACCUMULATOR sum_so_far: keep track of the running sum of the numbers.</span></span>
<span id="cb3-4-f02d52a916"><a href="#cb3-4-f02d52a916"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb3-5-f02d52a916"><a href="#cb3-5-f02d52a916"></a></span>
<span id="cb3-6-f02d52a916"><a href="#cb3-6-f02d52a916"></a> <span class="cf">for</span> ... <span class="kw">in</span> lists_of_numbers:</span>
<span id="cb3-7-f02d52a916"><a href="#cb3-7-f02d52a916"></a> sum_so_far <span class="op">=</span> ...</span>
<span id="cb3-8-f02d52a916"><a href="#cb3-8-f02d52a916"></a></span>
<span id="cb3-9-f02d52a916"><a href="#cb3-9-f02d52a916"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>The difference between this function and in <a href="04-for-loops.html"><code>my_sum</code> from 4.4</a> is that here our loop variable in <code>for ... in lists_of_numbers</code> does not refer to a single number, but rather a list of numbers:</p>
<div class="sourceCode" id="cb4-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-f02d52a916"><a href="#cb4-1-f02d52a916"></a><span class="kw">def</span> sum_all(lists_of_numbers: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb4-2-f02d52a916"><a href="#cb4-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb4-3-f02d52a916"><a href="#cb4-3-f02d52a916"></a> <span class="co"># ACCUMULATOR sum_so_far: keep track of the running sum of the numbers.</span></span>
<span id="cb4-4-f02d52a916"><a href="#cb4-4-f02d52a916"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb4-5-f02d52a916"><a href="#cb4-5-f02d52a916"></a></span>
<span id="cb4-6-f02d52a916"><a href="#cb4-6-f02d52a916"></a> <span class="cf">for</span> numbers <span class="kw">in</span> lists_of_numbers: <span class="co"># numbers is a list of numbers, not a single number!</span></span>
<span id="cb4-7-f02d52a916"><a href="#cb4-7-f02d52a916"></a> sum_so_far <span class="op">=</span> ...</span>
<span id="cb4-8-f02d52a916"><a href="#cb4-8-f02d52a916"></a></span>
<span id="cb4-9-f02d52a916"><a href="#cb4-9-f02d52a916"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>So here is one way of completing this function, by using the builtin <code>sum</code> function:</p>
<div class="sourceCode" id="cb5-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-f02d52a916"><a href="#cb5-1-f02d52a916"></a><span class="kw">def</span> sum_all(lists_of_numbers: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb5-2-f02d52a916"><a href="#cb5-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb5-3-f02d52a916"><a href="#cb5-3-f02d52a916"></a> <span class="co"># ACCUMULATOR sum_so_far: keep track of the running sum of the numbers.</span></span>
<span id="cb5-4-f02d52a916"><a href="#cb5-4-f02d52a916"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb5-5-f02d52a916"><a href="#cb5-5-f02d52a916"></a></span>
<span id="cb5-6-f02d52a916"><a href="#cb5-6-f02d52a916"></a> <span class="cf">for</span> numbers <span class="kw">in</span> lists_of_numbers: <span class="co"># numbers is a list of numbers, not a single number!</span></span>
<span id="cb5-7-f02d52a916"><a href="#cb5-7-f02d52a916"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> <span class="bu">sum</span>(numbers)</span>
<span id="cb5-8-f02d52a916"><a href="#cb5-8-f02d52a916"></a></span>
<span id="cb5-9-f02d52a916"><a href="#cb5-9-f02d52a916"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>This implementation is structurally similar to the <code>my_sum</code> implementation we had in Section 4.4. But how would we implement this function <em>without</em> using <code>sum</code>? For this we need another for loop:</p>
<div class="sourceCode" id="cb6-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-f02d52a916"><a href="#cb6-1-f02d52a916"></a><span class="kw">def</span> sum_all(lists_of_numbers: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb6-2-f02d52a916"><a href="#cb6-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb6-3-f02d52a916"><a href="#cb6-3-f02d52a916"></a> <span class="co"># ACCUMULATOR sum_so_far: keep track of the running sum of the numbers.</span></span>
<span id="cb6-4-f02d52a916"><a href="#cb6-4-f02d52a916"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb6-5-f02d52a916"><a href="#cb6-5-f02d52a916"></a></span>
<span id="cb6-6-f02d52a916"><a href="#cb6-6-f02d52a916"></a> <span class="cf">for</span> numbers <span class="kw">in</span> lists_of_numbers: <span class="co"># numbers is a list of numbers, not a single number!</span></span>
<span id="cb6-7-f02d52a916"><a href="#cb6-7-f02d52a916"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers: <span class="co"># number is a single number</span></span>
<span id="cb6-8-f02d52a916"><a href="#cb6-8-f02d52a916"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> number</span>
<span id="cb6-9-f02d52a916"><a href="#cb6-9-f02d52a916"></a></span>
<span id="cb6-10-f02d52a916"><a href="#cb6-10-f02d52a916"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>We say that the <code>for number in numbers</code> loops is <em>nested</em> within the <code>for numbers in lists_of_numbers</code>. What happens when we call our doctest example, <code>sum_all([[1, 2, 3], [10, -5], [100]])</code>? Lets break this down step by step.</p>
<ol type="1">
<li><p>First, the assignment statement <code>sum_so_far = 0</code> executes, creating our accumulator variable.</p></li>
<li><p>The outer loop is reached.</p>
<ul>
<li><p>The loop variable <code>list_of_numbers</code> is assigned the first element in <code>lists_of_numbers</code>, which is <code>[1, 2, 3]</code>.</p></li>
<li><p>Then, the body of the outer loop is executed. Its body is just one statement: the inner for loop, <code>for number in numbers</code>.</p>
<ul>
<li><p>The inner loop variable <code>number</code> is assigned the first value in <code>numbers</code>, which is <code>1</code>.</p></li>
<li><p>The inner loop body gets executed, updating the accumulator. <code>sum_so_far</code> is reassigned to <code>1</code> (since <code>0 + 1 == 1</code>).</p></li>
<li><p>The inner loop iterates twice more, for <code>number = 2</code> and <code>number = 3</code>.<label for="sn-0-f02d52a916" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-f02d52a916" class="margin-toggle"/><span class="sidenote"> Notice that <code>numbers</code> is the *same value (<code>[1, 2, 3]</code>) for this entire part. </span> At each iteration, the accumulator is updated, first by adding <code>2</code> and then <code>3</code>. At this point, <code>sum_so_far = 6</code> (<code>0 + 1 + 2 + 3</code>).</p></li>
<li><p>After all three iterations of the inner loop occur, the inner loop stops. The Python interpreter is done executing this statement.</p></li>
</ul></li>
<li><p>The next iteration of the <em>outer loop</em> occurs; <code>numbers</code> is assigned to the list <code>[10, -5]</code>.</p></li>
<li><p>Again, the body of the outer loop occurs.</p>
<ul>
<li>The inner loop now iterates twice: for <code>number = 10</code> and <code>number = -5</code>. <code>sum_so_far</code> is reassigned twice more, with a final value of <code>11</code> (<code>6 + 10 + -5</code>).</li>
</ul></li>
<li><p>The outer loop iterates one more time, for <code>numbers = [100]</code>.</p></li>
<li><p>Again, the body of the outer loop occurs.</p>
<ul>
<li>The inner loop iterates once, for <code>number = 100</code>. <code>sum_so_far</code> is reassigned to <code>111</code> (<code>11 + 100</code>).</li>
</ul></li>
<li><p>At last, there are no more iterations of the outer loop, and so it stops.</p></li>
</ul></li>
<li><p>After the outer loop is done, the <code>return</code> statement executes, returning the value of <code>sum_so_far</code>, which is <code>111</code>.</p></li>
</ol>
<p>Whew, thats a lot of writing! We can summarize the above behaviour by creating a <em>loop accumulation table</em>. Note that the table below has the same structure as the ones weve seen before, but is more complex because its columns include both the outer and inner loop variables and iterations. The <code>accumulator</code> column shows the value of <code>sum_so_far</code> at the <em>end</em> of the iteration of the inner loop. Pay close attention to the <em>order</em> of the rows, as this matches the order of execution we described above.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 21%" />
<col style="width: 20%" />
<col style="width: 21%" />
<col style="width: 20%" />
<col style="width: 15%" />
</colgroup>
<thead>
<tr class="header">
<th>Outer loop iteration</th>
<th>Outer loop variable (<code>list_of_numbers</code>)</th>
<th>Inner loop iteration</th>
<th>Inner loop variable (<code>number</code>)</th>
<th>Accumulator (<code>sum_so_far</code>)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td></td>
<td></td>
<td></td>
<td><code>0</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>[1, 2, 3]</code></td>
<td>0</td>
<td></td>
<td><code>0</code></td>
</tr>
<tr class="odd">
<td>1</td>
<td><code>[1, 2, 3]</code></td>
<td>1</td>
<td><code>1</code></td>
<td><code>1</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>[1, 2, 3]</code></td>
<td>2</td>
<td><code>2</code></td>
<td><code>3</code></td>
</tr>
<tr class="odd">
<td>1</td>
<td><code>[1, 2, 3]</code></td>
<td>3</td>
<td><code>3</code></td>
<td><code>6</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>[10, -5]</code></td>
<td>0</td>
<td></td>
<td><code>6</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>[10, -5]</code></td>
<td>1</td>
<td><code>10</code></td>
<td><code>16</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>[10, -5]</code></td>
<td>2</td>
<td><code>-5</code></td>
<td><code>11</code></td>
</tr>
<tr class="odd">
<td>3</td>
<td><code>[100]</code></td>
<td>0</td>
<td></td>
<td><code>11</code></td>
</tr>
<tr class="even">
<td>3</td>
<td><code>[100]</code></td>
<td>1</td>
<td><code>100</code></td>
<td><code>111</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="the-cartesian-product-f02d52a916">The Cartesian product</h2>
<p>Our next example illustrates how to use nested loops on two different collections, obtaining all pairs of possible values from each collection. If that sounds familiar, well, it should be!</p>
<div class="sourceCode" id="cb7-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-f02d52a916"><a href="#cb7-1-f02d52a916"></a><span class="kw">def</span> product(set1: <span class="bu">set</span>, set2: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">set</span>[<span class="bu">tuple</span>]:</span>
<span id="cb7-2-f02d52a916"><a href="#cb7-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;Return the Cartesian product of set1 and set2.</span></span>
<span id="cb7-3-f02d52a916"><a href="#cb7-3-f02d52a916"></a></span>
<span id="cb7-4-f02d52a916"><a href="#cb7-4-f02d52a916"></a><span class="co"> &gt;&gt;&gt; result = product({10, 11}, {5, 6, 7})</span></span>
<span id="cb7-5-f02d52a916"><a href="#cb7-5-f02d52a916"></a><span class="co"> &gt;&gt;&gt; result == {(10, 5), (10, 6), (10, 7), (11, 5), (11, 6), (11, 7)}</span></span>
<span id="cb7-6-f02d52a916"><a href="#cb7-6-f02d52a916"></a><span class="co"> True</span></span>
<span id="cb7-7-f02d52a916"><a href="#cb7-7-f02d52a916"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>Before we get to writing any loops at all, lets remind ourselves how we would write a comprehension to compute the Cartesian product:</p>
<div class="sourceCode" id="cb8-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-f02d52a916"><a href="#cb8-1-f02d52a916"></a><span class="op">&gt;&gt;&gt;</span> set1 <span class="op">=</span> {<span class="dv">10</span>, <span class="dv">11</span>}</span>
<span id="cb8-2-f02d52a916"><a href="#cb8-2-f02d52a916"></a><span class="op">&gt;&gt;&gt;</span> set2 <span class="op">=</span> {<span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>}</span>
<span id="cb8-3-f02d52a916"><a href="#cb8-3-f02d52a916"></a><span class="op">&gt;&gt;&gt;</span> result <span class="op">=</span> {(x, y) <span class="cf">for</span> x <span class="kw">in</span> set1 <span class="cf">for</span> y <span class="kw">in</span> set2}</span>
<span id="cb8-4-f02d52a916"><a href="#cb8-4-f02d52a916"></a><span class="op">&gt;&gt;&gt;</span> result <span class="op">==</span> {(<span class="dv">10</span>, <span class="dv">5</span>), (<span class="dv">10</span>, <span class="dv">6</span>), (<span class="dv">10</span>, <span class="dv">7</span>), (<span class="dv">11</span>, <span class="dv">5</span>), (<span class="dv">11</span>, <span class="dv">6</span>), (<span class="dv">11</span>, <span class="dv">7</span>)}</span>
<span id="cb8-5-f02d52a916"><a href="#cb8-5-f02d52a916"></a><span class="va">True</span></span></code></pre></div>
<p>Now well see how to write this using nested for loop:</p>
<div class="sourceCode" id="cb9-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-f02d52a916"><a href="#cb9-1-f02d52a916"></a><span class="kw">def</span> cartesian_product(set1: <span class="bu">set</span>, set2: <span class="bu">set</span>) <span class="op">-&gt;</span> <span class="bu">set</span>[<span class="bu">tuple</span>]:</span>
<span id="cb9-2-f02d52a916"><a href="#cb9-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;Return the Cartesian product of set1 and set2.</span></span>
<span id="cb9-3-f02d52a916"><a href="#cb9-3-f02d52a916"></a></span>
<span id="cb9-4-f02d52a916"><a href="#cb9-4-f02d52a916"></a><span class="co"> &gt;&gt;&gt; result = cartesian_product({10, 11}, {5, 6, 7})</span></span>
<span id="cb9-5-f02d52a916"><a href="#cb9-5-f02d52a916"></a><span class="co"> &gt;&gt;&gt; result == {(10, 5), (10, 6), (10, 7), (11, 5), (11, 6), (11, 7)}</span></span>
<span id="cb9-6-f02d52a916"><a href="#cb9-6-f02d52a916"></a><span class="co"> True</span></span>
<span id="cb9-7-f02d52a916"><a href="#cb9-7-f02d52a916"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb9-8-f02d52a916"><a href="#cb9-8-f02d52a916"></a> <span class="co"># ACCUMULATOR product_so_far: keep track of the tuples from the pairs</span></span>
<span id="cb9-9-f02d52a916"><a href="#cb9-9-f02d52a916"></a> <span class="co"># of elements visited so far.</span></span>
<span id="cb9-10-f02d52a916"><a href="#cb9-10-f02d52a916"></a> product_so_far <span class="op">=</span> <span class="bu">set</span>()</span>
<span id="cb9-11-f02d52a916"><a href="#cb9-11-f02d52a916"></a></span>
<span id="cb9-12-f02d52a916"><a href="#cb9-12-f02d52a916"></a> <span class="cf">for</span> x <span class="kw">in</span> set1:</span>
<span id="cb9-13-f02d52a916"><a href="#cb9-13-f02d52a916"></a> <span class="cf">for</span> y <span class="kw">in</span> set2:</span>
<span id="cb9-14-f02d52a916"><a href="#cb9-14-f02d52a916"></a> product_so_far <span class="op">=</span> <span class="bu">set</span>.union(product_so_far, {(x, y)})</span>
<span id="cb9-15-f02d52a916"><a href="#cb9-15-f02d52a916"></a></span>
<span id="cb9-16-f02d52a916"><a href="#cb9-16-f02d52a916"></a> <span class="cf">return</span> product_so_far</span></code></pre></div>
<p>As we saw in our first example, here the inner loop <code>for y in set2</code> iterates through every element of <code>set2</code> for every element of <code>x</code> in <code>set1</code>. You can visualize this in the following loop accumulation table:</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 16%" />
<col style="width: 12%" />
<col style="width: 16%" />
<col style="width: 12%" />
<col style="width: 42%" />
</colgroup>
<thead>
<tr class="header">
<th>Outer loop iteration</th>
<th>Outer loop var (<code>x</code>)</th>
<th>Inner loop iteration</th>
<th>Inner loop var (<code>y</code>)</th>
<th>Accumulator (<code>product_so_far</code>)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td></td>
<td></td>
<td></td>
<td><code>set()</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>10</code></td>
<td>0</td>
<td></td>
<td><code>set()</code></td>
</tr>
<tr class="odd">
<td>1</td>
<td><code>10</code></td>
<td>1</td>
<td><code>5</code></td>
<td><code>{(10, 5)}</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>10</code></td>
<td>2</td>
<td><code>6</code></td>
<td><code>{(10, 5), (10, 6)}</code></td>
</tr>
<tr class="odd">
<td>1</td>
<td><code>10</code></td>
<td>3</td>
<td><code>7</code></td>
<td><code>{(10, 5), (10, 6), (10, 7)}</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>11</code></td>
<td>0</td>
<td></td>
<td><code>{(10, 5), (10, 6), (10, 7)}</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>11</code></td>
<td>1</td>
<td><code>5</code></td>
<td><code>{(10, 5), (10, 6), (10, 7), (11, 5)}</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>11</code></td>
<td>2</td>
<td><code>6</code></td>
<td><code>{(10, 5), (10, 6), (10, 7), (11, 5), (11, 6)}</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>11</code></td>
<td>3</td>
<td><code>7</code></td>
<td><code>{(10, 5), (10, 6), (10, 7), (11, 5), (11, 6), (11, 7)}</code></td>
</tr>
</tbody>
</table>
</div>
<p>Another way of visualizing the return value is:</p>
<div class="sourceCode" id="cb10-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-f02d52a916"><a href="#cb10-1-f02d52a916"></a>{</span>
<span id="cb10-2-f02d52a916"><a href="#cb10-2-f02d52a916"></a> (<span class="dv">10</span>, <span class="dv">5</span>), (<span class="dv">10</span>, <span class="dv">6</span>), (<span class="dv">10</span>, <span class="dv">7</span>), <span class="co"># First three tuples are from the first iteration of the outer loop</span></span>
<span id="cb10-3-f02d52a916"><a href="#cb10-3-f02d52a916"></a> (<span class="dv">11</span>, <span class="dv">5</span>), (<span class="dv">11</span>, <span class="dv">6</span>), (<span class="dv">11</span>, <span class="dv">7</span>) <span class="co"># Next three tuples are from the second iteration of the outer loop</span></span>
<span id="cb10-4-f02d52a916"><a href="#cb10-4-f02d52a916"></a>}</span></code></pre></div>
<h2 id="outer-and-inner-accumulators-f02d52a916">Outer and inner accumulators</h2>
<p>Both the <code>sum_all</code> and <code>cartesian_product</code> examples weve seen so far have used a single accumulator that is updated inside the inner loop body. However, <em>each loop</em> can have its own accumulator (and in fact, more than one accumulator). This is more complex, but offers more flexibilty than a single accumulator does alone.</p>
<p>As an example, suppose we have a list of lists of integers called <code>grades</code>. Each element of <code>grades</code> corresponds to a course and contains a list of grades obtained in that course. Lets see an example of the data:</p>
<div class="sourceCode" id="cb11-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-f02d52a916"><a href="#cb11-1-f02d52a916"></a><span class="op">&gt;&gt;&gt;</span> grades <span class="op">=</span> [</span>
<span id="cb11-2-f02d52a916"><a href="#cb11-2-f02d52a916"></a>... [<span class="dv">70</span>, <span class="dv">75</span>, <span class="dv">80</span>], <span class="co"># ENG196</span></span>
<span id="cb11-3-f02d52a916"><a href="#cb11-3-f02d52a916"></a>... [<span class="dv">70</span>, <span class="dv">80</span>, <span class="dv">90</span>, <span class="dv">100</span>], <span class="co"># CSC110</span></span>
<span id="cb11-4-f02d52a916"><a href="#cb11-4-f02d52a916"></a>... [<span class="dv">80</span>, <span class="dv">100</span>] <span class="co"># MAT137</span></span>
<span id="cb11-5-f02d52a916"><a href="#cb11-5-f02d52a916"></a>... ]</span></code></pre></div>
<p>Notice how the list of grades for course ENG196 does not have the same length as CSC110 or MAT137. Our goal is to return a new list containing the <em>average grade</em> of each course. We saw in Section 4.5 how to use loops to calculate the average of a collection of numbers:</p>
<div class="sourceCode" id="cb12-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-f02d52a916"><a href="#cb12-1-f02d52a916"></a><span class="kw">def</span> average(numbers: Iterable[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">float</span>:</span>
<span id="cb12-2-f02d52a916"><a href="#cb12-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;Return the average of a collection of integers.</span></span>
<span id="cb12-3-f02d52a916"><a href="#cb12-3-f02d52a916"></a></span>
<span id="cb12-4-f02d52a916"><a href="#cb12-4-f02d52a916"></a><span class="co"> Preconditions:</span></span>
<span id="cb12-5-f02d52a916"><a href="#cb12-5-f02d52a916"></a><span class="co"> - len(numbers) &gt; 0</span></span>
<span id="cb12-6-f02d52a916"><a href="#cb12-6-f02d52a916"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb12-7-f02d52a916"><a href="#cb12-7-f02d52a916"></a> <span class="co"># ACCUMULATOR len_so_far: keep track of the number of elements seen so far in the loop.</span></span>
<span id="cb12-8-f02d52a916"><a href="#cb12-8-f02d52a916"></a> len_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb12-9-f02d52a916"><a href="#cb12-9-f02d52a916"></a> <span class="co"># ACCUMULATOR total_so_far: keep track of the total of the elements seen so far in the loop.</span></span>
<span id="cb12-10-f02d52a916"><a href="#cb12-10-f02d52a916"></a> total_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb12-11-f02d52a916"><a href="#cb12-11-f02d52a916"></a></span>
<span id="cb12-12-f02d52a916"><a href="#cb12-12-f02d52a916"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb12-13-f02d52a916"><a href="#cb12-13-f02d52a916"></a> len_so_far <span class="op">=</span> len_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb12-14-f02d52a916"><a href="#cb12-14-f02d52a916"></a> total_so_far <span class="op">=</span> total_so_far <span class="op">+</span> number</span>
<span id="cb12-15-f02d52a916"><a href="#cb12-15-f02d52a916"></a></span>
<span id="cb12-16-f02d52a916"><a href="#cb12-16-f02d52a916"></a> <span class="cf">return</span> total_so_far <span class="op">/</span> len_so_far</span></code></pre></div>
<p>We can calculate a list of averages for each course using a comprehension:<label for="sn-1-f02d52a916" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-f02d52a916" class="margin-toggle"/><span class="sidenote"> Exercise: write a precondition expression to guarantee there are no empty lists in <code>grades</code>.</span></p>
<div class="sourceCode" id="cb13-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-f02d52a916"><a href="#cb13-1-f02d52a916"></a><span class="kw">def</span> course_averages_v1(grades: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">float</span>]:</span>
<span id="cb13-2-f02d52a916"><a href="#cb13-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;Return a new list for which each element is the average of the grades</span></span>
<span id="cb13-3-f02d52a916"><a href="#cb13-3-f02d52a916"></a><span class="co"> in the inner list at the corresponding position of grades.</span></span>
<span id="cb13-4-f02d52a916"><a href="#cb13-4-f02d52a916"></a></span>
<span id="cb13-5-f02d52a916"><a href="#cb13-5-f02d52a916"></a><span class="co"> &gt;&gt;&gt; course_averages_v1([[70, 75, 80], [70, 80, 90, 100], [80, 100]])</span></span>
<span id="cb13-6-f02d52a916"><a href="#cb13-6-f02d52a916"></a><span class="co"> [75.0, 85.0, 90.0]</span></span>
<span id="cb13-7-f02d52a916"><a href="#cb13-7-f02d52a916"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-8-f02d52a916"><a href="#cb13-8-f02d52a916"></a> <span class="cf">return</span> [average(course_grades) <span class="cf">for</span> course_grades <span class="kw">in</span> grades]</span></code></pre></div>
<p>We can translate this into a for loop using a list accumulator variable and list concatenation for the update:</p>
<div class="sourceCode" id="cb14-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-f02d52a916"><a href="#cb14-1-f02d52a916"></a><span class="kw">def</span> course_averages_v2(grades: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">float</span>]:</span>
<span id="cb14-2-f02d52a916"><a href="#cb14-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;Return a new list for which each element is the average of the grades</span></span>
<span id="cb14-3-f02d52a916"><a href="#cb14-3-f02d52a916"></a><span class="co"> in the inner list at the corresponding position of grades.</span></span>
<span id="cb14-4-f02d52a916"><a href="#cb14-4-f02d52a916"></a></span>
<span id="cb14-5-f02d52a916"><a href="#cb14-5-f02d52a916"></a><span class="co"> &gt;&gt;&gt; course_averages_v2([[70, 75, 80], [70, 80, 90, 100], [80, 100]])</span></span>
<span id="cb14-6-f02d52a916"><a href="#cb14-6-f02d52a916"></a><span class="co"> [75.0, 85.0, 90.0]</span></span>
<span id="cb14-7-f02d52a916"><a href="#cb14-7-f02d52a916"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb14-8-f02d52a916"><a href="#cb14-8-f02d52a916"></a> <span class="co"># ACCUMULATOR averages_so_far: keep track of the averages of the lists</span></span>
<span id="cb14-9-f02d52a916"><a href="#cb14-9-f02d52a916"></a> <span class="co"># visited so far in grades.</span></span>
<span id="cb14-10-f02d52a916"><a href="#cb14-10-f02d52a916"></a> averages_so_far <span class="op">=</span> []</span>
<span id="cb14-11-f02d52a916"><a href="#cb14-11-f02d52a916"></a></span>
<span id="cb14-12-f02d52a916"><a href="#cb14-12-f02d52a916"></a> <span class="cf">for</span> course_grades <span class="kw">in</span> grades:</span>
<span id="cb14-13-f02d52a916"><a href="#cb14-13-f02d52a916"></a> course_average <span class="op">=</span> average(course_grades)</span>
<span id="cb14-14-f02d52a916"><a href="#cb14-14-f02d52a916"></a> averages_so_far <span class="op">=</span> averages_so_far <span class="op">+</span> [course_average]</span>
<span id="cb14-15-f02d52a916"><a href="#cb14-15-f02d52a916"></a></span>
<span id="cb14-16-f02d52a916"><a href="#cb14-16-f02d52a916"></a> <span class="cf">return</span> averages_so_far</span></code></pre></div>
<p>Now lets see how to calculate the <code>course_average</code> variable for each course by using an inner loop instead of the <code>average</code> function. We can do this by <em>expanding the definition of <code>average</code></em> directly in the loop body, with just a few minor tweaks:</p>
<div class="sourceCode" id="cb15-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-f02d52a916"><a href="#cb15-1-f02d52a916"></a><span class="kw">def</span> course_averages_v3(grades: <span class="bu">list</span>[<span class="bu">list</span>[<span class="bu">int</span>]]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">float</span>]:</span>
<span id="cb15-2-f02d52a916"><a href="#cb15-2-f02d52a916"></a> <span class="co">&quot;&quot;&quot;Return a new list for which each element is the average of the grades</span></span>
<span id="cb15-3-f02d52a916"><a href="#cb15-3-f02d52a916"></a><span class="co"> in the inner list at the corresponding position of grades.</span></span>
<span id="cb15-4-f02d52a916"><a href="#cb15-4-f02d52a916"></a></span>
<span id="cb15-5-f02d52a916"><a href="#cb15-5-f02d52a916"></a><span class="co"> &gt;&gt;&gt; course_averages_v3([[70, 75, 80], [70, 80, 90, 100], [80, 100]])</span></span>
<span id="cb15-6-f02d52a916"><a href="#cb15-6-f02d52a916"></a><span class="co"> [75.0, 85.0, 90.0]</span></span>
<span id="cb15-7-f02d52a916"><a href="#cb15-7-f02d52a916"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb15-8-f02d52a916"><a href="#cb15-8-f02d52a916"></a> <span class="co"># ACCUMULATOR averages_so_far: keep track of the averages of the lists</span></span>
<span id="cb15-9-f02d52a916"><a href="#cb15-9-f02d52a916"></a> <span class="co"># visited so far in grades.</span></span>
<span id="cb15-10-f02d52a916"><a href="#cb15-10-f02d52a916"></a> averages_so_far <span class="op">=</span> []</span>
<span id="cb15-11-f02d52a916"><a href="#cb15-11-f02d52a916"></a></span>
<span id="cb15-12-f02d52a916"><a href="#cb15-12-f02d52a916"></a> <span class="cf">for</span> course_grades <span class="kw">in</span> grades:</span>
<span id="cb15-13-f02d52a916"><a href="#cb15-13-f02d52a916"></a> <span class="co"># ACCUMULATOR len_so_far: keep track of the number of elements seen so far in course_grades.</span></span>
<span id="cb15-14-f02d52a916"><a href="#cb15-14-f02d52a916"></a> len_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb15-15-f02d52a916"><a href="#cb15-15-f02d52a916"></a> <span class="co"># ACCUMULATOR total_so_far: keep track of the total of the elements seen so far in course_grades.</span></span>
<span id="cb15-16-f02d52a916"><a href="#cb15-16-f02d52a916"></a> total_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb15-17-f02d52a916"><a href="#cb15-17-f02d52a916"></a></span>
<span id="cb15-18-f02d52a916"><a href="#cb15-18-f02d52a916"></a> <span class="cf">for</span> grade <span class="kw">in</span> course_grades:</span>
<span id="cb15-19-f02d52a916"><a href="#cb15-19-f02d52a916"></a> len_so_far <span class="op">=</span> len_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb15-20-f02d52a916"><a href="#cb15-20-f02d52a916"></a> total_so_far <span class="op">=</span> total_so_far <span class="op">+</span> grade</span>
<span id="cb15-21-f02d52a916"><a href="#cb15-21-f02d52a916"></a></span>
<span id="cb15-22-f02d52a916"><a href="#cb15-22-f02d52a916"></a> course_average <span class="op">=</span> total_so_far <span class="op">/</span> len_so_far</span>
<span id="cb15-23-f02d52a916"><a href="#cb15-23-f02d52a916"></a></span>
<span id="cb15-24-f02d52a916"><a href="#cb15-24-f02d52a916"></a> averages_so_far <span class="op">=</span> averages_so_far <span class="op">+</span> [course_average]</span>
<span id="cb15-25-f02d52a916"><a href="#cb15-25-f02d52a916"></a></span>
<span id="cb15-26-f02d52a916"><a href="#cb15-26-f02d52a916"></a> <span class="cf">return</span> averages_so_far</span></code></pre></div>
<p>It may be surprising to you that we can do this! Just as how in the last chapter we saw that we can take a predicate and expand it into its definition, we can do the same thing for Python functions with multiple statements in their body. The only change we needed to make was the return statement of <code>average</code>. The original function had the statement <code>return total_so_far / len_so_far</code>. Because our loop assigned this return value to <code>course_average</code>, we changed the code to:</p>
<div class="sourceCode" id="cb16-f02d52a916"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1-f02d52a916"><a href="#cb16-1-f02d52a916"></a>course_average <span class="op">=</span> total_so_far <span class="op">/</span> len_so_far</span></code></pre></div>
<p>One important note about the structure of this nested loop is that the inner loop accumulators are assigned to <em>inside</em> the body of the outer loop*, rather than at the top of the function body. This is because the accumulators <code>len_so_far</code> and <code>total_so_far</code> are specific to <code>course_grades</code>, which changes at each iteration of the outer loop. The statements <code>len_so_far = 0</code> and <code>total_so_far = 0</code> act to “reset” these accumulators for each new <code>course_grades</code> list.</p>
<p>Lets take a look at our final loop accumulation table in this section, which illustrates the execution of <code>course_averages_v3([[70, 75, 80], [70, 80, 90, 100], [80, 100]])</code> and how each loop variable and accumulator changes. Please take your time studying this table carefully—it isnt designed to be a “quick read”, but to really deepen your understand of whats going on!</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 9%" />
<col style="width: 16%" />
<col style="width: 9%" />
<col style="width: 16%" />
<col style="width: 15%" />
<col style="width: 15%" />
<col style="width: 17%" />
</colgroup>
<thead>
<tr class="header">
<th>Outer loop iteration</th>
<th>Outer loop variable (<code>course_grades</code>)</th>
<th>Inner loop iteration</th>
<th>Inner loop variable (<code>grade</code>)</th>
<th>Inner accumulator (<code>len_so_far</code>)</th>
<th>Inner accumulator (<code>total_so_far</code>)</th>
<th>Outer accumulator (<code>averages_so_far</code>)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><code>[]</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>[70, 75, 80]</code></td>
<td>0</td>
<td></td>
<td><code>0</code></td>
<td><code>0</code></td>
<td><code>[]</code></td>
</tr>
<tr class="odd">
<td>1</td>
<td><code>[70, 75, 80]</code></td>
<td>1</td>
<td><code>70</code></td>
<td><code>1</code></td>
<td><code>70</code></td>
<td><code>[]</code></td>
</tr>
<tr class="even">
<td>1</td>
<td><code>[70, 75, 80]</code></td>
<td>2</td>
<td><code>75</code></td>
<td><code>2</code></td>
<td><code>145</code></td>
<td><code>[]</code></td>
</tr>
<tr class="odd">
<td>1</td>
<td><code>[70, 75, 80]</code></td>
<td>3</td>
<td><code>80</code></td>
<td><code>3</code></td>
<td><code>225</code></td>
<td><code>[75.0]</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>[70, 80, 90, 100]</code></td>
<td>0</td>
<td></td>
<td><code>0</code></td>
<td><code>0</code></td>
<td><code>[75.0]</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>[70, 80, 90, 100]</code></td>
<td>1</td>
<td><code>70</code></td>
<td><code>1</code></td>
<td><code>70</code></td>
<td><code>[75.0]</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>[70, 80, 90, 100]</code></td>
<td>2</td>
<td><code>80</code></td>
<td><code>2</code></td>
<td><code>150</code></td>
<td><code>[75.0]</code></td>
</tr>
<tr class="odd">
<td>2</td>
<td><code>[70, 80, 90, 100]</code></td>
<td>3</td>
<td><code>90</code></td>
<td><code>3</code></td>
<td><code>240</code></td>
<td><code>[75.0]</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>[70, 80, 90, 100]</code></td>
<td>4</td>
<td><code>100</code></td>
<td><code>4</code></td>
<td><code>340</code></td>
<td><code>[75.0, 85.0]</code></td>
</tr>
<tr class="odd">
<td>3</td>
<td><code>[80, 100]</code></td>
<td>0</td>
<td></td>
<td><code>0</code></td>
<td><code>0</code></td>
<td><code>[75.0, 85.0]</code></td>
</tr>
<tr class="even">
<td>3</td>
<td><code>[80, 100]</code></td>
<td>1</td>
<td><code>80</code></td>
<td><code>1</code></td>
<td><code>80</code></td>
<td><code>[75.0, 85.0]</code></td>
</tr>
<tr class="odd">
<td>3</td>
<td><code>[80, 100]</code></td>
<td>2</td>
<td><code>100</code></td>
<td><code>2</code></td>
<td><code>180</code></td>
<td><code>[75.0, 85.0, 90.0]</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="summary-understanding-and-simplifying-nested-for-loops-f02d52a916">Summary: understanding and simplifying nested for loops</h2>
<p>Nested for loops are a powerful tool in our understanding of the Python programming language, but they are by far the most complex and most error-prone that weve studied so far. Just as we saw with nested expressions and nested if statements, nested loops have the potential to greatly increase the size and complexity of our code. Contrast the implementation of <code>course_averages_v3</code> against <code>course_averages_v2</code> (or <code>course_averages_v1</code>), for example.</p>
<p>While nested loops are sometimes inevitable or convenient, we recommend following these guidelines to simplify your use of nested loops to help you better understand your code:</p>
<ol type="1">
<li>Use nested loops when you have a single accumulator that can be initialized just once before the nested loop (e.g., <code>sum_all</code> and <code>cartesian_product</code>).</li>
<li>If you have a nested loop where the inner loop can be replaced by a built-in aggregation function (e.g., <code>sum</code> or <code>len</code>), use the built-in function instead.</li>
<li>If you have a nested loop where the inner loop has a separate accumulator that is assigned inside the outer loop (e.g., <code>course_averages_v3</code>), move the accumulator and inner loop into a new function, and call that function from within the original outer loop.</li>
</ol>
<!-- ## From nested quantifiers to nested for loops
Recall once again our example of who loves whom:
```python
>>> LOVES = [
... [False, True, True, False],
... [False, True, True, True],
... [False, False, True, False],
... [False, False, False, True]
... ]
```
We used this data to discover that everyone is loved by someone else:^[
This is actually [not unusual](https://www.youtube.com/watch?v=Vc_BU87ZDfg).
]
```python
>>> A = range(0, 4) # We'll represent the people as indexes from 0 to 3,
>>> B = range(0, 4) # for both A and B. We use the same variable names for clarity.
``` -->
<!-- TODO Not sure which example you'd like to do here? Are we looking at alternating qualifiers? Or multiple, non-alternating qualifiers? -->
<h2 id="references-f02d52a916">References</h2>
<ul>
<li>CSC108 videos: Nested loops (<a href="https://youtu.be/IW4J0lwc8zE">Part 1</a>, <a href="https://youtu.be/3oSEWc2avns">Part 2</a>)</li>
</ul>
</section>
<br/>
<!--
[4.8 Testing Functions III: Code Coverage](04-complex-data/08-testing-functions-3.html) -->
<h2 class="unnumbered" id="modifying-values-and-variables">5. Modifying Values and Variables</h2>
<a id="anchor-05-01"></a>
<header id="title-block-header-8f594cd6a6">
<h1 class="title">5.1 Variable Reassignment and Object Mutation</h1>
</header>
<section>
<p>So far, we have largely treated objects and variables in Python as being constant over time: once an object is created or a variable is initialized, its value has not changed during the program. This property has made it easier to reason about our code: once we set the value of the variable once, we can easily look up its value at any later point in the program.<label for="sn-0-8f594cd6a6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-8f594cd6a6" class="margin-toggle"/><span class="sidenote">Indeed, this is a fact that we take for granted in mathematics: if we say “let <span class="math inline">\(x\)</span> = 10” in a calculation or proof, we expect <span class="math inline">\(x\)</span> to keep that same value from start to finish!</span></p>
<p>However, in programs it is sometimes useful to have objects and variables change value over time. We saw one example of this last week when we studied for loops, in which both the loop variable and accumulator take on multiple values over the course of running the loop. In this section, well introduce two related but distinct actions in a program: <em>variable reassignment</em> and <em>object mutation</em>.</p>
<h2 id="variable-reassignment-8f594cd6a6">Variable reassignment</h2>
<p>Recall that a statement of the form <code>___ = ___</code> is called an <em>assignment statement</em>, which takes a variable name on the left-hand side and an expression on the right-hand side, and assigns the value of the expression to the variable.</p>
<p>A <strong>variable reassignment</strong> is a Python action that assigns a value to a variable that already refers to a value. The most common kind of variable reassignment is with an assignment statement:</p>
<div class="sourceCode" id="cb1-8f594cd6a6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-8f594cd6a6"><a href="#cb1-1-8f594cd6a6"></a>x <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb1-2-8f594cd6a6"><a href="#cb1-2-8f594cd6a6"></a>x <span class="op">=</span> <span class="dv">5</span> <span class="co"># The variable x is reassigned on this line.</span></span></code></pre></div>
<p>A variable reassignment <em>changes which object a variable refers to</em>. In the above example, variable <code>x</code> changes from referring to an object representing the number <code>1</code> to an object representing <code>5</code>.</p>
<p>The loops that we studied last week all used variable reassignment to update the <em>accumulator variable</em> inside the loop.</p>
<div class="sourceCode" id="cb2-8f594cd6a6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-8f594cd6a6"><a href="#cb2-1-8f594cd6a6"></a><span class="kw">def</span> my_sum(nums: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-2-8f594cd6a6"><a href="#cb2-2-8f594cd6a6"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb2-3-8f594cd6a6"><a href="#cb2-3-8f594cd6a6"></a> <span class="cf">for</span> num <span class="kw">in</span> nums:</span>
<span id="cb2-4-8f594cd6a6"><a href="#cb2-4-8f594cd6a6"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> num</span>
<span id="cb2-5-8f594cd6a6"><a href="#cb2-5-8f594cd6a6"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<p>At each iteration, the statement <code>sum_so_far = sum_so_far + num</code> did two things:</p>
<ol type="1">
<li>Evaluate the right-hand side (<code>sum_so_far + num</code>) using the <em>current</em> value of <code>sum_so_far</code>, obtaining a new object.</li>
<li>Reassign <code>sum_so_far</code> to refer to that new object.</li>
</ol>
<p>This is the Python mechanism that causes <code>sum_so_far</code> to refer to the total sum at the end of the loop, which of course was the whole point of the loop! Indeed, updating loop accumulators is one of the most natural uses of variable reassignment.</p>
<p>This loop actually illustrates another common form of variable reassignment: reassigning the <em>loop variable</em> to a different value at each for loop iteration. For example, when we call <code>my_sum([10, 20, 30])</code>, the loop variable <code>num</code> gets assigned to the value <code>10</code>, then the value <code>20</code>, and then the value <code>30</code>.</p>
<h2 id="reassignment-is-independent-of-prior-uses-8f594cd6a6">Reassignment is independent of prior uses</h2>
<p>Consider the following Python code snippet:</p>
<div class="sourceCode" id="cb3-8f594cd6a6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-8f594cd6a6"><a href="#cb3-1-8f594cd6a6"></a>x <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb3-2-8f594cd6a6"><a href="#cb3-2-8f594cd6a6"></a>y <span class="op">=</span> x <span class="op">+</span> <span class="dv">2</span></span>
<span id="cb3-3-8f594cd6a6"><a href="#cb3-3-8f594cd6a6"></a>x <span class="op">=</span> <span class="dv">7</span></span></code></pre></div>
<p>Here, the variable <code>x</code> is reassigned to <code>7</code> on line 3. But what happens to <code>y</code>? Does it now also get “reassigned” to <code>9</code> (which is <code>7 + 2</code>), or does it stay at its original value <code>3</code>?</p>
<p>We can express Pythons behaviour here with one simple rule: <strong>variable reassignment only changes the immediate variable being reassigned, and does not change any other variables or objects, even ones that were defined using the variable being reassigned</strong>. And so in the above example, <code>y</code> still refers to the value <code>3</code>, even after <code>x</code> is reassigned to <code>7</code>.</p>
<p>This rule might seem a bit strange at first, but is actually the simplest way that Python could execute variable reassignment: it allows programmers to reason about these assignment statements in a top-down order, without worrying that future assignment statements could affect previous ones. If were tracing through our code carefully and read <code>y = x + 2</code>, I can safely predict the value of <code>y</code> based on the current value of <code>x</code>, without worrying about how <code>x</code> might be reassigned later in the program.</p>
<p>That said, there is one complication with this line of reasoning that comes up with the next form of “value change”, object mutation.</p>
<h2 id="object-mutation-8f594cd6a6">Object mutation</h2>
<p>In <a href="../04-complex-data/07-nested-loops.html">4.7 Nested Loops</a>, we saw how <code>product</code> could help us calculate the Cartesian product by accumulating all possible pairs of elements in a list. Consider a function that also accumulates values in a list:</p>
<div class="sourceCode" id="cb4-8f594cd6a6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-8f594cd6a6"><a href="#cb4-1-8f594cd6a6"></a><span class="kw">def</span> squares(nums: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">int</span>]:</span>
<span id="cb4-2-8f594cd6a6"><a href="#cb4-2-8f594cd6a6"></a> <span class="co">&quot;&quot;&quot;Return a list of the squares of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb4-3-8f594cd6a6"><a href="#cb4-3-8f594cd6a6"></a> squares_so_far <span class="op">=</span> []</span>
<span id="cb4-4-8f594cd6a6"><a href="#cb4-4-8f594cd6a6"></a></span>
<span id="cb4-5-8f594cd6a6"><a href="#cb4-5-8f594cd6a6"></a> <span class="cf">for</span> num <span class="kw">in</span> nums:</span>
<span id="cb4-6-8f594cd6a6"><a href="#cb4-6-8f594cd6a6"></a> squares_so_far <span class="op">=</span> squares_so_far <span class="op">+</span> [num <span class="op">*</span> num]</span>
<span id="cb4-7-8f594cd6a6"><a href="#cb4-7-8f594cd6a6"></a> <span class="cf">return</span> squares_so_far</span></code></pre></div>
<p>Both the <code>squares</code> and <code>product</code> functions work properly, but are rather inefficient.<label for="sn-1-8f594cd6a6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-8f594cd6a6" class="margin-toggle"/><span class="sidenote"> Well study what we mean by “inefficient” more precisely later in this course.</span> In <code>squares</code>, each loop iteration creates a new <code>list</code> object (a copy of the current list plus one more element at the end) and reassigns <code>squares_so_far</code> to it. It would be easier (and faster) if we could somehow reuse the same object but modify it by adding elements to it; the same applies to other collection data types like <code>set</code> and <code>dict</code> as well.</p>
<p>In Python, <strong>object mutation</strong> (often shortened to just <strong>mutation</strong>) is an operation that changes the value of an existing object. For example, Pythons <code>list</code> data type contains several methods that <strong>mutate</strong> the given <code>list</code> object rather than create a new one. Heres how we could improve our <code>squares</code> implementation by using <code>list.append</code>,<label for="sn-2-8f594cd6a6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-8f594cd6a6" class="margin-toggle"/><span class="sidenote">Check out <a href="../A-python-builtins/02-types.html">Appendix A.2 Python Built-In Data Types Reference</a> for a list of methods, including mutating ones, for lists, sets, dictionaries, and more.</span> a method that adds a single value to the end of a list:</p>
<div class="sourceCode" id="cb5-8f594cd6a6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-8f594cd6a6"><a href="#cb5-1-8f594cd6a6"></a><span class="kw">def</span> squares(nums: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">int</span>]:</span>
<span id="cb5-2-8f594cd6a6"><a href="#cb5-2-8f594cd6a6"></a> <span class="co">&quot;&quot;&quot;Return a list of the squares of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb5-3-8f594cd6a6"><a href="#cb5-3-8f594cd6a6"></a> squares_so_far <span class="op">=</span> []</span>
<span id="cb5-4-8f594cd6a6"><a href="#cb5-4-8f594cd6a6"></a></span>
<span id="cb5-5-8f594cd6a6"><a href="#cb5-5-8f594cd6a6"></a> <span class="cf">for</span> num <span class="kw">in</span> nums:</span>
<span id="cb5-6-8f594cd6a6"><a href="#cb5-6-8f594cd6a6"></a> <span class="bu">list</span>.append(squares_so_far, num <span class="op">*</span> num)</span>
<span id="cb5-7-8f594cd6a6"><a href="#cb5-7-8f594cd6a6"></a> <span class="cf">return</span> squares_so_far</span></code></pre></div>
<p>Now, <code>squares</code> runs by assigning <code>squares_so_far</code> to a single list object before the loop, and then mutating that list object at each loop iteration. The outward behaviour is the same, but this code is more efficient because a bunch of new list objects are not created. To use the terminology from before, <code>squares_so_far</code> is <em>not</em> reassigned; instead, the object that it refers to gets mutated.</p>
<p>One final note: you might notice that the loop body calls <code>list.append</code> without an assignment statement. This is because <code>list.append</code> returns <code>None</code>, a special Python value that indicates “no value”. Just as we explored previously with the <code>print</code> function, <code>list.append</code> has a <em>side effect</em> that it mutates its <code>list</code> argument, but does not return anything.</p>
<h2 id="mutable-and-immutable-data-types-8f594cd6a6">Mutable and immutable data types</h2>
<p>We say that a Python data type is <strong>mutable</strong> when it supports at least one kind of mutating operation, and <strong>immutable</strong> if it does not. Sets, lists, and dictionaries are all mutable data types, as are the data classes we studied in the previous chapter. All of the non-collection types weve studied—<code>int</code>, <code>float</code>, <code>bool</code>, and <code>str</code>—are immutable.</p>
<p>Instances of an immutable data type cannot change their value during the execution of a Python program. So for example, if we have an object representing the number <code>3</code> in Python, that objects value will <em>always</em> be 3. But remember, a variable that refers to this object might be reassigned to a different object later. This is why is is important that we differentiate between variables and objects!</p>
<h2 id="list-vs.-tuple-and-whats-in-a-set-8f594cd6a6"><code>list</code> vs. <code>tuple</code>, and whats in a <code>set</code></h2>
<p>All the way back in <a href="../01-working-with-data/03-python-data-types.html">1.3 Representing Data in Python</a>, we introduced two Python data types that could be used to represent ordered sequences, <code>list</code> and <code>tuple</code>. Weve been using them fairly interchangeably for the past few chapters, but are now ready to discuss the difference between them. <em>In Python, a <code>list</code> is mutable, but a <code>tuple</code> is immutable.</em> For example, we can modify a <code>list</code> value by adding an element with <code>list.append</code>, but there is no equivalent <code>tuple.append</code>, nor any other mutating method on tuples.</p>
<p>So why bother with tuples at all? Because in Python, <code>set</code>s may only contain <em>immutable</em> objects, and <code>dict</code>s may only contain <em>immutable keys</em>. So for example, we cannot have a <code>set</code> of <code>set</code>s or <code>set</code> of <code>list</code>s in Python, but we can have a <code>list</code> of <code>lists</code>, which is why studied nested lists in the last chapter.</p>
<p>Of course, from a theoretical standpoint a set can have elements that are other sets! So this restriction is a quirk of Pythons built-in data types that we just have to live with when using this programming language.<label for="sn-3-8f594cd6a6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-8f594cd6a6" class="margin-toggle"/><span class="sidenote"> In case youre curious, there is another Python data type, <code>frozenset</code>, which is an immutable version of <code>set</code>. We just wont be using it in this course.</span></p>
<h2 id="reasoning-about-code-with-changing-values-8f594cd6a6">Reasoning about code with changing values</h2>
<p>Variable reassignment and object mutation are distinct concepts. Reassignment will change which object a variable refers to, sometimes creating a brand new object (e.g., when we used a list accumulator in <code>squares</code>). Object mutation changes the object itself, independent of what variable(s) refer t othat object.</p>
<p>Yet we have presented them here in the same section because they share a fundamental similarity: they both result in variables changing values over the course of a program. To illustrate this point, consider the following hypothetical function definition:</p>
<div class="sourceCode" id="cb6-8f594cd6a6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-8f594cd6a6"><a href="#cb6-1-8f594cd6a6"></a><span class="kw">def</span> my_function(...) <span class="op">-&gt;</span> ...:</span>
<span id="cb6-2-8f594cd6a6"><a href="#cb6-2-8f594cd6a6"></a> x <span class="op">=</span> <span class="dv">10</span></span>
<span id="cb6-3-8f594cd6a6"><a href="#cb6-3-8f594cd6a6"></a> y <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb6-4-8f594cd6a6"><a href="#cb6-4-8f594cd6a6"></a></span>
<span id="cb6-5-8f594cd6a6"><a href="#cb6-5-8f594cd6a6"></a> ... <span class="co"># Many lines of code</span></span>
<span id="cb6-6-8f594cd6a6"><a href="#cb6-6-8f594cd6a6"></a> ... <span class="co"># Many lines of code</span></span>
<span id="cb6-7-8f594cd6a6"><a href="#cb6-7-8f594cd6a6"></a> ... <span class="co"># Many lines of code</span></span>
<span id="cb6-8-8f594cd6a6"><a href="#cb6-8-8f594cd6a6"></a> ... <span class="co"># Many lines of code</span></span>
<span id="cb6-9-8f594cd6a6"><a href="#cb6-9-8f594cd6a6"></a> ... <span class="co"># Many lines of code</span></span>
<span id="cb6-10-8f594cd6a6"><a href="#cb6-10-8f594cd6a6"></a> ... <span class="co"># Many lines of code</span></span>
<span id="cb6-11-8f594cd6a6"><a href="#cb6-11-8f594cd6a6"></a></span>
<span id="cb6-12-8f594cd6a6"><a href="#cb6-12-8f594cd6a6"></a> <span class="cf">return</span> x <span class="op">*</span> <span class="bu">len</span>(y) <span class="op">+</span> ...</span></code></pre></div>
<p>Weve included for effect a large omitted “middle” section of the function body, showing only the initialization of two local variables at the start of the function and a final return statement at the end of the function.</p>
<p>If the omitted code does <em>not</em> contain any variable reassignment or object mutation, then we can be sure that in the return statement, <code>x</code> still refers to <code>10</code> and <code>y</code> still refers to <code>[1, 2, 3]</code>, regardless of what other computations occurred in the omitted lines! In other words, without reassignment and mutation, these assignment statements are universal across the function body: “for all points in the body of <code>my_function</code>, <code>x == 10</code> and <code>y == [1, 2, 3]</code>.” Such universal statements make our code easier to reason about, as we can determine the values of these variables from just the assignment statement that creates them.</p>
<p>Variable reassignment and object mutation weaken this property. For example, if we reassign <code>x</code> or <code>y</code> (e.g., <code>x = 100</code>) in the middle of the function body, the return statement obtains a different value for <code>x</code> than <code>10</code>. Similarly, if we mutate <code>y</code> (e.g., <code>list.append(y, 100)</code>), the reutn statement obtains a different value for <code>y</code> than <code>[1, 2, 3]</code>. <em>Introducing reassignment and mutation makes our code harder to reason about, as we need to track all changes to variable values line by line.</em></p>
<p>Because of this, you should avoid using variable reassignment and object mutation when possible, and use them in structured code patterns like we saw with the loop accumulator pattern. Over the course of this chapter, well study other situations where reassignment and mutation are useful, and introduce a new memory model to help us keep track of changing variable values in our code.</p>
</section>
<br/> <a id="anchor-05-02"></a>
<header id="title-block-header-1af1391c4f">
<h1 class="title">5.2 Operations on Mutable Data Types</h1>
</header>
<section>
<p>In the last section, we introduced the concept of mutable data types, and saw how we could mutate Python lists with the <code>list.append</code> method. In this section, well survey some of the other ways of mutating lists and other mutable Python data types. For a full reference of Pythons mutating methods on these data types, please see <a href="../A-python-builtins/02-types.html">Appendix A.2 Python Built-In Data Types Reference</a>.</p>
<h2 id="list.append-list.insert-and-list.extend-1af1391c4f"><code>list.append</code>, <code>list.insert</code>, and <code>list.extend</code></h2>
<p>In addition to <code>list.append</code>, there are two other ways of adding new items to a Python list. The first is <code>list.insert</code>, which takes a list, an <em>index</em> and an object, and inserts the object at the given index into the list at the given index.</p>
<div class="sourceCode" id="cb1-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-1af1391c4f"><a href="#cb1-1-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> strings <span class="op">=</span> [<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>, <span class="st">&#39;c&#39;</span>, <span class="st">&#39;d&#39;</span>]</span>
<span id="cb1-2-1af1391c4f"><a href="#cb1-2-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.insert(strings, <span class="dv">2</span>, <span class="st">&#39;hello&#39;</span>) <span class="co"># Insert &#39;hello&#39; into strings at index 2</span></span>
<span id="cb1-3-1af1391c4f"><a href="#cb1-3-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> strings</span>
<span id="cb1-4-1af1391c4f"><a href="#cb1-4-1af1391c4f"></a>[<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>, <span class="st">&#39;hello&#39;</span>, <span class="st">&#39;c&#39;</span>, <span class="st">&#39;d&#39;</span>]</span></code></pre></div>
<p>The second is <code>list.extend</code>, which takes two lists and adds all items from the second list at the end of the first list, as if <code>append</code> were called once per element of the second list.</p>
<div class="sourceCode" id="cb2-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-1af1391c4f"><a href="#cb2-1-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> strings <span class="op">=</span> [<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>, <span class="st">&#39;c&#39;</span>, <span class="st">&#39;d&#39;</span>]</span>
<span id="cb2-2-1af1391c4f"><a href="#cb2-2-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.extend(strings, [<span class="st">&#39;CSC110&#39;</span>, <span class="st">&#39;CSC111&#39;</span>])</span>
<span id="cb2-3-1af1391c4f"><a href="#cb2-3-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> strings</span>
<span id="cb2-4-1af1391c4f"><a href="#cb2-4-1af1391c4f"></a>[<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>, <span class="st">&#39;c&#39;</span>, <span class="st">&#39;d&#39;</span>, <span class="st">&#39;CSC110&#39;</span>, <span class="st">&#39;CSC111&#39;</span>]</span></code></pre></div>
<h2 id="assigning-to-a-specific-list-index-1af1391c4f">Assigning to a specific list index</h2>
<p>There is one more way to put a value into a list: by overwriting the element stored at a specific index. Given a list <code>lst</code>, weve seen that we can access specific elements using indexing syntax <code>lst[0]</code>, <code>lst[1]</code>, <code>lst[2]</code>, etc. We can also use this kind of expression as the <em>left side</em> of an assignment statement to mutate the list by modifying a specific index.</p>
<div class="sourceCode" id="cb3-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-1af1391c4f"><a href="#cb3-1-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> strings <span class="op">=</span> [<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>, <span class="st">&#39;c&#39;</span>, <span class="st">&#39;d&#39;</span>]</span>
<span id="cb3-2-1af1391c4f"><a href="#cb3-2-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> strings[<span class="dv">2</span>] <span class="op">=</span> <span class="st">&#39;Hello&#39;</span></span>
<span id="cb3-3-1af1391c4f"><a href="#cb3-3-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> strings</span>
<span id="cb3-4-1af1391c4f"><a href="#cb3-4-1af1391c4f"></a>[<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>, <span class="st">&#39;Hello&#39;</span>, <span class="st">&#39;d&#39;</span>]</span></code></pre></div>
<p>Note that unlike <code>list.insert</code>, assigning to an index removes the element previously stored at that index from the list!</p>
<h2 id="mutating-sets-1af1391c4f">Mutating sets</h2>
<p>Python <code>set</code>s are mutable. Because they are unordered, they are simpler than <code>list</code>s, and offer just two main mutating methods: <code>set.add</code> and <code>set.remove</code>, which (as you can probably guess) add and remove an element from a set, respectively.<label for="sn-0-1af1391c4f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-1af1391c4f" class="margin-toggle"/><span class="sidenote"> <code>list</code> also provides a few mutating methods that remove elements, though we did not cover them in this section.</span> Well illustrate <code>set.add</code> by showing how to re-implement our <code>squares</code> function from the previous section with <code>set</code> instead of <code>list</code>:</p>
<div class="sourceCode" id="cb4-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-1af1391c4f"><a href="#cb4-1-1af1391c4f"></a><span class="kw">def</span> squares(numbers: <span class="bu">set</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">set</span>[<span class="bu">int</span>]:</span>
<span id="cb4-2-1af1391c4f"><a href="#cb4-2-1af1391c4f"></a> <span class="co">&quot;&quot;&quot;Return a set containing the squares of all the given numbers.</span></span>
<span id="cb4-3-1af1391c4f"><a href="#cb4-3-1af1391c4f"></a></span>
<span id="cb4-4-1af1391c4f"><a href="#cb4-4-1af1391c4f"></a><span class="co"> ...</span></span>
<span id="cb4-5-1af1391c4f"><a href="#cb4-5-1af1391c4f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-6-1af1391c4f"><a href="#cb4-6-1af1391c4f"></a> squares_so_far <span class="op">=</span> <span class="bu">set</span>()</span>
<span id="cb4-7-1af1391c4f"><a href="#cb4-7-1af1391c4f"></a> <span class="cf">for</span> n <span class="kw">in</span> numbers:</span>
<span id="cb4-8-1af1391c4f"><a href="#cb4-8-1af1391c4f"></a> <span class="bu">set</span>.add(squares_so_far, n <span class="op">*</span> n)</span>
<span id="cb4-9-1af1391c4f"><a href="#cb4-9-1af1391c4f"></a></span>
<span id="cb4-10-1af1391c4f"><a href="#cb4-10-1af1391c4f"></a> <span class="cf">return</span> squares_so_far</span></code></pre></div>
<p>Note that <code>set.add</code> will only add the element if the set does not already contain it, as sets cannot contain duplicates. In addition, sets are unordered whereas <code>list.append</code> will add the element to the end of the sequence.</p>
<h2 id="mutating-dictionaries-1af1391c4f">Mutating dictionaries</h2>
<p>The most common ways for dictionaries to be mutated is by adding a new key-value pair, or changing the associated value for a key-value pair in the dictionary. This does not use a function call, but rather the same syntax as assigning by list index.</p>
<div class="sourceCode" id="cb5-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-1af1391c4f"><a href="#cb5-1-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> items <span class="op">=</span> {<span class="st">&#39;a&#39;</span>: <span class="dv">1</span>, <span class="st">&#39;b&#39;</span>: <span class="dv">2</span>}</span>
<span id="cb5-2-1af1391c4f"><a href="#cb5-2-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> items[<span class="st">&#39;c&#39;</span>] <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb5-3-1af1391c4f"><a href="#cb5-3-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> items</span>
<span id="cb5-4-1af1391c4f"><a href="#cb5-4-1af1391c4f"></a>{<span class="st">&#39;a&#39;</span>: <span class="dv">1</span>, <span class="st">&#39;b&#39;</span>: <span class="dv">2</span>, <span class="st">&#39;c&#39;</span>: <span class="dv">3</span>}</span></code></pre></div>
<p>The second assignment statement adds a new key-value pair to <code>items</code>, with the key being <code>'c'</code> and the items being <code>3</code>. In this case, the left-hand side of the assignment is not a variable but instead an expression representing a component of <code>items</code>, in this case the key <code>'c'</code> in the dictionary. When this assignment statement is evaluated, the right-hand side value <code>3</code> is stored in the dictionary items as the corresponding value for <code>'c'</code>.</p>
<p>Assignment statements in this form can also be used to mutate the dictionary by taking an existing key-value pair and replacing the value with a different one. Heres an example of that:</p>
<div class="sourceCode" id="cb6-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-1af1391c4f"><a href="#cb6-1-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> items[<span class="st">&#39;a&#39;</span>] <span class="op">=</span> <span class="dv">100</span></span>
<span id="cb6-2-1af1391c4f"><a href="#cb6-2-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> items</span>
<span id="cb6-3-1af1391c4f"><a href="#cb6-3-1af1391c4f"></a>{<span class="st">&#39;a&#39;</span>: <span class="dv">100</span>, <span class="st">&#39;b&#39;</span>: <span class="dv">2</span>, <span class="st">&#39;c&#39;</span>: <span class="dv">3</span>}</span></code></pre></div>
<h2 id="mutating-data-classes-1af1391c4f">Mutating data classes</h2>
<p>Python data classes are mutable by default.<label for="sn-1-1af1391c4f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-1af1391c4f" class="margin-toggle"/><span class="sidenote"> Technically there is a way to create immutable data classes, but this is beyond the scope of this course.</span> To illustrate this, well return to our <code>Person</code> class:</p>
<div class="sourceCode" id="cb7-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-1af1391c4f"><a href="#cb7-1-1af1391c4f"></a><span class="at">@dataclass</span></span>
<span id="cb7-2-1af1391c4f"><a href="#cb7-2-1af1391c4f"></a><span class="kw">class</span> Person:</span>
<span id="cb7-3-1af1391c4f"><a href="#cb7-3-1af1391c4f"></a> <span class="co">&quot;&quot;&quot;A person with some basic demographic information.</span></span>
<span id="cb7-4-1af1391c4f"><a href="#cb7-4-1af1391c4f"></a></span>
<span id="cb7-5-1af1391c4f"><a href="#cb7-5-1af1391c4f"></a><span class="co"> Representation Invariants:</span></span>
<span id="cb7-6-1af1391c4f"><a href="#cb7-6-1af1391c4f"></a><span class="co"> - self.age &gt;= 0</span></span>
<span id="cb7-7-1af1391c4f"><a href="#cb7-7-1af1391c4f"></a></span>
<span id="cb7-8-1af1391c4f"><a href="#cb7-8-1af1391c4f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-9-1af1391c4f"><a href="#cb7-9-1af1391c4f"></a> given_name: <span class="bu">str</span></span>
<span id="cb7-10-1af1391c4f"><a href="#cb7-10-1af1391c4f"></a> family_name: <span class="bu">str</span></span>
<span id="cb7-11-1af1391c4f"><a href="#cb7-11-1af1391c4f"></a> age: <span class="bu">int</span></span>
<span id="cb7-12-1af1391c4f"><a href="#cb7-12-1af1391c4f"></a> address: <span class="bu">str</span></span></code></pre></div>
<p>We mutate instances of data classes by modifying their attributes. We do this by assigning to their attributes directly, using <em>dot notation</em> on the left side of an assignment statement.</p>
<div class="sourceCode" id="cb8-1af1391c4f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-1af1391c4f"><a href="#cb8-1-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> p <span class="op">=</span> Person(<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Liu&#39;</span>, <span class="dv">100</span>, <span class="st">&#39;40 St. George Street&#39;</span>)</span>
<span id="cb8-2-1af1391c4f"><a href="#cb8-2-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> p.age <span class="op">=</span> <span class="dv">200</span></span>
<span id="cb8-3-1af1391c4f"><a href="#cb8-3-1af1391c4f"></a><span class="op">&gt;&gt;&gt;</span> p</span>
<span id="cb8-4-1af1391c4f"><a href="#cb8-4-1af1391c4f"></a>Person(given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>, family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>, age<span class="op">=</span><span class="dv">200</span>, address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>)</span></code></pre></div>
<p>One note of caution here: as you start mutating data class instances, you must always remember to respect the representation invariants associated with that data class. For example, setting <code>p.age = -1</code> would violate the <code>Person</code> representation invariant. To protect against this, <code>python_ta</code> checks representation invariants whenever you assign to attributes of data classes, as long as the <code>python_ta.contracts.check_all_contracts</code> function has been called in your file.</p>
</section>
<br/> <a id="anchor-05-03"></a>
<header id="title-block-header-6f95db54d4">
<h1 class="title">5.3 The Python Memory Model: Introduction</h1>
</header>
<section>
<p>In [1.4 Storing Data in Variables], we introduced the <em>value-based memory model</em> to help keep track of variables and their values:</p>
<div class="memory-model-values">
<table>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>distance1</code></td>
<td><code>1.118033988749895</code></td>
</tr>
<tr class="even">
<td><code>distance2</code></td>
<td><code>216.14809737770074</code></td>
</tr>
</tbody>
</table>
</div>
<p>From this table we can surmise that there are two variables (<code>distance1</code> and <code>distance2</code>), each associated with a <code>float</code> value. However, now that we know about reassignment and mutation, a more complex memory model is needed: the <em>object-based memory model</em>, which well simply call the <em>Python memory model</em>, as this is the “standard” representation Python stores data.</p>
<h2 id="representing-objects-6f95db54d4">Representing objects</h2>
<p>Recall that every piece of data is stored in a Python program in an <strong>object</strong>. But how are the objects themselves stored? Every computer program (whether written in Python or some other language) stores data in computer memory, which you can think of as a very long list of storage locations. Each storage location is labelled with a unique memory address. In Python, every object we use is stored in computer memory at a particular location, and it is the responsibility of the Python interpreter to keep track of which objects are stored at which memory locations.</p>
<p>As programmers, we cannot control which memory addresses are used to store objects, but we can access a representation of this memory address using the built-in <code>id</code> function:</p>
<div class="sourceCode" id="cb1-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-6f95db54d4"><a href="#cb1-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(<span class="dv">3</span>)</span>
<span id="cb1-2-6f95db54d4"><a href="#cb1-2-6f95db54d4"></a><span class="dv">1635361280</span></span>
<span id="cb1-3-6f95db54d4"><a href="#cb1-3-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(<span class="st">&#39;words&#39;</span>)</span>
<span id="cb1-4-6f95db54d4"><a href="#cb1-4-6f95db54d4"></a><span class="dv">4297547872</span></span></code></pre></div>
<p>Formally, we define the <strong>id</strong> of a Python object as a unique <code>int</code> identifier to refer to this object.<label for="sn-0-6f95db54d4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-6f95db54d4" class="margin-toggle"/><span class="sidenote">The details of how Python translates memory addresses into the integers are not important to us.</span> Every object in Python has three important properties—<em>id</em>, <em>value</em>, and <em>type</em>—but of these three, only its <em>id</em> is guaranteed to be unique.</p>
<p>In Python, a variable is not an object and so does not actually store data; variables store an id that <em>refers</em> to an object that stores data. We also say that variables <em>contain</em> the id of an object. This is the case whether the data is something very simple like an <code>int</code> or more complex like a <code>str</code>. To make this distinction between variable and objects clear, we separate them in different parts of the Python memory model.</p>
<p>As an example, consider this code:</p>
<div class="sourceCode" id="cb2-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-6f95db54d4"><a href="#cb2-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb2-2-6f95db54d4"><a href="#cb2-2-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> word <span class="op">=</span> <span class="st">&#39;bonjour&#39;</span></span></code></pre></div>
<p>In our value-based memory model we would have represented these variables in a table:</p>
<div class="memory-model-values">
<table>
<caption><code>__main__</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x</code></td>
<td><code>3</code></td>
</tr>
<tr class="even">
<td><code>word</code></td>
<td><code>'bonjour'</code></td>
</tr>
</tbody>
</table>
</div>
<p>With the full object-based Python memory model, we instead draw one table-like structure on the left showing the mapping between variables and object ids, and then the objects on the right. Each object is represented as a box, with its id in the upper-left corner, type in the upper-right corner, and value in the middle. The actual object id reported by the <code>id</code> function has many digits, and its true value isnt important; we just need to know that each object has a unique identifier. So for our drawings we make up short identifiers such as <code>id92</code>.</p>
<p><img src="images/variables.png" alt="There are two variables, x and word. Each is a container holding just one thing: the id of an object. x contains the id of an int object, and that int object is a container holding the value 3. word contains the id of a str object, and that str object is a container holding the value bonjour." /><br />
</p>
<p>So there is no <code>3</code> inside the box for variable <code>x</code>. Instead, there is the <em>id</em> of an object whose value is 3. The same holds for variable <code>word</code>; it references an object whose value is <code>'bonjour'</code>.</p>
<p>Notice that we didnt draw any arrows. Programmers often draw an arrow when they want to show that one thing references another. This is great once you are very confident with a language and how references work. But in the early stages, you are much more likely to make correct predictions if you write down references (you can just make up id values) rather than arrows.</p>
<h3 id="assignment-statements-and-evaluating-expressions-6f95db54d4">Assignment statements and evaluating expressions</h3>
<p>Youve written code much more complex that whats above, but now that we have the full Python memory model, we can understand a few more details for fundamental Python operations. These details are foundational for writing and debugging the more complex code you will work on this year. So lets pause for a moment and be explicit about two things.</p>
<p><em>Evaluating an expression</em>. First, we said earlier that evaluating any Python expression produces a value. We now know that it is more precise to say that evaluating any Python expression produces <em>an id of an object representing the value of the expression</em>. Exactly what this object is depends on the kind of expression evaluated:</p>
<ul>
<li>If the expression is a literal, such as <code>176.4</code> or <code>'hello'</code>, Python creates an object of the appropriate type to hold the value.</li>
<li>If the expression is a variable, Python looks up the variable. If the variable doesnt exist, a <code>NameError</code> is raised. If it does exist, the expression produces the id stored in that variable.</li>
<li>If the expression is a binary operation, such as <code>+</code> or <code>%</code>, first Python evaluates the expressions two operands and applies the operator to the resulting values, creating a new object of the appropriate type to hold the resulting value. The expression produces the id of the new object.</li>
<li>There are additional rules for other types of expression, but these will do for now.</li>
</ul>
<p><em>Assignment statements.</em> Second, we said earlier that an assignment statement is executed by first evaluating the right-hand side expression, and then storing it in the left-hand side variable. Here is a more precise version of what happens:</p>
<ol type="1">
<li>Evaluate the expression on the right-hand side, yielding the id of an object.</li>
<li>If the variable on the left-hand side doesnt already exist, create it.</li>
<li>Store the id from the expression on the right-hand side in the variable on the left-hand side.</li>
</ol>
<h2 id="representing-compound-data-6f95db54d4">Representing compound data</h2>
<p>So far, the only objects weve looked at in the Python memory model are instances of primitive data types. What about compound data types like collections and data classes? Now that we have our object-based memory model, we are in a position to truly understand how Python represents these data types. <em>An instance of a compound data type does not store values directly; instead, it stores the ids of other objects.</em></p>
<p>Lets see what this means for some familiar collection data types.</p>
<ul>
<li><p><em>Lists</em>. Here is an object-based memory model diagram showing the state of memory after executing <code>lst = [1, 2, 3]</code>.</p>
<p><img src="images/list.png" style="width:100.0%" alt="List memory model diagram" /><br />
</p>
<p>Notice that there are four separate objects in this diagram: one for the each of the <code>int</code>s <code>1</code>, <code>2</code>, and <code>3</code>, and then one for the <code>list</code> itself.<label for="sn-1-6f95db54d4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-6f95db54d4" class="margin-toggle"/><span class="sidenote"> This illustrates one of the trade-offs with the Python memory model. It is more accurate than our value-based memory model, but that accuracy comes at the cost of having more parts and therefore more time-consuming to create. </span></p></li>
<li><p><em>Sets</em>. Here is an object-based memory model diagram showing how Python represents the set <code>my_set = {1, 2, 3}</code>.</p>
<p><img src="images/set.png" style="width:100.0%" alt="Set memory model diagram" /><br />
</p></li>
<li><p><em>Dictionaries</em>. Here is an object-based memory model diagram showing the dictionary <code>my_dict = {'a': 1, 'b': 2}</code>. There are five objects in total!</p>
<p><img src="images/dict.png" style="width:100.0%" alt="Dictionary memory model diagram" /><br />
</p></li>
<li><p><em>Data classes</em>. All Python data classes are compound data types, and instances also store the ids of other objects. Unlike the collection data types we looked at above, these ids are not bundled in a collection, but instead each associated with a particular instance attribute. Here is how we represent our favourite <code>Person</code> object.</p>
<p><img src="images/person.png" style="width:100.0%" alt="Person data class memory model diagram" /><br />
</p></li>
</ul>
<p>You may have noticed one difference between how we drew the object boxes of the primitive vs. compound data types above. We will use the convention of drawing a <em>double box</em> around objects that are immutable. Think of it as signifying that you cant get in there and change anything.</p>
<h2 id="visualizing-variable-reassignment-and-object-mutation-6f95db54d4">Visualizing variable reassignment and object mutation</h2>
<p>Our last topic in this section will be to use our object-based memory model to visualize variable reassignment and object mutation in Python.</p>
<p>Consider this simple case of variable reassignment:</p>
<div class="sourceCode" id="cb3-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-6f95db54d4"><a href="#cb3-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>]</span>
<span id="cb3-2-6f95db54d4"><a href="#cb3-2-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>]</span></code></pre></div>
<p>Here is what our memory model looks like after the first and second lines execute:</p>
<div class="fullwidth image-table">
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Before reassignment</th>
<th style="text-align: left;">After reassignment</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><img src="images/reassignment1.png" alt="Before reassignment" /></td>
<td style="text-align: left;"><img src="images/reassignment2.png" alt="After reassignment" /></td>
</tr>
</tbody>
</table>
</div>
<p>Using this diagram, we can see what happens when we execute the reassignment <code>s = ['a', 'b']</code>: a new <code>list</code> object <code>['a', 'b']</code> is created, and variable <code>s</code> is assigned the id of the new object. The original list object <code>[1, 2]</code> is not mutated. Variable reassignment <em>does not mutate any objects</em>; instead, it changes what a variable refers to. We can see this in the interpreter by using the <code>id</code> function to tell what object <code>s</code> refers to before and after the reassignment:</p>
<div class="sourceCode" id="cb4-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-6f95db54d4"><a href="#cb4-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>]</span>
<span id="cb4-2-6f95db54d4"><a href="#cb4-2-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(s)</span>
<span id="cb4-3-6f95db54d4"><a href="#cb4-3-6f95db54d4"></a><span class="dv">1695325453760</span></span>
<span id="cb4-4-6f95db54d4"><a href="#cb4-4-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="st">&#39;a&#39;</span>, <span class="st">&#39;b&#39;</span>]</span>
<span id="cb4-5-6f95db54d4"><a href="#cb4-5-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(s)</span>
<span id="cb4-6-6f95db54d4"><a href="#cb4-6-6f95db54d4"></a><span class="dv">1695325453248</span></span></code></pre></div>
<p>Notice that the ids are different, indicating that <code>s</code> refers to a new object.</p>
<p>Contrast this with using a mutating <code>list</code> method like <code>list.append</code>:</p>
<div class="sourceCode" id="cb5-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-6f95db54d4"><a href="#cb5-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>]</span>
<span id="cb5-2-6f95db54d4"><a href="#cb5-2-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.append(s, <span class="dv">3</span>)</span></code></pre></div>
<div class="fullwidth image-table">
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Before mutation</th>
<th style="text-align: left;">After mutation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><img src="images/mutation1.png" alt="Before mutation" /></td>
<td style="text-align: left;"><img src="images/mutation2.png" alt="After mutation" /></td>
</tr>
</tbody>
</table>
</div>
<p>In this case, no new <code>list</code> object is created, though a new <code>int</code> object is. Instead, the list object <code>[1, 2]</code> is mutated, and a third id is added at its end. Note that even changing the lists size doesnt change its id! Again, we can verify that <code>x</code> refers to the same <code>list</code> object by inspecting ids:</p>
<div class="sourceCode" id="cb6-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-6f95db54d4"><a href="#cb6-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>]</span>
<span id="cb6-2-6f95db54d4"><a href="#cb6-2-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(s)</span>
<span id="cb6-3-6f95db54d4"><a href="#cb6-3-6f95db54d4"></a><span class="dv">1695325453760</span></span>
<span id="cb6-4-6f95db54d4"><a href="#cb6-4-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.append(s, <span class="dv">3</span>)</span>
<span id="cb6-5-6f95db54d4"><a href="#cb6-5-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(s)</span>
<span id="cb6-6-6f95db54d4"><a href="#cb6-6-6f95db54d4"></a><span class="dv">1695325453760</span></span></code></pre></div>
<p>And finally, one last example that blends assignment and mutation: assigning to part of a compound data type. Consider this code:</p>
<div class="sourceCode" id="cb7-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-6f95db54d4"><a href="#cb7-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>]</span>
<span id="cb7-2-6f95db54d4"><a href="#cb7-2-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="dv">1</span>] <span class="op">=</span> <span class="dv">300</span></span></code></pre></div>
<p>What happens in this case?</p>
<div class="fullwidth image-table">
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Before mutation</th>
<th style="text-align: left;">After mutation</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><img src="images/mutation1.png" alt="Before mutation" /></td>
<td style="text-align: left;"><img src="images/mutation3.png" alt="After mutation" /></td>
</tr>
</tbody>
</table>
</div>
<p>The statement <code>s[1] = 300</code> is also a form of reassignment, but rather than reassigning a variable, it reassigns an id that is part of an object. This means that this statement <em>does</em> mutate an object, and doesnt reassign any variables. We can verify that the id of <code>s</code> doesnt change after the index assignment.</p>
<div class="sourceCode" id="cb8-6f95db54d4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-6f95db54d4"><a href="#cb8-1-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>]</span>
<span id="cb8-2-6f95db54d4"><a href="#cb8-2-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(s)</span>
<span id="cb8-3-6f95db54d4"><a href="#cb8-3-6f95db54d4"></a><span class="dv">1695325453760</span></span>
<span id="cb8-4-6f95db54d4"><a href="#cb8-4-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="dv">1</span>] <span class="op">=</span> <span class="dv">300</span></span>
<span id="cb8-5-6f95db54d4"><a href="#cb8-5-6f95db54d4"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(s)</span>
<span id="cb8-6-6f95db54d4"><a href="#cb8-6-6f95db54d4"></a><span class="dv">1695325453760</span></span></code></pre></div>
</section>
<br/> <a id="anchor-05-04"></a>
<header id="title-block-header-4c0ecbd79c">
<h1 class="title">5.4 Aliasing and “Mutation at a Distance”</h1>
</header>
<section>
<p>Through our new object-based memory model, weve seen that the Python interpreter associates each variable with the <em>id</em> of an object. There is nothing stopping two or more variables from containing the same id, which means that two variables can refer to the same object. This causes some interesting situations when more than one variable refers to the same mutable object. In this section, we will use our memory model to better understand this specific (and common) situation.</p>
<h2 id="aliasing-4c0ecbd79c">Aliasing</h2>
<p>Let <code>v1</code> and <code>v2</code> be Python variables. We saw that <code>v1</code> and <code>v2</code> are <strong>aliases</strong> when they refer to the same object.<label for="sn-0-4c0ecbd79c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-4c0ecbd79c" class="margin-toggle"/><span class="sidenote"> The word “alias” is commonly used when a person is also known under a different name. For example, we might say “Eric Blair, alias George Orwell.” We have two names for the same thing, in this case a person.</span></p>
<p>Consider the following Python code:</p>
<div class="sourceCode" id="cb1-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-4c0ecbd79c"><a href="#cb1-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb1-2-4c0ecbd79c"><a href="#cb1-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb1-3-4c0ecbd79c"><a href="#cb1-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z <span class="op">=</span> x</span></code></pre></div>
<p><code>x</code> and <code>z</code> are aliases, as they both reference the same object. As a result, they have the same id. You should think of the assignment statement <code>z = x</code> as saying “make <code>z</code> refer to the object that <code>x</code> refers to.” After doing so, they have the same id.</p>
<div class="sourceCode" id="cb2-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-4c0ecbd79c"><a href="#cb2-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(x)</span>
<span id="cb2-2-4c0ecbd79c"><a href="#cb2-2-4c0ecbd79c"></a><span class="dv">4401298824</span></span>
<span id="cb2-3-4c0ecbd79c"><a href="#cb2-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(z)</span>
<span id="cb2-4-4c0ecbd79c"><a href="#cb2-4-4c0ecbd79c"></a><span class="dv">4401298824</span></span></code></pre></div>
<p>In contrast, <code>x</code> and <code>y</code> are not aliases. They each refer to a <code>list</code> object with <code>[1, 2, 3]</code> as its value, but they are two different list objects, stored separately in your computers memory. This is again reflected in their different ids.</p>
<div class="sourceCode" id="cb3-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-4c0ecbd79c"><a href="#cb3-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(x)</span>
<span id="cb3-2-4c0ecbd79c"><a href="#cb3-2-4c0ecbd79c"></a><span class="dv">4401298824</span></span>
<span id="cb3-3-4c0ecbd79c"><a href="#cb3-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(y)</span>
<span id="cb3-4-4c0ecbd79c"><a href="#cb3-4-4c0ecbd79c"></a><span class="dv">4404546056</span></span></code></pre></div>
<p>Here is the state of memory after the code executes:</p>
<div class="fullscreen">
<p><img src="images/aliasing_intro.png" alt="Aliasing example. There are two different list objects. They have identical contents, but are distinct objects, each with their own id. There are three variables, x, y, and z. x and z both contain the same id, the id of one of the list objects. y contains the id of the other list object." /><br />
</p>
<h2 id="aliasing-and-mutation-4c0ecbd79c">Aliasing and mutation</h2>
<p>Aliasing is often a source of confusion for programmers because it allows “mutation at a distance”: the modification of a variables value without explicitly mentioning that variable. Heres an example:</p>
<div class="sourceCode" id="cb4-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-4c0ecbd79c"><a href="#cb4-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb4-2-4c0ecbd79c"><a href="#cb4-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb4-3-4c0ecbd79c"><a href="#cb4-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z <span class="op">=</span> x</span>
<span id="cb4-4-4c0ecbd79c"><a href="#cb4-4-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z[<span class="dv">0</span>] <span class="op">=</span> <span class="op">-</span><span class="dv">999</span></span>
<span id="cb4-5-4c0ecbd79c"><a href="#cb4-5-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="co"># What is the value?</span></span></code></pre></div>
<p>The statement <code>x[0] = -999</code> line mutates the value of <code>z</code>. But without ever mentioning <code>x</code>, it also mutates the value of <code>x</code>!</p>
<p>Imprecise language can lead us into misunderstanding the code. We said above that “the third line mutates the value of <code>z</code>”. To be more precise, the third line mutates the object that <code>z</code> refers to. Of course we can also say that it mutates the object that <code>x</code> refers to—they are the same object.</p>
<div class="fullwidth">
<p><img src="images/aliasing_mutation1.png" alt="Aliasing with mutation, first example" /><br />
</p>
</div>
<p>The key thing to notice about this example is that just by looking at the line of code, <code>z[0] = -999</code>, you cant tell that <code>x</code> has changed. You need to know that on a previous line, <code>z</code> was made an alias of <code>x</code>. This is why you have to be careful when aliasing occurs.</p>
<p>Contrast the previous code with this sequence of statements instead:</p>
<div class="sourceCode" id="cb5-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-4c0ecbd79c"><a href="#cb5-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb5-2-4c0ecbd79c"><a href="#cb5-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb5-3-4c0ecbd79c"><a href="#cb5-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z <span class="op">=</span> x</span>
<span id="cb5-4-4c0ecbd79c"><a href="#cb5-4-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y[<span class="dv">0</span>] <span class="op">=</span> <span class="op">-</span><span class="dv">999</span></span>
<span id="cb5-5-4c0ecbd79c"><a href="#cb5-5-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="co"># What is the value?</span></span></code></pre></div>
<p>Can you predict the value of <code>x</code> on the last line? Here, the third line mutates the object that <code>y</code> refers to, but because it is not the same object that <code>x</code> refers to, we still see <code>[1, 2, 3]</code> if we evaluate <code>x</code>. Heres the state of memory after these lines execute:</p>
<div class="fullwidth">
<p><img src="images/aliasing_mutation2.png" alt="Aliasing with mutation, second example" /><br />
</p>
</div>
<h2 id="variable-reassignment-again-4c0ecbd79c">Variable reassignment, again</h2>
<p>What if we did this instead?</p>
<div class="sourceCode" id="cb6-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-4c0ecbd79c"><a href="#cb6-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>)</span>
<span id="cb6-2-4c0ecbd79c"><a href="#cb6-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z <span class="op">=</span> x</span>
<span id="cb6-3-4c0ecbd79c"><a href="#cb6-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z <span class="op">=</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">40</span>)</span>
<span id="cb6-4-4c0ecbd79c"><a href="#cb6-4-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="co"># What is the value?</span></span></code></pre></div>
<p>Again, we have made <code>x</code> and <code>z</code> refer to the same object. So when we change <code>z</code> on the third line, does <code>x</code> also change? This time, the answer is an emphatic <strong>no</strong>, and it is because of the kind of change we make on the third line. Instead of mutating the object that <code>z</code> refers to, we reassign <code>z</code> refer to a new object. This obviously can have no effect on the object that <code>x</code> refers to (or <em>any</em> object). Even if we switched the example from using immutable tuples to using mutable lists, <code>x</code> would be unchanged.</p>
<p>Given two aliases <code>x</code> and <code>z</code>, if we reassign <code>x</code> to a new object, that has <em>no effect</em> on <code>z</code>. We say that reassigning <code>x</code> <em>breaks the aliasing</em>, as afterwards <code>x</code> and <code>z</code> no longer refer to the same object, and so are no longer aliases.</p>
<h2 id="aliasing-and-loop-variables-4c0ecbd79c">Aliasing and loop variables</h2>
<p>In Chapter 4, we saw two types of loops: element-based and index-based for loops. With index-based loops, the loop variable referred to an integer object that could be used as an index to a collection (typically a <code>list</code>). But in element-based for loops, the loop variable is an alias to one of the objects <em>within</em> the collection. Suppose we have the following element-based for loop:</p>
<div class="sourceCode" id="cb7-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-4c0ecbd79c"><a href="#cb7-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> numbers <span class="op">=</span> [<span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>]</span>
<span id="cb7-2-4c0ecbd79c"><a href="#cb7-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb7-3-4c0ecbd79c"><a href="#cb7-3-4c0ecbd79c"></a>... number <span class="op">=</span> number <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb7-4-4c0ecbd79c"><a href="#cb7-4-4c0ecbd79c"></a>...</span>
<span id="cb7-5-4c0ecbd79c"><a href="#cb7-5-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> numbers</span>
<span id="cb7-6-4c0ecbd79c"><a href="#cb7-6-4c0ecbd79c"></a>[<span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>]</span></code></pre></div>
<p>Notice how the values in the list <code>numbers</code> did not change (i.e., the for loop did not mutate <code>numbers</code>). This is because the loop variable <code>number</code> is an alias for the integer objects found inside <code>numbers</code>. The assignment statement inside the for loop simply changes what the loop variable refers to, but does not change what the contents of the list <code>numbers</code> refers to. If we would like to increment each object contained in the list, we must use an index-based for loop:</p>
<div class="sourceCode" id="cb8-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-4c0ecbd79c"><a href="#cb8-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> numbers</span>
<span id="cb8-2-4c0ecbd79c"><a href="#cb8-2-4c0ecbd79c"></a>[<span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>]</span>
<span id="cb8-3-4c0ecbd79c"><a href="#cb8-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(numbers)):</span>
<span id="cb8-4-4c0ecbd79c"><a href="#cb8-4-4c0ecbd79c"></a>... numbers[i] <span class="op">=</span> numbers[i] <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb8-5-4c0ecbd79c"><a href="#cb8-5-4c0ecbd79c"></a>...</span>
<span id="cb8-6-4c0ecbd79c"><a href="#cb8-6-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> numbers</span>
<span id="cb8-7-4c0ecbd79c"><a href="#cb8-7-4c0ecbd79c"></a>[<span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>]</span></code></pre></div>
<p>The assignment statement in the index-based for loop is fundamentally different from the assignment statement in the element-based for loop. Statements of the form <code>&lt;name&gt; = _______</code> are <em>reassign</em> the variable <code>&lt;name&gt;</code> to a new value. But assignment statements of the form <code>&lt;name&gt;[&lt;index&gt;] = ______</code> <em>mutate</em> the list object that <code>&lt;name&gt;</code> currently refers to.</p>
<h2 id="two-types-of-equality-4c0ecbd79c">Two types of equality</h2>
<p>Lets look one more time at this code:</p>
<div class="sourceCode" id="cb9-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-4c0ecbd79c"><a href="#cb9-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb9-2-4c0ecbd79c"><a href="#cb9-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb9-3-4c0ecbd79c"><a href="#cb9-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z <span class="op">=</span> x</span>
<span id="cb9-4-4c0ecbd79c"><a href="#cb9-4-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(x)</span>
<span id="cb9-5-4c0ecbd79c"><a href="#cb9-5-4c0ecbd79c"></a><span class="dv">4401298824</span></span>
<span id="cb9-6-4c0ecbd79c"><a href="#cb9-6-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(y)</span>
<span id="cb9-7-4c0ecbd79c"><a href="#cb9-7-4c0ecbd79c"></a><span class="dv">4404546056</span></span>
<span id="cb9-8-4c0ecbd79c"><a href="#cb9-8-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(z)</span>
<span id="cb9-9-4c0ecbd79c"><a href="#cb9-9-4c0ecbd79c"></a><span class="dv">4401298824</span></span></code></pre></div>
<p>What if we wanted to see whether <code>x</code> and <code>y</code>, for instance, were the same? Well, wed need to define precisely what we mean by “the same”. Our familiar <code>==</code> operator checks whether two objects have the same <em>value</em>. This is called <strong>value equality</strong>.</p>
<div class="sourceCode" id="cb10-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-4c0ecbd79c"><a href="#cb10-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">==</span> y</span>
<span id="cb10-2-4c0ecbd79c"><a href="#cb10-2-4c0ecbd79c"></a><span class="va">True</span></span>
<span id="cb10-3-4c0ecbd79c"><a href="#cb10-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">==</span> z</span>
<span id="cb10-4-4c0ecbd79c"><a href="#cb10-4-4c0ecbd79c"></a><span class="va">True</span></span></code></pre></div>
<p>But there is another Python operator, <code>is</code>, which checks whether two objects have the same <em>ids</em>. This is called <strong>identity equality</strong>.</p>
<div class="sourceCode" id="cb11-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-4c0ecbd79c"><a href="#cb11-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="kw">is</span> y</span>
<span id="cb11-2-4c0ecbd79c"><a href="#cb11-2-4c0ecbd79c"></a><span class="va">False</span></span>
<span id="cb11-3-4c0ecbd79c"><a href="#cb11-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="kw">is</span> z</span>
<span id="cb11-4-4c0ecbd79c"><a href="#cb11-4-4c0ecbd79c"></a><span class="va">True</span></span></code></pre></div>
<p>Identity equality is a <em>stronger</em> property than value equality: for all objects <code>a</code> and <code>b</code>, if <code>a is b</code> then <code>a == b</code>.<label for="sn-1-4c0ecbd79c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-4c0ecbd79c" class="margin-toggle"/><span class="sidenote"> In Python it is technically possible to change the behaviour of <code>==</code> in unexpected ways (like always returning <code>False</code>), but this is a poor programming practice and we wont consider it in this course.</span> The converse is not true, as we see in the above example: <code>a == b</code> does not imply <code>a is b</code>.</p>
<h2 id="aliasing-with-immutable-data-types-4c0ecbd79c">Aliasing with immutable data types</h2>
<p>Aliasing also exists for immutable data types, but in this case there is never any “action at a distance”, precisely because immutable values can never change. In the example below, <code>x</code> and <code>z</code> are aliases of a tuple object. It is impossible to modify <code>x</code>s value by mutating the object <code>z</code> refers to, since we cant mutate tuples at all.</p>
<div class="sourceCode" id="cb12-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-4c0ecbd79c"><a href="#cb12-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>)</span>
<span id="cb12-2-4c0ecbd79c"><a href="#cb12-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z <span class="op">=</span> x</span>
<span id="cb12-3-4c0ecbd79c"><a href="#cb12-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> z[<span class="dv">0</span>] <span class="op">=</span> <span class="op">-</span><span class="dv">999</span></span>
<span id="cb12-4-4c0ecbd79c"><a href="#cb12-4-4c0ecbd79c"></a>Traceback (most recent call last):</span>
<span id="cb12-5-4c0ecbd79c"><a href="#cb12-5-4c0ecbd79c"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb12-6-4c0ecbd79c"><a href="#cb12-6-4c0ecbd79c"></a><span class="pp">TypeError</span>: <span class="st">&#39;tuple&#39;</span> <span class="bu">object</span> does <span class="kw">not</span> support item assignment</span></code></pre></div>
<h3 id="automatic-aliasing-of-some-immutable-objects-4c0ecbd79c">Automatic aliasing of (some) immutable objects</h3>
<p>The above discussion actually has a very interesting implication for how we reason about variables referring to immutable objects: <em>if two variables have the same immutable value, the programs behaviour does not depend on whether the two variables are aliases or not</em>.</p>
<p>For example, consider the following two code snippets:</p>
<table style="width:75%;">
<colgroup>
<col style="width: 37%" />
<col style="width: 37%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb13-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-4c0ecbd79c"><a href="#cb13-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>)</span>
<span id="cb13-2-4c0ecbd79c"><a href="#cb13-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>)</span>
<span id="cb13-3-4c0ecbd79c"><a href="#cb13-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> my_function(x, y)</span>
<span id="cb13-4-4c0ecbd79c"><a href="#cb13-4-4c0ecbd79c"></a><span class="dv">10</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb14-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-4c0ecbd79c"><a href="#cb14-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> (<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>)</span>
<span id="cb14-2-4c0ecbd79c"><a href="#cb14-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> x</span>
<span id="cb14-3-4c0ecbd79c"><a href="#cb14-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> my_function(x, y)</span>
<span id="cb14-4-4c0ecbd79c"><a href="#cb14-4-4c0ecbd79c"></a><span class="dv">10</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>These two code snippets will always behave the same way, regardless of what <code>my_function</code> actually does! Because <code>x</code> and <code>y</code> refer to immutable values, the behaviour of <code>my_function</code> depends only on the values of the object, and not their ids.</p>
<p>This allows the Python interpreter to save a bit of computer memory by not creating new objects for some immutable values. For example, every occurrence of the boolean value <code>True</code> refers to the same object:</p>
<div class="sourceCode" id="cb15-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-4c0ecbd79c"><a href="#cb15-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(<span class="va">True</span>)</span>
<span id="cb15-2-4c0ecbd79c"><a href="#cb15-2-4c0ecbd79c"></a><span class="dv">1734328640</span></span>
<span id="cb15-3-4c0ecbd79c"><a href="#cb15-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="va">True</span></span>
<span id="cb15-4-4c0ecbd79c"><a href="#cb15-4-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(<span class="va">True</span>)</span>
<span id="cb15-5-4c0ecbd79c"><a href="#cb15-5-4c0ecbd79c"></a><span class="dv">1734328640</span></span>
<span id="cb15-6-4c0ecbd79c"><a href="#cb15-6-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(<span class="dv">10</span> <span class="op">&gt;</span> <span class="dv">3</span>)</span>
<span id="cb15-7-4c0ecbd79c"><a href="#cb15-7-4c0ecbd79c"></a><span class="dv">1734328640</span></span>
<span id="cb15-8-4c0ecbd79c"><a href="#cb15-8-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(<span class="kw">not</span> <span class="va">False</span>)</span>
<span id="cb15-9-4c0ecbd79c"><a href="#cb15-9-4c0ecbd79c"></a><span class="dv">1734328640</span></span></code></pre></div>
<p>A bit more surprisingly, “small” integers are automatically aliased, while “large” integers are not:</p>
<div class="sourceCode" id="cb16-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1-4c0ecbd79c"><a href="#cb16-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">43</span></span>
<span id="cb16-2-4c0ecbd79c"><a href="#cb16-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> <span class="dv">43</span></span>
<span id="cb16-3-4c0ecbd79c"><a href="#cb16-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="kw">is</span> y</span>
<span id="cb16-4-4c0ecbd79c"><a href="#cb16-4-4c0ecbd79c"></a><span class="va">True</span></span>
<span id="cb16-5-4c0ecbd79c"><a href="#cb16-5-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(x)</span>
<span id="cb16-6-4c0ecbd79c"><a href="#cb16-6-4c0ecbd79c"></a><span class="dv">1734453840</span></span>
<span id="cb16-7-4c0ecbd79c"><a href="#cb16-7-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(y)</span>
<span id="cb16-8-4c0ecbd79c"><a href="#cb16-8-4c0ecbd79c"></a><span class="dv">1734453840</span></span>
<span id="cb16-9-4c0ecbd79c"><a href="#cb16-9-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> a <span class="op">=</span> <span class="dv">1000</span></span>
<span id="cb16-10-4c0ecbd79c"><a href="#cb16-10-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> b <span class="op">=</span> <span class="dv">1000</span></span>
<span id="cb16-11-4c0ecbd79c"><a href="#cb16-11-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> a <span class="kw">is</span> b</span>
<span id="cb16-12-4c0ecbd79c"><a href="#cb16-12-4c0ecbd79c"></a><span class="va">False</span></span>
<span id="cb16-13-4c0ecbd79c"><a href="#cb16-13-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(a)</span>
<span id="cb16-14-4c0ecbd79c"><a href="#cb16-14-4c0ecbd79c"></a><span class="dv">16727840</span></span>
<span id="cb16-15-4c0ecbd79c"><a href="#cb16-15-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">id</span>(b)</span>
<span id="cb16-16-4c0ecbd79c"><a href="#cb16-16-4c0ecbd79c"></a><span class="dv">16727856</span></span></code></pre></div>
<p>The other immutable data type where the Python interpret takes this object creation “shortcut” is with <em>some</em> string values:</p>
<div class="sourceCode" id="cb17-4c0ecbd79c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1-4c0ecbd79c"><a href="#cb17-1-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> name1 <span class="op">=</span> <span class="st">&#39;David&#39;</span></span>
<span id="cb17-2-4c0ecbd79c"><a href="#cb17-2-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> name2 <span class="op">=</span> <span class="st">&#39;David&#39;</span></span>
<span id="cb17-3-4c0ecbd79c"><a href="#cb17-3-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> name1 <span class="kw">is</span> name2</span>
<span id="cb17-4-4c0ecbd79c"><a href="#cb17-4-4c0ecbd79c"></a><span class="va">True</span></span>
<span id="cb17-5-4c0ecbd79c"><a href="#cb17-5-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> full_name1 <span class="op">=</span> <span class="st">&#39;David Liu&#39;</span></span>
<span id="cb17-6-4c0ecbd79c"><a href="#cb17-6-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> full_name2 <span class="op">=</span> <span class="st">&#39;David Liu&#39;</span></span>
<span id="cb17-7-4c0ecbd79c"><a href="#cb17-7-4c0ecbd79c"></a><span class="op">&gt;&gt;&gt;</span> full_name1 <span class="kw">is</span> full_name2</span>
<span id="cb17-8-4c0ecbd79c"><a href="#cb17-8-4c0ecbd79c"></a><span class="va">False</span></span></code></pre></div>
<p>The exact rules for when the Python interpreter does and does not take this shortcut are beyond the scope of this course, and actually change from one version of Python to the next. For the purpose of writing Python code and doing object comparisons, the bottom line is:</p>
<ul>
<li>For <em>boolean</em> values, use <code>is</code> to compare for equality.<label for="sn-2-4c0ecbd79c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-4c0ecbd79c" class="margin-toggle"/><span class="sidenote"> Though also keep in mind that you should never write <code>&lt;expr&gt; is True</code> or <code>&lt;expr&gt; is False</code>, since these are equivalent to the simpler <code>&lt;expr&gt;</code> and <code>not &lt;expr&gt;</code>, respectively.</span></li>
<li>For <em>non-boolean</em> <em>immutable</em> values, use <code>==</code> to compare for equality, as using <code>is</code> can lead to surprsing results.</li>
<li>For <em>mutable</em> values, use <code>==</code> to compare value equality (almost always what you want).</li>
<li>For <em>mutable</em> values, use <code>is</code> to check for aliasing (almost never what you want).</li>
</ul>
</section>
<br/> <a id="anchor-05-05"></a>
<header id="title-block-header-00012df2d9">
<h1 class="title">5.5 The Full Python Memory Model: Function Calls</h1>
</header>
<section>
<p>So far in this chapter, we have talked only about variables defined within the Python console. In <a href="../02-functions/03-function-scope.html">2.3 Local Variables and Function Scope</a>, we saw how to represent function scope in the value-based memory model using separate “tables of values” for each function call. In this section, well see how to represent function scope in the full Python memory model so that we can capture exactly how function scope works and impacts the variables we use throughout the lifetime of our programs.</p>
<h2 id="stack-frames-00012df2d9">Stack frames</h2>
<p>Suppose we define the following function, and then call it in the Python console:</p>
<div class="sourceCode" id="cb1-00012df2d9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-00012df2d9"><a href="#cb1-1-00012df2d9"></a><span class="kw">def</span> repeat(n: <span class="bu">int</span>, s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb1-2-00012df2d9"><a href="#cb1-2-00012df2d9"></a> message <span class="op">=</span> s <span class="op">*</span> n</span>
<span id="cb1-3-00012df2d9"><a href="#cb1-3-00012df2d9"></a> <span class="cf">return</span> message</span>
<span id="cb1-4-00012df2d9"><a href="#cb1-4-00012df2d9"></a></span>
<span id="cb1-5-00012df2d9"><a href="#cb1-5-00012df2d9"></a></span>
<span id="cb1-6-00012df2d9"><a href="#cb1-6-00012df2d9"></a><span class="co"># In the Python console</span></span>
<span id="cb1-7-00012df2d9"><a href="#cb1-7-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> count <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb1-8-00012df2d9"><a href="#cb1-8-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> word <span class="op">=</span> <span class="st">&#39;abc&#39;</span></span>
<span id="cb1-9-00012df2d9"><a href="#cb1-9-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> result <span class="op">=</span> repeat(count, word)</span></code></pre></div>
<p>Consider what the state of memory is when <code>repeat(count, word)</code> is called, <em>immediately before</em> the <code>return message</code> statement executes. Lets first recall how we would draw the <em>value-based</em> memory model for this point:</p>
<div class="memory-model-values">
<table>
<caption><code>__main__</code></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>count</code></td>
<td><code>3</code></td>
</tr>
<tr class="even">
<td><code>word</code></td>
<td><code>'abc'</code></td>
</tr>
</tbody>
</table>
<table>
<caption><mark><strong><code>repeat</code></strong></mark></caption>
<thead>
<tr class="header">
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>n</code></td>
<td><code>3</code></td>
</tr>
<tr class="even">
<td><code>s</code></td>
<td><code>'abc'</code></td>
</tr>
<tr class="odd">
<td><code>message</code></td>
<td><code>'abcabcabc'</code></td>
</tr>
</tbody>
</table>
</div>
</div>
<p>This memory model shows two tables, showing the variables defined in the Python console (<code>count</code>, <code>word</code>), and the variables local to the function <code>repeat</code> (<code>n</code>, <code>s</code>, and <code>message</code>).</p>
<p>Here is how we would translate this into a full Python memory model diagram:</p>
<p><img src="images/call_stack_repeat.png" alt="Memory model diagram showing __main__ and repeat" /><br />
</p>
<p>As with the diagrams we saw in the previous sections of this chapter, our variables are on the left side of the diagram, and the objects on the right. The variables are separated into two separate boxes, one for the Python console and one for the function call for <code>repeat</code>. All variables, regardless of which box theyre in, store only ids that refer to objects on the right-hand side. Notice that <code>count</code> and <code>n</code> are aliases, as are <code>word</code> and <code>s</code>.</p>
<p>Now that we have this full diagram, well introduce a more formal piece of terminology. Each “box” on the left-hand side of our diagram represents a <strong>stack frame</strong> (or just <strong>frame</strong> for short), which is a special data type used by the Python interpreter to keep track of the functions that have been called in a program, and the variables defined within each function. We call the collection of stack frames the <strong>function call stack</strong>.</p>
<p>Every time we call a function, the Python interpreter does the following:</p>
<ol type="1">
<li>Create a new stack frame and add it to the call stack.</li>
<li>Evaluate the arguments in the function call, yielding the ids of objects (one per argument). Each of these ids is assigned to the corresponding parameter, as an entry in the new stack frame.</li>
<li>Execute the body of the function.</li>
<li>When a return statement is executed in the function body, the id of the returned object is saved and the stack frame for the function call is removed from the call stack.</li>
</ol>
<h2 id="argument-passing-and-aliasing-00012df2d9">Argument passing and aliasing</h2>
<p>What we often call “parameter passing” is a special form of variable assignment in the Python interpreter. In the example above, when we called <code>repeat(count, word)</code>, it is as if we wrote</p>
<div class="sourceCode" id="cb2-00012df2d9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-00012df2d9"><a href="#cb2-1-00012df2d9"></a>n <span class="op">=</span> count</span>
<span id="cb2-2-00012df2d9"><a href="#cb2-2-00012df2d9"></a>s <span class="op">=</span> word</span></code></pre></div>
<p>before executing the body of the function.</p>
<p>This aliasing is what allows us to define functions that mutate their argument values, and have that effect persist after the function ends. Here is an example:</p>
<div class="sourceCode" id="cb3-00012df2d9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-00012df2d9"><a href="#cb3-1-00012df2d9"></a><span class="kw">def</span> emphasize(words: <span class="bu">list</span>[<span class="bu">str</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-2-00012df2d9"><a href="#cb3-2-00012df2d9"></a> <span class="co">&quot;&quot;&quot;Add emphasis to the end of a list of words.&quot;&quot;&quot;</span></span>
<span id="cb3-3-00012df2d9"><a href="#cb3-3-00012df2d9"></a> new_words <span class="op">=</span> [<span class="st">&#39;believe&#39;</span>, <span class="st">&#39;me!&#39;</span>]</span>
<span id="cb3-4-00012df2d9"><a href="#cb3-4-00012df2d9"></a> <span class="bu">list</span>.extend(words, new_words)</span>
<span id="cb3-5-00012df2d9"><a href="#cb3-5-00012df2d9"></a></span>
<span id="cb3-6-00012df2d9"><a href="#cb3-6-00012df2d9"></a></span>
<span id="cb3-7-00012df2d9"><a href="#cb3-7-00012df2d9"></a><span class="co"># In the Python console</span></span>
<span id="cb3-8-00012df2d9"><a href="#cb3-8-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> sentence <span class="op">=</span> [<span class="st">&#39;winter&#39;</span>, <span class="st">&#39;is&#39;</span>, <span class="st">&#39;coming&#39;</span>]</span>
<span id="cb3-9-00012df2d9"><a href="#cb3-9-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> emphasize(sentence)</span>
<span id="cb3-10-00012df2d9"><a href="#cb3-10-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> sentence</span>
<span id="cb3-11-00012df2d9"><a href="#cb3-11-00012df2d9"></a>[<span class="st">&#39;winter&#39;</span>, <span class="st">&#39;is&#39;</span>, <span class="st">&#39;coming&#39;</span>, <span class="st">&#39;believe&#39;</span>, <span class="st">&#39;me!&#39;</span>]</span></code></pre></div>
<p>When <code>emphasize(sentence)</code> is called in the Python console, this is the state of memory:</p>
<div class="fullwidth">
<p><img src="images/call_stack_mutation.png" alt="Memory model diagram for emphasize" /><br />
</p>
</div>
<p>In this case, <code>words</code> and <code>sentence</code> are aliases, and so mutating <code>words</code> within the function causes a change to occur in <code>__main__</code> as well.</p>
<p>On the other hand, consider what happens with this version of the function:</p>
<div class="sourceCode" id="cb4-00012df2d9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-00012df2d9"><a href="#cb4-1-00012df2d9"></a><span class="kw">def</span> emphasize_v2(words: <span class="bu">list</span>[<span class="bu">str</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb4-2-00012df2d9"><a href="#cb4-2-00012df2d9"></a> <span class="co">&quot;&quot;&quot;Add emphasis to the end of a list of words.&quot;&quot;&quot;</span></span>
<span id="cb4-3-00012df2d9"><a href="#cb4-3-00012df2d9"></a> new_words <span class="op">=</span> [<span class="st">&#39;believe&#39;</span>, <span class="st">&#39;me!&#39;</span>]</span>
<span id="cb4-4-00012df2d9"><a href="#cb4-4-00012df2d9"></a> words <span class="op">=</span> words <span class="op">+</span> new_words</span>
<span id="cb4-5-00012df2d9"><a href="#cb4-5-00012df2d9"></a></span>
<span id="cb4-6-00012df2d9"><a href="#cb4-6-00012df2d9"></a></span>
<span id="cb4-7-00012df2d9"><a href="#cb4-7-00012df2d9"></a><span class="co"># In the Python console</span></span>
<span id="cb4-8-00012df2d9"><a href="#cb4-8-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> sentence <span class="op">=</span> [<span class="st">&#39;winter&#39;</span>, <span class="st">&#39;is&#39;</span>, <span class="st">&#39;coming&#39;</span>]</span>
<span id="cb4-9-00012df2d9"><a href="#cb4-9-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> emphasize_v2(sentence)</span>
<span id="cb4-10-00012df2d9"><a href="#cb4-10-00012df2d9"></a><span class="op">&gt;&gt;&gt;</span> sentence</span>
<span id="cb4-11-00012df2d9"><a href="#cb4-11-00012df2d9"></a>[<span class="st">&#39;winter&#39;</span>, <span class="st">&#39;is&#39;</span>, <span class="st">&#39;coming&#39;</span>]</span></code></pre></div>
<p>After we call <code>emphasize_v2</code> in the Python console, the value of <code>sentence</code> is unchanged! To understand why, lets look at two memory model diagrams. The first shows the state of memory immediately after <code>new_words = ['believe', 'me!']</code> is executed:</p>
<div class="fullwidth">
<p><img src="images/call_stack_reassignment1.png" alt="Diagram of emphasize_v2 after new_words = [believe, me!]." /><br />
</p>
</div>
<p>The next statement to execute is <code>words = words + new_words</code>. The key to understanding the next diagram is to recall <em>variable reassignment</em>: the right-hand side (<code>words + new_words</code>) is evaluated, and then the resulting object id is assigned to <code>words</code>. <em>List concatenation with <code>+</code> creates a new list object</em>.</p>
<div class="fullwidth">
<p><img src="images/call_stack_reassignment2.png" alt="Diagram of emphasize_v2 after words = words + new_words." /><br />
</p>
</div>
<p>Notice that in this diagram, <code>words</code> and <code>sentence</code> are no longer aliases! Instead, <code>words</code> has been assigned to a new list object, but <code>sentence</code> has remained unchanged.<label for="sn-0-00012df2d9" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-00012df2d9" class="margin-toggle"/><span class="sidenote"> Remember the rule of variable reassignment: an assignment statement <code>&lt;name&gt; = ...</code> only changes what object the variable <code>&lt;name&gt;</code> refers to, but never changes any other variables.</span> This illustrates the importance of keeping variable reassignment and object mutation as distinct concepts. Even though the bodies of <code>emphasize</code> and <code>emphasize_v2</code> look very similar, the end result is very different: <code>emphasize</code> mutates its argument object, while <code>emphasize_v2</code> actually leaves it unchanged!</p>
</section>
<br/> <a id="anchor-05-06"></a>
<header id="title-block-header-781de3460f">
<h1 class="title">5.6 Testing Functions III: Testing Mutation</h1>
</header>
<section>
<p>The ability to mutate objects means that we have to be careful when writing functions that accept mutable types as parameters. In general, if a functions documentation does not specify that an object will be mutated, then it <strong>must not</strong> be mutated. How can we test that no mutation occured? And, for functions that intend to mutate an object, how can we test that the correct change occured? In this section, we will extend our study of writing tests to answer both of these questions.</p>
<h2 id="identifying-mutable-parameters-781de3460f">Identifying mutable parameters</h2>
<p>Consider the <code>squares</code> function we introduced at the beginning of the chapter:</p>
<div class="sourceCode" id="cb1-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-781de3460f"><a href="#cb1-1-781de3460f"></a><span class="kw">def</span> squares(nums: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">int</span>]:</span>
<span id="cb1-2-781de3460f"><a href="#cb1-2-781de3460f"></a> <span class="co">&quot;&quot;&quot;Return a list of the squares of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb1-3-781de3460f"><a href="#cb1-3-781de3460f"></a> squares_so_far <span class="op">=</span> []</span>
<span id="cb1-4-781de3460f"><a href="#cb1-4-781de3460f"></a></span>
<span id="cb1-5-781de3460f"><a href="#cb1-5-781de3460f"></a> <span class="cf">for</span> num <span class="kw">in</span> nums:</span>
<span id="cb1-6-781de3460f"><a href="#cb1-6-781de3460f"></a> <span class="bu">list</span>.append(squares_so_far, num <span class="op">*</span> num)</span>
<span id="cb1-7-781de3460f"><a href="#cb1-7-781de3460f"></a></span>
<span id="cb1-8-781de3460f"><a href="#cb1-8-781de3460f"></a> <span class="cf">return</span> squares_so_far</span></code></pre></div>
<p>There are two lists in <code>squares</code>: the <code>nums</code> parameter, which is an input to the function; and the <code>squares_so_far</code> variable, which is an output of the function. Because <code>squares_so_far</code> is created by the function <code>squares</code>, it is okay that it is mutated (i.e., the call to <code>list.append</code> inside the for loop). However, the <code>nums</code> list is passed as an argument to <code>squares</code>. Because the docstring does not indicate that <code>nums</code> will be mutated, it is expected that the <code>squares</code> function will not mutate the list object referred to by <code>nums</code>.</p>
<p>We can contrast this with how we would document and implement a similar function that <em>does</em> mutate its input:</p>
<div class="sourceCode" id="cb2-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-781de3460f"><a href="#cb2-1-781de3460f"></a><span class="kw">def</span> square_all(nums: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-2-781de3460f"><a href="#cb2-2-781de3460f"></a> <span class="co">&quot;&quot;&quot;Modify nums by squaring each of its elements.&quot;&quot;&quot;</span></span>
<span id="cb2-3-781de3460f"><a href="#cb2-3-781de3460f"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(nums)):</span>
<span id="cb2-4-781de3460f"><a href="#cb2-4-781de3460f"></a> nums[i] <span class="op">=</span> nums[i] <span class="op">*</span> nums[i]</span></code></pre></div>
<h2 id="testing-for-no-mutation-781de3460f">Testing for no mutation</h2>
<p>Let us write a test that ensures the <code>squares</code> function does not mutate the list referred to by <code>nums</code>:</p>
<div class="sourceCode" id="cb3-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-781de3460f"><a href="#cb3-1-781de3460f"></a><span class="kw">def</span> test_squares_no_mutation() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-2-781de3460f"><a href="#cb3-2-781de3460f"></a> <span class="co">&quot;&quot;&quot;Confirm that squares does not mutate the list it is given.</span></span>
<span id="cb3-3-781de3460f"><a href="#cb3-3-781de3460f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-4-781de3460f"><a href="#cb3-4-781de3460f"></a> lst <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb3-5-781de3460f"><a href="#cb3-5-781de3460f"></a> squares(lst)</span>
<span id="cb3-6-781de3460f"><a href="#cb3-6-781de3460f"></a></span>
<span id="cb3-7-781de3460f"><a href="#cb3-7-781de3460f"></a> <span class="co"># </span><span class="al">TODO</span><span class="co">: complete the test</span></span></code></pre></div>
<p>In order to test that a list is not mutated, we first create a list <code>lst</code>. Second, we call the <code>squares</code> function on <code>lst</code>; note that this function call returns a list of squares, but we do not assign the result to a variable because we dont actually care about the returned value for the purpose of this test.<label for="sn-0-781de3460f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-781de3460f" class="margin-toggle"/><span class="sidenote"> This might seem a bit strange, as all of our tests so far have been about checking the return value of the function being tested. In practice, we would have such unit/property-based tests for <code>squares</code> as well, we just arent showing them here.</span> We can now add an assertion that ensures <code>lst</code> has not been mutated:</p>
<div class="sourceCode" id="cb4-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-781de3460f"><a href="#cb4-1-781de3460f"></a><span class="kw">def</span> test_squares_no_mutation() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb4-2-781de3460f"><a href="#cb4-2-781de3460f"></a> <span class="co">&quot;&quot;&quot;Test that squares does not mutate the list it is given.</span></span>
<span id="cb4-3-781de3460f"><a href="#cb4-3-781de3460f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-4-781de3460f"><a href="#cb4-4-781de3460f"></a> lst <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb4-5-781de3460f"><a href="#cb4-5-781de3460f"></a> squares(lst)</span>
<span id="cb4-6-781de3460f"><a href="#cb4-6-781de3460f"></a></span>
<span id="cb4-7-781de3460f"><a href="#cb4-7-781de3460f"></a> <span class="cf">assert</span> lst <span class="op">==</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span></code></pre></div>
<p>The variable <code>lst</code> originally had value <code>[1, 2, 3]</code>. So our assertion checks that <em>after</em> the call to <code>squares</code>, <code>lst</code> still has value <code>[1, 2, 3]</code>. Another way to accomplish this, without re-typing the list value, is by creating a copy of <code>lst</code> before the call to <code>squares</code>. We can do this using the <code>list.copy</code> method:</p>
<div class="sourceCode" id="cb5-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-781de3460f"><a href="#cb5-1-781de3460f"></a><span class="kw">def</span> test_squares_no_mutation() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb5-2-781de3460f"><a href="#cb5-2-781de3460f"></a> <span class="co">&quot;&quot;&quot;Test that squares does not mutate the list it is given.</span></span>
<span id="cb5-3-781de3460f"><a href="#cb5-3-781de3460f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-4-781de3460f"><a href="#cb5-4-781de3460f"></a> lst <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb5-5-781de3460f"><a href="#cb5-5-781de3460f"></a> lst_copy <span class="op">=</span> <span class="bu">list</span>.copy(lst) <span class="co"># Create a copy of lst (not an alias!)</span></span>
<span id="cb5-6-781de3460f"><a href="#cb5-6-781de3460f"></a> squares(lst)</span>
<span id="cb5-7-781de3460f"><a href="#cb5-7-781de3460f"></a></span>
<span id="cb5-8-781de3460f"><a href="#cb5-8-781de3460f"></a> <span class="cf">assert</span> lst <span class="op">==</span> lst_copy</span></code></pre></div>
<p>Note that the order of statements is very important when testing for mutation. We need to create the list and its copy before the call to <code>squares</code>. And we need to test for mutation (i.e., the assertion) after the call to <code>squares</code>.</p>
<h3 id="generalizing-this-test-781de3460f">Generalizing this test</h3>
<p>You might notice that the above <code>test_squares_no_mutation</code> test function doesnt actually use the specific elements of the list <code>lst</code>. That is, if we replaced <code>lst</code>s value with another list, the test would behave in the exact same way. That makes this test very suitable to be generalized into a <em>property-based test</em>, representing the following property:</p>
<blockquote>
<p>For all lists of integers <code>lst</code>, calling <code>squares(lst)</code> does not mutate <code>lst</code>.</p>
</blockquote>
<p>Here is how we could implement such a property-based test using the technique we learned in <a href="../03-logic/10-testing-fucntions-2.html">3.10 Testing Functions II: <code>hypothesis</code></a>.<label for="sn-1-781de3460f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-781de3460f" class="margin-toggle"/><span class="sidenote"> Weve included the import statements to remind you about the ones from <code>hypothesis</code> you need for property-based tests.</span></p>
<div class="sourceCode" id="cb6-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-781de3460f"><a href="#cb6-1-781de3460f"></a><span class="im">from</span> hypothesis <span class="im">import</span> given</span>
<span id="cb6-2-781de3460f"><a href="#cb6-2-781de3460f"></a><span class="im">from</span> hypothesis.strategies <span class="im">import</span> lists, integers</span>
<span id="cb6-3-781de3460f"><a href="#cb6-3-781de3460f"></a></span>
<span id="cb6-4-781de3460f"><a href="#cb6-4-781de3460f"></a></span>
<span id="cb6-5-781de3460f"><a href="#cb6-5-781de3460f"></a><span class="at">@given</span>(lst<span class="op">=</span>lists(integers()))</span>
<span id="cb6-6-781de3460f"><a href="#cb6-6-781de3460f"></a><span class="kw">def</span> test_squares_no_mutation_general(lst: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-7-781de3460f"><a href="#cb6-7-781de3460f"></a> <span class="co">&quot;&quot;&quot;Test that squares does not mutate the list it is given.</span></span>
<span id="cb6-8-781de3460f"><a href="#cb6-8-781de3460f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb6-9-781de3460f"><a href="#cb6-9-781de3460f"></a> lst_copy <span class="op">=</span> <span class="bu">list</span>.copy(lst) <span class="co"># Create a copy of lst (not an alias!)</span></span>
<span id="cb6-10-781de3460f"><a href="#cb6-10-781de3460f"></a> squares(lst)</span>
<span id="cb6-11-781de3460f"><a href="#cb6-11-781de3460f"></a></span>
<span id="cb6-12-781de3460f"><a href="#cb6-12-781de3460f"></a> <span class="cf">assert</span> lst <span class="op">==</span> lst_copy</span></code></pre></div>
<h2 id="testing-for-mutation-781de3460f">Testing for mutation</h2>
<p>Now lets consider testing the <code>square_all</code> function. One common error students make when writing tests for mutating functions is to check the return value of the function.</p>
<div class="sourceCode" id="cb7-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-781de3460f"><a href="#cb7-1-781de3460f"></a><span class="kw">def</span> test_square_all() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb7-2-781de3460f"><a href="#cb7-2-781de3460f"></a> <span class="co">&quot;&quot;&quot;Test that square_all mutates the list it is given correctly.</span></span>
<span id="cb7-3-781de3460f"><a href="#cb7-3-781de3460f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb7-4-781de3460f"><a href="#cb7-4-781de3460f"></a> lst <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb7-5-781de3460f"><a href="#cb7-5-781de3460f"></a> result <span class="op">=</span> square_all(lst)</span>
<span id="cb7-6-781de3460f"><a href="#cb7-6-781de3460f"></a></span>
<span id="cb7-7-781de3460f"><a href="#cb7-7-781de3460f"></a> <span class="cf">assert</span> result <span class="op">==</span> [<span class="dv">1</span>, <span class="dv">4</span>, <span class="dv">9</span>]</span></code></pre></div>
<p>This test fails because <code>square_all</code> returns <code>None</code>, and <code>None == [1, 4, 9]</code> is False. Using <code>result</code> in our assertion is not useful for testing if <code>lst</code> was mutated. Instead, we must test if the value of <code>lst</code> has changed:<label for="sn-2-781de3460f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-781de3460f" class="margin-toggle"/><span class="sidenote"> Like <code>test_squares_no_mutation</code>, this test does not store the return value of the function being tested. But the reason is quite different!</span></p>
<div class="sourceCode" id="cb8-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-781de3460f"><a href="#cb8-1-781de3460f"></a><span class="kw">def</span> test_square_all_mutation() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb8-2-781de3460f"><a href="#cb8-2-781de3460f"></a> <span class="co">&quot;&quot;&quot;Test that square_all mutates the list it is given correctly.</span></span>
<span id="cb8-3-781de3460f"><a href="#cb8-3-781de3460f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb8-4-781de3460f"><a href="#cb8-4-781de3460f"></a> lst <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb8-5-781de3460f"><a href="#cb8-5-781de3460f"></a> square_all(lst)</span>
<span id="cb8-6-781de3460f"><a href="#cb8-6-781de3460f"></a></span>
<span id="cb8-7-781de3460f"><a href="#cb8-7-781de3460f"></a> <span class="cf">assert</span> lst <span class="op">==</span> [<span class="dv">1</span>, <span class="dv">4</span>, <span class="dv">9</span>]</span></code></pre></div>
<p>We can again generalize this test into a property-based test by storing a copy of the original list and verifying the relationship between corresponding elements. Well leave it as an exercise for you to read through and understand the following property-based test:</p>
<div class="sourceCode" id="cb9-781de3460f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-781de3460f"><a href="#cb9-1-781de3460f"></a><span class="at">@given</span>(lst<span class="op">=</span>lists(integers()))</span>
<span id="cb9-2-781de3460f"><a href="#cb9-2-781de3460f"></a><span class="kw">def</span> test_square_all_mutation_general(lst: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb9-3-781de3460f"><a href="#cb9-3-781de3460f"></a> <span class="co">&quot;&quot;&quot;Test that square_all mutates the list it is given correctly.</span></span>
<span id="cb9-4-781de3460f"><a href="#cb9-4-781de3460f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb9-5-781de3460f"><a href="#cb9-5-781de3460f"></a> lst_copy <span class="op">=</span> <span class="bu">list</span>.copy(lst)</span>
<span id="cb9-6-781de3460f"><a href="#cb9-6-781de3460f"></a> square_all(lst)</span>
<span id="cb9-7-781de3460f"><a href="#cb9-7-781de3460f"></a></span>
<span id="cb9-8-781de3460f"><a href="#cb9-8-781de3460f"></a> <span class="cf">assert</span> <span class="bu">all</span>({lst[i] <span class="op">==</span> lst_copy[i] <span class="op">**</span> <span class="dv">2</span> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(lst))})</span></code></pre></div>
</section>
<br/>
<h2 class="unnumbered" id="formal-proofs">6. Formal Proofs</h2>
<a id="anchor-06-01"></a>
<header id="title-block-header-5c5c5ed880">
<h1 class="title">6.1 An Introduction to Number Theory</h1>
</header>
<section>
<p>Weve spent the first five chapters of this course studying programming in Python. Weve been mainly focused on how we represent data and designing functions to operate on this data. Up to this point, the <em>ideas</em> behind the functions that weve written have been relatively straight-forward, and the challenge has been in implementing these ideas correctly using various programming techniques. Over the next two chapters, we are going to study algorithms where the ideas themselves will be more complex. It wont be “obvious” how or why these algorithms work, and so to convince ourselves that these algorithms are correct, well study the formal mathematics behind them.</p>
<p>Our first large example of this is one that will take us the next two chapters to develop: the RSA cryptosystem, consisting of a pair of algorithms that are central to modern Internet security. If you havent heard about RSA, cryptosystems, or ever thought about security, dont worry, well be building all of these concepts from the ground up over the course of this chapter and the next. What will set this apart from the kind of work weve done so far is that to understand what these algorithms do and why they work, well need to step away from code and into the realm of <em>number theory</em>, the branch of mathematics concerned with properties of integers.</p>
<p>Well start our journey here with a few key definitions, some of which youve seen before defined formally in this course, and others that you might have heard about before, but not seen a formal definition.</p>
<h2 id="divisibility-primality-and-the-greatest-common-divisor-5c5c5ed880">Divisibility, primality, and the greatest common divisor</h2>
<p>Here are our first two definitions; these are repeated from <a href="../03-logic/09-working-with-definitions.html">3.9 Working with Definitions</a>.</p>
<div class="definition" data-terms="divides, divisible, factor, multiple">
<p>Let <span class="math inline">\(n, d \in \Z\)</span>. We say that <span class="math inline">\(d\)</span> <strong>divides</strong> <span class="math inline">\(n\)</span> when there exists a <span class="math inline">\(k \in \Z\)</span> such that <span class="math inline">\(n = dk\)</span>. We use the notation <span class="math inline">\(d \mid n\)</span> to represent the statement “<span class="math inline">\(d\)</span> divides <span class="math inline">\(n\)</span>”.</p>
<p>The following phrases are synonymous with “<span class="math inline">\(d\)</span> divides <span class="math inline">\(n\)</span>”:</p>
<ul>
<li><span class="math inline">\(n\)</span> <strong>is divisible by</strong> <span class="math inline">\(d\)</span></li>
<li><span class="math inline">\(d\)</span> is a <strong>factor</strong> of <span class="math inline">\(n\)</span></li>
<li><span class="math inline">\(n\)</span> is a <strong>multiple</strong> of <span class="math inline">\(d\)</span></li>
</ul>
</div>
<div class="definition" data-terms="prime">
<p>Let <span class="math inline">\(p \in \Z\)</span>. We say <span class="math inline">\(p\)</span> is <strong>prime</strong> when it is greater than 1 and the only natural numbers that divide it are 1 and itself.</p>
</div>
<p>The next few definitions introduce and expand on the notion of common divisors between two numbers.</p>
<div class="definition" data-terms="common divisor, greatest common divisor">
<p>Let <span class="math inline">\(x, y, d \in \Z\)</span>. We say that <span class="math inline">\(d\)</span> is a <strong>common divisor</strong> of <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> when <span class="math inline">\(d\)</span> divides <span class="math inline">\(x\)</span> and <span class="math inline">\(d\)</span> divides <span class="math inline">\(y\)</span>.</p>
<p>We say that <span class="math inline">\(d\)</span> is the <strong>greatest common divisor</strong> of <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> when it the largest number that is a common divisor of <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span>, or 0 when <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> are both 0.<label for="sn-0-5c5c5ed880" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-5c5c5ed880" class="margin-toggle"/><span class="sidenote">According to this definition, what is <span class="math inline">\(\gcd(0, n)\)</span> when <span class="math inline">\(n &gt; 0\)</span>?</span> We can define the function <span class="math inline">\(\gcd : \Z \times \Z \to \N\)</span> as the function which takes numbers <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span>, and returns their greatest common divisor.</p>
</div>
<p>You might wonder whether this definition makes sense in all cases: is it possible for two numbers to have no divisors in common? One of the statements we will prove later in this chapter is that <span class="math inline">\(1\)</span> divides every natural number. So at the very least, <span class="math inline">\(1\)</span> is a common divisor between any two natural numbers. There is a special case, when <span class="math inline">\(1\)</span> is the <em>only</em> positive divisor between two numbers.</p>
<div class="definition" data-terms="coprime">
<p>Let <span class="math inline">\(m, n \in \Z\)</span>. We say that <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span> are <strong>coprime</strong> when <span class="math inline">\(\gcd(m, n) = 1\)</span>.</p>
</div>
<h2 id="quotients-and-remainders-5c5c5ed880">Quotients and remainders</h2>
<p>The next definitions are introduced through a fundamental theorem in number theory, which extends the relationship of divisibility to that of remainders.</p>
<div id="Quotient-Remainder Theorem-5c5c5ed880" class="theorem">
<p>(Quotient-Remainder Theorem) For all <span class="math inline">\(n \in \Z\)</span> and <span class="math inline">\(d \in \Z^+\)</span>, there exist <span class="math inline">\(q \in \Z\)</span> and <span class="math inline">\(r \in \N\)</span> such that <span class="math inline">\(n = qd + r\)</span> and <span class="math inline">\(0 \leq r &lt; d\)</span>. Moreover, these <span class="math inline">\(q\)</span> and <span class="math inline">\(r\)</span> are <em>unique</em> for a given <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>.</p>
<p>We say that <span class="math inline">\(q\)</span> is the <strong>quotient</strong> when <span class="math inline">\(n\)</span> is divided by <span class="math inline">\(d\)</span>, and that <span class="math inline">\(r\)</span> is the <strong>remainder</strong> when <span class="math inline">\(n\)</span> is divided by <span class="math inline">\(d\)</span>.</p>
</div>
<p>In Python, for given integers <code>n</code> and <code>d</code>, we can compute their quotient using <code>//</code>, their remainder using <code>%</code>, and both at the same time using the built-in function <code>divmod</code>:</p>
<div class="sourceCode" id="cb1-5c5c5ed880"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-5c5c5ed880"><a href="#cb1-1-5c5c5ed880"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">9</span> <span class="op">//</span> <span class="dv">2</span></span>
<span id="cb1-2-5c5c5ed880"><a href="#cb1-2-5c5c5ed880"></a><span class="dv">4</span></span>
<span id="cb1-3-5c5c5ed880"><a href="#cb1-3-5c5c5ed880"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">9</span> <span class="op">%</span> <span class="dv">2</span></span>
<span id="cb1-4-5c5c5ed880"><a href="#cb1-4-5c5c5ed880"></a><span class="dv">1</span></span>
<span id="cb1-5-5c5c5ed880"><a href="#cb1-5-5c5c5ed880"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">divmod</span>(<span class="dv">9</span>, <span class="dv">2</span>)</span>
<span id="cb1-6-5c5c5ed880"><a href="#cb1-6-5c5c5ed880"></a>(<span class="dv">4</span>, <span class="dv">1</span>)</span></code></pre></div>
<h2 id="modular-arithmetic-5c5c5ed880">Modular arithmetic</h2>
<p>The final definition in this section introduces some notation that is extremely commonplace in number theory, and by extension in many areas of computer science. Often when we are dealing with relationships between numbers, divisibility is too coarse a relationship: as a predicate, it is constrained by the binary nature of its output. Instead, we often care about the <em>remainder</em> when we divide a number by another.</p>
<div class="definition" data-terms="modular equivalence">
<p>Let <span class="math inline">\(a, b, n \in \Z\)</span> and assume <span class="math inline">\(n \neq 0\)</span>. We say that <span class="math inline">\(a\)</span> is <strong>equivalent to <span class="math inline">\(b\)</span> modulo <span class="math inline">\(n\)</span></strong> when <span class="math inline">\(n \mid a - b\)</span>. In this case, we write <span class="math inline">\(a \equiv b \pmod n\)</span>.<label for="sn-1-5c5c5ed880" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-5c5c5ed880" class="margin-toggle"/><span class="sidenote">One warning: the notation <span class="math inline">\(a \equiv b \MOD n\)</span> is not exactly the same as <code>mod</code> or <code>%</code> operator you are familiar with from programming; here, both <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> could be much larger than <span class="math inline">\(n\)</span>, or even negative.</span></p>
</div>
<p>There are two related reasons why this notation is so useful in number theory. The first is that modular equivalence can be used to divide up numbers based on their remainders when divided by <span class="math inline">\(n\)</span>:</p>
<div class="theorem">
<p>Let <span class="math inline">\(a, b, n \in \Z\)</span> with <span class="math inline">\(n \neq 0\)</span>. Then <span class="math inline">\(a \equiv b \pmod n\)</span> if and only if <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> have the same remainder when divided by <span class="math inline">\(n\)</span>.<label for="sn-2-5c5c5ed880" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-5c5c5ed880" class="margin-toggle"/><span class="sidenote"> In Python, we could represent this as the expression <code>a % n == b % n</code>.</span></p>
</div>
<p>The second reason this is so useful is that almost all of the “standard” intuitions we have about equality transfer over this new notation as well, making it pretty easy to work with right at the very start.</p>
<div class="theorem">
<p>Let <span class="math inline">\(a, b, c, n \in \Z\)</span> with <span class="math inline">\(n \neq 0\)</span>. Then the following hold:</p>
<ol type="1">
<li><span class="math inline">\(a \equiv a \pmod n\)</span>.</li>
<li>If <span class="math inline">\(a \equiv b \pmod n\)</span> then <span class="math inline">\(b \equiv a \pmod n\)</span>.</li>
<li>If <span class="math inline">\(a \equiv b \pmod n\)</span> and <span class="math inline">\(b \equiv c \pmod n\)</span> then <span class="math inline">\(a \equiv c \pmod n\)</span>.</li>
</ol>
</div>
<div class="theorem">
<p>Let <span class="math inline">\(a, b, c, d, n \in \Z\)</span> with <span class="math inline">\(n \neq 0\)</span>. If <span class="math inline">\(a \equiv c \pmod n\)</span> and <span class="math inline">\(b \equiv d \pmod n\)</span>, then the following hold:</p>
<ol type="1">
<li><span class="math inline">\(a + b \equiv c + d \pmod n\)</span>.</li>
<li><span class="math inline">\(a - b \equiv c - d \pmod n\)</span>.</li>
<li><span class="math inline">\(a b \equiv c d \pmod n\)</span>.</li>
</ol>
</div>
<p>Note that this second theorem shows that the familiar addition, subtraction, and multiplication operations preserve modular equivalence relationships. However, as well study further in this chapter, this is <em>not</em> the case with division!</p>
</section>
<br/> <a id="anchor-06-02"></a>
<header id="title-block-header-06d807034a">
<h1 class="title">6.2 Proofs with Number Theory</h1>
</header>
<section>
<p>In Chapter 3, we studied how to express statements precisely using the language of predicate logic. But just as English enables us to make both true and false claims, the language of predicate logic allows for the expression of both true and false sentences. In this chapter, we will turn our attention to analyzing and communicating the truth or falsehood of these statements. You will develop the skills required to answer the following questions:</p>
<ul>
<li>How can you figure out if a given statement is True or False?</li>
<li>If you know a statement is True, how can you convince others that it is True? How can you do the same if you know the statement is False instead?</li>
<li>If someone gives you an explanation of why a statement is True, how do you know whether to believe them or not?</li>
</ul>
<p>These questions draw a distinction between the internal and external components of mathematical reasoning. When given a new statement, youll first need to figure out for yourself whether it is true (internal), and then be able to express your thought process to others (external). But even though we make a separation, these two processes are certainly connected: it is only after convincing yourself that a statement is true that you should then try to convince others. And often in the process of formalizing your intuition for others, you notice an error or gap in your reasoning that causes you to revisit your intuition—or make you question whether the statement is actually true!</p>
<p>A <strong>mathematical proof</strong> is how we communicate ideas about the truth or falsehood of a statement to others. There are many different philosophical ideas about what constitutes a proof, but what they all have in common is that a proof is a mode of <em>communication</em>, from the person creating the proof to the person digesting it. In this course, we will focus on reading and creating our own written mathematical proofs, which is the standard proof medium in computer science.</p>
<p>As with all forms of communication, the style and content of a proof varies depending on the audience. In this course, the audience for all of our proofs will be an average computer science student (and not your TA or instructor). As we will discuss, your audience determines how formal a proof should be (here, quite formal), and what background knowledge you can assume is understood without explanation (here, not much).</p>
<p>However, there is even variation in the typical computer science student with experience in this area, so as much as possible in this course, we will introduce <em>new mathematical domains</em> to serve as the objects of study in our proofs.</p>
<p>This approach has three very nice benefits: first, by building domains from the ground up, we can specify absolutely the common definitions and properties that everyone may assume and use freely in proofs; second, these domains are the theoretical foundation of many areas of computer science, and learning about them here will serve you well in many future courses; and third, learning about new domains will help develop the skill of <em>reading about a new mathematical context and understanding it</em>.<label for="sn-0-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-06d807034a" class="margin-toggle"/><span class="sidenote">In other words, you wont just learn about new domains; youll learn <em>how</em> to learn about new domains!</span> The definitions and axioms of a new domain communicate the foundation upon which we build new proofs—in order to prove things, we need to understand the objects that were talking about first.</p>
<h2 id="first-examples-06d807034a">First examples</h2>
<p>Were going to start out our exploration of proofs by studying a few simple statements. Our first foray into domain exploration will be into number theory, which you can think of as taking a type of entity with which we are quite familiar, and formalizing definitions and pushing the boundaries of what we actually know about these <em>numbers</em> that we use every day.</p>
<p>You may find our first few examples a bit on the easy side, which is fine. We are using them not so much for their ability to generate mathematical insight, but rather to model both the <em>thinking</em> and the <em>writing</em> that would go into approaching a problem.</p>
<p>Each example in this section is divided into three or four parts:</p>
<ol type="1">
<li>The statement that we want to prove or disprove. Sometimes, well specify whether to prove or disprove it, and other times deciding whether the statement is true or false is part of the exercise.</li>
<li>A translation of the statement into predicate logic. This step often provides insight into the <em>logical structure</em> of the statement that we are considering, which in turn informs the structure and techniques that we will use in our proofs.</li>
<li>A discussion to try to gain some intuition about why the statement is true. Youll tend to see that these are written very informally, as if we are talking to a friend on a whiteboard. The discussion usually will reveal the mathematical insight that forms the content of a proof. <strong>This is often the hardest part of developing a proof, so please dont skip these sections!</strong></li>
<li>A formal proof. This is meant to be a standalone piece of writing, the “final product” of our earlier work. Depending on the depth of the discussion, the formal proof might end up being almost mechanical a matter of formalizing our intuition.</li>
</ol>
<p>With this in mind, lets dive right in!</p>
<div class="example">
<p>Prove that <span class="math inline">\(23 \mid 115\)</span>.</p>
<div class="translation">
<p>We will <em>expand</em> the definition of divisibility to rewrite this statement in terms of simpler operations: <span class="math display">\[\exists k \in \Z,~ 115 = 23k.\]</span></p>
</div>
<div class="discussion">
<p>We just need to divide 115 by 23, right?</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(k = 5\)</span>.</p>
<p>Then <span class="math inline">\(115 = 23 \cdot 5 = 23 \cdot k\)</span>.<label for="sn-1-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-06d807034a" class="margin-toggle"/><span class="sidenote"> We typically signal the end of a proof by writing a black square ◼ in the bottom-right corner.</span></p>
</div>
</div>
<p>We can draw from this example a more general technique for structuring our existence proofs. A statement of the form <span class="math inline">\(\exists x \in S,~P(x)\)</span> is True when at least one element of <span class="math inline">\(S\)</span> satisfies <span class="math inline">\(P\)</span> (hence our use of <code>any</code> in Python). The easiest way to convince someone that this is True is to actually find the concrete element that satisfies <span class="math inline">\(P\)</span>, and then show that it does.<label for="sn-2-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-06d807034a" class="margin-toggle"/><span class="sidenote"> Of course, this is <em>not</em> the only proof technique used for existence proofs. Youll study more sophisticated ways of doing such proofs in future courses.</span> This is so natural a strategy that it should not be surprising that there is a “standard proof format” when dealing with such statements.</p>
<div class="framed">
<p><strong>A typical proof of an existential.</strong></p>
<p>Given statement to prove: <span class="math inline">\(\exists x \in S,~P(x)\)</span>.</p>
<div class="proof">
<p>Let <span class="math inline">\(x = \_\_\_\_\_\_\_\)</span>.</p>
<p>[Proof that <span class="math inline">\(P(\_\_\_\_\_\_\_)\)</span> is True.]</p>
</div>
</div>
<p>Note that the two blanks represent the same element of <span class="math inline">\(S\)</span>, which <em>you</em> get to choose as a prover. Thus existence proofs usually come down to <em>finding</em> a correct element of the domain which satisfy the required properties.</p>
<p>Here is another example which uses the same idea, but with two existentially-quantified variables.</p>
<div class="example">
<p>Prove that there exists an integer that divides 104.</p>
<div class="translation">
<p>There is the key phrase “there exists” right in the problem statement, so we could write <span class="math inline">\(\exists a \in \Z,~a \mid 104\)</span>. We can once again expand the definition of divisibility to write:<label for="sn-3-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-06d807034a" class="margin-toggle"/><span class="sidenote">We use the abbreviated form for two quantifications of the same type.</span> <span class="math display">\[\exists a, k \in \Z,~104 = ak.\]</span></p>
</div>
<div class="discussion">
<p>Basically, we need to pick a pair of divisors of 104. Since this is an existential proof and we get to pick both <span class="math inline">\(a\)</span> and <span class="math inline">\(k\)</span>, any pair of divisors will work.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(a = -2\)</span> and let <span class="math inline">\(k = -52\)</span>.</p>
<p>Then <span class="math inline">\(104 = ak\)</span>.</p>
</div>
</div>
<p>The previous example is the first one that had multiple quantifiers. In our proof, we had to give explicit values for both <span class="math inline">\(a\)</span> and <span class="math inline">\(k\)</span> to show that the statement held. Just as how a <em>sentence</em> in predicate logic must have all its variables quantified, a <em>mathematical proof</em> must introduce all variables contained in the sentence being proven.</p>
<h3 id="alternating-quantifiers-revisited-06d807034a">Alternating quantifiers, revisited</h3>
<p>In the Chapter 3, we saw how changing the order of an existential and universal quantifier changed the meaning of a statement. Now, well study how the order of quantifiers changes how we can introduce variables in a proof.</p>
<div class="example">
<p>Prove that all integers are divisible by <span class="math inline">\(1\)</span>.</p>
<div class="translation">
<p>The statement contains a universal quantification: <span class="math inline">\(\forall n \in \Z,~1 \mid n\)</span>. We can unpack the definition of divisibility to <span class="math display">\[\forall n \in \Z,~\exists k \in \Z,~n = 1 \cdot k.\]</span></p>
</div>
<div class="discussion">
<p>The final equation in the fully-expanded form of the statement is straightforward, and is valid when <span class="math inline">\(k\)</span> equals <span class="math inline">\(n\)</span>. But how should I introduce these variables? Answer: <em>in the same order they are quantified in the statement.</em></p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(n \in \Z\)</span>. Let <span class="math inline">\(k = n\)</span>.</p>
<p>Then <span class="math inline">\(n = 1 \cdot n = 1 \cdot k\)</span>.</p>
</div>
</div>
<p>This proof is quite short, but introduces a few new elements. First, it introduced a variable <span class="math inline">\(n\)</span> that could represent any real number. Unlike the previous existence proofs, when we introduced this variable <span class="math inline">\(n\)</span> we did not specify a concrete value like <span class="math inline">\(10\)</span>, but rather said that <span class="math inline">\(n\)</span> was an arbitrary real number by writing ``Let <span class="math inline">\(n \in \Z\)</span>.<label for="sn-4-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-06d807034a" class="margin-toggle"/><span class="sidenote">You might notice that we use the same word “let” to introduce both existentially- and universally-quantified variables. However, you should always be able to tell how the variable is quantified based on whether it is given a concrete value or an “arbitrary” value in the proof.</span></p>
<div class="framed">
<p><strong>A typical proof of a universal.</strong></p>
<p>Given statement to prove: <span class="math inline">\(\forall x \in S,~P(x)\)</span>.</p>
<div class="proof">
<p>Let <span class="math inline">\(x \in S\)</span>. (That is, let <span class="math inline">\(x\)</span> be an arbitrary element of <span class="math inline">\(S\)</span>.)</p>
<p>[Proof that <span class="math inline">\(P(x)\)</span> is True].</p>
</div>
</div>
<p>The other interesting element of this proof was that it contained an existentially-quantified variable <span class="math inline">\(k\)</span> after the <span class="math inline">\(\forall n \in \Z\)</span>. We used an extremely important tool at our disposal when it comes to proofs with multiple quantifiers: <strong>any existentially-quantified variable can be assigned a value that depends on the variables defined before it.</strong></p>
<p>In our proof, we first defined <span class="math inline">\(n\)</span> to be an arbitrary integer. Immediately after this, we wanted to show that for this <span class="math inline">\(n\)</span>, <span class="math inline">\(\exists k \in \Z,~ n = 1 \cdot k\)</span>. And to prove this, we needed a value for <span class="math inline">\(k\)</span>—a “let” statement. Because we define <span class="math inline">\(k\)</span> after having defined <span class="math inline">\(n\)</span>, we can use <span class="math inline">\(n\)</span> in the definition of <span class="math inline">\(k\)</span> and say “Let <span class="math inline">\(k = n\)</span>.” It may be helpful to think about the analogous process in programming. We first initialize a variable <span class="math inline">\(n\)</span>, and then define a new variable <span class="math inline">\(k\)</span> that is assigned the value of <span class="math inline">\(n\)</span>.</p>
<p>Even though this may seem obvious, one important thing to note is that the <em>order of variables in the statement determines the order in which the variables must be introduced in the proof</em>, and hence which variables can depend on which other variables. For example, consider the following erroneous “proof.”</p>
<div class="example">
<p>(Wrong!) Prove that <span class="math inline">\(\exists k \in \Z,~\forall n \in \Z,~n = 1 \cdot k.\)</span></p>
<div class="proof">
<p>Let <span class="math inline">\(k = n\)</span>. Let <span class="math inline">\(n \in \Z\)</span>.</p>
<p>Then <span class="math inline">\(n = 1 \cdot k\)</span>.</p>
</div>
</div>
<p>This proof may look very similar to the previous one, but it contains one crucial difference. The very first sentence, “Let <span class="math inline">\(k = n\)</span>,” is invalid: at that point, <span class="math inline">\(n\)</span> has not yet been defined!<label for="sn-5-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-06d807034a" class="margin-toggle"/><span class="sidenote"> This is analagous to a <code>NameError</code> in Python.</span> This is the result of having switched around the order of the quantifiers, which forces <span class="math inline">\(k\)</span> to be defined independently of whatever <span class="math inline">\(n\)</span> is chosen.</p>
<p>Note: dont assume that just because <em>one</em> proof is invalid, that <em>all</em> proofs of this statement are invalid! We cannot conclude that this statement is False just because we found one proof that didnt work.<label for="sn-6-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-06d807034a" class="margin-toggle"/><span class="sidenote">A meta way of looking at this: a statement is True when <em>there exists</em> a correct proof of it.</span> That said, this statement is indeed False, and well see later on in this chapter how to prove that a statement is False instead of True.</p>
<h2 id="proofs-involving-implications-06d807034a">Proofs involving implications</h2>
<p>Lets look at one new example.</p>
<div class="example">
<p>Prove that for all integers <span class="math inline">\(x\)</span>, if <span class="math inline">\(x\)</span> divides <span class="math inline">\((x + 5)\)</span>, then <span class="math inline">\(x\)</span> also divides <span class="math inline">\(5\)</span>.</p>
<div class="translation">
<p>There is both a universal quantification and implication in this statement:<label for="sn-7-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7-06d807034a" class="margin-toggle"/><span class="sidenote">As we noted back in Chapter 3, the “universal + implication” form is the most common form of statement we encounter.</span> <span class="math display">\[\forall x \in \Z,~ x \mid (x + 5) \Rightarrow x \mid 5.\]</span> When we unpack the definition of divisibility, we need to be careful about how the quantifiers are grouped: <span class="math display">\[\forall x \in \Z,~ \big( \exists k_1 \in \Z,~ x + 5 = k_1x \big) \Rightarrow \big( \exists k_2 \in \Z,~ 5 = k_2x \big).\]</span></p>
</div>
<div class="discussion">
<p>I need to prove that if <span class="math inline">\(x\)</span> divides <span class="math inline">\(x + 5\)</span>, then it also divides 5. To prove this, Im going to <em>assume</em> that <span class="math inline">\(x\)</span> divides <span class="math inline">\(x + 5\)</span>, and I need to <em>prove</em> that <span class="math inline">\(x\)</span> divides 5.</p>
<p>Since <span class="math inline">\(x\)</span> is divisible by <span class="math inline">\(x\)</span>, I should be able to subtract it from <span class="math inline">\(x + 5\)</span> and keep the result a multiple of <span class="math inline">\(x\)</span>. Can I prove that using the definition of divisibility? I basically need to “turn” the equation <span class="math inline">\(x + 5 = k_1x\)</span> into the equation <span class="math inline">\(5 = k_2x\)</span>.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(x\)</span> be an arbitrary integer. <em>Assume</em> that <span class="math inline">\(x \mid (x + 5)\)</span>, i.e., that there exists <span class="math inline">\(k_1 \in \Z\)</span> such that <span class="math inline">\(x + 5 = k_1x\)</span>. We want to prove that there exists <span class="math inline">\(k_2 \in \Z\)</span> such that <span class="math inline">\(5 = k_2x\)</span>.</p>
<p>Let <span class="math inline">\(k_2 = k_1 - 1\)</span>.</p>
<p>Then we can calculate: <span class="math display">\[\begin{align*}
k_2x &amp;= (k_1 - 1)x \\
&amp;= k_1 x - x \\
&amp;= (x + 5) - x \tag{we assumed $x + 5 = k_1 x$}\\
&amp;= 5
\end{align*}\]</span></p>
</div>
</div>
<p>Whew, that was a bit longer than the proofs weve already done. There were a lot of new elements that we introduced here, so lets break them down:</p>
<ul>
<li><p>After introducing <span class="math inline">\(x\)</span>, we wanted to prove the <em>implication</em> <span class="math inline">\(x \mid (x + 5) \Rightarrow x \mid 5\)</span>. To prove an implication, we needed to assume that the hypothesis was True, and then prove that the conclusion is also True. In our proof, we wrote “<strong>Assume</strong> <span class="math inline">\(x \mid (x + 5)\)</span>.”</p>
<p>This is <em>not</em> a claim that <span class="math inline">\(x \mid (x + 5)\)</span> is True; rather, it is a way to consider what would happen <em>if</em> <span class="math inline">\(x \mid (x + 5)\)</span> were True. The goal for the rest of the proof was to prove that <span class="math inline">\(x \mid 5\)</span>.</p>
<p>This proof structure is common when proving an implication:</p>
<div class="framed">
<p><strong>A typical proof of an implication (direct).</strong></p>
<p>Given statement to prove: <span class="math inline">\(p \Rightarrow q\)</span>.</p>
<div class="proof">
<p>Assume <span class="math inline">\(p\)</span>.</p>
<p>[Proof that <span class="math inline">\(q\)</span> is True.]</p>
</div>
</div></li>
<li><p>When we assumed that <span class="math inline">\(x \mid (x + 5)\)</span>, what this really did was introduce a new variable <span class="math inline">\(k_1 \in \Z\)</span> from the definition of divisibility. This might seem a little odd, but take a moment to think about what this means in English. We assumed that <span class="math inline">\(x\)</span> divides <span class="math inline">\(x + 5\)</span>, which (by definition) is the same as assuming that there exists an integer <span class="math inline">\(k_1\)</span> such that <span class="math inline">\(x + 5 = k_1x\)</span>. Given that such a number exists, we can give it a name and refer to it in the rest of our proof.<label for="sn-8-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-8-06d807034a" class="margin-toggle"/><span class="sidenote">In other words, we introduced a variable into the proof through an <em>assumption</em> we made.</span></p></li>
</ul>
<h3 id="generalizing-our-example-06d807034a">Generalizing our example</h3>
<p>One of the most important meta-techniques in mathematical proof is that of <strong>generalization</strong>: taking a true statement (and a proof of the statement), and then replacing a concrete value in the statement with a universally quantified variable. For example, consider the statement from the previous example, <span class="math inline">\(\forall x \in \Z,~ x \mid (x + 5) \Rightarrow x \mid 5\)</span>. It doesnt seem like the “<span class="math inline">\(5\)</span>” serves any special purpose; it is highly likely that it could be replaced by another number like <span class="math inline">\(165\)</span>, and the statement would still hold.<label for="sn-9-06d807034a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-9-06d807034a" class="margin-toggle"/><span class="sidenote">Concretely, consider the statement <span class="math inline">\(\forall x \in \Z,~ x \mid (x + 165) \Rightarrow x \mid 165\)</span>, which is at least as plausible as the original statement with <span class="math inline">\(5\)</span>s.</span></p>
<p>But rather than replace the <span class="math inline">\(5\)</span> with another concrete number and then re-proving the statement, we will instead replace it with a universally-quantified variable, and prove the corresponding statement. This way, we will know that in fact we could replace the <span class="math inline">\(5\)</span> with <em>any</em> integer and the statement would still hold.</p>
<div class="example">
<p>Prove that for all <span class="math inline">\(d \in \Z\)</span>, and for all <span class="math inline">\(x \in \Z\)</span>, if <span class="math inline">\(x\)</span> divides <span class="math inline">\((x + d)\)</span>, then <span class="math inline">\(x\)</span> also divides <span class="math inline">\(d\)</span>.</p>
<div class="translation">
<p>This has basically the same translation as last time, except now we have an extra variable: <span class="math display">\[\forall d,x \in \Z,~ \big( \exists k_1 \in \Z,~ x + d = k_1x \big) \Rightarrow \big( \exists k_2 \in \Z,~ d = k_2x \big).\]</span></p>
</div>
<div class="discussion">
<p>I should be able to use the same set of calculations as last time.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(d\)</span> and <span class="math inline">\(x\)</span> be arbitrary integers. <em>Assume</em> that <span class="math inline">\(x \mid (x + d)\)</span>, i.e., there exists <span class="math inline">\(k_1 \in \Z\)</span> such that <span class="math inline">\(x + d = k_1x\)</span>. We want to prove that there exists <span class="math inline">\(k_2 \in \Z\)</span> such that <span class="math inline">\(d = k_2x\)</span>.</p>
<p>Let <span class="math inline">\(k_2 = k_1 - 1\)</span>.</p>
<p>Then we can calculate: <span class="math display">\[\begin{align*}
k_2x &amp;= (k_1 - 1)x \\
&amp;= k_1 x - x \\
&amp;= (x + d) - x \\
&amp;= d
\end{align*}\]</span></p>
</div>
</div>
<p>This proof is basically the same as the previous one: we have simply swapped out all of the <span class="math inline">\(5\)</span>s with <span class="math inline">\(d\)</span>s. We say that the proof <em>did not depend on the value <span class="math inline">\(5\)</span></em>, meaning there was no place that we used some special property of <span class="math inline">\(5\)</span>, where we could have used a generic integer instead. We can also say that the original statement and proof <em>generalize</em> to this second version.</p>
<p>Why does generalization matter? By generalizing the previous statement from being about the number <span class="math inline">\(5\)</span> to an arbitrary integer, we have essentially gone from one statement being true to an infinite number of statements being true. The more general the statement, the more useful it becomes. We care about exponent laws like <span class="math inline">\(a^b \cdot a^c = a^{b + c}\)</span> precisely because they apply to every possible number; regardless of what our concrete calculation is, we know we can use this law in our calculations.</p>
<!-- ## False statements and disproofs
Suppose we have a friend who is trying to convince us that a certain
statement $X$ is false. If they tell you that statement $X$ is false
because they tried really hard to come up with a proof of it and failed,
you might believe them, or you might wonder if maybe they just missed a
crucial idea leading to a correct proof.^[Maybe they skipped all their CSC110 classes.] An absence of proof is not
enough to convince us that the statement is false.
Instead, we must see a
**disproof**, which is simply a proof that the *negation* of the
statement is true.^[In other words, if we can prove that $\NOT X$ is true, then $X$ must be false.] For this section, well be using the simplification
rules from the first chapter to make negations of statements easier to
work with.
Here are two examples: the first one is quite simple, and is used to
introduce the basic idea. The second is more subtle, and really requires
good understanding of how we manipulate a statement to get a simple form
for its negation.
<div class="example">
Disprove the following statement: every natural number divides 360.
<div class="translation">
This statement can be written as $\forall n \in \N,~n \mid 360$.
However, we want to prove that it is false, so we really need to study
its negation.
\begin{align*}
\NOT \big(\forall n \in \N,~n \mid 360 \big) \\
\exists n \in \N,~ n \NDIV 360
\end{align*}
</div>
<div class="discussion">
The original statement is obviously not true: the number 7 doesnt
divide 360, for instance. Is that a proof? We wrote the negation of the
statement in symbolic form above, and if we translate it back into
English, we get "there exists a natural number which does not divide
360." So, yes. Thats enough for a proof.
</div>
<div class="proof">
Let $n = 7$.
Then $n \NDIV 360$, since $\frac{360}{7}$ is not an integer.
</div>
</div>
When we want disprove a universally-quantified statement ("every element
of $S$ satisfies predicate $P$"), the negation of that statement becomes
an existentially-quantified one ("there exists an element of $S$ that
doesnt satisfy predicate $P$"). Since proofs of existential
quantification involve just finding one value, the disproof of the
original statement involves finding such a value which causes the
predicate to be false (or alternatively, causes the negation of the
predicate to be true). We call this value a **counterexample** for the
original statement. In the previous example, we would say that 7 is a counterexample of the given statement.
<div framed>
**A typical disproof of a universal (counterexample).**
Given statement to *disprove*: $\forall x \in S,~P(x)$.
<div class="proof">
We prove the negation, $\exists x \in S,~\NOT P(x)$.
Let $x=$ `_______`.
[Proof that $\NOT P$(`_______`) is True.]
</div>
</div>
Now let's look at at a more complex disproof.
<div class="example">
Disprove the following claim: for all natural numbers $a$ and $b$, there
exists a natural number $c$ which is less than $a + b$, and greater than
both $a$ and $b$, such that $c$ is divisible by $a$ or by $b$.
<div class="translation">
The original statement can be translated as follows. Weve underlined
the four different propositions which are joined with **AND** operators to make
them stand out.
$$\forall a, b \in \N,~\exists c \in \N,~
\underline{c < a + b} \AND
\underline{c > a} \AND
\underline{c > b} \AND
\underline{(a \mid c \OR b \mid c)}.$$
Well derive the negation step by step, though once you get comfortable
with the negation rules, youll be able to handle even complex formulas
like this one quite quickly.
\begin{align*}
\NOT \Big(
\forall a, b \in \N,~\exists c \in \N,~
\underline{c < a + b} \AND
\underline{c > a} \AND
\underline{c > b} \AND
\underline{(a \mid c \OR b \mid c)} \Big) \\
\exists a, b \in \N,~ \NOT \Big(
\exists c \in \N,~
\underline{c < a + b} \AND
\underline{c > a} \AND
\underline{c > b} \AND
\underline{(a \mid c \OR b \mid c)} \Big) \\
\exists a, b \in \N,~ \forall c \in \N,~
\NOT \Big(
\underline{c < a + b} \AND
\underline{c > a} \AND
\underline{c > b} \AND
\underline{(a \mid c \OR b \mid c)} \Big) \\
\exists a, b \in \N,~ \forall c \in \N,~
\underline{c \geq a + b} \OR
\underline{c \leq a} \OR
\underline{c \leq b} \OR
\underline{\Big(\NOT (a \mid c \OR b \mid c) \Big)} \\
\exists a, b \in \N,~ \forall c \in \N,~
\underline{c \geq a + b} \OR
\underline{c \leq a} \OR
\underline{c \leq b} \OR
\underline{(a \NDIV c \AND b \NDIV c)}\end{align*}
</div>
<div class="discussion">
That symbolic negation involved quite a bit of work. Lets make sure we
can translate the final result back into English: there exist natural
numbers $a$ and $b$ such that for all natural numbers $c$,
$c \geq a + b$ or $c \leq a$ or $c \leq b$ or neither $a$ nor $b$ divide
$c$. Hopefully this example illustrates the power of predicate logic: by
first translating the original statement into symbolic logic, we were
able to obtain a negation by applying some standard manipulation rules
and then translating the resulting statement back into English. For a
statement as complex as this one, it is usually easier to do this than
to try to intuit what the English negation of the original is, at
least when youre first starting out.
Okay, so how do we prove the negation? The existential quantifier tells
us we get to pick $a$ and $b$. Lets think simple: what if $a$ and $b$
are both 2? Then $a + b = 4$. If $c \geq 4$, the first clause in the OR
is satisfied, and if $c \leq 2$, the second and third clauses are
satisfied. So we only need to worry about when $c$ is 3, because in this
case the only clause that could possibly be satisfied is the last one,
$a \NDIV c \AND b \NDIV c$. Luckily, $a$ and $b$ are both 2, and 2
doesnt divide 3, so it seems like were good in this case as well.
It was particularly helpful that we chose such small values for $a$ and
$b$, so that there werent a lot of numbers in between them and their
sum to care about. As you do your own proofs of existentially-quantified
statements, remember that you have the power to pick values for these
variables!
</div>
<div class="proof">
Let $a = 2$ and $b = 2$, and let $c \in \N$. We now need to prove that
$$c \geq a + b \OR c \leq a \OR c \leq b \OR (a \NDIV c \AND b \NDIV c).$$
Substituting in the values for $a$ and $b$, this gets simplified to:
\begin{align*}
c \geq 4 \OR c \leq 2 \OR 2 \NDIV c \tag{$*$}
\end{align*}
To prove an OR, we only need one of the three parts to be true, and
different ones can be true for different values of $c$.
However, precisely which part is true depends on the value of $c$. For
example, we cant say that for an *arbitrary* value of $c$, that
$c \geq 4$. So well split up the remainder of the proof into three
cases for the values for $c$: numbers $\geq 4$, numbers $\leq 2$, and
the single value 3.
**Case 1**. We will *assume* that $c \geq 4$, and prove the
statement $(*)$ is true.
In this case, the first part of the OR in $(*)$ is true (this is exactly what we've assumed).
**Case 2**. We will *assume* that $c \leq 2$, and prove the
statement $(*)$ is true.
In this case, the second part of the OR in $(*)$ is true (this is exactly what we've assumed).
**Case 3**. We will *assume* that $c = 3$, and prove the statement
$(*)$ is true.
This case is the trickiest, because unlike the others, our assumption
that $c = 3$ is not verbatim one of the parts of $(*)$. However, we note
that $2 \NDIV 3$, and so the third part of the OR is satisfied.
Since in all possible cases statement $(*)$ is true, we conclude that
this statement is always true.
</div>
</div>
## Proof by cases
The previous proof illustrated a new proof technique known as **proof by
cases**. Remember that for a universal proof, we typically let a
variable be an arbitrary element of the domain, and then make an
argument in the proof body to prove our goal statement. However, even
when the goal statement is true for all elements of the domain, it isnt
always easy to construct a single argument that works for all of those elements!
Sometimes, different arguments are required for different elements.
In this case, we divide the domain into different parts, and
then write a separate argument for each part.
A bit more formally, we pick a set of unary predicates $P_1$, $P_2$, …,
$P_k$ (for some positive integer $k$), such that for every element $x$
in the domain, $x$ satisfies at least one of the predicates (we say that
these predicates are *exhaustive*).
You should think of these predicates as describing how we divide up the domain;
in the previous example, the predicates were:
$$P_1(c): c \leq 2, \qquad P_2(c): c \geq 4, \qquad P_3(c): c = 3.$$
Then, we divide the proof body into cases, where in each case we
*assume* that one of the predicates is True, and use that assumption to construct a
proof that specifically works under that assumption.^[
Recall that there's an equivalence between predicates and sets.
Another way of looking at a proof by cases is that we divide the domain into subsets $S_1, S_2, \dots S_k$, and then prove the desired statement separately for each of these subsets.
]
<div framed>
**A typical proof by cases.**
Given statement to prove: $\forall x \in S, P(x).$
Pick a set of exhaustive predicates $P_1, \dots, P_k$ of $S$.
<div class="proof">
Let $x \in S$.
We will use a proof by cases.
**Case 1**. *Assume* $P_1(x)$ is True.
[Proof that $P(x)$ is True, assuming $P_1(x)$.]
**Case 2**. *Assume* $P_2(x)$ is True.
[Proof that $P(x)$ is True, assuming $P_2(x)$.]
$\vdots$
**Case $k$**. *Assume* $P_k(x)$ is True.
[Proof that $P(x)$ is True, assuming $P_k(x)$.]
</div>
</div>
Proof by cases is a very versatile proof technique, since it allows the
combining of simpler proofs together to form a whole proof. Often it is
easier to prove a property about some (or even most) elements of the
domain than it is to prove that same property about all the elements.
But do keep in mind that if you can find a *simple* proof which works
for all elements of the domain, thats generally preferable than
combining multiple proofs together in a proof by cases.
To see one natural use of proof by cases in number theory, we introduce the following theorem, which formalizes our intuitions about another familiar term: remainders.
<div theorem id="theorem:quotient_remainder-06d807034a">
(Quotient-Remainder Theorem)
For all $n \in \Z$ and $d \in \Z$, if $d \neq 0$ then
there exist $q, r \in \Z$ such that $n = qd + r$ and $0 \leq r < |d|$.
Moreover, these $q$ and $r$ are *unique* (they are determined entirely by the values of $n$ and $d$).
</div>
<div definition data-terms="quotient,remainder">
Let $n, d, q, r$ be the variables in the previous theorem.
We say that $q$ and $r$ are the **quotient** and **remainder**, respectively, when $n$ is divided by $d$.
</div>
The reason this theorem is powerful is that it tells us that for any non-zero divisor $d \in \Z$, we can separate all possible integers into $d$ different groups, corresponding to their possible remainders (between $0$ and $|d|-1$) when divided by $d$.
Let's see this how to use this fact to perform a proof by cases.
<div class="example">
Prove that for all integers $x$, $2 \mid x^2 + 3x$.
<div class="translation">
Using the divisibility predicate: $\forall x \in \Z,~ 2 \mid x^2 + 3x$.
Or expanding the definition of divisibility:
$\forall x \in \Z,~ \exists k \in \Z,~ x^2 + 3x = 2k$.
</div>
<div class="discussion">
We want to "factor out a $2$" from the expression $x^2 + 3x$, but this only works if $x$ is even.
If $x$ is odd, though, then both $x^2$ and $3x$ will be odd, and adding two odd numbers together produces an even number.
But how do we "know" that every number has to be either even or odd?
And how can we formalize the algebraic operations of "factoring out a $2$" or "adding two odd numbers together"?
This is where the Quotient-Remainder Theorem comes in.
</div>
<div class="proof">
Let $x \in \Z$.
By the Quotient-Remainder Theorem, we know that when $x$ is divided by $2$, the two possible remainders are $0$ and $1$.
We will divide up the proof into two cases based on these remainders.
**Case 1**: assume the remainder when $x$ is divided by $2$ is $0$.
That is, we assume there exists $q \in \Z$ such that $x = 2q + 0$.
Let $k = 2q^2 + 3q$. We will show that $x^2 + 3x = 2k$.
We have:
\begin{align*}
x^2 + 3x &= (2q)^2 + 3(2q) \\
&= 4q^2 + 6q \\
&= 2(2q^2 + 3q) \\
&= 2k
\end{align*}
**Case 2**: assume the remainder when $x$ is divided by 2 is $1$.
That is, we assume there exists $q \in \Z$ such that $x = 2q + 1$.
Let $k = 2q^2 + 5q + 2$. We will show that $x^2 + 3x = 2k$.
We have:
\begin{align*}
x^2 + 3x &= (2q+1)^2 + 3(2q+1) \\
&= 4q^2 + 4q + 1 + 6q + 3 \\
&= 2(2q^2 + 5q + 2) \\
&= 2k
\end{align*}
</div>
</div> -->
</section>
<br/> <a id="anchor-06-03"></a>
<header id="title-block-header-de59c2d507">
<h1 class="title">6.3 Proofs and Algorithms I: Primality Testing</h1>
</header>
<section>
<p>Now lets see an example of applying the concept of mathematical proof to justify the correctness of an algorithm. First, recall that we say that an integer <span class="math inline">\(p\)</span> is <em>prime</em> when it is greater than 1 and the only numbers that divide <span class="math inline">\(p\)</span> are 1 and <span class="math inline">\(p\)</span> itself. We saw earlier that we could implement a predicate in Python to determine whether <code>p</code> is prime:</p>
<div class="sourceCode" id="cb1-de59c2d507"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-de59c2d507"><a href="#cb1-1-de59c2d507"></a><span class="kw">def</span> is_prime(p: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-de59c2d507"><a href="#cb1-2-de59c2d507"></a> <span class="co">&quot;&quot;&quot;Return whether p is prime.&quot;&quot;&quot;</span></span>
<span id="cb1-3-de59c2d507"><a href="#cb1-3-de59c2d507"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="dv">0</span>, p <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb1-4-de59c2d507"><a href="#cb1-4-de59c2d507"></a> <span class="cf">return</span> (</span>
<span id="cb1-5-de59c2d507"><a href="#cb1-5-de59c2d507"></a> p <span class="op">&gt;</span> <span class="dv">1</span> <span class="kw">and</span></span>
<span id="cb1-6-de59c2d507"><a href="#cb1-6-de59c2d507"></a> <span class="bu">all</span>({d <span class="op">==</span> <span class="dv">1</span> <span class="kw">or</span> d <span class="op">==</span> p <span class="cf">for</span> d <span class="kw">in</span> possible_divisors <span class="cf">if</span> divides(d, p)})</span>
<span id="cb1-7-de59c2d507"><a href="#cb1-7-de59c2d507"></a> )</span></code></pre></div>
<p>This implementation is a direct translation of the mathematical definition of prime numbers, with the only difference being our restriction of the range of possible divisors.<label for="sn-0-de59c2d507" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-de59c2d507" class="margin-toggle"/><span class="sidenote"> In fact, we can justify that this range is correct in a separate proof!</span> However, you might have noticed that this algorithm is “inefficient” because it checks more numbers than necessary.</p>
<p>Often when this version of <code>is_prime</code> is taught, the range of possible divisors extends only to the square root of the input <code>p</code>:</p>
<div class="sourceCode" id="cb2-de59c2d507"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-de59c2d507"><a href="#cb2-1-de59c2d507"></a><span class="im">from</span> math <span class="im">import</span> floor, sqrt</span>
<span id="cb2-2-de59c2d507"><a href="#cb2-2-de59c2d507"></a></span>
<span id="cb2-3-de59c2d507"><a href="#cb2-3-de59c2d507"></a></span>
<span id="cb2-4-de59c2d507"><a href="#cb2-4-de59c2d507"></a><span class="kw">def</span> is_prime(p: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-5-de59c2d507"><a href="#cb2-5-de59c2d507"></a> <span class="co">&quot;&quot;&quot;Return whether p is prime.&quot;&quot;&quot;</span></span>
<span id="cb2-6-de59c2d507"><a href="#cb2-6-de59c2d507"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="dv">2</span>, floor(sqrt(p)) <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb2-7-de59c2d507"><a href="#cb2-7-de59c2d507"></a> <span class="cf">return</span> (</span>
<span id="cb2-8-de59c2d507"><a href="#cb2-8-de59c2d507"></a> p <span class="op">&gt;</span> <span class="dv">1</span> <span class="kw">and</span></span>
<span id="cb2-9-de59c2d507"><a href="#cb2-9-de59c2d507"></a> <span class="bu">all</span>({<span class="kw">not</span> divides(d, p) <span class="cf">for</span> d <span class="kw">in</span> possible_divisors})</span>
<span id="cb2-10-de59c2d507"><a href="#cb2-10-de59c2d507"></a> )</span></code></pre></div>
<p>This version is intuitively faster, as the range of possible divisors to check is smaller. But how do we actually know that this version of <code>is_prime</code> is correct? We could write some tests, but as we discussed earlier both unit tests and property-based tests do not guarantee absolute correctness, they just give confidence. Luckily, for algorithms like this one that are based on the mathematical properties of the input, we do have a tool that guarantees absolutely certainty: proofs!</p>
<h2 id="a-property-of-prime-numbers-de59c2d507">A property of prime numbers</h2>
<p>Formally, we can justify the correctness by formally proving the following statement.</p>
<div class="theorem">
<p>Let <span class="math inline">\(p \in \Z\)</span>. Then <span class="math inline">\(p\)</span> is prime if and only if <span class="math inline">\(p &gt; 1\)</span> and for every integer <span class="math inline">\(d\)</span> in the range <span class="math inline">\(2 \leq d \leq \sqrt{p}\)</span>, <span class="math inline">\(d\)</span> does not divide <span class="math inline">\(p\)</span>.</p>
<p>Or, translated into predicate logic: <span class="math display">\[\forall p \in \Z,~ \mathit{Prime}(p) \Leftrightarrow \big(p &gt; 1 \land (\forall d \in \N,~ 2 \leq d \leq \sqrt{p} \Rightarrow d \nmid p) \big).\]</span></p>
</div>
<p>How do we go about proving that this statement is correct? Weve seen in the past how to prove implications, but how about biconditionals? Recall that a biconditional <span class="math inline">\(p \Leftrightarrow q\)</span> is equivalent to <span class="math inline">\((p \Rightarrow q) \land (q \Rightarrow p)\)</span>. So if we want to argue that a biconditional is True, we do so by proving the two different implications.</p>
<div class="framed">
<p><strong>A typical proof of a biconditional.</strong></p>
<p>Given statement to prove: <span class="math inline">\(p \Leftrightarrow q\)</span>.</p>
<div class="proof">
<p>This proof is divided into two parts.</p>
<p><strong>Part 1</strong> (<span class="math inline">\(p \Rightarrow q\)</span>): Assume <span class="math inline">\(p\)</span>.</p>
<p>[Proof that <span class="math inline">\(q\)</span> is True.]</p>
<p><strong>Part 2</strong> (<span class="math inline">\(q \Rightarrow p\)</span>): Assume <span class="math inline">\(q\)</span>.</p>
<p>[Proof that <span class="math inline">\(p\)</span> is True.]</p>
</div>
</div>
<h3 id="proving-the-first-implication-de59c2d507">Proving the first implication</h3>
<div class="discussion">
<p>The first implication well prove is that if <span class="math inline">\(p\)</span> is prime, then <span class="math inline">\(p &gt; 1\)</span> and <span class="math inline">\(\forall d \in \N,~ 2 \leq d \leq \sqrt{p} \Rightarrow d \nmid p\)</span>. We get to assume that <span class="math inline">\(p\)</span> is prime, and will need to prove two things: that <span class="math inline">\(p &gt; 1\)</span>, and that <span class="math inline">\(\forall d \in \N,~ 2 \leq d \leq \sqrt{p} \Rightarrow d \nmid p\)</span>.</p>
<p>Lets remind ourselves what the definition of prime is in predicate logic:</p>
<p><span class="math display">\[\mathit{Prime}(p):~ p &gt; 1 \land \big(\forall d \in \N,~ d \mid p \Rightarrow d = 1 \lor d = p \big)\]</span></p>
<p>The first part comes straight from the definition of prime. For the second part, we should also be able to use the definition of prime: if <span class="math inline">\(d\)</span> is between 2 and <span class="math inline">\(\sqrt{p}\)</span>, then it cant equal 1 or <span class="math inline">\(p\)</span>, which are the only possible divisors of <span class="math inline">\(p\)</span>.</p>
<p>Lets see how to write this up formally.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(p \in \Z\)</span> and assume that <span class="math inline">\(p\)</span> is prime. We need to prove that <span class="math inline">\(p &gt; 1\)</span> and for all <span class="math inline">\(d \in \N\)</span>, if <span class="math inline">\(2 \leq d \leq \sqrt p\)</span> then <span class="math inline">\(d\)</span> does not divide <span class="math inline">\(p\)</span>.</p>
<p><strong>Part 1</strong>: proving that <span class="math inline">\(p &gt; 1\)</span>.</p>
<p>By the definition of prime, we know that <span class="math inline">\(p &gt; 1\)</span>.</p>
<p><strong>Part 2</strong>: proving that for all <span class="math inline">\(d \in \N\)</span>, if <span class="math inline">\(2 \leq d \leq \sqrt p\)</span> then <span class="math inline">\(d\)</span> does not divide <span class="math inline">\(p\)</span>.</p>
<p>Let <span class="math inline">\(d \in \N\)</span> and assume <span class="math inline">\(2 \leq d \leq \sqrt p\)</span>. Well prove that <span class="math inline">\(d\)</span> does not divide <span class="math inline">\(p\)</span>.</p>
<p>First, since <span class="math inline">\(2 \leq d\)</span>, we know <span class="math inline">\(d &gt; 1\)</span>, and so <span class="math inline">\(d \neq 1\)</span>. Second, since <span class="math inline">\(p &gt; 1\)</span>, we know that <span class="math inline">\(\sqrt p &lt; p\)</span>, and so <span class="math inline">\(d \leq \sqrt p &lt; p\)</span>.</p>
<p>This means that <span class="math inline">\(d \neq 1\)</span> and <span class="math inline">\(d \neq p\)</span>. By the definition of prime again, we can conclude that <span class="math inline">\(d \nmid p\)</span>.</p>
</div>
<p>What weve proved so far is that if <span class="math inline">\(p\)</span> is prime, then it has no divisors between 2 and <span class="math inline">\(\sqrt p\)</span>. How does this apply to our algorithm <code>is_prime</code>? When its input <code>p</code> is a prime number, we know that the expressions <code>p &gt; 1</code> and <code>all(not divides(d, p) for d in possible_divisors)</code> will both evaluate to <code>True</code>, and so the function will return <code>True</code>. In other words, weve proven that <code>is_prime</code> returns the correct value for <em>every</em> prime number, without a single test case! Pretty awesome.</p>
<h3 id="proving-the-second-implication-de59c2d507">Proving the second implication</h3>
<p>Though we know that <code>is_prime</code> is correct for prime numbers, weve said nothing at all about how it behaves when given a non-prime number. To prove that its behaviour is correct in this case as well, we need to prove the other conditional.</p>
<div class="discussion">
<p>We now need to prove the second implication, which is the converse of the first: if <span class="math inline">\(p &gt; 1\)</span> and <span class="math inline">\(\forall d \in \N,~ 2 \leq d \leq \sqrt{p} \Rightarrow d \nmid p\)</span>, then <span class="math inline">\(p\)</span> must be prime. Expanding the definition of prime, we need to prove that <span class="math inline">\(p &gt; 1\)</span> (which weve assumed!) and that for all <span class="math inline">\(d_1 \in \N,~ d_1 \mid p \Rightarrow d_1 = 1 \lor d_1 = p\)</span>.</p>
<p>So the idea here is to let <span class="math inline">\(d_1 \in \N\)</span> and assume <span class="math inline">\(d_1 \mid p\)</span>, and use the condition that <span class="math inline">\(\forall d \in \N,~ 2 \leq d \leq \sqrt{p} \Rightarrow d \nmid p\)</span> to prove that <span class="math inline">\(d_1\)</span> is 1 or <span class="math inline">\(p\)</span>.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(p \in \N\)</span>, and assume <span class="math inline">\(p &gt; 1\)</span> and that <span class="math inline">\(\forall d \in \N,~ 2 \leq d \leq \sqrt{p} \Rightarrow d \nmid p\)</span>. We want to prove that <span class="math inline">\(p\)</span> is prime, i.e., that <span class="math inline">\(p &gt; 1\)</span> and that <span class="math inline">\(\forall d_1 \in \N,~ d_1 \mid p \Rightarrow d_1 = 1 \lor d_1 = p\)</span>.</p>
<p>We know the first part (<span class="math inline">\(p &gt; 1\)</span>) is true because its one of our assumptions. For the second part, first let <span class="math inline">\(d_1 \in \N\)</span>, and assume <span class="math inline">\(d_1 \mid p\)</span>. Well prove that <span class="math inline">\(d_1 = 1 \lor d_1 = p\)</span>.</p>
<p>From our second assumption, we know that since <span class="math inline">\(d_1 \mid p\)</span>, it is not between 2 and <span class="math inline">\(\sqrt p\)</span>.<label for="sn-1-de59c2d507" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-de59c2d507" class="margin-toggle"/><span class="sidenote"> More precisely, the <em>contrapositive</em> of our second assumption says that for all <span class="math inline">\(d \in \N\)</span>, <span class="math inline">\(d \mid p \Rightarrow d &lt; 2 \lor d &gt; \sqrt p\)</span>.</span> So then either <span class="math inline">\(d_1 &lt; 2\)</span> or <span class="math inline">\(d_1 &gt; \sqrt p\)</span>. We divide our proof into two <strong>cases</strong> based on these possibilities.</p>
<p><strong>Case 1</strong>: assume <span class="math inline">\(d_1 &lt; 2\)</span>.</p>
<p>Since <span class="math inline">\(d_1 \in \N\)</span>, it must be 0 or 1 in this case. We know <span class="math inline">\(0 \nmid p\)</span> because <span class="math inline">\(p &gt; 1\)</span>, and so <span class="math inline">\(d_1 = 1\)</span>.</p>
<p><strong>Case 2</strong>: assume <span class="math inline">\(d_1 &gt; \sqrt p\)</span>.</p>
<p>Since we assumed <span class="math inline">\(d_1 \mid p\)</span>, we expand the definition of divisibility to conclude that <span class="math inline">\(\exists k \in \Z,~ p = d_1 k\)</span>. Since <span class="math inline">\(d_1 &gt; \sqrt p\)</span> in this case, we know that <span class="math inline">\(k = \frac{p}{d_1} &lt; \frac{p}{\sqrt{p}} = \sqrt{p}\)</span>.</p>
<p>Since <span class="math inline">\(p = d_1k\)</span>, we know that <span class="math inline">\(k \mid p\)</span> as well, and so our second assumption applied to <span class="math inline">\(k\)</span> tells us that <span class="math inline">\(k\)</span> is not between 2 and <span class="math inline">\(\sqrt p\)</span>.</p>
<p>So <span class="math inline">\(k &lt; \sqrt{p}\)</span> and is not between 2 and <span class="math inline">\(\sqrt p\)</span>. Therefore <span class="math inline">\(k = 1\)</span>, and so <span class="math inline">\(d_1 = \frac{p}{k} = p\)</span>.</p>
</div>
<p>To wrap up this example, lets see how this implication connects to our function <code>is_prime</code>. What weve proved is that if <code>is_prime(p)</code> returns <code>True</code>, then <code>p</code> must be prime. This sounds very similar to what we said in the previous section, but it is different! The contrapositive this statement here is useful: if <code>p</code> is NOT prime, then <code>is_prime(p)</code> returns <code>False</code>.</p>
<p>So putting the two implications together, we have:</p>
<ul>
<li>For all integers <code>p</code>, if <code>p</code> is prime then <code>is_prime(p)</code> returns <code>True</code>.</li>
<li>For all integers <code>p</code>, if <code>is_prime(p)</code> returns <code>True</code> then <code>p</code> is prime.<label for="sn-2-de59c2d507" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-de59c2d507" class="margin-toggle"/><span class="sidenote"> Or equivalently, if <code>p</code> is not prime then <code>is_prime(p)</code> returns <code>False</code>.</span></li>
</ul>
<p>Since every integer <code>p</code> is either prime or not prime, we can conclude that this implementation of <code>is_prime</code> is <strong>correct</strong> according to its specification.</p>
<h2 id="algorithm-correctness-and-theoretical-properties-de59c2d507">Algorithm correctness and theoretical properties</h2>
<p>Notice the duality between the statement of correctness for <code>is_prime</code> and the biconditional we had set out to prove: for every natural number <span class="math inline">\(p\)</span>, <span class="math inline">\(p\)</span> is prime if and only if <span class="math inline">\(p &gt; 1\)</span> and for every integer <span class="math inline">\(d\)</span> in the range <span class="math inline">\(2 \leq d \leq \sqrt{p}\)</span>, <span class="math inline">\(d \nmid p\)</span>. The correctness of our <em>algorithm</em> is derived from the <em>theoretical properties of prime numbers</em> that we expressed in formal predicate logic. We admit this is a relatively simple example of this connection between algorithm and mathematical theory, but we had to start somewhere! Our future examples will draw on connections like this, but in far deeper ways.</p>
</section>
<br/> <a id="anchor-06-04"></a>
<header id="title-block-header-884c50e3d0">
<h1 class="title">6.4 Proof by Cases and Disproofs</h1>
</header>
<section>
<p>In the last proof of the previous section, we did something interesting: having concluded that <span class="math inline">\(d_1 &lt; 2\)</span> or <span class="math inline">\(d_1 &gt; \sqrt p\)</span>, we proceeded to split up our proof into two cases, one where we assumed that each part of the OR was true. This is a proof technique known as <strong>proof by cases</strong>.</p>
<h2 id="proof-by-cases-884c50e3d0">Proof by cases</h2>
<p>Remember that for a universal proof, we typically let a variable be an arbitrary element of the domain, and then make an argument in the proof body to prove our goal statement. However, even when the goal statement is True for all elements of the domain, it isnt always easy to construct a single argument that works for all of those elements! Sometimes, different arguments are required for different elements. In this case, we divide the domain into different parts, and then write a separate argument for each part.</p>
<p>A bit more formally, we pick a set of unary predicates <span class="math inline">\(P_1\)</span>, <span class="math inline">\(P_2\)</span>, …, <span class="math inline">\(P_k\)</span> (for some positive integer <span class="math inline">\(k\)</span>), such that for every element <span class="math inline">\(x\)</span> in the domain, <span class="math inline">\(x\)</span> satisfies at least one of the predicates (we say that these predicates are <em>exhaustive</em>). Note that the domain can be narrowed based on additional assumptions or conclusions made earlier in the proof. In our previous example, we started with a domain “<span class="math inline">\(d_1 \in \N\)</span>”, and then narrowed this to “<span class="math inline">\(d_1 \in \N\)</span> and <span class="math inline">\((d_1 &lt; 2 \lor d_1 &gt; \sqrt p)\)</span>”, leading to the following predicates for our cases: <span class="math display">\[P_1(d_1): d_1 &lt; 2, \qquad P_2(d_1): d_1 &gt; \sqrt p.\]</span></p>
<p>Then, we divide the proof body into cases, where in each case we <em>assume</em> that one of the predicates is True, and use that assumption to construct a proof that specifically works under that assumption.<label for="sn-0-884c50e3d0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-884c50e3d0" class="margin-toggle"/><span class="sidenote"> Recall that theres an equivalence between predicates and sets. Another way of looking at a proof by cases is that we divide the domain into subsets <span class="math inline">\(S_1, S_2, \dots S_k\)</span>, and then prove the desired statement separately for each of these subsets.</span></p>
<div class="framed">
<p><strong>A typical proof by cases.</strong></p>
<p>Given statement to prove: <span class="math inline">\(\forall x \in S, P(x).\)</span> Pick a set of exhaustive predicates <span class="math inline">\(P_1, \dots, P_k\)</span> of <span class="math inline">\(S\)</span>.</p>
<div class="proof">
<p>Let <span class="math inline">\(x \in S\)</span>. We will use a proof by cases.</p>
<p><strong>Case 1</strong>. <em>Assume</em> <span class="math inline">\(P_1(x)\)</span> is True.</p>
<p>[Proof that <span class="math inline">\(P(x)\)</span> is True, assuming <span class="math inline">\(P_1(x)\)</span>.]</p>
<p><strong>Case 2</strong>. <em>Assume</em> <span class="math inline">\(P_2(x)\)</span> is True.</p>
<p>[Proof that <span class="math inline">\(P(x)\)</span> is True, assuming <span class="math inline">\(P_2(x)\)</span>.]</p>
<p><span class="math inline">\(\vdots\)</span></p>
<p><strong>Case <span class="math inline">\(k\)</span></strong>. <em>Assume</em> <span class="math inline">\(P_k(x)\)</span> is True.</p>
<p>[Proof that <span class="math inline">\(P(x)\)</span> is True, assuming <span class="math inline">\(P_k(x)\)</span>.]</p>
</div>
</div>
<p>Proof by cases is a very versatile proof technique, since it allows the combining of simpler proofs together to form a whole proof. Often it is easier to prove a property about some (or even most) elements of the domain than it is to prove that same property about all the elements. But do keep in mind that if you can find a <em>simple</em> proof which works for all elements of the domain, thats generally preferable than combining multiple proofs together in a proof by cases.</p>
<h2 id="cases-and-the-quotient-remainder-theorem-884c50e3d0">Cases and the Quotient-Remainder Theorem</h2>
<p>One natural use of proof by cases in number theory is to apply the Quotient-Remainder Theorem that we introduced in <a href="01-number-theory-definitions.html">Section 6.1</a>.</p>
<div id="Quotient-Remainder Theorem-884c50e3d0" class="theorem">
<p>(Quotient-Remainder Theorem) For all <span class="math inline">\(n \in \Z\)</span> and <span class="math inline">\(d \in \Z^+\)</span>, there exist <span class="math inline">\(q \in \Z\)</span> and <span class="math inline">\(r \in \N\)</span> such that <span class="math inline">\(n = qd + r\)</span> and <span class="math inline">\(0 \leq r &lt; d\)</span>. Moreover, these <span class="math inline">\(q\)</span> and <span class="math inline">\(r\)</span> are <em>unique</em> for a given <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>.</p>
<p>We say that <span class="math inline">\(q\)</span> is the <strong>quotient</strong> when <span class="math inline">\(n\)</span> is divided by <span class="math inline">\(d\)</span>, and that <span class="math inline">\(r\)</span> is the <strong>remainder</strong> when <span class="math inline">\(n\)</span> is divided by <span class="math inline">\(d\)</span>.</p>
</div>
<p>The reason this theorem is powerful is that it tells us that for any non-zero divisor <span class="math inline">\(d \in \Z^+\)</span>, we can separate all possible integers into <span class="math inline">\(d\)</span> different groups, corresponding to their possible remainders (between <span class="math inline">\(0\)</span> and <span class="math inline">\(d-1\)</span>) when divided by <span class="math inline">\(d\)</span>. Lets see this how to use this fact to perform a proof by cases.</p>
<div class="example">
<p>Prove that for all integers <span class="math inline">\(x\)</span>, <span class="math inline">\(2 \DIV x^2 + 3x\)</span>.</p>
<div class="translation">
<p>Using the divisibility predicate: <span class="math inline">\(\forall x \in \Z,~ 2 \DIV x^2 + 3x\)</span>. Or expanding the definition of divisibility: <span class="math display">\[\forall x \in \Z,~ \exists k \in \Z,~ x^2 + 3x = 2k.\]</span></p>
</div>
<div class="discussion">
<p>We want to “factor out a <span class="math inline">\(2\)</span>” from the expression <span class="math inline">\(x^2 + 3x\)</span>, but this only works if <span class="math inline">\(x\)</span> is even. If <span class="math inline">\(x\)</span> is odd, though, then both <span class="math inline">\(x^2\)</span> and <span class="math inline">\(3x\)</span> will be odd, and adding two odd numbers together produces an even number.</p>
<p>But how do we “know” that every number has to be either even or odd? And how can we formalize the algebraic operations of “factoring out a <span class="math inline">\(2\)</span>” or “adding two odd numbers together”? This is where the Quotient-Remainder Theorem comes in.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(x \in \Z\)</span>. By the Quotient-Remainder Theorem, we know that when <span class="math inline">\(x\)</span> is divided by <span class="math inline">\(2\)</span>, the two possible remainders are <span class="math inline">\(0\)</span> and <span class="math inline">\(1\)</span>. We will divide up the proof into two cases based on these remainders.</p>
<p><strong>Case 1</strong>: assume the remainder when <span class="math inline">\(x\)</span> is divided by <span class="math inline">\(2\)</span> is <span class="math inline">\(0\)</span>. That is, we assume there exists <span class="math inline">\(q \in \Z\)</span> such that <span class="math inline">\(x = 2q + 0\)</span>. We will show that there exists <span class="math inline">\(k \in \Z\)</span> such that <span class="math inline">\(x^2 + 3x = 2k\)</span>.</p>
<p>We have: <span class="math display">\[\begin{align*}
x^2 + 3x &amp;= (2q)^2 + 3(2q) \\
&amp;= 4q^2 + 6q \\
&amp;= 2(2q^2 + 3q)
\end{align*}\]</span></p>
<p>So let <span class="math inline">\(k = 2q^2 + 3q\)</span>. Then <span class="math inline">\(x^2 + 3x = 2k\)</span>.</p>
<p><strong>Case 2</strong>: assume the remainder when <span class="math inline">\(x\)</span> is divided by 2 is <span class="math inline">\(1\)</span>. That is, we assume there exists <span class="math inline">\(q \in \Z\)</span> such that <span class="math inline">\(x = 2q + 1\)</span>. We will show that there exists <span class="math inline">\(k \in \Z\)</span> such that <span class="math inline">\(x^2 + 3x = 2k\)</span>.</p>
<p>We have: <span class="math display">\[\begin{align*}
x^2 + 3x &amp;= (2q+1)^2 + 3(2q+1) \\
&amp;= 4q^2 + 4q + 1 + 6q + 3 \\
&amp;= 2(2q^2 + 5q + 2)
\end{align*}\]</span></p>
<p>So let <span class="math inline">\(k = 2q^2 + 5q + 2\)</span>. Then <span class="math inline">\(x^2 + 3x = 2k\)</span>.</p>
</div>
</div>
<h2 id="false-statements-and-disproofs-884c50e3d0">False statements and disproofs</h2>
<p>Suppose we have a friend who is trying to convince us that a certain statement <span class="math inline">\(X\)</span> is False. If they tell you that statement <span class="math inline">\(X\)</span> is false because they tried really hard to come up with a proof of it and failed, you might believe them, or you might wonder if maybe they just missed a crucial idea leading to a correct proof.<label for="sn-1-884c50e3d0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-884c50e3d0" class="margin-toggle"/><span class="sidenote">Maybe they skipped all their CSC110 classes.</span> An absence of proof is not enough to convince us that the statement is False.</p>
<p>Instead, we must see a <strong>disproof</strong>, which is simply a proof that the <em>negation</em> of the statement is True.<label for="sn-2-884c50e3d0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-884c50e3d0" class="margin-toggle"/><span class="sidenote">In other words, if we can prove that <span class="math inline">\(\NOT X\)</span> is True, then <span class="math inline">\(X\)</span> must be False.</span> For this section, well be using the simplification rules from <a href="../03-logic/02-predicate-logic.html">Section 3.2</a> to make negations of statements easier to work with.</p>
<div class="example">
<p>Disprove the following statement: every natural number divides 360.</p>
<div class="translation">
<p>This statement can be written as <span class="math inline">\(\forall n \in \N,~n \DIV 360\)</span>. However, we want to prove that it is False, so we really need to study its negation. <span class="math display">\[\begin{align*}
\NOT \big(\forall n \in \N,~n \DIV 360 \big) \\
\exists n \in \N,~ n \NDIV 360
\end{align*}\]</span></p>
</div>
<div class="discussion">
<p>The original statement is obviously not True: the number 7 doesnt divide 360, for instance. Is that a proof? We wrote the negation of the statement in symbolic form above, and if we translate it back into English, we get “there exists a natural number which does not divide 360.” So, yes. Thats enough for a proof.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(n = 7\)</span>.</p>
<p>Then <span class="math inline">\(n \NDIV 360\)</span>, since <span class="math inline">\(\frac{360}{7} = 51.428\dots\)</span> is not an integer.</p>
</div>
</div>
<p>When we want disprove a universally-quantified statement (“every element of <span class="math inline">\(S\)</span> satisfies predicate <span class="math inline">\(P\)</span>”), the negation of that statement becomes an existentially-quantified one (“there exists an element of <span class="math inline">\(S\)</span> that doesnt satisfy predicate <span class="math inline">\(P\)</span>”). Since proofs of existential quantification involve just finding one value, the disproof of the original statement involves finding such a value which causes the predicate to be False (or alternatively, causes the negation of the predicate to be True). We call this value a <strong>counterexample</strong> for the original statement. In the previous example, we would say that 7 is a counterexample of the given statement.</p>
<div class="framed">
<p><strong>A typical disproof of a universal (counterexample).</strong></p>
<p>Given statement to <em>disprove</em>: <span class="math inline">\(\forall x \in S,~P(x)\)</span>.</p>
<div class="proof">
<p>We prove the negation, <span class="math inline">\(\exists x \in S,~\NOT P(x)\)</span>. Let <span class="math inline">\(x=\)</span> <code>_______</code>.</p>
<p>[Proof that <span class="math inline">\(\NOT P\)</span>(<code>_______</code>) is True.]</p>
</div>
</div>
</section>
<br/> <a id="anchor-06-05"></a>
<header id="title-block-header-db1b9d088b">
<h1 class="title">6.5 Greatest Common Divisor</h1>
</header>
<section>
<p>In this section, well take a closer look at the <em>greatest common divisor</em> of two numbers. Recall the following definitions from <a href="01-number-theory-definitions.html">6.1 An Introduction to Number Theory</a>.</p>
<div class="definition" data-terms="common divisor, greatest common divisor">
<p>Let <span class="math inline">\(x, y, d \in \Z\)</span>. We say that <span class="math inline">\(d\)</span> is a <strong>common divisor</strong> of <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> when <span class="math inline">\(d\)</span> divides <span class="math inline">\(x\)</span> and <span class="math inline">\(d\)</span> divides <span class="math inline">\(y\)</span>.</p>
<p>We say that <span class="math inline">\(d\)</span> is the <strong>greatest common divisor</strong> of <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> when it is the largest number that is a common divisor of <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span>, or 0 when <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> are both 0. We can define the function <span class="math inline">\(\gcd : \Z \times \Z \to \N\)</span> as the function which takes numbers <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span>, and returns their greatest common divisor.</p>
</div>
<p>To make it easier to translate this statement into symbolic form, we can restate the “maximum” part by saying that if <span class="math inline">\(e\)</span> is any number which divides <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span>, then <span class="math inline">\(e \leq d\)</span>. Let <span class="math inline">\(m, n, d \in \Z\)</span>, and suppose <span class="math inline">\(d = \gcd(m, n)\)</span>. Then <span class="math inline">\(d\)</span> satisfies the following statement:</p>
<p><span class="math display">\[\begin{align*}
&amp;\Big(m = 0 \land n = 0 \Rightarrow d = 0 \Big)~\land \\
&amp;\Big(m \neq 0 \lor n \neq 0 \Rightarrow \\
&amp; \qquad d \mid m \land d \mid n \land \big(\forall e \in \N,~e \mid m \land e \mid n \Rightarrow e \leq d\big) \Big)
\end{align*}\]</span></p>
<p>This expression has a few subtleties. First, because we actually have separate definitions for <span class="math inline">\(\gcd(m, n)\)</span> when both arguments are zero and when at least one of them is non-zero, these two definitions are expressed as two different implications.<label for="sn-0-db1b9d088b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-db1b9d088b" class="margin-toggle"/><span class="sidenote"> This is analogous to writing an if statement in Python. In this case, were saying that only one of the conclusions needs to be True, depending on which of the hypotheses are True.</span></p>
<p>Here is an example proof which makes use of both this definition, and the definition of prime.</p>
<div class="example">
<p>Prove that for all integers <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span>, if <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> are distinct primes, then <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> are <em>coprime</em>, meaning <span class="math inline">\(\gcd(p, q) = 1\)</span>.</p>
<div class="translation">
<p>Here is an initial translation which focuses on the structure of the above statement, but doesnt unpack any definitions: <span class="math display">\[\forall p, q \in \Z,~\big(Prime(p) \land Prime(q) \land p \neq q\big) \IMP \gcd(p, q) = 1.\]</span> We could unpack the definitions of <span class="math inline">\(Prime\)</span> and gcd, but doing so would not add any insight at this point. While we will almost certainly end up using these definitions in the discussion and proof sections, expanding it here actually obscures the meaning of the statement.<label for="sn-1-db1b9d088b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-db1b9d088b" class="margin-toggle"/><span class="sidenote"> In general, use translation as a way of precisely specifying the <em>structure</em> of a statement; as we have seen repeatedly, the high-level structure of a statement is mimicked in the structure of its proof. And while you dont need to expand every definition in a statement, you should <em>always</em> keep in mind that definitions referred to in the statement will require unpacking in the proof itself.</span></p>
</div>
<div class="discussion">
<p>We know that primes dont have many divisors, and that <span class="math inline">\(1\)</span> is a common divisor for any pair of numbers. So to show that <span class="math inline">\(\gcd(p, q) = 1\)</span>, we just need to make sure that neither <span class="math inline">\(p\)</span> nor <span class="math inline">\(q\)</span> divides the other (otherwise that would be a common divisor larger than <span class="math inline">\(1\)</span>).</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(p, q \in \Z\)</span>. Assume that <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> are both prime, and that <span class="math inline">\(p \neq q\)</span>. We want to prove that <span class="math inline">\(\gcd(p, q) = 1\)</span>.</p>
<p>By the definition of prime, we know that <span class="math inline">\(p \neq 1\)</span> (since <span class="math inline">\(p &gt; 1\)</span>). Also by the definition of prime, the only positive divisors of <span class="math inline">\(q\)</span> are <span class="math inline">\(1\)</span> and <span class="math inline">\(q\)</span> itself. So then since <span class="math inline">\(p \neq q\)</span> (our assumption) and <span class="math inline">\(p \neq 1\)</span>, we know that <span class="math inline">\(p \NDIV q\)</span>.</p>
<p>Next, we know that <span class="math inline">\(1\)</span> divides every number<label for="sn-2-db1b9d088b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-db1b9d088b" class="margin-toggle"/><span class="sidenote">We proved this in Section 6.2!</span>, and so <span class="math inline">\(1\)</span> is the only positive common divisor of <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span>, so <span class="math inline">\(\gcd(p, q) = 1\)</span>.</p>
</div>
</div>
<p>In the above proof, we did something new in the last paragraph: we referred to a statement we had proved to justify a step in the proof. This might sound kind of funny—after all, many of our proofs so far have relied on some algebraic manipulations which are valid but are really knowledge we learned prior to this course. The subtle difference is that those algebraic laws we take for granted as “obvious” because we learned them so long ago. But in fact our proofs can consist of steps which are statements that we know are true because of an external source, even one that <em>we dont know how to prove ourselves</em>.</p>
<p>This is a fundamental parallel between writing proofs and writing computer programs. In programming, we start with some basic building blocks of a language—data types, control flow constructs, etc.—but we often rely on libraries as well to simplify our tasks. We can use these libraries by reading their documentation and understanding how to use them, but dont need to understand how they are implemented. In the same way, we can use an external theorem in our proof by understanding what it means, but without knowing how to prove it.</p>
<p>Lets look at one example of this in action.</p>
<h2 id="linear-combinations-and-the-greatest-common-divisor-db1b9d088b">Linear combinations and the greatest common divisor</h2>
<p>First, a “helper” definition:</p>
<div class="definition" data-terms="linear-combination">
<p>Let <span class="math inline">\(m, n, a \in \Z\)</span>. We say that <span class="math inline">\(a\)</span> is a <strong>linear combination of <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span></strong> when there exist <span class="math inline">\(p, q \in \Z\)</span> such that <span class="math inline">\(a = pm + qn\)</span>.</p>
</div>
<p>For example, 101 is a linear combination of 5 and 3, since <span class="math inline">\(101 = 10 \cdot 5 + 17 \cdot 3\)</span>.</p>
<p>We can use this definition to state one fairly straightforward property of divisibility, and one surprising property of the greatest common divisor.</p>
<div id="theorem:divide_lin_comb-db1b9d088b" class="theorem">
<p>(<em>Divisibility of Linear Combinations</em>) Let <span class="math inline">\(m, n, d \in \Z\)</span>. If <span class="math inline">\(d\)</span> divides <span class="math inline">\(m\)</span> and <span class="math inline">\(d\)</span> divides <span class="math inline">\(n\)</span>, then <span class="math inline">\(d\)</span> divides every linear combination of <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span>.</p>
</div>
<div id="theorem:gcd_characterization-db1b9d088b" class="theorem">
<p>(<em>GCD Characterization</em>) Let <span class="math inline">\(m, n \in \Z\)</span>, and assume at least one of them is non-zero. Then <span class="math inline">\(\gcd(m, n)\)</span> is the smallest positive integer that is a linear combination of <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span>.</p>
</div>
<p>Next, well see how to use these two theorems as “helpers” inside a proof of the following statement, which is yet another property of the greatest common divisor.</p>
<div class="example">
<p>For all <span class="math inline">\(m, n, d \in \Z\)</span>, if <span class="math inline">\(d\)</span> divides both <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span> then <span class="math inline">\(d\)</span> also divides <span class="math inline">\(\gcd(m, n)\)</span>.</p>
<div class="translation">
<p>We can translate this statement as follows: <span class="math display">\[\forall m, n, d \in \Z,~ d \mid m \land d \mid n \Rightarrow d \mid \gcd(m, n).\]</span></p>
</div>
<div class="discussion">
<p>This one is a bit tougher. All we know from the definition of gcd is that <span class="math inline">\(d \leq \gcd(m, n)\)</span>, but that doesnt imply <span class="math inline">\(d \mid \gcd(m, n)\)</span> by any means.</p>
<p>But given the context that we just discussed in the preceding paragraphs, Id guess that we should also use the <a href="#theorem:gcd_characterization-db1b9d088b">GCD Characterization Theorem</a> to write <span class="math inline">\(\gcd(m, n)\)</span> as <span class="math inline">\(pm + qn\)</span>. Oh, and the theorem before that one said that any number that divides <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span> will divide <span class="math inline">\(pm + qn\)</span> as well!</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(m, n, d \in \Z\)</span>. Assume that <span class="math inline">\(d \mid m\)</span> and <span class="math inline">\(d \mid n\)</span>. We want to prove that <span class="math inline">\(d \mid \gcd(m, n)\)</span>. Well divide our proof into two cases.<label for="sn-3-db1b9d088b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-db1b9d088b" class="margin-toggle"/><span class="sidenote"> After reading the next two cases, answer: why did we need to divide our proof into cases? Is there another way we could have written this proof?</span></p>
<p><strong>Case 1</strong>: assume <span class="math inline">\(m = 0\)</span> and <span class="math inline">\(n = 0\)</span>.</p>
<p>In this case, by the definition of <span class="math inline">\(\gcd\)</span> we know that <span class="math inline">\(\gcd(m, n) = 0\)</span>. So <span class="math inline">\(d \mid \gcd(m, n)\)</span>, since we assumed that <span class="math inline">\(d\)</span> divides <span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span>, which are 0.</p>
<p><strong>Case 2</strong>: assume <span class="math inline">\(m \neq 0\)</span> or <span class="math inline">\(n \neq 0\)</span>.</p>
<p>Then By the <a href="#theorem:gcd_characterization-db1b9d088b">GCD Characterization Theorem</a>, there exist integers <span class="math inline">\(p, q \in \Z\)</span> such that <span class="math inline">\(\gcd(m, n) = pm + qn\)</span>.<label for="sn-4-db1b9d088b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-db1b9d088b" class="margin-toggle"/><span class="sidenote">This line uses a known external fact that is an existential to <em>introduce</em> two variables <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> to use in our proof.</span></p>
<p>Then by the the <a href="#theorem:divide_lin_comb-db1b9d088b">Divisibility of Linear Combinations Theorem</a>, since <span class="math inline">\(d \mid m\)</span> and <span class="math inline">\(d \mid n\)</span> (by assumption), we know that <span class="math inline">\(d \mid pm + qn\)</span>.</p>
<p>Therefore <span class="math inline">\(d \mid \gcd(m, n)\)</span>.</p>
</div>
</div>
</section>
<br/> <a id="anchor-06-06"></a>
<header id="title-block-header-31dc2f7c50">
<h1 class="title">6.6 Proofs and Algorithms II: Computing the Greatest Common Divisor</h1>
</header>
<section>
<p>In the previous section, we studied some mathematical properties of the greatest common divisor. Now in this section, well look at how to implement algorithms for calculating the greatest common divisor, and introduce a new form of Python loops along the way.</p>
<h2 id="naively-searching-for-the-gcd-31dc2f7c50">Naively searching for the gcd</h2>
<p>In this chapter we have used the divides predicate (e.g., <span class="math inline">\(d \mid n\)</span>) liberally. In <a href="../03-logic/09-working-with-definitions.html">Section 3.9</a>, we saw a possible implementation of the predicate as a function called <code>divides</code>:</p>
<div class="sourceCode" id="cb1-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-31dc2f7c50"><a href="#cb1-1-31dc2f7c50"></a><span class="kw">def</span> divides(d: <span class="bu">int</span>, n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-31dc2f7c50"><a href="#cb1-2-31dc2f7c50"></a> <span class="co">&quot;&quot;&quot;Return whether d divides n.&quot;&quot;&quot;</span></span>
<span id="cb1-3-31dc2f7c50"><a href="#cb1-3-31dc2f7c50"></a> <span class="cf">if</span> d <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb1-4-31dc2f7c50"><a href="#cb1-4-31dc2f7c50"></a> <span class="cf">return</span> n <span class="op">==</span> <span class="dv">0</span></span>
<span id="cb1-5-31dc2f7c50"><a href="#cb1-5-31dc2f7c50"></a> <span class="cf">else</span>:</span>
<span id="cb1-6-31dc2f7c50"><a href="#cb1-6-31dc2f7c50"></a> <span class="cf">return</span> n <span class="op">%</span> d <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
<p>With this function in hand, we can implement a <code>gcd</code> function as follows:<label for="sn-0-31dc2f7c50" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-31dc2f7c50" class="margin-toggle"/><span class="sidenote"> In this implementation, we use <code>abs</code> because <code>m</code> and/or <code>n</code> might be negative.</span></p>
<div class="sourceCode" id="cb2-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-31dc2f7c50"><a href="#cb2-1-31dc2f7c50"></a><span class="kw">def</span> naive_gcd(m: <span class="bu">int</span>, n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-2-31dc2f7c50"><a href="#cb2-2-31dc2f7c50"></a> <span class="co">&quot;&quot;&quot;Return the gcd of m and n.&quot;&quot;&quot;</span></span>
<span id="cb2-3-31dc2f7c50"><a href="#cb2-3-31dc2f7c50"></a> <span class="cf">if</span> m <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb2-4-31dc2f7c50"><a href="#cb2-4-31dc2f7c50"></a> <span class="cf">return</span> <span class="bu">abs</span>(n)</span>
<span id="cb2-5-31dc2f7c50"><a href="#cb2-5-31dc2f7c50"></a> <span class="cf">elif</span> n <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb2-6-31dc2f7c50"><a href="#cb2-6-31dc2f7c50"></a> <span class="cf">return</span> <span class="bu">abs</span>(m)</span>
<span id="cb2-7-31dc2f7c50"><a href="#cb2-7-31dc2f7c50"></a> <span class="cf">else</span>:</span>
<span id="cb2-8-31dc2f7c50"><a href="#cb2-8-31dc2f7c50"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="dv">1</span>, <span class="bu">min</span>(<span class="bu">abs</span>(m), <span class="bu">abs</span>(n)) <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb2-9-31dc2f7c50"><a href="#cb2-9-31dc2f7c50"></a> <span class="cf">return</span> <span class="bu">max</span>({d <span class="cf">for</span> d <span class="kw">in</span> possible_divisors <span class="cf">if</span> divides(d, m) <span class="kw">and</span> divides(d, n)})</span></code></pre></div>
<h2 id="gcd-and-remainders-31dc2f7c50">GCD and remainders</h2>
<p>Here is the Quotient-Remainder Theorem we saw earlier in this chapter, slightly modified to allow for negative divisors as well.</p>
<div id="Quotient-Remainder Theorem-31dc2f7c50" class="theorem">
<p>(Quotient-Remainder Theorem) For all <span class="math inline">\(n \in \Z\)</span> and <span class="math inline">\(d \in \Z\)</span>, if <span class="math inline">\(d \neq 0\)</span> then there exist <span class="math inline">\(q \in \Z\)</span> and <span class="math inline">\(r \in \N\)</span> such that <span class="math inline">\(n = qd + r\)</span> and <span class="math inline">\(0 \leq r &lt; |d|\)</span>. Moreover, these <span class="math inline">\(q\)</span> and <span class="math inline">\(r\)</span> are <em>unique</em> for a given <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>.</p>
<p>We say that <span class="math inline">\(q\)</span> is the <strong>quotient</strong> when <span class="math inline">\(n\)</span> is divided by <span class="math inline">\(d\)</span>, and that <span class="math inline">\(r\)</span> is the <strong>remainder</strong> when <span class="math inline">\(n\)</span> is divided by <span class="math inline">\(d\)</span>, and write <span class="math inline">\(r = n~\%~d\)</span>.</p>
</div>
<p>We can use this theorem to improve our algorithm by breaking down the problem into a smaller one. The key idea is the following theorem.</p>
<div class="theorem">
<p>For all <span class="math inline">\(a, b \in \Z\)</span> where <span class="math inline">\(b \neq 0\)</span>, <span class="math inline">\(\gcd(a, b) = \gcd(b, a~\%~b)\)</span>.</p>
</div>
<div class="translation">
<p><span class="math inline">\(\forall a, b \in \Z,~ b \neq 0 \Rightarrow \gcd(a, b) = \gcd(b, a~\%~b)\)</span>.</p>
</div>
<div class="discussion">
<p>Before we try to prove this statement, lets consider an example using the two numbers <span class="math inline">\(a = 24\)</span> and <span class="math inline">\(b = 16\)</span>. We know that <span class="math inline">\(\gcd(24, 16) = 8\)</span>. Also, the remainder when 24 is divided by 16 is 8, and <span class="math inline">\(\gcd(16, 8) = 8\)</span> as well.</p>
<p>Before we get to a formal proof, lets preview the main idea. Well define the variable <span class="math inline">\(d = \gcd(b, a~\%~b)\)</span>, and prove that <span class="math inline">\(d = \gcd(a, b)\)</span> as well. To do so, well need to prove that <span class="math inline">\(d\)</span> divides both <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span>, and that it is greater than every other common divisor of <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span>. Watch for this structure in our actual proof below!</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(a, b \in \Z\)</span> and assume <span class="math inline">\(b \neq 0\)</span>. Also let <span class="math inline">\(r = a~\%~b\)</span> (the remainder when <span class="math inline">\(a\)</span> is divided by <span class="math inline">\(b\)</span>). We need to prove that <span class="math inline">\(\gcd(a, b) = \gcd(b, r)\)</span>.</p>
<p>To do this, let <span class="math inline">\(d = \gcd(b, r)\)</span>. Well prove that <span class="math inline">\(d = \gcd(a, b)\)</span> as well, by proving three things: that <span class="math inline">\(d \mid a\)</span>, that <span class="math inline">\(d \mid b\)</span>, and that every common divisor of <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> is <span class="math inline">\(\leq d\)</span>.</p>
<p><strong>Part 1</strong>: proving that <span class="math inline">\(d \mid a\)</span>.</p>
<p>By our definition of <span class="math inline">\(r\)</span> and the Quotient-Remainder Theorem, we know that there exists <span class="math inline">\(q \in Z\)</span> such that <span class="math inline">\(a = qb + r\)</span>. Since <span class="math inline">\(d = \gcd(b, r)\)</span>, we know that <span class="math inline">\(d\)</span> divides both <span class="math inline">\(b\)</span> and <span class="math inline">\(r\)</span>. And so by the <a href="05-greatest-common-divisor.html##theorem:divide_lin_comb">Divisibility of Linear Combinations Theorem</a>, we know that <span class="math inline">\(d \mid qb + r\)</span>, and so <span class="math inline">\(d \mid a\)</span>.</p>
<p><strong>Part 2</strong>: proving that <span class="math inline">\(d \mid b\)</span>.</p>
<p>Since we defined <span class="math inline">\(d = \gcd(b, r)\)</span>, it must divide <span class="math inline">\(b\)</span> (by the definition of <span class="math inline">\(\gcd\)</span>).</p>
<p><strong>Part 3</strong>: proving that every common divisor of <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> is <span class="math inline">\(\leq d\)</span>.</p>
<p>Let <span class="math inline">\(d_1 \in \Z\)</span> and assume that <span class="math inline">\(d_1 \mid a\)</span> and <span class="math inline">\(d_1 \mid b\)</span>. Well prove that <span class="math inline">\(d_1 \leq d\)</span>.</p>
<p>First, well prove that <span class="math inline">\(d_1 \mid r\)</span>. We can rewrite the equation <span class="math inline">\(a = qb + r\)</span> (from the Quotient-Remainder Theorem) to obtain <span class="math inline">\(r = a - qb\)</span>. Then using our assumption that <span class="math inline">\(d_1\)</span> is a common divisor of <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> and <a href="05-greatest-common-divisor.html##theorem:divide_lin_comb">Divisibility of Linear Combinations Theorem</a> again, we can conclude that <span class="math inline">\(d_1 \mid r\)</span>.</p>
<p>So then <span class="math inline">\(d_1 \mid b\)</span> (by our assumption), and <span class="math inline">\(d_1 \mid r\)</span>, and so it is a common divisor of <span class="math inline">\(b\)</span> and <span class="math inline">\(r\)</span>. Therefore by the definition of <span class="math inline">\(\gcd\)</span>, we know that <span class="math inline">\(d_1 \leq \gcd(b, r) = d\)</span>.</p>
</div>
<h2 id="gcd-remainders-and-a-new-algorithm-31dc2f7c50">GCD, remainders, and a new algorithm</h2>
<p>The theorem we just proved suggests a possible way of computing the gcd of two numbers in an iterative (repeated) fashion. Lets again use 24 and 16 as our example.</p>
<ul>
<li>Since the remainder <span class="math inline">\(24~\%~16\)</span> is 8, we know that <span class="math inline">\(\gcd(24, 16) = \gcd(16, 8)\)</span>.</li>
<li>Also, the remainder <span class="math inline">\(16~\%~8\)</span> is 0, and so we know that <span class="math inline">\(\gcd(16, 8) = \gcd(8, 0)\)</span>.</li>
<li>But the gcd of any positive integer <span class="math inline">\(n\)</span> and 0 is simply <span class="math inline">\(n\)</span> itself,<label for="sn-1-31dc2f7c50" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-31dc2f7c50" class="margin-toggle"/><span class="sidenote"> Exercise: prove this using the definition of gcd!</span> and so we know <span class="math inline">\(\gcd(8, 0) = 8\)</span>.</li>
<li>This tells use that <span class="math inline">\(\gcd(24, 16) = 8\)</span> as well!</li>
</ul>
<p>Lets formalize this in a high-level description of an algorithm before we write the code. This algorithm for computing the gcd of two numbers is known as the <em>Euclidean algorithm</em>.<label for="sn-2-31dc2f7c50" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-31dc2f7c50" class="margin-toggle"/><span class="sidenote"> This is named after the Greek mathematician Euclid, although he originally developed the algorithm using subtraction (<span class="math inline">\(a - b\)</span>) rather than remainders (<span class="math inline">\(a~\%~b\)</span>).</span></p>
<div class="framed">
<p><strong>Euclidean Algorithm</strong></p>
<p><em>Given</em>: integers <code>a</code> and <code>b</code>. <em>Returns</em>: <code>gcd(a, b)</code>.</p>
<ol type="1">
<li>Initialize two variables <code>x</code>, <code>y</code> to the given numbers <code>a</code> and <code>b</code>.</li>
<li>Let <code>r</code> be the remainder when <code>x</code> is divided by <code>y</code>.</li>
<li>Reassign <code>x</code> and <code>y</code> to <code>y</code> and <code>r</code>, respectively.</li>
<li>Repeat steps 2 and 3 until <code>y</code> is 0.</li>
<li>At this point, <code>x</code> refers to the gcd of <code>a</code> and <code>b</code>.</li>
</ol>
</div>
<p>Here is how we can visualize the changing values of <code>x</code> and <code>y</code> for the given 24 and 6 in our previous example:<label for="sn-3-31dc2f7c50" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-31dc2f7c50" class="margin-toggle"/><span class="sidenote"> Note the similarity between this and the <em>loop accumulation tables</em> of Chapter 4.</span></p>
<div class="reference-table">
<table>
<thead>
<tr class="header">
<th style="text-align: center;">Iteration</th>
<th style="text-align: center;"><code>x</code></th>
<th style="text-align: center;"><code>y</code></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">0</td>
<td style="text-align: center;">24</td>
<td style="text-align: center;">16</td>
</tr>
<tr class="even">
<td style="text-align: center;">1</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">8</td>
</tr>
<tr class="odd">
<td style="text-align: center;">2</td>
<td style="text-align: center;">8</td>
<td style="text-align: center;">0</td>
</tr>
</tbody>
</table>
</div>
<p>The main question for us in implementing this algorithm in Python is how we achieve step 4: repeating the two previous steps until some condition (“<code>y</code> is 0”) is satisfied. We know how to use for loops to iterate over a collection of values. This allowed us to repeat a sequence of statements (i.e., the body of the for loop) on every iteration. Naturally, the for loop ends when the statements have been repeated for all elements in a collection or range.</p>
<p>But in the case of step 4, we would like to repeat code based on some condition: “Repeat steps 2 and 3 until the remainder is 0”. In these scenarios, we must use a different kind of loop in Python: the <strong>while loop</strong>.</p>
<h2 id="the-while-loop-31dc2f7c50">The while loop</h2>
<p>A while loop looks very similar to an if statement:</p>
<div class="sourceCode" id="cb3-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-31dc2f7c50"><a href="#cb3-1-31dc2f7c50"></a><span class="cf">while</span> <span class="op">&lt;</span>condition<span class="op">&gt;</span>:</span>
<span id="cb3-2-31dc2f7c50"><a href="#cb3-2-31dc2f7c50"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb3-3-31dc2f7c50"><a href="#cb3-3-31dc2f7c50"></a> ...</span></code></pre></div>
<p>Unlike an if statement, after executing its body the while loop will check the condition again. If the condition still evaluates to <code>True</code>, then the body is repeated. Lets try an example:</p>
<div class="sourceCode" id="cb4-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-31dc2f7c50"><a href="#cb4-1-31dc2f7c50"></a><span class="op">&gt;&gt;&gt;</span> numbers <span class="op">=</span> []</span>
<span id="cb4-2-31dc2f7c50"><a href="#cb4-2-31dc2f7c50"></a><span class="op">&gt;&gt;&gt;</span> number <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb4-3-31dc2f7c50"><a href="#cb4-3-31dc2f7c50"></a><span class="op">&gt;&gt;&gt;</span> <span class="cf">while</span> number <span class="op">&lt;</span> <span class="dv">100</span>:</span>
<span id="cb4-4-31dc2f7c50"><a href="#cb4-4-31dc2f7c50"></a>... numbers.append(number)</span>
<span id="cb4-5-31dc2f7c50"><a href="#cb4-5-31dc2f7c50"></a>... number <span class="op">=</span> number <span class="op">*</span> <span class="dv">2</span></span>
<span id="cb4-6-31dc2f7c50"><a href="#cb4-6-31dc2f7c50"></a>...</span>
<span id="cb4-7-31dc2f7c50"><a href="#cb4-7-31dc2f7c50"></a><span class="op">&gt;&gt;&gt;</span> numbers</span>
<span id="cb4-8-31dc2f7c50"><a href="#cb4-8-31dc2f7c50"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">4</span>, <span class="dv">8</span>, <span class="dv">16</span>, <span class="dv">32</span>, <span class="dv">64</span>]</span></code></pre></div>
<p>Notice how <code>number</code> appears in both the while loops body and its condition. In the loop body, <code>number</code> is increasing at each iteration (we accumulated the values in the list <code>numbers</code>). Eventually, <code>number</code> refers to the value <code>128</code> and the while loop is done because <code>128 &lt; 100</code> evaluates to <code>False</code>. Note that the number of iterations of our while loop is dependent on the initial value of <code>number</code>. Had we started with a value of, for example, <code>10</code>, the loop would have only 4 iterations (not 6, as when <code>number</code> started with <code>2</code>). Similarly, if <code>number</code> was initially some value greater than or equal to <code>100</code>, then the while loop would never have executed its body (just as a for loop does not execute its body if given an empty collection).</p>
<h2 id="implementing-the-euclidean-algorithm-31dc2f7c50">Implementing the Euclidean Algorithm</h2>
<p>Here is our (first) implementation of the Euclidean algorithm for computing the gcd of two numbers.</p>
<div class="sourceCode" id="cb5-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-31dc2f7c50"><a href="#cb5-1-31dc2f7c50"></a><span class="kw">def</span> euclidean_gcd(a: <span class="bu">int</span>, b: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb5-2-31dc2f7c50"><a href="#cb5-2-31dc2f7c50"></a> <span class="co">&quot;&quot;&quot;Return the gcd of a and b.&quot;&quot;&quot;</span></span>
<span id="cb5-3-31dc2f7c50"><a href="#cb5-3-31dc2f7c50"></a> <span class="co"># Step 1: initialize x and y</span></span>
<span id="cb5-4-31dc2f7c50"><a href="#cb5-4-31dc2f7c50"></a> x <span class="op">=</span> a</span>
<span id="cb5-5-31dc2f7c50"><a href="#cb5-5-31dc2f7c50"></a> y <span class="op">=</span> b</span>
<span id="cb5-6-31dc2f7c50"><a href="#cb5-6-31dc2f7c50"></a> <span class="cf">while</span> y <span class="op">!=</span> <span class="dv">0</span>: <span class="co"># Step 4: repeat Steps 2 and 3 until y is 0</span></span>
<span id="cb5-7-31dc2f7c50"><a href="#cb5-7-31dc2f7c50"></a> <span class="co"># Step 2: calculate the remainder of x divided by y</span></span>
<span id="cb5-8-31dc2f7c50"><a href="#cb5-8-31dc2f7c50"></a> r <span class="op">=</span> x <span class="op">%</span> y</span>
<span id="cb5-9-31dc2f7c50"><a href="#cb5-9-31dc2f7c50"></a></span>
<span id="cb5-10-31dc2f7c50"><a href="#cb5-10-31dc2f7c50"></a> <span class="co"># Step 3: reassign x and y</span></span>
<span id="cb5-11-31dc2f7c50"><a href="#cb5-11-31dc2f7c50"></a> x <span class="op">=</span> y</span>
<span id="cb5-12-31dc2f7c50"><a href="#cb5-12-31dc2f7c50"></a> y <span class="op">=</span> r</span>
<span id="cb5-13-31dc2f7c50"><a href="#cb5-13-31dc2f7c50"></a></span>
<span id="cb5-14-31dc2f7c50"><a href="#cb5-14-31dc2f7c50"></a> <span class="co"># Step 5: x now refers to the gcd of a and b</span></span>
<span id="cb5-15-31dc2f7c50"><a href="#cb5-15-31dc2f7c50"></a> <span class="cf">return</span> x</span></code></pre></div>
<p>How does this loop work? To understand it better, lets see how this maps onto our original algorithm.</p>
<ul>
<li>Step 1, initializing <code>x</code> and <code>y</code>, occurs in the code before the while loop begins.</li>
<li>Steps 2 and 3 are performed inside the loop body.</li>
<li>Step 4, the repetition, is achieved by the while loop. One subtlety is that our original algorithm specified a <em>stopping condition</em>, “repeat until X”. When writing Python <code>while</code> loops, however, we must write a <em>continuing condition</em>, which is the negation of the stopping condition. So “until <span class="math inline">\(y = 0\)</span>” becomes <code>while y != 0</code>.</li>
<li>Step 5, the return value, is exactly what is specified by the algorithm.</li>
</ul>
<p>Lets see an example trace of the <code>euclidean_gcd</code> loop for the sample call <code>euclidean_gcd(24, 16)</code>:</p>
<div class="reference-table">
<table>
<thead>
<tr class="header">
<th style="text-align: center;">Iteration</th>
<th style="text-align: center;"><code>x</code></th>
<th style="text-align: center;"><code>y</code></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">0</td>
<td style="text-align: center;">24</td>
<td style="text-align: center;">16</td>
</tr>
<tr class="even">
<td style="text-align: center;">1</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">8</td>
</tr>
<tr class="odd">
<td style="text-align: center;">2</td>
<td style="text-align: center;">8</td>
<td style="text-align: center;">0</td>
</tr>
</tbody>
</table>
</div>
<p>In our implementation, we dont have a typical accumulator pattern. Instead, both <code>x</code> and <code>y</code> are <em>loop variables</em> for the while loop, which illustrates one major difference between while loops and for loops. In a for loop, the loop variable is initialized and reassigned automatically by the Python interpreter to each element of the collection being looped over. In a while loop, the loop variable(s) must be initialized and reassigned explicitly in code that we write.</p>
<p>This difference makes while loops more flexible than for loops, as the programmer has full control over exactly how the loop variable changes. This is both a strength and a weakness! While loops can be used to express algorithms that are cumbersome or impossible to express with for loops, but at the cost of requiring the programmer to write more code to keep track of loop variables.<label for="sn-4-31dc2f7c50" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-31dc2f7c50" class="margin-toggle"/><span class="sidenote"> Remember: the more code you write, the more potential there is for error.</span> So a good rule of thumb is to use for loops where possible (when you have an explicit collection to loop over), and reserve while loops for situations that cant be easily implemented with a for loop.</p>
<h3 id="parallel-assignment-31dc2f7c50">Parallel assignment</h3>
<p>One subtlety of our loop body is the order in which the loop variables are updated. Suppose we had swapped the last two lines of the loop body:</p>
<div class="sourceCode" id="cb6-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-31dc2f7c50"><a href="#cb6-1-31dc2f7c50"></a> <span class="cf">while</span> y <span class="op">!=</span> <span class="dv">0</span>:</span>
<span id="cb6-2-31dc2f7c50"><a href="#cb6-2-31dc2f7c50"></a> r <span class="op">=</span> x <span class="op">%</span> y</span>
<span id="cb6-3-31dc2f7c50"><a href="#cb6-3-31dc2f7c50"></a> y <span class="op">=</span> r</span>
<span id="cb6-4-31dc2f7c50"><a href="#cb6-4-31dc2f7c50"></a> x <span class="op">=</span> y</span></code></pre></div>
<p>This is a really easy change to make, but also incorrect: because the statement <code>y = r</code> is executed first, the next statement <code>x = y</code> assigns <code>x</code> to the <em>new</em> value of <code>y</code> rather than its old one!</p>
<p>When performing reassignment of multiple variables, where the new variable values depend on the old ones, it is important to keep track of the reassignment order so that you dont accidentally lose previous variable values. To avoid this problem altogether, Python has a neat feature called <em>parallel assignment</em>, in which multiple variables can be assigned in the same statment.</p>
<p>Here is how we can rewrite the loop body using parallel assignment:</p>
<div class="sourceCode" id="cb7-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-31dc2f7c50"><a href="#cb7-1-31dc2f7c50"></a> <span class="cf">while</span> y <span class="op">!=</span> <span class="dv">0</span>:</span>
<span id="cb7-2-31dc2f7c50"><a href="#cb7-2-31dc2f7c50"></a> r <span class="op">=</span> x <span class="op">%</span> y</span>
<span id="cb7-3-31dc2f7c50"><a href="#cb7-3-31dc2f7c50"></a> x, y <span class="op">=</span> y, r</span></code></pre></div>
<p>The assignment statement <code>x, y = y, r</code> is evaluated as follows:</p>
<ul>
<li>First, the right-hand side <code>y, r</code> is evaluated, producing two objects.<label for="sn-5-31dc2f7c50" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-31dc2f7c50" class="margin-toggle"/><span class="sidenote">Or more precisely, the <em>ids</em> of two objects.</span></li>
<li>Then, each object is assigned to the corresponding variable on the left-hand side.</li>
</ul>
<p>In parallel assignment, the right-hand side is fully evaluated before any variable reassignment occurs. This means that the assignment statement <code>x, y = y, r</code> has the <em>same effect</em> as <code>y, x = r, y</code>—order doesnt matter, and so we can think of each variable assignment happening in parallel, without one affecting the other.</p>
<p>Parallel is a very useful tool when reassigning variables, so please take advantage of it to help simplify your code and avoid the “update order” problem of variable reassignment. Here is how we can rewrite the <code>euclidean_gcd</code> using parallel assignment:</p>
<div class="sourceCode" id="cb8-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-31dc2f7c50"><a href="#cb8-1-31dc2f7c50"></a><span class="kw">def</span> euclidean_gcd(a: <span class="bu">int</span>, b: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb8-2-31dc2f7c50"><a href="#cb8-2-31dc2f7c50"></a> <span class="co">&quot;&quot;&quot;Return the gcd of a and b.&quot;&quot;&quot;</span></span>
<span id="cb8-3-31dc2f7c50"><a href="#cb8-3-31dc2f7c50"></a> x, y <span class="op">=</span> a, b</span>
<span id="cb8-4-31dc2f7c50"><a href="#cb8-4-31dc2f7c50"></a> <span class="cf">while</span> y <span class="op">!=</span> <span class="dv">0</span>:</span>
<span id="cb8-5-31dc2f7c50"><a href="#cb8-5-31dc2f7c50"></a> r <span class="op">=</span> x <span class="op">%</span> y</span>
<span id="cb8-6-31dc2f7c50"><a href="#cb8-6-31dc2f7c50"></a> x, y <span class="op">=</span> y, r</span>
<span id="cb8-7-31dc2f7c50"><a href="#cb8-7-31dc2f7c50"></a></span>
<span id="cb8-8-31dc2f7c50"><a href="#cb8-8-31dc2f7c50"></a> <span class="cf">return</span> x</span></code></pre></div>
<h3 id="documenting-loop-properties-loop-invariants-31dc2f7c50">Documenting loop properties: loop invariants</h3>
<p>Our implementation of <code>euclidean_gcd</code> doesnt follow a typical pattern of code weve seen so far. If we didnt know anything about the algorithm and were simply looking at the code, it would be quite mysterious why it works. To improve the readability of this code, we want some way of documenting what we know about the loop variables <code>x</code> and <code>y</code> inside the loop body.</p>
<p>Recall that the Euclidean Algorithm relies on one key property, that <code>gcd(x, y) == gcd(y, x % y)</code>. At each loop iteration, <code>x</code> and <code>y</code> are updated so that <code>x = y</code> and <code>y = x % y</code>. The key property that we want to capture is that <em>even though <code>x</code> and <code>y</code> change, their gcd doesnt</em>. Since <code>x</code> and <code>y</code> are initialized to <code>a</code> and <code>b</code>, another way to express this is that at every loop iteration, <code>gcd(x, y) == gcd(a, b)</code>. We call this statement a <strong>loop invariant</strong>, which is a property about loop variables that must be true at the start and end of each loop iteration.<label for="sn-6-31dc2f7c50" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-31dc2f7c50" class="margin-toggle"/><span class="sidenote"> This is similar to representation invariants, which are properties of instance attributes that must be true for every instance of a given data class.</span></p>
<p>By convention, we document loop invariants at the top of a loop body using an assert statement.</p>
<div class="sourceCode" id="cb9-31dc2f7c50"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-31dc2f7c50"><a href="#cb9-1-31dc2f7c50"></a><span class="kw">def</span> euclidean_gcd(a: <span class="bu">int</span>, b: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb9-2-31dc2f7c50"><a href="#cb9-2-31dc2f7c50"></a> <span class="co">&quot;&quot;&quot;Return the gcd of a and b.&quot;&quot;&quot;</span></span>
<span id="cb9-3-31dc2f7c50"><a href="#cb9-3-31dc2f7c50"></a> x, y <span class="op">=</span> a, b</span>
<span id="cb9-4-31dc2f7c50"><a href="#cb9-4-31dc2f7c50"></a></span>
<span id="cb9-5-31dc2f7c50"><a href="#cb9-5-31dc2f7c50"></a> <span class="cf">while</span> y <span class="op">!=</span> <span class="dv">0</span>:</span>
<span id="cb9-6-31dc2f7c50"><a href="#cb9-6-31dc2f7c50"></a> <span class="co"># Loop invariant (we use naive_gcd to check that the gcd are correct)</span></span>
<span id="cb9-7-31dc2f7c50"><a href="#cb9-7-31dc2f7c50"></a> <span class="cf">assert</span> naive_gcd(x, y) <span class="op">==</span> naive_gcd(a, b)</span>
<span id="cb9-8-31dc2f7c50"><a href="#cb9-8-31dc2f7c50"></a></span>
<span id="cb9-9-31dc2f7c50"><a href="#cb9-9-31dc2f7c50"></a> r <span class="op">=</span> x <span class="op">%</span> y</span>
<span id="cb9-10-31dc2f7c50"><a href="#cb9-10-31dc2f7c50"></a> x, y <span class="op">=</span> y, r</span>
<span id="cb9-11-31dc2f7c50"><a href="#cb9-11-31dc2f7c50"></a></span>
<span id="cb9-12-31dc2f7c50"><a href="#cb9-12-31dc2f7c50"></a> <span class="cf">return</span> x</span></code></pre></div>
<p>Because this loop invariant must be true at the start and end of each loop iteration, it is also true after the loop stops (i.e., when <code>y == 0</code>). In this case, the loop invariant tells us that <code>gcd(x, 0) == gcd(a, b)</code>, and so we know that <code>x == gcd(a, b)</code>, which is why <code>x</code> is returned.</p>
<p>Loop invariants are a powerful way to document properties of our code, to better enable us to reason about our code. But remember that loop invariants by themselves are just statements; the only way to know for sure whether a loop invariant is correct is to do a proof, much like the one we did at the beginning of this section.</p>
<!-- ## The Extended Euclidean Algorithm
Recall the *GCD characterization theorem* from the previous section, which said that $\gcd(a, b)$ is the smallest positive integer that can be written as a linear combination of $a$ and $b$.
How would we go about proving such a statement?
Our previous proofs of existential statements were all *constructive*: we pick values for the existentially-quantified variables and show that those variables satisfy the rest of the statement we're trying to prove.
First, we're going to see a non-constructive proof: a proof that shows the existence of values, but doesn't necessarily give explicit expressions for them.
<div class="proof">
Let $x, y \in Z$, and assume $x \neq 0$ or $y \neq 0$.
We define the set $S = \{ px + qy \mid p, q \in \Z \land px + qy > 0 \}$,
and let $d = \min(S)$.
We'll prove that $d = \gcd(x, y)$.
This proof uses a new technique to show equality: first, we show $d \geq \gcd(x, y)$, and then $d \leq \gcd(x, y)$, so that the only possibility is that $d$ in fact equals $\gcd(x, y)$.
**Part 1**: proving that $d \geq \gcd(x, y)$.
Since $\gcd(x, y)$ divides both $x$ and $y$, by Theorem TODO, we know that it divides any linear combination of $x$ and $y$.
And so $\gcd(x, y) \mid d$; since both numbers are positive, this implies that $\gcd(x, y) \leq d$.
**Part 2**: proving that $d \leq \gcd(x, y)$.
First, we'll prove that $d \mid x$.
By the Quotient-Remainder Theorem, we write $x = dq + r$, where $q, r \in Z$ and $0 \leq r < d$.
We can rearrange this equation to obtain $r = x - dq$, which means $r$ is a linear combination of $x$ and $y$ (since $d$ is a linear combination of $x$ and $y$).
But since we know $r < d$ and $d = \min(S)$, this implies $r \notin S$, which is only possible when $r = 0$.
So $d \mid x$.
Similarly, $d \mid y$, and so $d$ is a common divisor of $x$ and $y$.
By the definition of $\gcd$, we can conclude that $d \leq \gcd(x, y)$.
</div>
This proof is technically correct, and interesting because it shows a new technique for proving existentials.
But it is also a bit unsatisfying in that it proves the existence of some values (coefficients of the linear combination) without showing how to find them.
It turns out that a variation of the Euclidean Algorithm called the *Extended Euclidean Algorithm* can be used to not just find the gcd of two numbers, but find the coefficients of the linear combination that equals that gcd.
You'll explore this more on an exercise a bit later in this course.
</section> -->
<!--
Recall that the implementation relies on a *property* of divisibility to restrict the set of numbers to quantify over:
when $n \neq 0$, every number that divides $n$ must lie in the range ${- |n|, -|n| + 1, \dots, |n| - 1, |n|}$.
We can use `divides` in another function that searches for the gcd.
In this scenario, it makes sense to start from the end of the `possible_divisors` range and work our way backwards.
For example, for two numbers `x = 16` and `y = 24`:
```python
>>> x = 16
>>> y = 24
>>> range(min(abs(y), abs(x)), 0, -1)
range(16, 0, -1)
>>> list(range(min(abs(y), abs(x)), 0, -1))
[16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
```
In this scenario, we asked range to start at a value greater than its stop (i.e., `16` > `0`, recall that the stop is not included).
In addition, we provided range with a step value of `-1`.
We can now test if, for each `d` in the range above, `d` divides evenly into both `x` and `y`:
```python
def gcd(x: int, y: int) -> int:
"""Return the greatest common divisor of x and y."""
for d in range(min(abs(y), abs(x)), 0, -1):
if divides(d, x) and divides(d, y):
return d
return 0
```
-->
<br/> <a id="anchor-06-07"></a>
<header id="title-block-header-b8121c763b">
<h1 class="title">6.7 Modular Arithmetic</h1>
</header>
<section>
<p>In this section, well explore some properties of modular arithmetic that will be useful in the next chapter, when we study cryptographic algorithms based on modular arithmetic. First, recall the definition of modular equivalence from <a href="01-number-theory-definitions.html">6.1 An Introduction to Number Theory</a>.</p>
<div class="definition">
<p>Let <span class="math inline">\(a, b, n \in \Z\)</span>, and assume <span class="math inline">\(n \neq 0\)</span>. We say that <strong><span class="math inline">\(a\)</span> is equivalent to <span class="math inline">\(b\)</span> modulo <span class="math inline">\(n\)</span></strong> when <span class="math inline">\(n \mid a - b\)</span>. In this case, we write <span class="math inline">\(a \equiv b \pmod n\)</span>.<label for="sn-0-b8121c763b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-b8121c763b" class="margin-toggle"/><span class="sidenote">One warning: the notation <span class="math inline">\(a \equiv b \pmod n\)</span> is not exactly the same as <code>mod</code> or <code>%</code> operator you are familiar with from programming; here, both <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> could be much larger than <span class="math inline">\(n\)</span>, or even negative.</span></p>
</div>
<p>This definition captures the idea that <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> have the <em>same remainder</em> when divided by <span class="math inline">\(n\)</span>. You should think of this congruence relation as being analogous to numeric equality, with a relaxation. When we write <span class="math inline">\(a = b\)</span>, we mean that the numeric values of <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> are literally equal. When we write <span class="math inline">\(a \equiv b \pmod n\)</span>, we we mean that if you look at the remainders of <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> when divided by <span class="math inline">\(n\)</span>, those remainders are literally equal.</p>
<p>We will next look at how addition, subtraction, and multiplication all behave in an analogous fashion under modular arithmetic. The following proof is a little tedious because it is calculation-heavy; the main benefits here are practicing reading and using a new definition, and getting comfortable with this particular notation.</p>
<div class="theorem">
<p>For all <span class="math inline">\(a, b, c, d, n \in \Z\)</span>, if <span class="math inline">\(n \neq 0\)</span>, if <span class="math inline">\(a \equiv c \pmod n\)</span> and <span class="math inline">\(b \equiv d \pmod n\)</span>, then:</p>
<ol type="1">
<li><span class="math inline">\(a + b \equiv c + d \pmod n\)</span></li>
<li><span class="math inline">\(a - b \equiv c - d \pmod n\)</span></li>
<li><span class="math inline">\(ab \equiv cd \pmod n\)</span></li>
</ol>
<div class="translation">
<p>We will only show how to translate and prove (2), and leave (1) and (3) as exercises. <span class="math display">\[\forall a, b, c, d, n \in \Z,~ \big(n \neq 0 \AND (n \DIV a - c) \AND (n \DIV b - d) \big) \IMP n \DIV (a - b) - (c - d).\]</span></p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(a, b, c, d, n \in \Z\)</span>. Assume that <span class="math inline">\(n \neq 0\)</span>, <span class="math inline">\(n \DIV a - c\)</span>, and <span class="math inline">\(n \DIV b - d\)</span>. This means we want to prove that <span class="math inline">\(n \DIV (a-c) - (b-d).\)</span></p>
<p>By the <a href="05-greatest-common-divisor.html#theorem:divide_lin_comb">Divisibility of Linear Combinations Theorem</a>, since <span class="math inline">\(n \DIV (a-c)\)</span> and <span class="math inline">\(n \DIV (b - d)\)</span>, it divides their difference:</p>
<p><span class="math display">\[\begin{align*}
n &amp;\DIV (a-c) - (b-d) \\
n &amp;\DIV (a-b) - (c-d)
\end{align*}\]</span></p>
</div>
</div>
<h2 id="modular-division-b8121c763b">Modular division</h2>
<p>The above example stated that addition, subtraction, and multiples all preserve modular equivalence—but what above division? The following statement is a “divide by <span class="math inline">\(k\)</span>” property, but is actually <strong>False</strong>:<label for="sn-1-b8121c763b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-b8121c763b" class="margin-toggle"/><span class="sidenote"> A good exercise is to disprove this statement!</span> <span class="math display">\[
\forall a, b, k, n \in \Z,~ n &gt; 0 \land ak \equiv bk \pmod n \Rightarrow a \equiv b \pmod n
\]</span></p>
<p>For the real numbers, division <span class="math inline">\(\frac{x}{y}\)</span> has a single gap: when <span class="math inline">\(y = 0\)</span>. As well see in the next theorem, division in modular arithmetic can have many such gaps, but we can also predict exactly where these gaps will occur.</p>
<div id="theorem:modular-inverse-b8121c763b" class="theorem" data-label="Modular inverse">
<p>(<em>Modular inverse</em>) Let <span class="math inline">\(n \in \Z^+\)</span> and <span class="math inline">\(a \in \Z\)</span>. If <span class="math inline">\(\gcd(a, n) = 1\)</span>, then there exists <span class="math inline">\(p \in \Z\)</span> such that <span class="math inline">\(ap \equiv 1 \pmod n\)</span>.</p>
<p>We call this <span class="math inline">\(p\)</span> a <strong>modular inverse of <span class="math inline">\(a\)</span> modulo <span class="math inline">\(n\)</span></strong>.</p>
</div>
<div class="translation">
<p><span class="math inline">\(\forall n \in \Z^+, \forall a \in \Z,~ \gcd(a, n) = 1 \Rightarrow \big(\exists p \in \Z,~ ap \equiv 1 \pmod n \big)\)</span></p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(n \in \Z^+\)</span> and <span class="math inline">\(a \in Z\)</span>. Assume <span class="math inline">\(\gcd(a, n) = 1\)</span>.</p>
<p>Since <span class="math inline">\(\gcd(a, n) = 1\)</span>, by the <a href="05-greatest-common-divisor.html#theorem:gcd_characterization">GCD Characterization Theorem</a> we know that there exist integers <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> such that <span class="math inline">\(pa + qn = \gcd(a, n) = 1\)</span>.</p>
<p>Rearranging this equation, we get that <span class="math inline">\(pa - 1 = qn\)</span>, and so (by the definition of divisibility, taking <span class="math inline">\(k = q\)</span>), <span class="math inline">\(n \mid pa - 1\)</span>.</p>
<p>Then by the definition of modular equivalence, <span class="math inline">\(pa \equiv 1 \pmod n\)</span>.</p>
</div>
<p>From this theorem about modular inverses, we can build up a form of division for modular arithmetic. To gain some intuition, first think about division <span class="math inline">\(\frac{a}{b}\)</span> as the <em>solution</em> to an equation of the form <span class="math inline">\(ax = b\)</span>. Well turn this into a statement about modular equivalence now.</p>
<div class="example">
<p>Let <span class="math inline">\(a \in \Z\)</span> and <span class="math inline">\(n \in \Z^+\)</span>. If <span class="math inline">\(\gcd(a, n) = 1\)</span>, then for all <span class="math inline">\(b \in \Z\)</span>, there exists <span class="math inline">\(k \in \Z\)</span> such that <span class="math inline">\(ak \equiv b \pmod n\)</span>.</p>
<div class="translation">
<p>This statement is quite complex! Remember that we focus on translation to examine the structure of the statement, so that we know how to set up a proof. We arent going to expand every single definition for the sake of expanding definitions.</p>
<p><span class="math display">\[\forall n \in \Z^+, \forall a \in \Z,~ \gcd(a, n) = 1 \Rightarrow
\big(\forall b \in \Z,~ \exists k \in \Z,~ ak \equiv b \pmod n \big).\]</span></p>
</div>
<div class="discussion">
<p>So this is saying that under the given assumptions, <span class="math inline">\(b\)</span> is “divisible” by <span class="math inline">\(a\)</span> modulo <span class="math inline">\(n\)</span>. This comes after the theorem about modular inverses, so that should be useful. The conclusion is “there exists a <span class="math inline">\(k \in \Z\)</span> such that…” so that I know that at some point Ill need to define a variable <span class="math inline">\(k\)</span> in terms of <span class="math inline">\(a\)</span>, <span class="math inline">\(b\)</span>, and/or <span class="math inline">\(n\)</span>, which satisfies the congruence.</p>
<p>I notice that the hypothesis here (<span class="math inline">\(\gcd(a, n) = 1\)</span>) matches with the hypothesis from the previous theorem, so that seems to be something I can use. That gives me a <span class="math inline">\(p \in \Z\)</span> such that <span class="math inline">\(ap \equiv 1 \pmod n\)</span>…</p>
<p>Wait, I can multiply both sides by <span class="math inline">\(b\)</span>, right?!</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(a \in \Z\)</span> and <span class="math inline">\(n \in \Z^+\)</span>. Assume <span class="math inline">\(\gcd(a, n) = 1\)</span>, and let <span class="math inline">\(b \in \Z\)</span>. We want to prove that there exists <span class="math inline">\(k \in \Z\)</span> such that <span class="math inline">\(ak \equiv b \pmod n\)</span>.</p>
<p>First, using the previous <em>Modular Inverses</em> theorem, since we assmed <span class="math inline">\(\gcd(a, n) = 1\)</span>, we know that there exists <span class="math inline">\(p \in \Z\)</span> such that <span class="math inline">\(ap \equiv 1 \pmod n\)</span>.</p>
<p>Second, we know from (3) of our first example above that we can modular equivalence preserves multiplication, and so we know <span class="math inline">\(apb \equiv b \pmod n\)</span>.</p>
<p>Then we let <span class="math inline">\(k = pb\)</span>, and we have that <span class="math inline">\(ak \equiv b \pmod n\)</span>.</p>
</div>
</div>
<p>These two theorems bring together elements from all of our study of proofs so far. We have both types of quantifiers, mixed with a larger implication. We used the <a href="05-greatest-common-divisor.html#theorem:gcd_characterization">GCD Characterization Theorem</a> for a key step in our proof. This illustrates the power of separating ideas into different statements and using each one to prove the next, just like we separate code into different functions in our programs!</p>
<h2 id="exponentiation-and-order-b8121c763b">Exponentiation and order</h2>
<p>The last ingredient well need to understand for our study of cryptography next week is the patterns that emerge when it comes to exponentiation in modular arithmetic. In normal arithmetic, powers of positive integers increase without bound, but in modular arithmetic we can focus on the <em>remainders</em> of powers, and discover some wonderful properties. For example, <span class="math inline">\(10^{13}\)</span> is a very large number indeed, but <span class="math inline">\(10^{13} \equiv 3 \pmod 7\)</span>! In fact, because there are only a finite number of remainders for any given <span class="math inline">\(n \in \Z^+\)</span>, for any <span class="math inline">\(a \in \Z\)</span> the infinite sequence of <em>remainders</em> of <span class="math inline">\(a^0\)</span>, <span class="math inline">\(a^1\)</span>, <span class="math inline">\(a^2\)</span>, <span class="math inline">\(a^3\)</span>, <span class="math inline">\(\dots\)</span> must repeat at some point.</p>
<p>For example, lets see what happens for each of the possible bases modulo 7:<label for="sn-2-b8121c763b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-b8121c763b" class="margin-toggle"/><span class="sidenote"> Because exponentiation by positive integers corresponds to repeated multiplication, which behaves “nicely” with modular arithmetic, the list below covers all possible integers. For example, because <span class="math inline">\(10 \equiv 3 \pmod 7\)</span>, we also know that <span class="math inline">\(10^{13} \equiv 3^{13} \pmod 7\)</span>.</span></p>
<ul>
<li>0: <span class="math inline">\(0^1 \equiv 0 \pmod 7\)</span>, <span class="math inline">\(0^2 \equiv 0 \pmod 7\)</span></li>
<li>1: <span class="math inline">\(1^1 \equiv 1 \pmod 7\)</span>, <span class="math inline">\(1^2 \equiv 1 \pmod 7\)</span></li>
<li>2: <span class="math inline">\(2^1 \equiv 2 \pmod 7\)</span>, <span class="math inline">\(2^2 \equiv 4 \pmod 7\)</span>, <span class="math inline">\(2^3 \equiv 1 \pmod 7\)</span>, <span class="math inline">\(2^4 \equiv 2 \pmod 7\)</span></li>
<li>3: <span class="math inline">\(3^1 \equiv 3 \pmod 7\)</span>, <span class="math inline">\(3^2 \equiv 2 \pmod 7\)</span>, <span class="math inline">\(3^3 \equiv 6 \pmod 7\)</span>, <span class="math inline">\(3^4 \equiv 4 \pmod 7\)</span>, <span class="math inline">\(3^5 \equiv 5 \pmod 7\)</span>, <span class="math inline">\(3^6 \equiv 1 \pmod 7\)</span>, <span class="math inline">\(3^7 \equiv 3 \pmod 7\)</span></li>
<li>4: <span class="math inline">\(4^1 \equiv 4 \pmod 7\)</span>, <span class="math inline">\(4^2 \equiv 2 \pmod 7\)</span>, <span class="math inline">\(4^3 \equiv 1 \pmod 7\)</span>, <span class="math inline">\(4^4 \equiv 4 \pmod 7\)</span></li>
<li>5: <span class="math inline">\(5^1 \equiv 5 \pmod 7\)</span>, <span class="math inline">\(5^2 \equiv 4 \pmod 7\)</span>, <span class="math inline">\(5^3 \equiv 6 \pmod 7\)</span>, <span class="math inline">\(5^4 \equiv 2 \pmod 7\)</span>, <span class="math inline">\(5^5 \equiv 3 \pmod 7\)</span>, <span class="math inline">\(5^6 \equiv 1 \pmod 7\)</span>, <span class="math inline">\(5^7 \equiv 5 \pmod 7\)</span></li>
<li>6: <span class="math inline">\(6^1 \equiv 6 \pmod 7\)</span>, <span class="math inline">\(6^2 \equiv 1 \pmod 7\)</span>, <span class="math inline">\(6^3 \equiv 6 \pmod 7\)</span></li>
</ul>
<p>No matter which base we start with, we enter a cycle. For example, the cycle starting with 2 is <span class="math inline">\([2, 4, 1, 2, \dots]\)</span>. We say this cycle has length 3, since it takes three elements in the sequence for the 2 to repeat. Here are the cycle lengths for each possible <span class="math inline">\(a \in \{0, 1, \dots, 6\}\)</span>:</p>
<table>
<thead>
<tr class="header">
<th><span class="math inline">\(a\)</span></th>
<th>Cycle length</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1</td>
</tr>
<tr class="even">
<td>1</td>
<td>1</td>
</tr>
<tr class="odd">
<td>2</td>
<td>3</td>
</tr>
<tr class="even">
<td>3</td>
<td>6</td>
</tr>
<tr class="odd">
<td>4</td>
<td>3</td>
</tr>
<tr class="even">
<td>5</td>
<td>6</td>
</tr>
<tr class="odd">
<td>6</td>
<td>2</td>
</tr>
</tbody>
</table>
<p>For each base other than 0, there is another way of looking at the cycle length: the cycle length for base <span class="math inline">\(a\)</span> is the smallest positive integer <span class="math inline">\(k\)</span> such that <span class="math inline">\(a^k \equiv 1 \pmod 7\)</span>. For example, <span class="math inline">\(2^3 \equiv 1 \pmod 7\)</span>, and the cycle repeats at <span class="math inline">\(2^4 \equiv 2^3 \cdot 2 \equiv 2 \pmod 7\)</span>.</p>
<p>This “cycle length” is a fundamental property of modular exponentiation, and warrants its own definition.</p>
<div class="definition">
<p>Let <span class="math inline">\(a \in \Z\)</span> and <span class="math inline">\(n \in \Z^+\)</span>. We define the <strong>order of <span class="math inline">\(a\)</span> modulo <span class="math inline">\(n\)</span></strong> to be the smallest positive integer <span class="math inline">\(k\)</span> such that <span class="math inline">\(a^k \equiv 1 \pmod n\)</span>, when such a number exists.</p>
<p>We denote the order of <span class="math inline">\(a\)</span> modulo <span class="math inline">\(n\)</span> as <span class="math inline">\(\text{ord}_n(a)\)</span>.</p>
</div>
<p>Something you might notice from our above table is that the cycle length for the remainders modulo 7 always divides 6. Here is another table, this time for modulo 17.</p>
<table>
<thead>
<tr class="header">
<th><span class="math inline">\(a\)</span></th>
<th>Cycle length</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1</td>
</tr>
<tr class="even">
<td>1</td>
<td>1</td>
</tr>
<tr class="odd">
<td>2</td>
<td>8</td>
</tr>
<tr class="even">
<td>3</td>
<td>16</td>
</tr>
<tr class="odd">
<td>4</td>
<td>4</td>
</tr>
<tr class="even">
<td>5</td>
<td>16</td>
</tr>
<tr class="odd">
<td>6</td>
<td>16</td>
</tr>
<tr class="even">
<td>7</td>
<td>16</td>
</tr>
<tr class="odd">
<td>8</td>
<td>8</td>
</tr>
<tr class="even">
<td>9</td>
<td>8</td>
</tr>
<tr class="odd">
<td>10</td>
<td>16</td>
</tr>
<tr class="even">
<td>11</td>
<td>16</td>
</tr>
<tr class="odd">
<td>12</td>
<td>16</td>
</tr>
<tr class="even">
<td>13</td>
<td>4</td>
</tr>
<tr class="odd">
<td>14</td>
<td>16</td>
</tr>
<tr class="even">
<td>15</td>
<td>8</td>
</tr>
<tr class="odd">
<td>16</td>
<td>2</td>
</tr>
</tbody>
</table>
<p>A similar pattern emerges: the cycle length for these bases always divides 16, which is one less than 17. And again, for each base <span class="math inline">\(a\)</span> other than 0, the cycle length corresponding to <span class="math inline">\(a\)</span> is the least positive integer <span class="math inline">\(k\)</span> such that <span class="math inline">\(a^k \equiv 1 \pmod{17}\)</span>.</p>
<p>Here is one more interesting fact about cycle length: because it is a number <span class="math inline">\(k\)</span> such that <span class="math inline">\(a^k \equiv 1 \pmod{17}\)</span>, <em>any</em> multiple <span class="math inline">\(n\)</span> of <span class="math inline">\(k\)</span> also satisfies <span class="math inline">\(a^n \equiv 1 \pmod{17}\)</span>. For example, <span class="math inline">\(13^4 \equiv 1 \pmod{17}\)</span>, and so <span class="math inline">\(13^{40} \equiv (13^4)^{10} \equiv 1^{10} \equiv 1 \pmod{17}\)</span>.</p>
<p>Combining these two observations allows us to conclude that, at least for 17, <em>every</em> base <span class="math inline">\(a\)</span> other than 0 satisfies <span class="math inline">\(a^{16} \pmod{17}\)</span>. It is a remarkable fact that this turns out to generalize to every prime number. Proving this theorem is beyond the scope of this course, but well state it formally here to let you marvel at it for a moment.</p>
<div class="theorem">
<p>(<em>Fermats Little Theorem</em>) Let <span class="math inline">\(p, a \in \Z\)</span> and assume <span class="math inline">\(p\)</span> is prime and that <span class="math inline">\(p \nmid a\)</span>. Then <span class="math inline">\(a^{p - 1} \equiv 1 \pmod p\)</span>.</p>
</div>
<!-- <div translation>
$\forall p, a \in \Z,~ \mathit{Prime}(p) \land p \nmid a \Rightarrow a^{p - 1} \equiv 1 \pmod p$.
</div>
<div discussion>
This proof is one of the most novel that we'll see in this course.
It is based not on a calculation or manipulation of inequalities, but rather a very clever construction of a function with particularly useful properties.
We wouldn't expect you to come up with this proof idea yourselves (we certainly didn't when we first learned this!), but you should be able to read through the proof below and understand it.
</div>
<div proof>
Let $p, a \in \Z$ and assume $p$ is prime and that $p \nmid a$.
We'll prove that $a^{p - 1} \equiv 1 \pmod p$.
First, we define the following set: let $S = \{x \mid x \in \Z \land 1 \leq x < p \}$.
We define the function $f: S \to S$ as $f(x) = ax \% n$, where $\%$ denotes the remainder operation.
We leave it as an exercise to prove that $f$ is well-defined, i.e., for all $x \in S$, it's true that $f(x) \in S$ as well.
Note that from ths definition, we have $f(x) \equiv ax \pmod p$ for all $x \in S$.
Next, we'll prove the following key property of this function $f$.
**Proving that $f$ is a bijection.**
Since $S$ is finite, it is enough to prove that $f$ is one-to-one.
Let $x, y \in S$ and assume $f(x) = f(y)$.
Then by the definition of $f$, we know that $ax \equiv ay \pmod p$.
Since $p \nmid a$, we know that $\gcd(p, a) = 1$, and so by the modular cancellation theorem (**TODO**:check name/reference), we know that $x \equiv y \pmod p$.
Since $x$ and $y$ are both in the range 1 to $p - 1$, this means $x = y$.
So $f$ is one-to-one.
Now here is the key idea: consider the product
\begin{align*}
\prod_{x \in S} f(x) &\equiv \prod_{x \in S} ax \pmod p \tag{since $f(x) \equiv ax \pmod p$} \\
\prod_{x \in S} f(x) &\equiv a^{|S|} \prod_{x \in S} x \pmod p
\end{align*}
But since $f$ is a bijection on $S$, the products $\prod_{x \in S} f(x)$ and $\prod_{x \in S} x$ are equal: they're both expressions multiplying all elements of $S$ modulo $p$!
Moreover, since all elements of $S$ have a gcd of $1$ with $p$, we can apply the cancellation law to both sides of the equivalence to obtain
$$1 \equiv a^{|S|} \pmod p.$$
Finally, we know that $|S| = p - 1$, and so $a^{p-1} \equiv 1 \pmod p$.
</div> -->
<h2 id="eulers-theorem-b8121c763b">Eulers Theorem</h2>
<p>Fermats Little Theorem is quite beautiful in its own right, but is limited in scope to prime numbers. It turns out that the key to generalizing this theorem lies with our very last definition in this chapter.</p>
<!-- It turns out that we can generalize it to any positive modulus by studying our above proof a bit more closely.
Why did we need that $p$ is prime?
In two places: so that we could use the assumption $p \nmid a$ to apply the cancellation theorem to $ax \equiv ay \pmod p$,
and later to apply the cancellation theorem to
$\prod_{x \in S} f(x) \equiv a^{|S|} \prod_{x \in S} x \pmod p$.
The cancellation theorem doesn't just apply to prime numbers, though; it applies to any pair of numbers $a$ and $n$ such that $\gcd(a, n) = 1$.
This is the key to generalizing Fermat's Little Theorem. -->
<div class="definition">
<p>We define the function <span class="math inline">\(\varphi : \Z^+ \to \N\)</span>, called the <strong>Euler totient function</strong> (or <strong>Euler phi function</strong>), as follows:</p>
<p><span class="math display">\[\varphi(n) = \big| \big\{ a \mid a \in \{1, \dots, n - 1\},~ \text{and $\gcd(a, n) = 1$} \big\} \big|.\]</span></p>
</div>
<p>Here are some examples of the Euler totient function:</p>
<ul>
<li><span class="math inline">\(\varphi(5) = 4\)</span>, since <span class="math inline">\(\{1, 2, 3, 4\}\)</span> are all coprime to 5.</li>
<li><span class="math inline">\(\varphi(6) = 2\)</span>, since only <span class="math inline">\(\{1, 5\}\)</span> are coprime to 6.</li>
<li>In general, for any prime number <span class="math inline">\(p\)</span>, <span class="math inline">\(\varphi(p) = p - 1\)</span>, since all the numbers <span class="math inline">\(\{1, 2, \dots, p - 1\}\)</span> are coprime to <span class="math inline">\(p\)</span>.<label for="sn-3-b8121c763b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-b8121c763b" class="margin-toggle"/><span class="sidenote"> Exercise: prove this using the definition of prime!</span></li>
<li><span class="math inline">\(\varphi(15) = 8\)</span>, since the numbers <span class="math inline">\(\{1, 2, 4, 7, 8, 11, 13, 14\}\)</span> are all coprime to 15. Note that the ``removed’’ numbers are all multiples of 3 or 5, the prime factors of 15.</li>
<li>In general, for any two distinct primes <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span>, <span class="math inline">\(\varphi(pq) = (p - 1)(q - 1)\)</span>, although this is certainly not obvious, and requires a proof!</li>
</ul>
<p>With the Euler totient function in hand, we can now state the generalization of Fermats Little Theorem, which is something well use in the next chapter.</p>
<div id="theorem:eulers-theorem-b8121c763b" class="theorem">
<p>(<em>Eulers Theorem</em>). For all <span class="math inline">\(a \in \Z\)</span> and <span class="math inline">\(n \in \Z^+\)</span>, if <span class="math inline">\(\gcd(a, n) = 1\)</span> then <span class="math inline">\(a^{\varphi(n)} \equiv 1 \pmod n\)</span>.</p>
<!-- <div class="proof">
Let $n \in \Z^+$ and let $a \in \Z$, and assume $\gcd(a, n) = 1$.
Let $S = \{x \mid x \in \Z \land 1 \leq x < n \land \gcd(x, n) = 1 \}$.
We define the function $f: S \to S$ as $f(x) = ax \% n$, where $\%$ denotes the remainder operation.
We leave it as an exercise to prove that $f$ is well-defined, i.e., for all $x \in S$, it's true that $f(x) \in S$ as well.
Note that from ths definition, we have $f(x) \equiv ax \pmod n$ for all $x \in S$.
First, we prove that $f$ is a bijection.
Since $S$ is finite, it is enough to prove that $f$ is one-to-one.
Let $x, y \in S$ and assume $f(x) = f(y)$.
Then by the definition of $f$, we know that $ax \equiv ay \pmod n$.
By the cancellation theorem, since $\gcd(a, n) = 1$, we know that $x \equiv y \pmod n$.
Since $x$ and $y$ are both in the range 1 to $n - 1$, this means $x = y$.
So $f$ is one-to-one.
Now here is the key idea: consider the product
\begin{align*}
\prod_{x \in S} f(x) &\equiv \prod_{x \in S} ax \pmod n \tag{since $f(x) \equiv ax \pmod n$} \\
\prod_{x \in S} f(x) &\equiv a^{|S|} \prod_{x \in S} x \pmod n
\end{align*}
But since $f$ is a bijection on $S$, the products $\prod_{x \in S} f(x)$ and $\prod_{x \in S} x$ are equal: they're both expressions multiplying all elements of $S$!
Moreover, since all elements of $S$ have a gcd of $1$ with $n$, we can apply the cancellation law to both sides of the equivalence to obtain
$$1 \equiv a^{|S|} \pmod n.$$
Finally, by the definition of the Euler totient function, we know that $|S| = \varphi(n)$, and so $a^{\varphi(n)} \equiv 1 \pmod n$.
</div> -->
</div>
</section>
<br/>
<h2 class="unnumbered" id="case-study-cryptography">7. Case Study: Cryptography</h2>
<a id="anchor-07-01"></a>
<header id="title-block-header-b6987c84a0">
<h1 class="title">7.1 An Introduction to Cryptography</h1>
</header>
<section>
<p>So far weve seen how the data types we introduced in Chapter 1 can be used to store a variety of different data. In our modern world, data is constantly being created, stored, sent, and received. But not all data is created equal; some data is inherently more sensitive than other data. And <a href="https://en.wikipedia.org/wiki/Personal_Information_Protection_and_Electronic_Documents_Act">there are laws</a> mandating the privacy of your data in Canada. Thanks to the explosion of data and the evolution of privacy policy, there are numerous technologies (backed by a strong theoretical underpinning) being developed to ensure data privacy.</p>
<p>After our work from last week, we now have the theoretical foundations necessary to learn about one of the coolest applications of number theory in computer science: encrypting messages so that only the sender and receiver can read them.<label for="sn-0-b6987c84a0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-b6987c84a0" class="margin-toggle"/><span class="sidenote"> Check out the movie <a href="https://en.wikipedia.org/wiki/The_Imitation_Game">The Imitation Game</a>, which is about some amazing codebreaking work done in World War II (and a crucial piece in the history of computing).</span> This is only one method for ensuring data privacy, but it is pervasive—nearly every time you send or receive something on your phone or web browser, cryptography plays a role. In this section, youll learn about the basics of <em>cryptography</em>, which is the study of theoretical and practical techniques for keeping data secure.</p>
<h2 id="what-is-cryptography-b6987c84a0">What is cryptography?</h2>
<p>Cryptography is the study of techniques used to keep communication secure in the face of adversaries who wish to eavesdrop on or interfere with the communication. Defining what <em>secure</em> communication between two parties means is complex, and involves several dimensions such as: confidentiality, data integrity, and authentication. In this chapter we will focus primarily on encryption, which involves turning coherent messages into seemingly-random nonsensical strings, and then back again.</p>
<p>As computers have become more powerful, cryptographic technologies have evolved to ensure that the “nonsense” strings are not easily converted back to the coherent message except by the intended recipient(s). But the growing power of computers is a double-edged sword; while cryptographic technologies have evolved, so have the technologies of malicious attackers and eavesdroppers who want to decipher the “nonsense” strings and gain access to sensitive data, such as passwords and social insurance numbers.</p>
<h2 id="setting-the-stage-alice-and-bob-b6987c84a0">Setting the stage: Alice and Bob</h2>
<p>The simplest setup that we study in cryptography is <em>two-party confidential communication</em>. In this setup, we have two people, Alice and Bob, who wish to send messages to each other that only they can read, and a third person, Eve, who has access to all of the communications between Alice and Bob, and wants to discover what theyre saying.</p>
<p>Since Eve has access to the communications between Alice and Bob, they cant just send their messages directly. So instead, Alice and Bob need to encrypt their messages using some sort of encryption algorithm, and send the encrypted versions to each other instead. The hope is that through some shared piece of information called a secret key, Alice and Bob can encrypt their messages in such a way that they will each be able to decrypt each others messages, but Eve wont be able to decrypt the messages without knowing their secret key.</p>
<p>More formally, we define a <strong>secure symmetric-key cryptosystem</strong> as a system with the following parts:</p>
<ul>
<li><p>A set <span class="math inline">\(\mathcal{P}\)</span> of possible original messages, called <strong>plaintext</strong> messages. (E.g., a set of strings)</p></li>
<li><p>A set <span class="math inline">\(\mathcal{C}\)</span> of possible encrypted messages, called <strong>ciphertext</strong> messages. (E.g., another set of strings)</p></li>
<li><p>A set <span class="math inline">\(\mathcal{K}\)</span> of possible <strong>shared secret keys</strong> (known by both Alice and Bob, but no one else).</p></li>
<li><p>Two functions <span class="math inline">\(Encrypt : \mathcal{K} \times \mathcal{P} \to \mathcal{C}\)</span> and <span class="math inline">\(Decrypt : \mathcal{K} \times \mathcal{C} \to \mathcal{P}\)</span> that satisfies the following two properties:</p>
<ul>
<li>(<em>correctness</em>) For all <span class="math inline">\(k \in \mathcal{K}\)</span> and <span class="math inline">\(m \in \mathcal{P}\)</span>, <span class="math inline">\(Decrypt(k, Encrypt(k, m)) = m\)</span>. (That is, if you encrypt and then decrypt the same message with the same key, you get back the original message.)</li>
<li>(<em>security</em>) For all <span class="math inline">\(k \in \mathcal{K}\)</span> and <span class="math inline">\(m \in \mathcal{P}\)</span>, if an eavesdropper only knows the value of <span class="math inline">\(c = Encrypt(k, m)\)</span> but does not know <span class="math inline">\(k\)</span>, it is computationally infeasible to find <span class="math inline">\(m\)</span>.</li>
</ul></li>
</ul>
<h2 id="example-caesars-substitution-cipher-b6987c84a0">Example: Caesars substitution cipher</h2>
<p>One of the earliest examples we have of a symmetric-key cryptosystem is the <em>Caesar cipher</em>, named after the Roman general Julius Caesar. In this system, the plaintext and ciphertext sets are simply strings, and the secret key is some positive integer <span class="math inline">\(k\)</span>.</p>
<p>The idea of this cryptosystem, as well as the starting point of many others, is to associate characters with numbers, because we can do more things with numbers. In this example, well first only consider messages that consist of uppercase letters and spaces, and associate each of these letters with a number as follows:</p>
<div class="reference-table">
<table>
<thead>
<tr class="header">
<th style="text-align: center;">Character</th>
<th style="text-align: center;">Value</th>
<th style="text-align: center;">Character</th>
<th style="text-align: center;">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><code>'A'</code></td>
<td style="text-align: center;"><code>0</code></td>
<td style="text-align: center;"><code>'O'</code></td>
<td style="text-align: center;"><code>14</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><code>'B'</code></td>
<td style="text-align: center;"><code>1</code></td>
<td style="text-align: center;"><code>'P'</code></td>
<td style="text-align: center;"><code>15</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><code>'C'</code></td>
<td style="text-align: center;"><code>2</code></td>
<td style="text-align: center;"><code>'Q'</code></td>
<td style="text-align: center;"><code>16</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><code>'D'</code></td>
<td style="text-align: center;"><code>3</code></td>
<td style="text-align: center;"><code>'R'</code></td>
<td style="text-align: center;"><code>17</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><code>'E'</code></td>
<td style="text-align: center;"><code>4</code></td>
<td style="text-align: center;"><code>'S'</code></td>
<td style="text-align: center;"><code>18</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><code>'F'</code></td>
<td style="text-align: center;"><code>5</code></td>
<td style="text-align: center;"><code>'T'</code></td>
<td style="text-align: center;"><code>19</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><code>'G'</code></td>
<td style="text-align: center;"><code>6</code></td>
<td style="text-align: center;"><code>'U'</code></td>
<td style="text-align: center;"><code>20</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><code>'H'</code></td>
<td style="text-align: center;"><code>7</code></td>
<td style="text-align: center;"><code>'V'</code></td>
<td style="text-align: center;"><code>21</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><code>'I'</code></td>
<td style="text-align: center;"><code>8</code></td>
<td style="text-align: center;"><code>'W'</code></td>
<td style="text-align: center;"><code>22</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><code>'J'</code></td>
<td style="text-align: center;"><code>9</code></td>
<td style="text-align: center;"><code>'X'</code></td>
<td style="text-align: center;"><code>23</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><code>'K'</code></td>
<td style="text-align: center;"><code>10</code></td>
<td style="text-align: center;"><code>'Y'</code></td>
<td style="text-align: center;"><code>24</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><code>'L'</code></td>
<td style="text-align: center;"><code>11</code></td>
<td style="text-align: center;"><code>'Z'</code></td>
<td style="text-align: center;"><code>25</code></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><code>'M'</code></td>
<td style="text-align: center;"><code>12</code></td>
<td style="text-align: center;"><code>' '</code></td>
<td style="text-align: center;"><code>26</code></td>
</tr>
<tr class="even">
<td style="text-align: center;"><code>'N'</code></td>
<td style="text-align: center;"><code>13</code></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
</tr>
</tbody>
</table>
</div>
<p>In Python, we can implement this conversion as follows:</p>
<div class="sourceCode" id="cb1-b6987c84a0"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-b6987c84a0"><a href="#cb1-1-b6987c84a0"></a>LETTERS <span class="op">=</span> <span class="st">&#39;ABCDEFGHIJKLMNOPQRSTUVWXYZ &#39;</span></span>
<span id="cb1-2-b6987c84a0"><a href="#cb1-2-b6987c84a0"></a></span>
<span id="cb1-3-b6987c84a0"><a href="#cb1-3-b6987c84a0"></a></span>
<span id="cb1-4-b6987c84a0"><a href="#cb1-4-b6987c84a0"></a><span class="kw">def</span> letter_to_num(c: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb1-5-b6987c84a0"><a href="#cb1-5-b6987c84a0"></a> <span class="co">&quot;&quot;&quot;Return the number that corresponds to the given letter.</span></span>
<span id="cb1-6-b6987c84a0"><a href="#cb1-6-b6987c84a0"></a></span>
<span id="cb1-7-b6987c84a0"><a href="#cb1-7-b6987c84a0"></a><span class="co"> Preconditions:</span></span>
<span id="cb1-8-b6987c84a0"><a href="#cb1-8-b6987c84a0"></a><span class="co"> - len(c) == 1 and c in LETTERS</span></span>
<span id="cb1-9-b6987c84a0"><a href="#cb1-9-b6987c84a0"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-10-b6987c84a0"><a href="#cb1-10-b6987c84a0"></a> <span class="cf">return</span> <span class="bu">str</span>.index(LETTERS, c)</span>
<span id="cb1-11-b6987c84a0"><a href="#cb1-11-b6987c84a0"></a></span>
<span id="cb1-12-b6987c84a0"><a href="#cb1-12-b6987c84a0"></a></span>
<span id="cb1-13-b6987c84a0"><a href="#cb1-13-b6987c84a0"></a><span class="kw">def</span> num_to_letter(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb1-14-b6987c84a0"><a href="#cb1-14-b6987c84a0"></a> <span class="co">&quot;&quot;&quot;Return the letter that corresponds to the given number.</span></span>
<span id="cb1-15-b6987c84a0"><a href="#cb1-15-b6987c84a0"></a></span>
<span id="cb1-16-b6987c84a0"><a href="#cb1-16-b6987c84a0"></a><span class="co"> Precondtions:</span></span>
<span id="cb1-17-b6987c84a0"><a href="#cb1-17-b6987c84a0"></a><span class="co"> - 0 &lt;= n &lt; len(LETTERS)</span></span>
<span id="cb1-18-b6987c84a0"><a href="#cb1-18-b6987c84a0"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-19-b6987c84a0"><a href="#cb1-19-b6987c84a0"></a> <span class="cf">return</span> LETTERS[n]</span></code></pre></div>
<p>In the Caesar cipher, the secret key <span class="math inline">\(k\)</span> is an integer from the set <span class="math inline">\(\{1, 2, \dots, 26\}\)</span>. So before sending any messages, Alice and Bob meet and decide on a secret key from this set.</p>
<p>Now when Alice wants to send a string message <span class="math inline">\(m\)</span> to Bob, she <em>encrypts</em> her message as follows:</p>
<ul>
<li>For each character of <span class="math inline">\(m\)</span>, Alice shifts it by adding the secret key <span class="math inline">\(k\)</span> to its corresponding numbers, taking remainders modulo 27, the length of <code>LETTERS</code>. Note that the space character <code></code> comes after <code>Z</code>.</li>
</ul>
<p>For example, if <span class="math inline">\(k = 3\)</span>, and the plaintext message is <code>'HAPPY'</code>, encryption happens as follows:</p>
<div class="reference-table">
<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 28%" />
<col style="width: 20%" />
<col style="width: 26%" />
</colgroup>
<thead>
<tr class="header">
<th>Plaintext character</th>
<th>Corresponding Integer</th>
<th>Shifted Integer</th>
<th>Ciphertext character</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>'H'</code></td>
<td><code>7</code></td>
<td><code>10</code></td>
<td><code>'K'</code></td>
</tr>
<tr class="even">
<td><code>'A'</code></td>
<td><code>0</code></td>
<td><code>3</code></td>
<td><code>'D'</code></td>
</tr>
<tr class="odd">
<td><code>'P'</code></td>
<td><code>15</code></td>
<td><code>18</code></td>
<td><code>'S'</code></td>
</tr>
<tr class="even">
<td><code>'P'</code></td>
<td><code>15</code></td>
<td><code>18</code></td>
<td><code>'S'</code></td>
</tr>
<tr class="odd">
<td><code>'Y'</code></td>
<td><code>24</code></td>
<td><code>0</code></td>
<td><code>'A'</code></td>
</tr>
</tbody>
</table>
</div>
<p>The corresponding ciphertext is <code>'KDSSA'</code>. Note that the <code>Y</code>, when shifted by 3, wraps around to become <code>A</code>.</p>
<p>Then when Bob receives the ciphertext <code>'KDSSA'</code>, he decrypts the ciphertext by applying the corresponding shift in reverse (subtracting the secret key <span class="math inline">\(k\)</span> instead of adding it). We can implement this in Python as follows:<label for="sn-1-b6987c84a0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-b6987c84a0" class="margin-toggle"/><span class="sidenote"> Note that weve dropped the <code>_so_far</code> suffix on these accumulator variables now that youre more experience writing loops!</span></p>
<div class="sourceCode" id="cb2-b6987c84a0"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-b6987c84a0"><a href="#cb2-1-b6987c84a0"></a><span class="kw">def</span> encrypt_caesar(k: <span class="bu">int</span>, plaintext: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb2-2-b6987c84a0"><a href="#cb2-2-b6987c84a0"></a> <span class="co">&quot;&quot;&quot;Return the encrypted message using the Caesar cipher with key k.</span></span>
<span id="cb2-3-b6987c84a0"><a href="#cb2-3-b6987c84a0"></a></span>
<span id="cb2-4-b6987c84a0"><a href="#cb2-4-b6987c84a0"></a><span class="co"> Preconditions:</span></span>
<span id="cb2-5-b6987c84a0"><a href="#cb2-5-b6987c84a0"></a><span class="co"> - all({x in LETTERS for x in plaintext})</span></span>
<span id="cb2-6-b6987c84a0"><a href="#cb2-6-b6987c84a0"></a><span class="co"> - 1 &lt;= k &lt;= 26</span></span>
<span id="cb2-7-b6987c84a0"><a href="#cb2-7-b6987c84a0"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-8-b6987c84a0"><a href="#cb2-8-b6987c84a0"></a> ciphertext <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb2-9-b6987c84a0"><a href="#cb2-9-b6987c84a0"></a></span>
<span id="cb2-10-b6987c84a0"><a href="#cb2-10-b6987c84a0"></a> <span class="cf">for</span> letter <span class="kw">in</span> plaintext:</span>
<span id="cb2-11-b6987c84a0"><a href="#cb2-11-b6987c84a0"></a> ciphertext <span class="op">=</span> ciphertext <span class="op">+</span> num_to_letter((letter_to_num(letter) <span class="op">+</span> k) <span class="op">%</span> <span class="bu">len</span>(LETTERS))</span>
<span id="cb2-12-b6987c84a0"><a href="#cb2-12-b6987c84a0"></a></span>
<span id="cb2-13-b6987c84a0"><a href="#cb2-13-b6987c84a0"></a> <span class="cf">return</span> ciphertext</span>
<span id="cb2-14-b6987c84a0"><a href="#cb2-14-b6987c84a0"></a></span>
<span id="cb2-15-b6987c84a0"><a href="#cb2-15-b6987c84a0"></a></span>
<span id="cb2-16-b6987c84a0"><a href="#cb2-16-b6987c84a0"></a><span class="kw">def</span> decrypt_caesar(k: <span class="bu">int</span>, ciphertext: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb2-17-b6987c84a0"><a href="#cb2-17-b6987c84a0"></a> <span class="co">&quot;&quot;&quot;Return the decrypted message using the Caesar cipher with key k.</span></span>
<span id="cb2-18-b6987c84a0"><a href="#cb2-18-b6987c84a0"></a></span>
<span id="cb2-19-b6987c84a0"><a href="#cb2-19-b6987c84a0"></a><span class="co"> Preconditions:</span></span>
<span id="cb2-20-b6987c84a0"><a href="#cb2-20-b6987c84a0"></a><span class="co"> - all({x in LETTERS for x in ciphertext})</span></span>
<span id="cb2-21-b6987c84a0"><a href="#cb2-21-b6987c84a0"></a><span class="co"> - 1 &lt;= k &lt;= 26</span></span>
<span id="cb2-22-b6987c84a0"><a href="#cb2-22-b6987c84a0"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-23-b6987c84a0"><a href="#cb2-23-b6987c84a0"></a> plaintext <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb2-24-b6987c84a0"><a href="#cb2-24-b6987c84a0"></a></span>
<span id="cb2-25-b6987c84a0"><a href="#cb2-25-b6987c84a0"></a> <span class="cf">for</span> letter <span class="kw">in</span> ciphertext:</span>
<span id="cb2-26-b6987c84a0"><a href="#cb2-26-b6987c84a0"></a> plaintext <span class="op">=</span> plaintext <span class="op">+</span> num_to_letter((letter_to_num(letter) <span class="op">-</span> k) <span class="op">%</span> <span class="bu">len</span>(LETTERS))</span>
<span id="cb2-27-b6987c84a0"><a href="#cb2-27-b6987c84a0"></a></span>
<span id="cb2-28-b6987c84a0"><a href="#cb2-28-b6987c84a0"></a> <span class="cf">return</span> plaintext</span></code></pre></div>
<h3 id="expanding-the-set-of-letters-b6987c84a0">Expanding the set of letters</h3>
<p>In our example above, we restricted ourselves to only upper-case letters and spaces. But the key mathematical idea of the Caesar cipher, shifting letters based on a secret key <span class="math inline">\(k\)</span> used as an offset, generalizes to larger sets of letters.</p>
<p>To see how to do this, first we recall two built-in Python functions from <a href="../02-functions/08-representing-text.html">Section 2.8 Application: Representing Text</a>:</p>
<div class="sourceCode" id="cb3-b6987c84a0"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-b6987c84a0"><a href="#cb3-1-b6987c84a0"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">ord</span>(<span class="st">&#39;A&#39;</span>) <span class="co"># Convert a character into an integer</span></span>
<span id="cb3-2-b6987c84a0"><a href="#cb3-2-b6987c84a0"></a><span class="dv">65</span></span>
<span id="cb3-3-b6987c84a0"><a href="#cb3-3-b6987c84a0"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">chr</span>(<span class="dv">33</span>) <span class="co"># Convert an integer into a character</span></span>
<span id="cb3-4-b6987c84a0"><a href="#cb3-4-b6987c84a0"></a><span class="co">&#39;!&#39;</span></span></code></pre></div>
<p>Using these two functions, we can modify our <code>encrypt</code> and <code>decrypt</code> functions in the Caesar cipher to operate on arbitrary Python strings. For simplicity, well stick only to the first 128 characters, which are known as the ASCII characters.<label for="sn-2-b6987c84a0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-b6987c84a0" class="margin-toggle"/><span class="sidenote">You might recall from Section 2.8 that <em>ASCII</em> is one of the earliest standard for encoding characters as natural numbers on a computer.</span> Our secret key will now take on values from the set <span class="math inline">\(\{1, 2, \dots, 127\}\)</span>.</p>
<div class="sourceCode" id="cb4-b6987c84a0"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-b6987c84a0"><a href="#cb4-1-b6987c84a0"></a><span class="kw">def</span> encrypt_ascii(k: <span class="bu">int</span>, plaintext: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb4-2-b6987c84a0"><a href="#cb4-2-b6987c84a0"></a> <span class="co">&quot;&quot;&quot;Return the encrypted message using the Caesar cipher with key k.</span></span>
<span id="cb4-3-b6987c84a0"><a href="#cb4-3-b6987c84a0"></a></span>
<span id="cb4-4-b6987c84a0"><a href="#cb4-4-b6987c84a0"></a><span class="co"> Preconditions:</span></span>
<span id="cb4-5-b6987c84a0"><a href="#cb4-5-b6987c84a0"></a><span class="co"> - all({ord(c) &lt; 128 for c in plaintext})</span></span>
<span id="cb4-6-b6987c84a0"><a href="#cb4-6-b6987c84a0"></a><span class="co"> - 1 &lt;= k &lt;= 127</span></span>
<span id="cb4-7-b6987c84a0"><a href="#cb4-7-b6987c84a0"></a></span>
<span id="cb4-8-b6987c84a0"><a href="#cb4-8-b6987c84a0"></a><span class="co"> &gt;&gt;&gt; encrypt_ascii(4, &#39;Good morning!&#39;)</span></span>
<span id="cb4-9-b6987c84a0"><a href="#cb4-9-b6987c84a0"></a><span class="co"> &#39;Kssh$qsvrmrk%&#39;</span></span>
<span id="cb4-10-b6987c84a0"><a href="#cb4-10-b6987c84a0"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-11-b6987c84a0"><a href="#cb4-11-b6987c84a0"></a> ciphertext <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb4-12-b6987c84a0"><a href="#cb4-12-b6987c84a0"></a></span>
<span id="cb4-13-b6987c84a0"><a href="#cb4-13-b6987c84a0"></a> <span class="cf">for</span> letter <span class="kw">in</span> plaintext:</span>
<span id="cb4-14-b6987c84a0"><a href="#cb4-14-b6987c84a0"></a> ciphertext <span class="op">=</span> ciphertext <span class="op">+</span> <span class="bu">chr</span>((<span class="bu">ord</span>(letter) <span class="op">+</span> k) <span class="op">%</span> <span class="dv">128</span>)</span>
<span id="cb4-15-b6987c84a0"><a href="#cb4-15-b6987c84a0"></a></span>
<span id="cb4-16-b6987c84a0"><a href="#cb4-16-b6987c84a0"></a> <span class="cf">return</span> ciphertext</span>
<span id="cb4-17-b6987c84a0"><a href="#cb4-17-b6987c84a0"></a></span>
<span id="cb4-18-b6987c84a0"><a href="#cb4-18-b6987c84a0"></a></span>
<span id="cb4-19-b6987c84a0"><a href="#cb4-19-b6987c84a0"></a><span class="kw">def</span> decrypt_ascii(k: <span class="bu">int</span>, ciphertext: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb4-20-b6987c84a0"><a href="#cb4-20-b6987c84a0"></a> <span class="co">&quot;&quot;&quot;Return the decrypted message using the Caesar cipher with key k.</span></span>
<span id="cb4-21-b6987c84a0"><a href="#cb4-21-b6987c84a0"></a></span>
<span id="cb4-22-b6987c84a0"><a href="#cb4-22-b6987c84a0"></a><span class="co"> Preconditions:</span></span>
<span id="cb4-23-b6987c84a0"><a href="#cb4-23-b6987c84a0"></a><span class="co"> - all({ord(c) &lt; 128 for c in ciphertext})</span></span>
<span id="cb4-24-b6987c84a0"><a href="#cb4-24-b6987c84a0"></a><span class="co"> - 1 &lt;= k &lt;= 127</span></span>
<span id="cb4-25-b6987c84a0"><a href="#cb4-25-b6987c84a0"></a></span>
<span id="cb4-26-b6987c84a0"><a href="#cb4-26-b6987c84a0"></a><span class="co"> &gt;&gt;&gt; decrypt_ascii(4, &#39;Kssh$qsvrmrk%&#39;)</span></span>
<span id="cb4-27-b6987c84a0"><a href="#cb4-27-b6987c84a0"></a><span class="co"> &#39;Good morning!&#39;</span></span>
<span id="cb4-28-b6987c84a0"><a href="#cb4-28-b6987c84a0"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-29-b6987c84a0"><a href="#cb4-29-b6987c84a0"></a> plaintext <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb4-30-b6987c84a0"><a href="#cb4-30-b6987c84a0"></a></span>
<span id="cb4-31-b6987c84a0"><a href="#cb4-31-b6987c84a0"></a> <span class="cf">for</span> letter <span class="kw">in</span> ciphertext:</span>
<span id="cb4-32-b6987c84a0"><a href="#cb4-32-b6987c84a0"></a> plaintext <span class="op">+=</span> <span class="bu">chr</span>((<span class="bu">ord</span>(letter) <span class="op">-</span> k) <span class="op">%</span> <span class="dv">128</span>)</span>
<span id="cb4-33-b6987c84a0"><a href="#cb4-33-b6987c84a0"></a></span>
<span id="cb4-34-b6987c84a0"><a href="#cb4-34-b6987c84a0"></a> <span class="cf">return</span> plaintext</span></code></pre></div>
<p><strong>WARNING</strong>: in practice, the Caeser cipher is not secure, as it is very possible for an eavesdropper to simply try all possible secret keys to decrypt a ciphertext, and pick out the most likely message that Alice sent. So while this example is good for educational purposes, you should <em>definitely not</em> use this cryptosystem for any real-world applications!</p>
</section>
<br/> <a id="anchor-07-02"></a>
<header id="title-block-header-bb56fde39a">
<h1 class="title">7.2 The One-Time Pad and Perfect Secrecy</h1>
</header>
<section>
<p>The Caesar cipher we studied in the previous section is simple enough as a starting point, but should never be used in practice! It suffers from the fatal flaw that each character of the plaintext is encrypted individually, using the same secret key each time. So for example, every occurrence of the character <code>'D'</code> in the plaintext is transformed into the same character in the ciphertext. Why is this a problem?</p>
<p>Consider the ciphertext <code>'OLaTO+T^+NZZW'</code> generated by the ASCII-based Caesar cipher. Even though it may look indecipherable at first, there is information that we can learn about the original plaintext just by looking at the distribution of letters in the ciphertext.<label for="sn-0-bb56fde39a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-bb56fde39a" class="margin-toggle"/><span class="sidenote"> Given these observations and the hint that the plaintext is a common phrase used in CSC110, can you determine the plaintext?</span></p>
<ul>
<li>The first and fifth letters in the plaintext must be the same, since they both map to <code>'O'</code> in the ciphertext.</li>
<li>Similarly, the sixth and ninth characters must be the same, and the eleventh and twelfth characters must be the same.</li>
<li>Because the Caesar cipher is <em>additive</em>, it preserves the relative <code>ord</code> of each character. Since <code>ord('O') = 79</code> and <code>ord('N') = 78</code>, we know that the first and tenth characters of the plaintext must be consecutive ASCII characters.</li>
</ul>
<p>In addition to what we can infer from the distribution of letters in the ciphertext, the ASCII-based Caesar cipher is vulnerable to a <em>brute-force exhaustive key search attack</em>. There are only 128 possible secret keys the cipher could use (corresponding to the possible remainders of modulo 128). So, given a ciphertext, it is possible to try out every secret key and see which key yields a meaningful plaintext message.<label for="sn-1-bb56fde39a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-bb56fde39a" class="margin-toggle"/><span class="sidenote"> For most ciphertexts generated from English plaintexts, only one possible secret key causes the decrypted message to be a meaningful English message.</span> Thats not very secure.</p>
<p>Even if we enlarge the set of possible keys (e.g., by using a more general text encoding like UTF8), Caesar ciphers are still vulnerable to observations like the ones we made earlier. From these observations, we can identify “likely” keys that a brute force search could try first. So the main weakness of the Caesar cipher is not just the number of possible keys.</p>
<h2 id="the-one-time-pad-bb56fde39a">The one-time pad</h2>
<p>We will now introduce a new symmetric-key cryptosystem known as the <strong>one-time pad</strong> that is structurally similar to the Caesar cipher, but avoids the issues we raised earlier. Encryption in the one-time pad works by shifting each character in the plaintext message, much like the Caesar cipher. But where the one-time pad differs is that the shift is <em>not</em> the same for each character. The one-time pad accomplishes this by not using a single number for the secret key, but rather a string of length greater than or equal to the length of the plaintext message you wish to encrypt.<label for="sn-2-bb56fde39a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-bb56fde39a" class="margin-toggle"/><span class="sidenote"> This secret key is colloquially referred to as a “one-time pad” (of characters), from which this cryptosystem gets its name.</span></p>
<p>To <em>encrypt</em> a plaintext ASCII message <span class="math inline">\(m\)</span> with secret key <span class="math inline">\(k\)</span>, for each index <span class="math inline">\(i\)</span> between 0 and <span class="math inline">\(|m| - 1\)</span>, we compute:</p>
<ul>
<li><span class="math inline">\((m[i] + k[i]) ~\%~ 128\)</span>, where <span class="math inline">\(m[i]\)</span> and <span class="math inline">\(k[i]\)</span> are converted to their numeric representations to do the arithmetic.<label for="sn-3-bb56fde39a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-bb56fde39a" class="margin-toggle"/><span class="sidenote"> In contrast, the Caesar cipher calculates <span class="math inline">\((m[i] + k) ~\%~ 128\)</span>, where <span class="math inline">\(k\)</span> is the secret key.</span></li>
</ul>
<p>Here is an example. Suppose we wanted to encrypt the plaintext <code>'HELLO'</code> with the secret key <code>'david'</code>. The ciphertext will have five characters, where the first is <code>'H' + 'd'</code> which results in <code>','</code>, the second is <code>'E' + 'A'</code> which results in <code>'&amp;'</code>, etc. The following diagram shows the full conversion:</p>
<p><img src="./images/one_time_pad.png" alt="One-Time Pad Example Diagram" /><br />
</p>
<p>Similarly, for decryption we take the ciphertext <code>c</code> and recover the plaintext by subtracting each letter of the secret key: <span class="math inline">\((c[i] - k[i]) ~\%~ 128\)</span>.</p>
<h2 id="perfect-secrecy-and-its-costs-bb56fde39a">Perfect secrecy and its costs</h2>
<p>The one-time pad cryptosystem is famous in cryptography for having a property known as <strong>perfect secrecy</strong>,<label for="sn-4-bb56fde39a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-bb56fde39a" class="margin-toggle"/><span class="sidenote"> This is a term termed by the mathematician and cryptographer Claude Shannon in 1949.</span> which informally means that a ciphertext reveals no information about its corresponding plaintext other than its length. To see why, take our previous example, with ciphertext <code>',&amp;B53'</code>. This ciphertext could have been generated by <em>any</em> five-letter plaintext message, because for any such message there exists a secret key that could encrypt that message to obtain <code>',&amp;B53'</code>. The sender could have been sending plaintext message <code>'HELLO'</code> with secret key <code>'david'</code>, but it is equally likely they could have been sending the message <code>'FUNNY'</code> with secret key <code>'fQtgZ'</code>. Because of perfect secrecy, an eavesdropper cannot gain any information about the original plaintext message, even if they know the whole ciphertext.</p>
<p>This perfect secrecy comes at a cost, however. The main drawback of the one-time pad cryptosystem, and why it is not actually used in practice, is that the secret key must have at least the same length as the message being sent, and cannot be reused from one message to another.<label for="sn-5-bb56fde39a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-bb56fde39a" class="margin-toggle"/><span class="sidenote"> The notion of perfect secrecy relies on every possible secret key to be chosen purely at random. This isnt the case if I reuse the same one-time pad for all my messages. This requirement is also why the term “one-time” is used for one-time pads.</span></p>
<h2 id="stream-ciphers-bb56fde39a">Stream ciphers</h2>
<p>The attraction of perfect secrecy has led cryptographers to develop <em>stream ciphers</em>, which are a type of symmetric-key cryptosystem that emulate a one-time pad but share a much smaller secret key. The details of stream ciphers are beyond the scope of this course, but the basic is idea is the following: the shared secret key is quite small (less than 1KB), and both parties use an algorithm to generate an arbitrary number of new random characters, based on both the secret key and any previously-generated characters.<label for="sn-6-bb56fde39a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-bb56fde39a" class="margin-toggle"/><span class="sidenote"> We say that this is a “stream” of characters, from which this type of cryptosystem gets its name.</span> These characters are then used in the same way as a one-time pad to encrypt messages.</p>
<p>Now, stream ciphers do not have perfect secrecy, since the characters used in encryption arent truly random. But if the generating algorithm is clever enough, each new character appears “random”, and the encrypted messages are computationally impossible to decrypt without knowing the starting secret key. In other words, stream ciphers give up on perfect secrecy in exchange for “good enough” secrecy and a much, much smaller shared secret key. Of course, the “good enough” is highly dependent on the algorithm used to generate the characters. A poorly-designed algorithm may unintentionally inject patterns in the generated characters, or even allow an eavesdropper to gain some information about the secret key itself!</p>
</section>
<br/> <a id="anchor-07-03"></a>
<header id="title-block-header-a5e1385c1c">
<h1 class="title">7.3 Computing Shared Secret Keys</h1>
</header>
<section>
<p>A historical limitation of symmetric-key cryptosystems was how to establish a shared, but secret, key. If the two communicating parties were able to meet in person, they could agree upon a shared secret key while physically together (assuming no one else was spying on them). But what if I want to communicate with someone securely in a different city or different country? Or, to use a more modern example, to communicate with a server across the Internet, which I cannot hope to meet in person?</p>
<p>One solution to this problem is the <em>Diffie-Hellman key exchange</em>, which is an algorithm that is executed by two people (or computers) to compute a shared secret, while communicating in public (open to eavesdroppers). We will introduce the intuitions of the Diffie-Hellman key exchange with an analogy that uses our familiar Alice and Bob communicating with colours. After, we will replace colours with numbers to understand how the process works in todays digital world.</p>
<h2 id="alice-and-bob-are-mixing-paint-a5e1385c1c">Alice and Bob are mixing paint</h2>
<p>Suppose that Alice and Bob would like to establish a secret <em>paint colour</em> that only the two of them know. They use the following procedure.</p>
<table class="fullwidth">
<tbody>
<tr>
<td style="width: 55%; vertical-align: top; padding-right: 2em;">
<p><em>First</em>, they both agree on a random, not-secret colour of paint to start with: yellow. They decide on this shared colour publicly, so eavesdroppers also know this colour!</p>
<p><em>Second</em>, they each choose their own secret colour, which they will never share with each other or anyone else. In our example, Alice decides on red and Bob chooses teal (a green-blue colour).</p>
<p><em>Third</em>, they each mix their secret colours with their shared colour yellow, producing a light orange for Alice and a blue for Bob. This is also done in secret.</p>
<p><em>Fourth</em>, they exchange these colours with each other, which is done publicly. At this point, there are three not-secret colours: yellow and the two mixtures. And there are two secret colours: Alices red and Bobs teal.</p>
<p><em>Fifth</em>, Alice mixes Bobs blue colour with her original secret red to produce a brown. Bob mixes Alices light orange with his original secret teal to produce the same brown. Why are these the same brown? Because they both consist of the same mixture of three colours: yellow (shared), red (Alices secret), and teal (Bobs secret)!</p>
<p>Finally, why is this brown a secret? Any eavesdropper has access to three colours: the original shared yellow (from the first step), and the two mixtures orange and blue (from the fourth step). If we assume that the colour mixtures are not easily separated (i.e., it is very difficult to extract the yellow from each mixture), then the eavesdropper cannot determine what Alice and Bobs secret colours were, and therefor cant mix them together with the yellow to produce the right shade of brown!</p>
</td>
<td>
<img src="./images/diffie-hellman-paint.png" alt="Alice and Bob paint mixing" /><br />
</td>
</tr>
</tbody>
</table>
<h2 id="the-diffie-hellman-key-exchange-a5e1385c1c">The Diffie-Hellman key exchange</h2>
<p>Unfortunately, transmitting paint across digital channels is intractable, but transmitting numbers isnt. The Diffie-Hellman key exchange uses some neat (yet simple) operations from modular arithmetic to play out the same scenario as our paint analogy.</p>
<div class="framed">
<p><strong>Diffie-Hellman Key Exhange Algorithm</strong></p>
<p>Setting: Two parties, Alice and Bob</p>
<p>Result: Alice and Bob share a secret key <span class="math inline">\(k\)</span>.</p>
<ol type="1">
<li><p>Alice chooses a prime number <span class="math inline">\(p\)</span> greater than two and an integer <span class="math inline">\(g\)</span> which satisfies <span class="math inline">\(2 \leq g \leq p - 1\)</span>, and sends both to Bob.</p></li>
<li><p>Alice chooses a secret number <span class="math inline">\(a \in \{1, 2, \dots, p-1\}\)</span> and sends Bob <span class="math inline">\(A = g^a ~\%~ p\)</span> to Bob.</p></li>
<li><p>Bob chooses a secret number <span class="math inline">\(b \in \{1, 2, \dots, p-1\}\)</span> and sends <span class="math inline">\(B = g^b ~\%~ p\)</span> to Alice.</p></li>
<li><p>Alice computes <span class="math inline">\(k_A = B^a ~\%~ p\)</span>. Bob computes <span class="math inline">\(k_B = A^b ~\%~ p\)</span>.</p>
<p>It turns out that <span class="math inline">\(k_A = k_B\)</span>, and so this value is chosen as the secret key <span class="math inline">\(k\)</span> that Alice and Bob share.</p></li>
</ol>
</div>
<h3 id="an-example-a5e1385c1c">An example</h3>
<p>Here is an example of the Diffie-Hellman key exchange in action.</p>
<ol type="1">
<li>Alice starts by choosing <span class="math inline">\(p = 23\)</span> and <span class="math inline">\(g = 2\)</span>. She sends both <span class="math inline">\(p\)</span> and <span class="math inline">\(g\)</span> to Bob.</li>
<li>Alice chooses a secret number <span class="math inline">\(a = 5\)</span>. She sends <span class="math inline">\(A = g^a ~\%~ p = 2^5 ~\%~ 23 = 9\)</span> to Bob.</li>
<li>Bob chooses a secret number <span class="math inline">\(b = 14\)</span>. He sends <span class="math inline">\(B = g^b ~\%~ p = 2^{14} ~\%~ 23 = 8\)</span> to Alice.</li>
<li>Alice computes <span class="math inline">\(k_A = B^a ~\%~ p = 8^5 ~\%~ 23 = 16\)</span>. Bob computes <span class="math inline">\(k_B = A^b ~\%~ p = 9^{14} ~\%~ 23 = 16\)</span>. As expected, <span class="math inline">\(k_A = k_B\)</span>, and these form the secret key <span class="math inline">\(k\)</span>!</li>
</ol>
<h2 id="correctness-are-k_a-and-k_b-always-equal-a5e1385c1c">Correctness: Are <span class="math inline">\(k_A\)</span> and <span class="math inline">\(k_B\)</span> always equal?</h2>
<p>That last sentence in the Diffie-Hellman key exchange algorithm description is doing a lot of work. How do we “know” that <span class="math inline">\(k_A = k_B\)</span>? With a proof, of course!</p>
<div class="theorem">
<p>(<em>Correctness of Diffie-Hellman key exchange</em>)</p>
<p>For all <span class="math inline">\(p, g, a, b \in \Z^+\)</span>, <span class="math inline">\((g^b ~\%~ p)^a ~\%~ p = (g^a ~\%~ p)^b ~\%~ p\)</span>.</p>
<div class="discussion">
<p>Even though the Diffie-Hellman algorithm frames the communication in terms of remainders, we can analyze the numbers using modular arithmetic modulo <span class="math inline">\(p\)</span>. In this case the calculation involves just switching around exponents in <span class="math inline">\(g^{ab}\)</span>.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(p, g, a, b \in Z^+\)</span>. Let <span class="math inline">\(A = g^a ~\%~ p\)</span> and <span class="math inline">\(B = g^b ~\%~ p\)</span>. Well prove that <span class="math inline">\(B^a ~\%~ p = A^b ~\%~ p\)</span>.</p>
<p>First, we have that <span class="math inline">\(A \equiv g^a \pmod p\)</span> and <span class="math inline">\(B \equiv g^b \pmod p\)</span>. So then <span class="math inline">\(A^b \equiv (g^a)^b \equiv g^{ab} \pmod p\)</span>, and <span class="math inline">\(B^a \equiv (g^b)^a \equiv g^{ba} \pmod p\)</span>. Since <span class="math inline">\(g^{ab} = g^{ba}\)</span>, we can conclude that <span class="math inline">\(A^b \equiv B^a \pmod p\)</span>.</p>
<p>So then <span class="math inline">\(A^b\)</span> and <span class="math inline">\(B^a\)</span> must have the same remainder when divided by <span class="math inline">\(p\)</span>, and so <span class="math inline">\(B^a ~\%~ p = A^b ~\%~ p\)</span>.</p>
</div>
</div>
<h2 id="security-how-secret-is-the-key-a5e1385c1c">Security: How secret is the key?</h2>
<p>Weve just proved that the Diffie-Hellman key exchange is <em>correct</em>, meaning the result at the end of the algorithm is that Alice and Bob have a shared key. But thats not the only purpose of this algorithm: it must also ensure that this shared key is also <em>secret</em>, unknown to anyone other than Alice and Bob.</p>
<p>So lets look at the Diffie-Hellman key exchange from the perspective of an eavesdropper that has access to everything Alice and Bob communicate to each other.<label for="sn-0-a5e1385c1c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-a5e1385c1c" class="margin-toggle"/><span class="sidenote"> We say that Alice and Bobs communications are <em>public</em>, while their own computing devices are <em>private</em>.</span> So over the course of the algorithm, the eavesdropper has access to <span class="math inline">\(p\)</span>, <span class="math inline">\(g\)</span>, <span class="math inline">\(g^a ~\%~ p\)</span>, and <span class="math inline">\(g^b ~\%~ p\)</span>. The question is: from this information, can the eavesdropper determine the secret key <span class="math inline">\(k\)</span>?</p>
<p>One approach an eavesdropper could take is to try to compute <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> directly. This is an instance of the <strong>discrete logarithm problem</strong>: given <span class="math inline">\(p, g, y \in \Z^+\)</span>, find an <span class="math inline">\(x \in \Z^+\)</span> such that <span class="math inline">\(g^x \equiv y \pmod p\)</span>. While we could implement a <em>brute-force</em> algorithm for solving this problem that simply tries all possible exponents <span class="math inline">\(x \in \{0, 1, \dots, p-1\}\)</span>, this is computationally inefficient in practice when <span class="math inline">\(p\)</span> is chosen to be extremely large.<label for="sn-1-a5e1385c1c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-a5e1385c1c" class="margin-toggle"/><span class="sidenote"> Well explore exactly what we mean by terms like “efficient” and “inefficient” more precisely in the next chapter.</span></p>
<p>Perhaps surprisingly, there is no known <em>efficient</em> algorithm for solving the discrete logarithm problem! So we say that the Diffie-Hellman key exchange is <strong>computationally secure</strong>: while there are known algorithms that eavesdroppers could use for determining the shared secret key, all known algorithms are computationally infeasible for standard primes chosen. In practice, Diffie-Hellman key exchanges tend to use primes on the order of <span class="math inline">\(2^{2048} \approx 10^{617}\)</span>!</p>
<!-- ## Diffie-Hellman in Practice
We have shown that Diffie-Hellman provides a way for two users to share a secret key.
However, the protocol we have presented is rarely used on its own.
The main reason for this is a lack of *authentication*;
there is no way for Bob to know that he is communicating with Alice, or vice versa.
One could imagine an evil and malicious man-in-the-middle, pretending to be Alice or Bob depending on who is sending messages.
Still, the Diffie-Hellman key exchange is typically combined with other algorithms and protocols in cryptography to allow for secure communication.
## Scalability of Symmetric Encryption
Our examples have looked at how two people, Alice and Bob, can communicate with a single key.
However, when we want more than two people to communicate, the number of keys needed will grow.
With symmetric encryption, each pair of users needs its own key to communicate securely.
So how many keys do we need for $n$ users to ensure encrypted, pairwise communication?
The answer is a summation:
$1 + 2 + 3 + ... + (n - 1) = N_k$
Which reduces to:
$N_k = n(n - 1) / 2$
Therefore, as the number of users $n$ grows, the number of keys needed $N_k$ grows quadratically (i.e., $n^2$).^[
We will introduce and define several new terms for scalability in the next chapter.
]
To understand why this is a big deal, consider this: how do we exchange all these keys if we don't have a secured form of communication?
Note that we don't have a secured form of communication until both users have the secret key.
Thus, there are two major drawbacks to symmetric encryption:
1. The number of keys needed grows quadratically with the number of users
2. Keys need to be shared securely before symmetric encryption can be used
Despite these drawbacks, symmetric encryption is still widely used today (e.g., AES).
In the next section, we will see how we can securely exchange a key over a public (i.e., unsecure) channel. -->
</section>
<br/> <a id="anchor-07-04"></a>
<header id="title-block-header-f5a539720b">
<h1 class="title">7.4 The RSA Cryptosystem</h1>
</header>
<section>
<p>So far, we have studied symmetric-key cryptosystems to allow two parties to communicate securely with each other when they share a secret key. We have also studied how two parties can establish a shared secret key using the Diffie-Hellman key exchange algorithm.</p>
<p>One of the limitations of symmetric-key encryption schemes is that a shared secret key needs to be established for every pair of people who want to communicate. If there are <span class="math inline">\(n\)</span> people who each want to communicate securely with each other, there are <span class="math inline">\(\frac{n(n-1)}{2}\)</span> keys needed:</p>
<ul>
<li>The first person needs <span class="math inline">\(n-1\)</span> secret keys to communicate with everyone else.</li>
<li>The second person needs <span class="math inline">\(n-2\)</span> secret keys to communicate with everyone else besides the first person.</li>
<li>The third person needs <span class="math inline">\(n-3\)</span> secret keys to communicate with everyone else besides the first two people.</li>
<li>This pattern repeats, for a total sum of <span class="math inline">\((n-1) + (n-2) + \cdots + 1 = \frac{n(n-1)}{2}\)</span>.</li>
</ul>
<!-- At the beginning of this chapter we introduced symmetric-key cryptosystems that can encrypt and decrypt messages given some key $k$.
The main issue with symmetric-key cryptosystems is that they do not provide a mechanism for exchanging $k$ securely.
We saw how the Diffie-Hellman key exchange could address this issue by relying on both a combination of private (one for Alice and one for Bob) and public (for both Alice and Bob) data to jointly establish a key $k$.
Unfortunately, the Diffie-Hellman key exchange does not provide any form of authentication;
Alice does not know if she is actually communicating with Bob, or some malicious man-in-the-middle. -->
<p>In this section, well introduce a new form of cryptosystem called a <strong>public-key cryptosystem</strong>, for each each person has two keys: a private key known only to them, and a public key known to everyone. Well see what how to encrypt and decrypt messages in these cryptosystems, how they reduce the number of keys needed for people to communicate, and learn about the most widely-used public-key cryptosystem today, the RSA cryptosystem.</p>
<h2 id="public-key-cryptography-f5a539720b">Public-key cryptography</h2>
<p>A <strong>public-key cryptosystem</strong> is one where each party in the communication generates a pair of keys: a <em>private</em> (or <em>secret</em> key, known only to them) and a <em>public</em> key which is known to everyone. Suppose Alice wants to send Bob a message. She uses Bobs <em>public key</em> to encrypt the message, and Bob uses his <em>private key</em> to decrypt the message.<label for="sn-0-f5a539720b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-f5a539720b" class="margin-toggle"/><span class="sidenote"> Recall that in a symmetric-key cryptosystem, messages are encrypted and decrypted with the same keyhence, the symmetry.</span> Similarly, if Bob wants to send a message to Alice, he uses Alices public key to encrypt the message, and Alice uses her private key to decrypt it.</p>
<p>More formally, we define a <strong>secure public-key cryptosystem</strong> as a system with the following parts:</p>
<ul>
<li><p>A set <span class="math inline">\(\mathcal{P}\)</span> of possible original messages, called <strong>plaintext</strong> messages. (E.g., a set of strings)</p></li>
<li><p>A set <span class="math inline">\(\mathcal{C}\)</span> of possible encrypted messages, called <strong>ciphertext</strong> messages. (E.g., another set of strings)</p></li>
<li><p>A set <span class="math inline">\(\mathcal{K}_1\)</span> of possible public keys and a set <span class="math inline">\(\mathcal{K}_2\)</span> of possible private keys.</p></li>
<li><p>A subset <span class="math inline">\(\mathcal{K} \subseteq \mathcal{K}_1 \times \mathcal{K}_2\)</span> of possible <strong>public-private key pairs</strong>. Note that we use <span class="math inline">\(\subseteq\)</span> and not <span class="math inline">\(=\)</span> because not every public key can be paired with every private key.</p></li>
<li><p>Two functions <span class="math inline">\(Encrypt : \mathcal{K_1} \times \mathcal{P} \to \mathcal{C}\)</span> and <span class="math inline">\(Decrypt : \mathcal{K}_2 \times \mathcal{C} \to \mathcal{P}\)</span> that satisfy the following two properties:</p>
<ul>
<li>(<em>correctness</em>) For all <span class="math inline">\((k_1, k_2) \in \mathcal{K}\)</span> and <span class="math inline">\(m \in \mathcal{P}\)</span>, <span class="math inline">\(Decrypt(k_2, Encrypt(k_1, m)) = m\)</span>. (That is, if you encrypt and then decrypt the same message with a public-private key pair, you get back the original message.)</li>
<li>(<em>security</em>) For all <span class="math inline">\((k_1, k_2) \in \mathcal{K}\)</span> and <span class="math inline">\(m \in \mathcal{P}\)</span>, if an eavesdropper only knows the values of the public key <span class="math inline">\(k_1\)</span> and the ciphertext <span class="math inline">\(c = Encrypt(k_1, m)\)</span> but does not know <span class="math inline">\(k_2\)</span>, it is computationally infeasible to find the plaintext message <span class="math inline">\(m\)</span>.</li>
</ul></li>
</ul>
<h2 id="the-rsa-cryptosystem-f5a539720b">The RSA cryptosystem</h2>
<p>The Diffie-Hellman key exchange algorithm we studied in the last section worked by relying on the hardness of the <em>discrete logarithm problem</em>. This allowed Alice and Bob to communicate their numbers <span class="math inline">\(g^a ~\%~ p\)</span> and $<span class="math inline">\(g^b ~\%~ p\)</span> publicly, without anyone being able to find the “secret” <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span>.</p>
<p>The <strong>Rivest-Shamir-Adleman (RSA) cryptosystem</strong> works with numbers as well, and relies on the surprising hardness of factoring large integers. For example, can you tell me which two prime numbers can be multiplied together to produce <span class="math inline">\(30,929\)</span>? You could write a small Python program to answer this question quite quickly, but that was only a number with 5 digits. What about the number <span class="math inline">\(1,455,980,635,647,702,351,701\)</span>, with 22 digits? In practice, RSA relies on the hardness of factoring integers with <em>hundreds</em> of digits!</p>
<p>Lets see how RSA works.</p>
<h3 id="phase-1-key-generation-f5a539720b">Phase 1: Key generation</h3>
<p>Each person in a public-key cryptosystem must first generate a public-private key pair before they can communicate with anyone else. (Think about this as choosing a valid key-pair from the set <span class="math inline">\(\mathcal{K} = \mathcal{K}_1 \times \mathcal{K}_2\)</span>.) For RSA, well put ourselves in Alices shoes and see what she must do to to generate a public and private key.</p>
<ol type="1">
<li><p>First, Alice picks two distinct prime numbers <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span>.</p></li>
<li><p>Next, Alice computes the product <span class="math inline">\(n = pq\)</span>.</p></li>
<li><p>Then, Alice chooses an integer <span class="math inline">\(e \in \{2, 3, \dots, \varphi(n) - 1\}\)</span> such that <span class="math inline">\(\gcd(e, \varphi(n)) = 1\)</span>.</p></li>
<li><p>Finally, Alice chooses an integer <span class="math inline">\(d \in \{2, 3, \dots, \varphi(n) - 1\}\)</span> that is the modular inverse of <span class="math inline">\(e\)</span> modulo <span class="math inline">\(\varphi(n)\)</span>. (That is, <span class="math inline">\(de \equiv 1 \pmod{\varphi(n)}\)</span>.)</p></li>
</ol>
<p>Thats it! Alices <em>private key</em> is the tuple <span class="math inline">\((p, q, d)\)</span>, and her public key is the tuple <span class="math inline">\((n, e)\)</span>. Alice shares her public key with the world, but she never tells her private key to anyone.</p>
<h3 id="phase-2-message-encryption-f5a539720b">Phase 2: Message encryption</h3>
<p>Now suppose that Bob wants to send Alice a plaintext message <span class="math inline">\(m\)</span>. For now well treat the message as a number between <span class="math inline">\(1\)</span> and <span class="math inline">\(n - 1\)</span>, and will discuss string messages later on in this section. Bob uses Alices public key <span class="math inline">\((n, e)\)</span>:</p>
<ol type="1">
<li>Bob computes the ciphertext <span class="math inline">\(c = m^e ~\%~ n\)</span> and sends it to Alice.</li>
</ol>
<h3 id="phase-3-message-decryption-f5a539720b">Phase 3: Message decryption</h3>
<p>Alice receives the ciphertext <span class="math inline">\(c\)</span>. She uses her private key <span class="math inline">\((p, q, d)\)</span> to decrypt the message:</p>
<ol type="1">
<li>Alice computes <span class="math inline">\(m&#39; = c^d ~\%~ n\)</span>.<label for="sn-1-f5a539720b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-f5a539720b" class="margin-toggle"/><span class="sidenote"> Techincally, Alice can recompute <span class="math inline">\(n\)</span> from the <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> of her private key. Another version of RSA is actually just to store <span class="math inline">\(n\)</span> in the private key, or use the <span class="math inline">\(n\)</span> from her public key (which Alice also has access to) and keep only <span class="math inline">\(d\)</span> as the private key.</span></li>
</ol>
<h3 id="an-example-f5a539720b">An example</h3>
<p>Before moving on, lets see an example of a full use of the RSA cryptosystem in action. Alice first needs to generate a public and private key.</p>
<ol type="1">
<li>Alice chooses the prime numbers <span class="math inline">\(p = 23\)</span> and <span class="math inline">\(q = 31\)</span>.</li>
<li>The product is <span class="math inline">\(n = p \cdot q = 23 \cdot 31 = 713\)</span></li>
<li>Next, Alice needs to choose an <span class="math inline">\(e\)</span> where <span class="math inline">\(\gcd(e, \varphi(n)) = 1\)</span>. Alice calculates that <span class="math inline">\(\varphi(713) = 660\)</span>, and chooses <span class="math inline">\(e = 547\)</span> to satisfy the constraints on <span class="math inline">\(e\)</span>.</li>
<li>Finally, Alice calculates the modular inverse to find the last part of the private key (<span class="math inline">\(d \cdot 547 \equiv 1 \pmod{660}\)</span>), so <span class="math inline">\(d = 403\)</span>.</li>
</ol>
<p>For reference, the private key is: <span class="math inline">\((p=23, q=31, d=403)\)</span> and the public key is: <span class="math inline">\((n=713, e=547)\)</span>.</p>
<p>Bob wants to send the number <span class="math inline">\(42\)</span> to Alice. He computes the encrypted number to be <span class="math inline">\(c = 42^e ~\%~ n = 42^{547} ~\%~ 713 = 106\)</span> and sends it to Alice. Alice receives the number <span class="math inline">\(106\)</span> from Bob. She computes the decrypted number to be <span class="math inline">\(m = 106^d ~\%~ 713 = 106^{403} ~\%~ 713 = 42\)</span>. Voila!</p>
<h2 id="proving-the-correctness-of-rsa-f5a539720b">Proving the correctness of RSA</h2>
<p>In the RSA cryptosystem, the encryption and decryption algorithms are very straightforward. The “interesting” part is in how the public-private key pair is generated to make the encryption and decryption work! In this section, well come to understand why the key generation involves the steps that it does by proving that the RSA algorithm works correctly, using all the number theory work we developed last week.</p>
<div class="theorem">
<p>Let <span class="math inline">\((p, q, d) \in \Z^+ \times \Z^+ \times \Z^+\)</span> be a private key and <span class="math inline">\((n, e) \in \Z^+ \times \Z^+\)</span> its corresponding public key as generated by “RSA Phase 1”. Let <span class="math inline">\(m, c, m&#39; \in \{1, \dots, n - 1\}\)</span> be the original plaintext message, ciphertext, and decrypted message, respectively, as described in the RSA encryption and decryption phases.</p>
<p>Then <span class="math inline">\(m&#39; = m\)</span> (i.e., the decrypted message is the same as the original message).</p>
<div class="proof">
<p>Let <span class="math inline">\(p, q, n, d, e, m, c, m&#39; \in \N\)</span> be defined as in the above definition of the RSA algorithm. We need to prove that <span class="math inline">\(m&#39; = m\)</span>.</p>
<p> (It is possible to prove this theorem without this assumption, but we will not do so here.)</p>
<p>From the definition of <span class="math inline">\(m&#39;\)</span> in the decryption step, we know <span class="math inline">\(m&#39; \equiv c^d \pmod n\)</span>. From the definition of <span class="math inline">\(c\)</span> in the encryption step, we know <span class="math inline">\(c \equiv m^e \pmod n\)</span>. Putting these together, we have: <span class="math display">\[m&#39; \equiv (m^e)^d \equiv m^{ed} \pmod n.\]</span></p>
<p>So we need to prove that <span class="math inline">\(m^{ed} \equiv m \pmod n\)</span>. From Steps 3 and 4 of the RSA key generation phase, we know that <span class="math inline">\(de \equiv 1 \pmod{\varphi(n)}\)</span>, i.e., there exists a <span class="math inline">\(k \in \Z\)</span> such that <span class="math inline">\(de = k \cdot \varphi(n) + 1\)</span>.</p>
<p>We also know that since <span class="math inline">\(\gcd(m, n) = 1\)</span>, by Eulers Theorem <span class="math inline">\(m^{\varphi(n)} \equiv 1 \pmod n\)</span>.</p>
<p>Putting this all together, we have <span class="math display">\[\begin{align*}
m&#39; &amp;\equiv m^{ed} \pmod n \\
&amp;\equiv m^{k \varphi(n) + 1} \pmod n \\
&amp;\equiv (m^{\varphi(n)})^k \cdot m \pmod n \\
&amp;\equiv 1^k \cdot m \pmod n \tag{by Euler&#39;s Theorem!} \\
&amp;\equiv m \pmod n
\end{align*}\]</span></p>
<p>So <span class="math inline">\(m&#39; \equiv m \pmod n\)</span>. Since we also know <span class="math inline">\(m\)</span> and <span class="math inline">\(m&#39;\)</span> are between <span class="math inline">\(1\)</span> and <span class="math inline">\(n-1\)</span>, we can conclude that <span class="math inline">\(m&#39; = m\)</span>.</p>
</div>
</div>
<h2 id="the-security-of-rsa-f5a539720b">The security of RSA</h2>
<p>Now that weve established the correctness of the RSA cryptosystem, lets now discuss its security. As we did for the Diffie-Hellman key exchange, well put ourselves in the role of an eavesdropper who is trying to gain information about a secret message. Suppose we observe Bob sending an encrypted message <span class="math inline">\(c\)</span> to Alice. In addition to the ciphertext, we also know Alices public key <span class="math inline">\((n, e)\)</span>.<label for="sn-2-f5a539720b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-f5a539720b" class="margin-toggle"/><span class="sidenote"> Remember that “public” means that <em>everyone</em> can see it—including possibly malicious users!</span> What information can we hope to gain about Bobs original plaintext message?</p>
<p>First, we know from the RSA encryption phase that <span class="math inline">\(c \equiv m^e \pmod n\)</span>, so if we know all three of <span class="math inline">\(c\)</span>, <span class="math inline">\(e\)</span>, and <span class="math inline">\(n\)</span>, can we determine the value of <span class="math inline">\(m\)</span>? <em>No!</em> We dont have an efficient way of computing “<span class="math inline">\(e\)</span>-th roots” in modular arithmetic.</p>
<p>Another approach we could take is to attempt to discover Alices private key. Recall that <span class="math inline">\(de \equiv 1 \pmod{\varphi(n)}\)</span>. So <span class="math inline">\(d\)</span> is the inverse of <span class="math inline">\(e\)</span> modulo <span class="math inline">\(\varphi(n)\)</span>, and we learned in the last chapter that we can compute modular inverses, so this should be easy, right?</p>
<p><em>Not so fast!</em> We can compute the modular inverse of <span class="math inline">\(d\)</span> modulo <span class="math inline">\(\varphi(n)\)</span> when we know both <span class="math inline">\(d\)</span> and <span class="math inline">\(\varphi(n)\)</span>, but right now we only know <span class="math inline">\(n\)</span>, not <span class="math inline">\(\varphi(n)\)</span>.</p>
<p>So how do we compute <span class="math inline">\(\varphi(n)\)</span>? Well, we know that if <span class="math inline">\(n = p \cdot q\)</span> where <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> are distinct primes, then <span class="math inline">\(\varphi(n) = (p - 1)(q - 1)\)</span>. But here is the problem: <em>it is not computationally feasible to factor <span class="math inline">\(n\)</span> when it is extremely large</em>. This is our second “computationally hard” problem in computer science, the <em>Integer Factorization Problem</em>. Despite the best efforts of computer scientists and mathematicians for centuries, there is no known efficient general algorithm for factoring integers, and it is this fact that keeps the RSA private key <span class="math inline">\((p, q, d)\)</span> secure.</p>
</section>
<br/> <a id="anchor-07-05"></a>
<header id="title-block-header-d638c380f2">
<h1 class="title">7.5 Implementing RSA in Python</h1>
</header>
<section>
<p>In the previous section we defined the RSA cryptosystem that used both a public key and private key to send encrypted messages between two parties. In this section, we will see how to implement the RSA cryptosystem in Python. First, we will see how to generate a private key when given two prime numbers. Second, we will see how to encrypt and decrypt a single number. Finally, we will see how to encrypt and decrypt text.</p>
<h2 id="key-generation-d638c380f2">Key generation</h2>
<p>Here is our implementation of the first phase of RSA: generating the public-private key pair. In this implementation, we will assume that the prime numbers <span class="math inline">\(p\)</span> and <span class="math inline">\(q\)</span> are given.<label for="sn-0-d638c380f2" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-d638c380f2" class="margin-toggle"/><span class="sidenote"> Algorithms do exist for generating these prime numbers, we just wont go over them here.</span></p>
<div class="sourceCode" id="cb1-d638c380f2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-d638c380f2"><a href="#cb1-1-d638c380f2"></a><span class="kw">def</span> rsa_generate_key(p: <span class="bu">int</span>, q: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="op">\</span></span>
<span id="cb1-2-d638c380f2"><a href="#cb1-2-d638c380f2"></a> <span class="bu">tuple</span>[<span class="bu">tuple</span>[<span class="bu">int</span>, <span class="bu">int</span>, <span class="bu">int</span>], <span class="bu">tuple</span>[<span class="bu">int</span>, <span class="bu">int</span>]]:</span>
<span id="cb1-3-d638c380f2"><a href="#cb1-3-d638c380f2"></a> <span class="co">&quot;&quot;&quot;Return an RSA key pair generated using primes p and q.</span></span>
<span id="cb1-4-d638c380f2"><a href="#cb1-4-d638c380f2"></a></span>
<span id="cb1-5-d638c380f2"><a href="#cb1-5-d638c380f2"></a><span class="co"> The return value is a tuple containing two tuples:</span></span>
<span id="cb1-6-d638c380f2"><a href="#cb1-6-d638c380f2"></a><span class="co"> 1. The first tuple is the private key, containing (p, q, d).</span></span>
<span id="cb1-7-d638c380f2"><a href="#cb1-7-d638c380f2"></a><span class="co"> 2. The second tuple is the public key, containing (n, e).</span></span>
<span id="cb1-8-d638c380f2"><a href="#cb1-8-d638c380f2"></a></span>
<span id="cb1-9-d638c380f2"><a href="#cb1-9-d638c380f2"></a><span class="co"> Preconditions:</span></span>
<span id="cb1-10-d638c380f2"><a href="#cb1-10-d638c380f2"></a><span class="co"> - p and q are prime</span></span>
<span id="cb1-11-d638c380f2"><a href="#cb1-11-d638c380f2"></a><span class="co"> - p != q</span></span>
<span id="cb1-12-d638c380f2"><a href="#cb1-12-d638c380f2"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-13-d638c380f2"><a href="#cb1-13-d638c380f2"></a> <span class="co"># Compute the product of p and q</span></span>
<span id="cb1-14-d638c380f2"><a href="#cb1-14-d638c380f2"></a> n <span class="op">=</span> p <span class="op">*</span> q</span>
<span id="cb1-15-d638c380f2"><a href="#cb1-15-d638c380f2"></a></span>
<span id="cb1-16-d638c380f2"><a href="#cb1-16-d638c380f2"></a> <span class="co"># Choose e such that gcd(e, phi_n) == 1.</span></span>
<span id="cb1-17-d638c380f2"><a href="#cb1-17-d638c380f2"></a> phi_n <span class="op">=</span> (p <span class="op">-</span> <span class="dv">1</span>) <span class="op">*</span> (q <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb1-18-d638c380f2"><a href="#cb1-18-d638c380f2"></a></span>
<span id="cb1-19-d638c380f2"><a href="#cb1-19-d638c380f2"></a> <span class="co"># Since e is chosen randomly, we repeat the random choice</span></span>
<span id="cb1-20-d638c380f2"><a href="#cb1-20-d638c380f2"></a> <span class="co"># until e is coprime to phi_n.</span></span>
<span id="cb1-21-d638c380f2"><a href="#cb1-21-d638c380f2"></a> e <span class="op">=</span> random.randint(<span class="dv">2</span>, phi_n <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb1-22-d638c380f2"><a href="#cb1-22-d638c380f2"></a> <span class="cf">while</span> math.gcd(e, phi_n) <span class="op">!=</span> <span class="dv">1</span>:</span>
<span id="cb1-23-d638c380f2"><a href="#cb1-23-d638c380f2"></a> e <span class="op">=</span> random.randint(<span class="dv">2</span>, phi_n <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb1-24-d638c380f2"><a href="#cb1-24-d638c380f2"></a></span>
<span id="cb1-25-d638c380f2"><a href="#cb1-25-d638c380f2"></a> <span class="co"># Choose d such that e * d % phi_n = 1.</span></span>
<span id="cb1-26-d638c380f2"><a href="#cb1-26-d638c380f2"></a> <span class="co"># Notice that we&#39;re using our modular_inverse from our work in the last chapter!</span></span>
<span id="cb1-27-d638c380f2"><a href="#cb1-27-d638c380f2"></a> d <span class="op">=</span> modular_inverse(e, phi_n)</span>
<span id="cb1-28-d638c380f2"><a href="#cb1-28-d638c380f2"></a></span>
<span id="cb1-29-d638c380f2"><a href="#cb1-29-d638c380f2"></a> <span class="cf">return</span> ((p, q, d), (n, e))</span></code></pre></div>
<p>The algorithm makes use of both a <code>while</code> loop and the <code>random</code> module. The <code>random</code> module is used to generate an <code>e</code>, but the while loop ensures that the <code>e</code> we finally choose is valid. That is, we continue to randomly generate an <code>e</code> <em>until</em> <code>e</code> and <code>phi_n</code> have a greatest common divisor of 1. Once we have <code>e</code>, we can finally calculate the last part of our private key: <code>d</code>. To do so, we make use of the <code>modular_inverse</code> function we defined in the last chapter (which, in turn, used the <code>extended_gcd</code> function).</p>
<h2 id="encrypting-and-decrypting-a-number-d638c380f2">Encrypting and decrypting a number</h2>
<p>Next, lets look at RSA encryption, which only uses the public key. Recall that the plaintext here is a number <span class="math inline">\(m\)</span> between <span class="math inline">\(1\)</span> and <span class="math inline">\(n - 1\)</span> inclusive, and the ciphertext is another number <span class="math inline">\(c = m^e ~\%~ n\)</span>. This mathematical definition translates directly into Python:</p>
<div class="sourceCode" id="cb2-d638c380f2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-d638c380f2"><a href="#cb2-1-d638c380f2"></a><span class="kw">def</span> rsa_encrypt(public_key: <span class="bu">tuple</span>[<span class="bu">int</span>, <span class="bu">int</span>], plaintext: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-2-d638c380f2"><a href="#cb2-2-d638c380f2"></a> <span class="co">&quot;&quot;&quot;Encrypt the given plaintext using the recipient&#39;s public key.</span></span>
<span id="cb2-3-d638c380f2"><a href="#cb2-3-d638c380f2"></a></span>
<span id="cb2-4-d638c380f2"><a href="#cb2-4-d638c380f2"></a><span class="co"> Preconditions:</span></span>
<span id="cb2-5-d638c380f2"><a href="#cb2-5-d638c380f2"></a><span class="co"> - public_key is a valid RSA public key (n, e)</span></span>
<span id="cb2-6-d638c380f2"><a href="#cb2-6-d638c380f2"></a><span class="co"> - 0 &lt; plaintext &lt; public_key[0]</span></span>
<span id="cb2-7-d638c380f2"><a href="#cb2-7-d638c380f2"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-8-d638c380f2"><a href="#cb2-8-d638c380f2"></a> n, e <span class="op">=</span> public_key</span>
<span id="cb2-9-d638c380f2"><a href="#cb2-9-d638c380f2"></a></span>
<span id="cb2-10-d638c380f2"><a href="#cb2-10-d638c380f2"></a> encrypted <span class="op">=</span> (plaintext <span class="op">**</span> e) <span class="op">%</span> n</span>
<span id="cb2-11-d638c380f2"><a href="#cb2-11-d638c380f2"></a></span>
<span id="cb2-12-d638c380f2"><a href="#cb2-12-d638c380f2"></a> <span class="cf">return</span> encrypted</span></code></pre></div>
<p>The implementation for RSA decryption is almost identical, except we use the private key (i.e., <code>d</code>) for exponentiation.</p>
<div class="sourceCode" id="cb3-d638c380f2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-d638c380f2"><a href="#cb3-1-d638c380f2"></a><span class="kw">def</span> rsa_decrypt(private_key: <span class="bu">tuple</span>[<span class="bu">int</span>, <span class="bu">int</span>, <span class="bu">int</span>] ciphertext: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-d638c380f2"><a href="#cb3-2-d638c380f2"></a> <span class="co">&quot;&quot;&quot;Decrypt the given ciphertext using the recipient&#39;s private key.</span></span>
<span id="cb3-3-d638c380f2"><a href="#cb3-3-d638c380f2"></a></span>
<span id="cb3-4-d638c380f2"><a href="#cb3-4-d638c380f2"></a><span class="co"> Preconditions:</span></span>
<span id="cb3-5-d638c380f2"><a href="#cb3-5-d638c380f2"></a><span class="co"> - private_key is a valid RSA private key (p, q, d)</span></span>
<span id="cb3-6-d638c380f2"><a href="#cb3-6-d638c380f2"></a><span class="co"> - 0 &lt; ciphertext &lt; private_key[0] * private_key[1]</span></span>
<span id="cb3-7-d638c380f2"><a href="#cb3-7-d638c380f2"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-8-d638c380f2"><a href="#cb3-8-d638c380f2"></a> p, q, d <span class="op">=</span> private_key</span>
<span id="cb3-9-d638c380f2"><a href="#cb3-9-d638c380f2"></a> n <span class="op">=</span> p <span class="op">*</span> q</span>
<span id="cb3-10-d638c380f2"><a href="#cb3-10-d638c380f2"></a></span>
<span id="cb3-11-d638c380f2"><a href="#cb3-11-d638c380f2"></a> decrypted <span class="op">=</span> (ciphertext <span class="op">**</span> d) <span class="op">%</span> n</span>
<span id="cb3-12-d638c380f2"><a href="#cb3-12-d638c380f2"></a></span>
<span id="cb3-13-d638c380f2"><a href="#cb3-13-d638c380f2"></a> <span class="cf">return</span> decrypted</span></code></pre></div>
<h2 id="encrypting-and-decrypting-text-using-rsa-d638c380f2">Encrypting and decrypting text using RSA</h2>
<p>The above implementation of RSA is correct, but is a little unsatisfying because it encrypts numbers instead of strings, like we saw with the Caesar cipher and One-Time Pad cryptosystem. So next, well see how to adapt the RSA encryption and decryption algorithms to strings.</p>
<p>Our strategy will be to take a string and break it up into individual characters and encrypt each character, just as we did with the Caesar cipher. Well use this approach for both encryption and decryption, using <code>ord</code>/<code>chr</code> to convert between characters and numbers, and a string accumulator to keep track of the encrypted/decrypted results.</p>
<div class="sourceCode" id="cb4-d638c380f2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-d638c380f2"><a href="#cb4-1-d638c380f2"></a><span class="kw">def</span> rsa_encrypt_text(public_key: <span class="bu">tuple</span>[<span class="bu">int</span>, <span class="bu">int</span>], plaintext: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb4-2-d638c380f2"><a href="#cb4-2-d638c380f2"></a> <span class="co">&quot;&quot;&quot;Encrypt the given plaintext using the recipient&#39;s public key.</span></span>
<span id="cb4-3-d638c380f2"><a href="#cb4-3-d638c380f2"></a></span>
<span id="cb4-4-d638c380f2"><a href="#cb4-4-d638c380f2"></a><span class="co"> Preconditions:</span></span>
<span id="cb4-5-d638c380f2"><a href="#cb4-5-d638c380f2"></a><span class="co"> - public_key is a valid RSA public key (n, e)</span></span>
<span id="cb4-6-d638c380f2"><a href="#cb4-6-d638c380f2"></a><span class="co"> - all({0 &lt; ord(c) &lt; public_key[0] for c in plaintext})</span></span>
<span id="cb4-7-d638c380f2"><a href="#cb4-7-d638c380f2"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-8-d638c380f2"><a href="#cb4-8-d638c380f2"></a> n, e <span class="op">=</span> public_key</span>
<span id="cb4-9-d638c380f2"><a href="#cb4-9-d638c380f2"></a></span>
<span id="cb4-10-d638c380f2"><a href="#cb4-10-d638c380f2"></a> encrypted <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb4-11-d638c380f2"><a href="#cb4-11-d638c380f2"></a> <span class="cf">for</span> letter <span class="kw">in</span> plaintext:</span>
<span id="cb4-12-d638c380f2"><a href="#cb4-12-d638c380f2"></a> <span class="co"># Note: we could have also used our rsa_encrypt function here instead</span></span>
<span id="cb4-13-d638c380f2"><a href="#cb4-13-d638c380f2"></a> encrypted <span class="op">=</span> encrypted <span class="op">+</span> <span class="bu">chr</span>((<span class="bu">ord</span>(letter) <span class="op">**</span> e) <span class="op">%</span> n)</span>
<span id="cb4-14-d638c380f2"><a href="#cb4-14-d638c380f2"></a></span>
<span id="cb4-15-d638c380f2"><a href="#cb4-15-d638c380f2"></a> <span class="cf">return</span> encrypted</span>
<span id="cb4-16-d638c380f2"><a href="#cb4-16-d638c380f2"></a></span>
<span id="cb4-17-d638c380f2"><a href="#cb4-17-d638c380f2"></a></span>
<span id="cb4-18-d638c380f2"><a href="#cb4-18-d638c380f2"></a><span class="kw">def</span> rsa_decrypt_text(private_key: <span class="bu">tuple</span>[<span class="bu">int</span>, <span class="bu">int</span>, <span class="bu">int</span>], ciphertext: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb4-19-d638c380f2"><a href="#cb4-19-d638c380f2"></a> <span class="co">&quot;&quot;&quot;Decrypt the given ciphertext using the recipient&#39;s private key.</span></span>
<span id="cb4-20-d638c380f2"><a href="#cb4-20-d638c380f2"></a></span>
<span id="cb4-21-d638c380f2"><a href="#cb4-21-d638c380f2"></a><span class="co"> Preconditions:</span></span>
<span id="cb4-22-d638c380f2"><a href="#cb4-22-d638c380f2"></a><span class="co"> - private_key is a valid RSA private key (p, q, d)</span></span>
<span id="cb4-23-d638c380f2"><a href="#cb4-23-d638c380f2"></a><span class="co"> - all({0 &lt; ord(c) &lt; private_key[0] * private_key[1] for c in ciphertext})</span></span>
<span id="cb4-24-d638c380f2"><a href="#cb4-24-d638c380f2"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-25-d638c380f2"><a href="#cb4-25-d638c380f2"></a> p, q, d <span class="op">=</span> private_key</span>
<span id="cb4-26-d638c380f2"><a href="#cb4-26-d638c380f2"></a> n <span class="op">=</span> p <span class="op">*</span> q</span>
<span id="cb4-27-d638c380f2"><a href="#cb4-27-d638c380f2"></a></span>
<span id="cb4-28-d638c380f2"><a href="#cb4-28-d638c380f2"></a> decrypted <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb4-29-d638c380f2"><a href="#cb4-29-d638c380f2"></a> <span class="cf">for</span> letter <span class="kw">in</span> ciphertext:</span>
<span id="cb4-30-d638c380f2"><a href="#cb4-30-d638c380f2"></a> <span class="co"># Note: we could have also used our rsa_decrypt function here instead</span></span>
<span id="cb4-31-d638c380f2"><a href="#cb4-31-d638c380f2"></a> decrypted <span class="op">=</span> decrypted <span class="op">+</span> <span class="bu">chr</span>((<span class="bu">ord</span>(letter) <span class="op">**</span> d) <span class="op">%</span> n)</span>
<span id="cb4-32-d638c380f2"><a href="#cb4-32-d638c380f2"></a></span>
<span id="cb4-33-d638c380f2"><a href="#cb4-33-d638c380f2"></a> <span class="cf">return</span> decrypted</span></code></pre></div>
<!-- ### Putting it all together
Let us use the prime numbers 23 and 31 as $p$ and $q$, respectively, to generate our private and public key.
Next, Bob will send the message that `'Shannon is also cool'` using only the public key.
Alice can decrypt the message using her own private key along with the public key.
```python
if __name__ == '__main__':
# 23 and 31 are prime numbers
private_key, public_key = rsa_generate_key(23, 31)
print(f'Private key: {private_key}')
print(f'Public key: {public_key}')
message = 'Shannon is also cool'
print(f'Message: {message_key}')
# Bob uses only the public key to encrypt the message
encrypted_msg = rsa_encrypt(public_key, message)
print(f'Encrypted: {encrypted_msg}')
# Alice uses her private key to decrypt the message
decrypted_msg = rsa_decrypt(private_key, encrypted_msg)
print(f'Decrypted: {decrypted_msg}')
``` -->
</section>
<br/> <a id="anchor-07-06"></a>
<header id="title-block-header-ac77007ee4">
<h1 class="title">7.6 Application: Securing Online Communications</h1>
</header>
<section>
<p>Cryptography is central to all kinds of computing and online communication in todays modern world. Modern security practices inform every stage of how we interact online, from the Wifi networks we connect to, to how data is transmitted back and forth between our computer and a server halfway around the world, and even how data is encrypted for storage on those servers. Every time we visit a website, watch a video on our phone, or post a photo or tweet, we are relying on modern cryptography to keep our communications private.</p>
<p>In this section, we will tie together our study of cryptography by looking at one specific link in the chain of Internet communication. While doing so, we will explore some of the real-world design decisions and trade-offs that go into implementing a secure communication protocol used by billions of people around the world.</p>
<h2 id="https-and-the-transport-layer-security-protocol-ac77007ee4">HTTPS and the Transport Layer Security protocol</h2>
<p>Whether you are browsing a website on your computer or on your phone, you can probably see a little padlock icon next to the websites URL. Heres what happens when you click on it:</p>
<div style="text-align: center">
<p><img src="images/https_browser.png" alt="Browser image showing HTTPS icon" /><br />
</p>
</div>
<p>This icon is our web browsers way of telling us that the the data being sent from the server (<code>www.teach.cs.toronto.edu</code> in our above picture) has been encrypted using a communication protocol called <em>HTTPS</em>.<label for="sn-0-ac77007ee4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-ac77007ee4" class="margin-toggle"/><span class="sidenote"> We wont define the term “protocol” formally in this course, but you can think of it as an algorithm where the steps are split among two (or more) parties, rather than just a single computer. For example, the Diffie-Hellman key exchange is more commonly referred to as a <em>protocol</em> rather than an algorithm.</span> This protocol consists of two parts:</p>
<ul>
<li><strong>HTTP (Hypertext Transfer Protocol)</strong>, which governs the format of the data being exchanged between your computer and the server.</li>
<li><strong>TLS (Transport Layer Security)</strong>, which governs how the data formatted by HTTP is encrypted during the communication process.</li>
</ul>
<p>On its own, HTTP allows your computer to communicate with servers around the world. But when combined with TLS, those communications are secure and cannot be “snooped” by an eavesdropper (at least not easily!).</p>
<p>An analogy here might be helpful. Suppose youre living in pre-Internet times, and writing a book (or set of course notes!), and want to send a draft to your publisher through mail. <em>HTTP</em> corresponds to the format in which you deliver the book: perhaps chapter by chapter, with a table of contents in front and appendices or an index at the end. <em>TLS</em> corresponds to how you encrypt the contents of what you send in this format. For example, you might apply a Caesar cipher to shift every character in your book or you might enclose each chapter in a separate locked briefcase for which only you and your publisher know the combination. Of course, TLS is much more sophisticated than either of the example “security” approaches. For the rest of this section, well study how TLS uses the concepts weve learned across this chapter to encrypt your online communications.</p>
<h2 id="tls-an-overview-simplified-ac77007ee4">TLS: An overview (simplified)</h2>
<p>For our description of the TLS protocol, well use the term <em>client</em> to refer to your computer and <em>server</em> to refer to the website you are communicating with. TLS starts off with the client initiating a request to the server (e.g., when you type in a URL into your web browser and press “Enter”). The following happens:</p>
<ol type="1">
<li>When the client initiates the request, the server sends a “proof of identity” that the client has connected with the intended server, which the client verifies. <em>This communication is not encrypted.</em></li>
<li>Then, the client and server perform the <a href="03-key-exchange.html">Diffie-Hellman key exchange algorithm</a> to establish a shared secret key.<label for="sn-1-ac77007ee4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-ac77007ee4" class="margin-toggle"/><span class="sidenote"> A new secret key is chosen every time you visit a given website. This provides <em>forward secrecy</em>, which means that if an attacker records your communication with a server across multiple sessions, but is only able to discover what your key for a single session, they can only decrypt your communication for that session rather than all your past sessions.</span> <em>This communication is not encrypted either.</em></li>
<li>All remaining communication (e.g., the actual website data!) is encrypted using an agreed-upon symmetric-key cryptosystem, like a <a href="02-one-time-pad.html#stream-ciphers">stream cipher</a>.</li>
</ol>
<p>Thats it! While the protocol seems straightforward, there are a few real-world details that well look at. Let us investigate two questions:</p>
<ol type="1">
<li>Why is symmetric-key encryption (rather than public-key encryption) used to encrypt the communication in step 3?</li>
<li>Given that the first two steps of of TLS are unencrypted, how can the client be sure it is actually communicating with the intended server the whole time?</li>
</ol>
<h2 id="why-symmetric-key-encryption-ac77007ee4">Why symmetric-key encryption?</h2>
<p>Our first example of symmetric encryption, Caesars cipher, shows just how old the idea is. Public-key encryption is, relatively, much more modern and does not require that the two communicating parties share a secret key. But modern doesnt always mean better—TLS relies on symmetric-key encryption because public-key cryptosystems, like RSA, are significantly <em>slower</em> than their symmetric-key counterparts. While RSA relies on modular exponentiation as the key encryption and decryption steps, modern symmetric-key cryptosystems use faster operations<label for="sn-2-ac77007ee4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-ac77007ee4" class="margin-toggle"/><span class="sidenote">Typically these operations act on swapping or combining individual bytes in computer memory.</span> to encrypt and decrypt data.</p>
<p>When computers became household commodities, performance was king. Here, performance is a broad term that typically refers to how quickly a computer can do something. For example: how long does it take to encrypt the frame of a video, send it over a wireless connection, and decrypt that frame on your phone? Consider that your phone is likely streaming at least 30 frames per second in order for you to enjoy a video of reasonable quality. Its also increasingly likely that, today, the frame of video is high-definition, which requires even more data to be encrypted and decrypted. While security and privacy is king in todays world, performance cannot be forgotten.</p>
<h2 id="who-am-i-connected-to-ac77007ee4">Who am I connected to?</h2>
<p>The first two steps of the TLS protocol are “setup” steps for the actual communication of data between the client and server. While a symmetric cryptosystem is used to encrypt the communicated data, these setup steps are unencrypted, and raise a natural question: how do we know we are communicating with the right server?</p>
<p>For example, when we visit <code>www.google.com</code>, and our computer performs the TLS protocol with a distant server, how do we know our computer is connecting to a real Google server, and not some fake server thats simply pretending to be Google? The consequences of establishing a connection with such a “fake Google” server are severe: that server might give us manipulated or fake search results, save our login information, or store text, images, and videos we upload to Google Drive or YouTube. Even if we encrypt all of this data in Step 3 of TLS, that encryption does not protect us from a malicious fake server posing as an honest one.</p>
<p>In order to avoid such a dangerous situation, we need some way to verify that the server (e.g., Google) we intended to speak with is actually who they say they are. Herein lies one of the main benefits of public-key cryptosystems. Every public-key cryptosystem, including RSA, can implement two additional algorithms to:</p>
<ol type="1">
<li>Sign message using the private key</li>
<li>Verify a signature using the public key</li>
</ol>
<p>These algorithms allow a server to <em>sign every message it sends</em> with is private key, and then have the client <em>verify</em> each message signature using the servers public key. We call these <strong>digital signatures</strong>, and they help us identify exactly who we are speaking with. We wont go into the specifics of the algorithms here, but the process for the RSA cryptosystem is similar to what weve outlined in this chapter (i.e., they exploit modular arithmetic). Alice can add her signature, which is a function of her private key, to a message. Bob can verify that Alice is the sender with Alices public key.</p>
<p>Digital signatures are used in each of the first two steps in the TLS protocol, which is what well look at next.</p>
<h3 id="establishing-identity-digital-certificates-ac77007ee4">Establishing identity: digital certificates</h3>
<p>In the first step of TLS, we said that the server sends the client a “proof of identity”. To make that more precise, the data the server sends in this step is called a <strong>digital certificate</strong>, which has identifying information for the server, including its domain (e.g., <code>www.google.com</code>), its organization name (e.g., “Google LLC”), and its <em>public key</em>.</p>
<p>But how do we know this digital certificate is the “real” one? The certificate also includes the digital signature of a <em>certificate authority</em>, which is an organization whose purpose is to issue digital certificates to website domains and verify the identities of the operators of each of those domains.<label for="sn-3-ac77007ee4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-ac77007ee4" class="margin-toggle"/><span class="sidenote"> The largest of these worldwide are IdenTrust and DigiCert, though a recent non-profit called <em>Lets Encrypt</em> launched in 2016.</span> So when the client “verifies” the digital certificate provided by the server, whats actually happening is that the client is verifying the digital signature provided by the certificate authority, using the certificate authoritys public key.<label for="sn-4-ac77007ee4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-ac77007ee4" class="margin-toggle"/><span class="sidenote"> You might ask: how does the client know the certificate authoritys public key? It turns out that web browsers come <em>pre-installed</em> with the public keys of many certificate authorities!</span></p>
<h3 id="maintaining-identity-during-diffie-hellman-ac77007ee4">Maintaining identity during Diffie-Hellman</h3>
<p>After Step 1 of TLS, the client is confident that it has connected with the right server. But we arent in the clear yet—because the Diffie-Hellman algorithm is performed unencrypted, there is still the danger that an attacker might wait for Step 1 to complete and then intercept the messages for Diffie-Hellman in Step 2. Thus the attacker tricking the client into sharing a secret key with the attacker instead of the intended server.</p>
<p>The servers digital certificate doesnt help here! Instead, the server <em>signs all messages</em> it sends during the Diffie-Hellman algorithm, so that at every step the client can verify that the message came from the intended server. Of course, this relies on the client knowing the servers public key, which it gets from the digital certificate in the previous step!</p>
<p>It is this <em>digital signature</em> from the server that allows the client to consistently verify that it is communicating with the server, and that the messages havent been tampered with. At the end of Step 2, the client and server have a shared secret key, and can now communicate safely using symmetric-key encryption.</p>
<!-- ### Key Management
Symmetric encryption only needs one key, but public-key cryptosystems requires both a public and private key (for each person who wants to receive messages).
With public-key cryptosystems, there must be some mechanism to actually *find* public keys.
Typically, public keys are found as *digital certificates* that identify a particular server and organization.
When you connect to the University of Toronto's WiFi for the first time, your computer discovered and validated a certificate.^[
On older operating systems, this may need to be [done manually](https://onesearch.library.utoronto.ca/ic-faq/36617).
]
The details of [key management](https://en.wikipedia.org/wiki/Key_management) is beyond the scope of this course, but it is an important necessity in the world of public-key cryptosystems. -->
<h2 id="ineffectiveness-of-cryptography-ac77007ee4">(In)effectiveness of Cryptography</h2>
<p>Weve mentioned that Diffie-Hellman and RSA are secure because it is very difficult to extract the private part of the data from what is being publicly communicated. But what if it wasnt that difficult? Remember that both RSA and Diffie-Hellman rely on very large prime numbers. But, as we saw in Chapter 6, generating these prime numbers is costly. And it turns out that, unfortunately, many servers use the same group of prime numbers.</p>
<p>Recall that Diffie-Hellman relies on the discrete logarithm problem being difficult to solve. But some steps of the algorithm can be precomputed for a specific group of prime numbers. In 2015, <a href="https://dl.acm.org/doi/abs/10.1145/2810103.2813707">a team of academics</a> discovered that 82% of servers used the same 512-bit group of prime numbers. The team proposed the Logjam attack, which exploited this vulnerability and compromised communications. They also extrapolated that Logjam applied to the 1024-bit case. Today, 2048-bit keys are used to avoid the Logjam attack—for example, Google <a href="https://www.computing.co.uk/news/2285984/google-updates-ssl-certificates-to-2048bit-encryption">announced in 2013</a> that it switched from 1024- to 2048-bit keys.</p>
<p>The Logjam attack is not an isolated incident. Security protocols are constantly being revised, leading to important updates for web browsers, email clients, servers, etc. Earlier versions of the TLS protocol (1.0 and 1.1) are <a href="https://arstechnica.com/gadgets/2018/10/browser-vendors-unite-to-end-support-for-20-year-old-tls-1-0/">deprecated as of March 2020</a>, which means that “secure” communication must use more recent versions of the protocol. Nor are attacks limited to cryptography. The security and privacy of our data can be attacked at multiple points, and attackers are not limited to exploiting weaknesses when we communicate data. The fields of computer security and data privacy are becoming one of the most important problems to solve as laws and policies slowly catch up to a world where a persons private information is used as a common commodity sold and exchanged by corporations.</p>
</section>
<br/>
<h2 class="unnumbered" id="analyzing-algorithm-running-time">8. Analyzing Algorithm Running Time</h2>
<a id="anchor-08-01"></a>
<header id="title-block-header-a699284f7f">
<h1 class="title">8.1 An Introduction to Running Time</h1>
</header>
<section>
<p>So far in this course, when we have studied programming concepts, we have focused on the <em>correctness</em> of our code. In Chapters 15, we learned about different programming constructs, understanding what to do, how to combine them into larger programs, and how to test these programs to make sure they are correct. In Chapters 6 and 7, we learned about mathematical proof, and applied this skill to proving the correctness of various algorithms, including every part of the RSA cryptosystem.</p>
<p>Yet when it comes to evaluating programs, correctness is not the only important measure. As we alluded to in Chapter 7, the amount of time a program takes to run, or program <em>running time</em>, is a critical consideration.<label for="sn-0-a699284f7f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-a699284f7f" class="margin-toggle"/><span class="sidenote"> Running time is often shortened to “runtime”, and is also know as the “efficiency” or “performance” of a program.</span> In this chapter, well study a formal approach to analysing the running time of a program. This section will introduce the topic, and then in future sections well build up some mathematical theory about comparing rates of function growth, and then apply this theory to real program code.</p>
<h2 id="how-do-we-measure-running-time-a699284f7f">How do we measure running time?</h2>
<p>Consider the following function, which prints out the first <code>n</code> natural numbers:</p>
<div class="sourceCode" id="cb1-a699284f7f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-a699284f7f"><a href="#cb1-1-a699284f7f"></a><span class="kw">def</span> print_integers(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-2-a699284f7f"><a href="#cb1-2-a699284f7f"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, n):</span>
<span id="cb1-3-a699284f7f"><a href="#cb1-3-a699284f7f"></a> <span class="bu">print</span>(i)</span></code></pre></div>
<p>What can we say about the running time of this function? An empirical approach would be to measure the time it takes for this function to run on a bunch of different inputs, and then take the average of these times to come up with some sort of estimate of the “average” running time.</p>
<p>But of course, given that this algorithm performs an action for every natural number between <code>0</code> and <code>n - 1</code>, we expect it to take longer as <code>n</code> gets larger, so taking an average of a bunch of running times loses important information about the inputs.<label for="sn-1-a699284f7f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-a699284f7f" class="margin-toggle"/><span class="sidenote">This is like doing a random poll of how many birthday cakes people have eaten without taking into account how old the respondents are.</span></p>
<p>How about choosing one particular input, calling the function multiple times on that input, and averaging those running times? This seems better, but even here there are some problems. For one, the computers hardware can affect running time; for another, computers all are running multiple programs at the same time, so what else is currently running on your computer also affects running time. So even running this experiment on one computer wouldnt necessarily be indicative of how long the function would take on a different computer, nor even how long it would take on the same computer running a different number of other programs.</p>
<p>While these sorts of timing experiments are actually done in practice for evaluating particular hardware or extremely low-level (close to hardware) programs, these details are often not helpful for most software developers, as they do not have control over the machine on which their software will be run.<label for="sn-2-a699284f7f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-a699284f7f" class="margin-toggle"/><span class="sidenote"> That said, these timing experiments can provide an intuitive understanding of the efficiency of our programs. We will explore how to conduct basic timing experiments at the end of this chapter.</span></p>
<p>So rather than use an empirical measurement of runtime, what we do instead is use an abstract representation of runtime: the number of “basic operations” an algorithm executes. This means that we can analyze functions without needing a computer, and our analysis theoretically applies to any computer system. However, there is a good reason “basic operation” is in quotation marks—this vague term raises a whole slew of questions:</p>
<ul>
<li>What counts as a “basic operation”?</li>
<li>How do we tell which “basic operations” are used by an algorithm?</li>
<li>Do all “basic operations” take the same amount of time?</li>
</ul>
<p>The answers to these questions can depend on the hardware being used, as well as what programming language the algorithm is written in. Of course, these are precisely the details we wish to avoid thinking about. In this section, we will count only the calls to <code>print</code> as basic operations, and study <code>print_integers</code> and some variations to establish some intuition and terminology.</p>
<h2 id="linear-running-time-a699284f7f">Linear running time</h2>
<p>First, lets return to <code>print_integers</code>.</p>
<div class="sourceCode" id="cb2-a699284f7f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-a699284f7f"><a href="#cb2-1-a699284f7f"></a><span class="kw">def</span> print_integers(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-2-a699284f7f"><a href="#cb2-2-a699284f7f"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, n):</span>
<span id="cb2-3-a699284f7f"><a href="#cb2-3-a699284f7f"></a> <span class="bu">print</span>(i)</span></code></pre></div>
<p>From Chapter 4, we know that the for loop will call <code>print</code> once per iteration. We also know that this loop iterates <span class="math inline">\(n\)</span> times (with <code>i</code> taking on the values 0, 1, 2, …, <span class="math inline">\(n - 1\)</span>):</p>
<div class="sourceCode" id="cb3-a699284f7f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-a699284f7f"><a href="#cb3-1-a699284f7f"></a><span class="op">&gt;&gt;&gt;</span> print_integers(<span class="dv">2</span>)</span>
<span id="cb3-2-a699284f7f"><a href="#cb3-2-a699284f7f"></a><span class="dv">0</span></span>
<span id="cb3-3-a699284f7f"><a href="#cb3-3-a699284f7f"></a><span class="dv">1</span></span>
<span id="cb3-4-a699284f7f"><a href="#cb3-4-a699284f7f"></a><span class="op">&gt;&gt;&gt;</span> print_integers(<span class="dv">4</span>)</span>
<span id="cb3-5-a699284f7f"><a href="#cb3-5-a699284f7f"></a><span class="dv">0</span></span>
<span id="cb3-6-a699284f7f"><a href="#cb3-6-a699284f7f"></a><span class="dv">1</span></span>
<span id="cb3-7-a699284f7f"><a href="#cb3-7-a699284f7f"></a><span class="dv">2</span></span>
<span id="cb3-8-a699284f7f"><a href="#cb3-8-a699284f7f"></a><span class="dv">3</span></span>
<span id="cb3-9-a699284f7f"><a href="#cb3-9-a699284f7f"></a><span class="op">&gt;&gt;&gt;</span> print_integers(<span class="dv">8</span>)</span>
<span id="cb3-10-a699284f7f"><a href="#cb3-10-a699284f7f"></a><span class="dv">0</span></span>
<span id="cb3-11-a699284f7f"><a href="#cb3-11-a699284f7f"></a><span class="dv">1</span></span>
<span id="cb3-12-a699284f7f"><a href="#cb3-12-a699284f7f"></a><span class="dv">2</span></span>
<span id="cb3-13-a699284f7f"><a href="#cb3-13-a699284f7f"></a><span class="dv">3</span></span>
<span id="cb3-14-a699284f7f"><a href="#cb3-14-a699284f7f"></a><span class="dv">4</span></span>
<span id="cb3-15-a699284f7f"><a href="#cb3-15-a699284f7f"></a><span class="dv">5</span></span>
<span id="cb3-16-a699284f7f"><a href="#cb3-16-a699284f7f"></a><span class="dv">6</span></span>
<span id="cb3-17-a699284f7f"><a href="#cb3-17-a699284f7f"></a><span class="dv">7</span></span></code></pre></div>
<p>So then for an input <span class="math inline">\(n\)</span>, there are <span class="math inline">\(n\)</span> calls to <code>print</code>. We say that the running time of <code>print_integers</code> on input <span class="math inline">\(n\)</span> is <span class="math inline">\(n\)</span> basic operations. If we plot <span class="math inline">\(n\)</span> against this measure running time, we obtain a line:</p>
<p>We say that <code>print_integers</code> has a <strong>linear</strong> running time, as the number of basic operations is a linear function of the input <span class="math inline">\(n\)</span>.</p>
<p><img src="images/Linear.png" /></p>
<h2 id="quadratic-running-time-a699284f7f">Quadratic running time</h2>
<p>Let us now consider a function that prints all combinations of pairs of integers:</p>
<div class="sourceCode" id="cb4-a699284f7f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-a699284f7f"><a href="#cb4-1-a699284f7f"></a><span class="kw">def</span> print_pairs(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb4-2-a699284f7f"><a href="#cb4-2-a699284f7f"></a> <span class="co">&quot;&quot;&quot;Print all combinations of pairs of the first n natural numbers.&quot;&quot;&quot;</span></span>
<span id="cb4-3-a699284f7f"><a href="#cb4-3-a699284f7f"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, n):</span>
<span id="cb4-4-a699284f7f"><a href="#cb4-4-a699284f7f"></a> <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, n):</span>
<span id="cb4-5-a699284f7f"><a href="#cb4-5-a699284f7f"></a> <span class="bu">print</span>(i, j)</span></code></pre></div>
<p>What is the running time of this function? Similar to our previous example, there is a for loop that calls <code>print</code> <span class="math inline">\(n\)</span> times, but now this loop is nested inside another for loop. Lets see some examples of this function being called:</p>
<div class="sourceCode" id="cb5-a699284f7f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-a699284f7f"><a href="#cb5-1-a699284f7f"></a><span class="op">&gt;&gt;&gt;</span> print_pairs(<span class="dv">1</span>)</span>
<span id="cb5-2-a699284f7f"><a href="#cb5-2-a699284f7f"></a><span class="dv">0</span> <span class="dv">0</span></span>
<span id="cb5-3-a699284f7f"><a href="#cb5-3-a699284f7f"></a><span class="op">&gt;&gt;&gt;</span> print_pairs(<span class="dv">2</span>)</span>
<span id="cb5-4-a699284f7f"><a href="#cb5-4-a699284f7f"></a><span class="dv">0</span> <span class="dv">0</span></span>
<span id="cb5-5-a699284f7f"><a href="#cb5-5-a699284f7f"></a><span class="dv">0</span> <span class="dv">1</span></span>
<span id="cb5-6-a699284f7f"><a href="#cb5-6-a699284f7f"></a><span class="dv">1</span> <span class="dv">0</span></span>
<span id="cb5-7-a699284f7f"><a href="#cb5-7-a699284f7f"></a><span class="dv">1</span> <span class="dv">1</span></span>
<span id="cb5-8-a699284f7f"><a href="#cb5-8-a699284f7f"></a><span class="op">&gt;&gt;&gt;</span> print_pairs(<span class="dv">3</span>)</span>
<span id="cb5-9-a699284f7f"><a href="#cb5-9-a699284f7f"></a><span class="dv">0</span> <span class="dv">0</span></span>
<span id="cb5-10-a699284f7f"><a href="#cb5-10-a699284f7f"></a><span class="dv">0</span> <span class="dv">1</span></span>
<span id="cb5-11-a699284f7f"><a href="#cb5-11-a699284f7f"></a><span class="dv">0</span> <span class="dv">2</span></span>
<span id="cb5-12-a699284f7f"><a href="#cb5-12-a699284f7f"></a><span class="dv">1</span> <span class="dv">0</span></span>
<span id="cb5-13-a699284f7f"><a href="#cb5-13-a699284f7f"></a><span class="dv">1</span> <span class="dv">1</span></span>
<span id="cb5-14-a699284f7f"><a href="#cb5-14-a699284f7f"></a><span class="dv">1</span> <span class="dv">2</span></span>
<span id="cb5-15-a699284f7f"><a href="#cb5-15-a699284f7f"></a><span class="dv">2</span> <span class="dv">0</span></span>
<span id="cb5-16-a699284f7f"><a href="#cb5-16-a699284f7f"></a><span class="dv">2</span> <span class="dv">1</span></span>
<span id="cb5-17-a699284f7f"><a href="#cb5-17-a699284f7f"></a><span class="dv">2</span> <span class="dv">2</span></span></code></pre></div>
<p>If we look at the outer loop (loop variable <code>i</code>), we see that it repeats its body <span class="math inline">\(n\)</span> times. But its body is another loop, which repeats <em>its</em> body <span class="math inline">\(n\)</span> times. So the inner loop takes <span class="math inline">\(n\)</span> calls to print each time it is executed, and it is executed <span class="math inline">\(n\)</span> times in total. This means <code>print</code> is called <span class="math inline">\(n^2\)</span> times in total.</p>
<p>We say that <code>print_pairs</code> has a <strong>quadratic</strong> running time, as the number of basic operations is a quadratic function of the input <span class="math inline">\(n\)</span>.</p>
<p><img src="images/Quadratic.png" /></p>
<h2 id="logarithmic-running-time-a699284f7f">Logarithmic running time</h2>
<p>Now lets consider the following function, which prints out the powers of two that are less than a positive integer <span class="math inline">\(n\)</span>.<label for="sn-3-a699284f7f" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-a699284f7f" class="margin-toggle"/><span class="sidenote"> These numbers are of the form <span class="math inline">\(2^i\)</span>, where <span class="math inline">\(i\)</span> can range from 0 to <span class="math inline">\(\ceil{\log_2(n)} - 1\)</span>. For example, when <span class="math inline">\(n = 16\)</span>, <span class="math inline">\(\ceil{\log_2(n)} = 4\)</span>, and <span class="math inline">\(i\)</span> ranges from 0 to 3. When <span class="math inline">\(n = 7\)</span>, <span class="math inline">\(\ceil{\log_2(n)} = 3\)</span>, and <span class="math inline">\(i\)</span> ranges from 0 to 2.</span></p>
<div class="sourceCode" id="cb6-a699284f7f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-a699284f7f"><a href="#cb6-1-a699284f7f"></a><span class="kw">def</span> print_powers_of_two(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-2-a699284f7f"><a href="#cb6-2-a699284f7f"></a> <span class="co">&quot;&quot;&quot;Print the powers of two that are less than n.</span></span>
<span id="cb6-3-a699284f7f"><a href="#cb6-3-a699284f7f"></a></span>
<span id="cb6-4-a699284f7f"><a href="#cb6-4-a699284f7f"></a><span class="co"> Preconditions:</span></span>
<span id="cb6-5-a699284f7f"><a href="#cb6-5-a699284f7f"></a><span class="co"> - n &gt; 0</span></span>
<span id="cb6-6-a699284f7f"><a href="#cb6-6-a699284f7f"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb6-7-a699284f7f"><a href="#cb6-7-a699284f7f"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, math.ceil(math.log2(n))):</span>
<span id="cb6-8-a699284f7f"><a href="#cb6-8-a699284f7f"></a> <span class="bu">print</span>(<span class="dv">2</span> <span class="op">**</span> i)</span></code></pre></div>
<p>In this case, the number of calls to <code>print</code> is <span class="math inline">\(\ceil{\log_2(n)}\)</span>. So the running time of <code>print_powers_of_two</code> is <em>approximately</em>, but not exactly, <span class="math inline">\(\log_2(n)\)</span>. Yet in this case we still say that <code>print_powers_of_two</code> has a <strong>logarithmic</strong> running time.</p>
<p><img src="images/Logarithmic.png" /></p>
<h2 id="constant-running-time-a699284f7f">Constant running time</h2>
<p>Our final example in this section is a bit unusual.</p>
<div class="sourceCode" id="cb7-a699284f7f"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-a699284f7f"><a href="#cb7-1-a699284f7f"></a><span class="kw">def</span> print_ten(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb7-2-a699284f7f"><a href="#cb7-2-a699284f7f"></a> <span class="co">&quot;&quot;&quot;Print n ten times.&quot;&quot;&quot;</span></span>
<span id="cb7-3-a699284f7f"><a href="#cb7-3-a699284f7f"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">10</span>):</span>
<span id="cb7-4-a699284f7f"><a href="#cb7-4-a699284f7f"></a> <span class="bu">print</span>(n)</span></code></pre></div>
<p>How many times is <code>print</code> called here? We can again tell from the header of the for loop: this loop iterates 10 times, and so <code>print</code> is called 10 times, <em>regardless of what <span class="math inline">\(n\)</span> is</em>!</p>
<p>We say that <code>print_ten</code> has a <strong>constant</strong> running time, as the number of basic operations is independent to the input size.</p>
<p><img src="images/Constant.png" /></p>
<h2 id="basic-operations-a699284f7f">Basic operations</h2>
<p>In the past four examples, we have seen examples of functions that have linear, quadratic, logarithmic, and constant running times. While these labels are not precise, they do give us intuition about the relative size of each function.</p>
<!-- ![](images/AllRuntime.png) -->
<p>Functions with linear running time are faster than ones with quadratic running time, and slower than ones with logarithmic running time. Functions with a constant running time are the fastest of all.</p>
<p>But all of our informal analyses in the previous section relied on defining a “basic operation” to be a call to <code>print</code>. We said, for example, that the running time of <code>print_integers</code> had a running time of <span class="math inline">\(n\)</span>. But what if we had a friend comes along and say, “No wait, the variable <code>i</code> must be assigned a new value at every loop iteration, and that counts as a basic operation.” Okay, so then we would say that there are <span class="math inline">\(n\)</span> <code>print</code> calls and <span class="math inline">\(n\)</span> assignments to <code>i</code>, for a total running time of <span class="math inline">\(2n\)</span> basic operations for an input <span class="math inline">\(n\)</span>.</p>
<p>But then another friend chimes in, saying “But <code>print</code> calls take longer than variable assignments, since they need to change pixels on your monitor, so you should count each <code>print</code> call as <span class="math inline">\(10\)</span> basic operations.” Okay, so then there are <span class="math inline">\(n\)</span> print calls worth <span class="math inline">\(10n\)</span> basic operations, plus the assignments to <code>i</code>, for a total of <span class="math inline">\(11n\)</span> basic operations for an input <span class="math inline">\(n\)</span>.</p>
<p>And then another friend joins in: “But you need to factor in an overhead of calling the function as a first step before the body executes, which counts as <span class="math inline">\(1.5\)</span> basic operations (slower than assignment, faster than <code>print</code>).” So then we now have a running time of <span class="math inline">\(11n + 1.5\)</span> basic operations for an input <span class="math inline">\(n\)</span>.</p>
<p>And then another friend starts to speak, but you cut them off and say “Thats it! This is getting way too complicated. Im going back to timing experiments, which may be inaccurate but at least I wont have to listen to these increasing levels of fussiness.”</p>
<p>The expressions <span class="math inline">\(n\)</span>, <span class="math inline">\(2n\)</span>, <span class="math inline">\(11n\)</span>, and <span class="math inline">\(11n + 1.5\)</span> may be different mathematically, but they share a common qualitative type of growth: they are all <em>linear</em>. And so we know, at least intuitively, that they are all faster than quadratic running times and slower than logarithmic running times. What we will study in the next section is how to make this observation precise, and thus avoid the tedium of trying to exactly quantify our “basic operations”, and instead measure the overall rate of growth in the number of operations.</p>
<h2 id="references-a699284f7f">References</h2>
<ul>
<li>CSC108 videos: <a href="https://www.youtube.com/watch?v=2QgtAWzBVuk&amp;list=PLfMGJf6SEIv7uysvvsaoknnzfrCCMMk5r">Algorithm Analysis</a></li>
</ul>
</section>
<!--
Let us now consider a very similar function, `print_odd_integers`:
```python
def print_odd_integers(n: int) -> None:
"""Print the odd integers from 1 to n, inclusive.
"""
for i in range(1, n + 1, 2):
print(i)
```
As the name implies, this function will only print odd integers up to n:
```python
>>> print_odd_integers(2)
1
>>> print_odd_integers(4)
1
3
>>> print_odd_integers(8)
1
3
5
7
```
For `print_integers`, the loop repeats $n$ times.
But for `print_odd_integers`, the loop repeats roughly $n / 2$ times.
Despite this difference, we say that both functions have **linear** runtime scaling.
That is, while the slopes of the lines may be different, the lines themselves still grow proportionally with the size of $n$. -->
<br/> <a id="anchor-08-02"></a>
<header id="title-block-header-dec297549b">
<h1 class="title">8.2 Comparing Asymptotic Function Growth with Big-O</h1>
</header>
<section>
<p>In the previous section, we began our study of program running time with a few simple examples to guide our intuition. One question that emerged from these examples was how we define what “basic operations” we actually count when analysing a programs running time—or better yet, how we can ignore small differences in counts that result from slighly different definitions of “basic operation”. This question grows even more important as we study more complex algorithms consisting of many lines of code.</p>
<p>Over the next two sections, well develop a powerful mathematical tool for comparing function growth rates. This will formalize the idea of “linear”, “quadratic”, “logarithmic”, and “constant” running times from the previous section, and extend these categories to all types of functions.</p>
<h2 id="four-kinds-of-dominance-dec297549b">Four kinds of dominance</h2>
<p>Here is a quick reminder about function notation. When we write <span class="math inline">\(f : A \to B\)</span>, we say that <span class="math inline">\(f\)</span> is a function which maps elements of <span class="math inline">\(A\)</span> to elements of <span class="math inline">\(B\)</span>. In this chapter, we will mainly be concerned about functions mapping the natural numbers to the nonnegative real numbers,<label for="sn-0-dec297549b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-dec297549b" class="margin-toggle"/><span class="sidenote">These are the domain and codomain which arise in algorithm analysis—an algorithm cant take “negative” time to run, after all.</span> i.e., functions <span class="math inline">\(f: \N \to \R^{\geq 0}\)</span>. Though there are many different properties of functions that mathematicians study, we are only going to look at one such property: describing the long-term (i.e., <strong>asymptotic</strong>) growth of a function. We will proceed by building up a few different definitions of comparing function growth, which will eventually lead into one which is robust enough to be used in practice.</p>
<div class="definition" data-terms="dominates (absolute)">
<p>Let <span class="math inline">\(f, g : \N \to \R^{\ge 0}\)</span>. We say that <span class="math inline">\(g\)</span> is <strong>absolutely dominated by</strong> <span class="math inline">\(f\)</span> when for all <span class="math inline">\(n \in \N\)</span>, <span class="math inline">\(g(n) \leq f(n)\)</span>.</p>
</div>
<div class="example">
<p>Let <span class="math inline">\(f(n) = n^2\)</span> and <span class="math inline">\(g(n) = n\)</span>. Prove that <span class="math inline">\(g\)</span> is absolutely dominated by <span class="math inline">\(f\)</span>.</p>
<div class="translation">
<p>This is a straightforward unpacking of a definition, which you should be very comfortable with by now: <span class="math inline">\(\forall n \in \N,~ g(n) \leq f(n)\)</span>.<label for="sn-1-dec297549b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-dec297549b" class="margin-toggle"/><span class="sidenote">Note that we arent quantifying over <span class="math inline">\(f\)</span> and <span class="math inline">\(g\)</span>; the “let” in the example defines concrete functions that we want to prove something about.</span></p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(n \in \N\)</span>. We want to show that <span class="math inline">\(n \leq n^2\)</span>.</p>
<p><strong>Case 1</strong>: Assume <span class="math inline">\(n = 0\)</span>. In this case, <span class="math inline">\(n^2 = n = 0\)</span>, so the inequality holds.</p>
<p><strong>Case 2</strong>: Assume <span class="math inline">\(n \geq 1\)</span>. In this case, we take the inequality <span class="math inline">\(n \geq 1\)</span> and multiply both sides by <span class="math inline">\(n\)</span> to get <span class="math inline">\(n^2 \geq n\)</span>, or equivalently <span class="math inline">\(n \leq n^2.\)</span></p>
</div>
</div>
<p>Unfortunately, absolute dominance is too strict for our purposes: if <span class="math inline">\(g(n) \leq f(n)\)</span> for every natural number except <span class="math inline">\(5\)</span>, then we cant say that <span class="math inline">\(g\)</span> is absolutely dominated by <span class="math inline">\(f\)</span>. For example, the function <span class="math inline">\(g(n) = 2n\)</span> is not absolutely dominated by <span class="math inline">\(f(n) = n^2\)</span>, even though <span class="math inline">\(g(n) \leq f(n)\)</span> everywhere except <span class="math inline">\(n = 1\)</span>. Graphically:</p>
<p><img src="images/LinearQuadratic.png" alt="Linear vs. Quadratic Runtime" /><br />
</p>
<p>Here is another definition which is a bit more flexible than absolute dominance.</p>
<div class="definition" data-terms="dominates (up to a constant factor)">
<p>Let <span class="math inline">\(f, g : \N \to \R^{\ge 0}\)</span>. We say that <span class="math inline">\(g\)</span> <strong>is dominated by <span class="math inline">\(f\)</span> up to a constant factor</strong> when there exists a positive real number <span class="math inline">\(c\)</span> such that for all <span class="math inline">\(n \in \N\)</span>, <span class="math inline">\(g(n) \leq c \cdot f(n)\)</span>.</p>
</div>
<div class="example">
<p>Let <span class="math inline">\(f(n) = n^2\)</span> and <span class="math inline">\(g(n) = 2n\)</span>. Prove that <span class="math inline">\(g\)</span> is dominated by <span class="math inline">\(f\)</span> up to a constant factor.</p>
<div class="translation">
<p>Once again, the translation is a simple unpacking of the previous definition:<label for="sn-2-dec297549b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-dec297549b" class="margin-toggle"/><span class="sidenote">Remember: the order of quantifiers matters! The choice of <span class="math inline">\(c\)</span> is <em>not</em> allowed to depend on <span class="math inline">\(n\)</span>.</span></p>
<p><span class="math display">\[\exists c \in \R^+,~ \forall n \in \N,~ g(n) \leq c \cdot f(n).\]</span></p>
</div>
<div class="discussion">
<p>The term “constant factor” is revealing. We already saw that <span class="math inline">\(n\)</span> is absolutely dominated by <span class="math inline">\(n^2\)</span>, so if the <span class="math inline">\(n\)</span> is multiplied by <span class="math inline">\(2\)</span>, then we should be able to multiply <span class="math inline">\(n^2\)</span> by <span class="math inline">\(2\)</span> as well to get the calculation to work out.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(c = 2\)</span>, and let <span class="math inline">\(n \in \N\)</span>. We want to prove that <span class="math inline">\(g(n) \leq c \cdot f(n)\)</span>, or in other words, <span class="math inline">\(2n \leq 2n^2\)</span>.</p>
<p><strong>Case 1</strong>: Assume <span class="math inline">\(n = 0\)</span>. In this case, <span class="math inline">\(2n = 0\)</span> and <span class="math inline">\(2n^2 = 0\)</span>, so the inequality holds.</p>
<p><strong>Case 2</strong>: Assume <span class="math inline">\(n \geq 1\)</span>. Taking the assumed inequality <span class="math inline">\(n \geq 1\)</span> and multiplying both sides by <span class="math inline">\(2n\)</span> yields <span class="math inline">\(2n^2 \geq 2n\)</span>, or equivalently <span class="math inline">\(2n \leq 2n^2\)</span>.</p>
</div>
</div>
<p>Intuitively, “dominated by up to a constant factor” allows us to ignore multiplicative constants in our functions. This will be very useful in our running time analysis because it frees us from worrying about the exact constants used to represent numbers of basic operations: <span class="math inline">\(n\)</span>, <span class="math inline">\(2n\)</span>, and <span class="math inline">\(11n\)</span> are all <em>equivalent</em> in the sense that each one dominates the other two up to a constant factor.</p>
<p>However, this second definition is still a little too restrictive, as the inequality must hold for every value of <span class="math inline">\(n\)</span>. Consider the functions <span class="math inline">\(f(n) = n^2\)</span> and <span class="math inline">\(g(n) = n + 90\)</span>. No matter how much we scale up <span class="math inline">\(f\)</span> by multiplying it by a constant, <span class="math inline">\(f(0)\)</span> will always be less than <span class="math inline">\(g(0)\)</span>, so we cannot say that <span class="math inline">\(g\)</span> is dominated by <span class="math inline">\(f\)</span> up to a constant factor. And again this is silly: it is certainly possible to find a constant <span class="math inline">\(c\)</span> such that <span class="math inline">\(g(n) \leq cf(n)\)</span> for every value except <span class="math inline">\(n = 0\)</span>. So we want some way of omitting the value <span class="math inline">\(n = 0\)</span> from consideration; this is precisely what our third definition gives us.</p>
<div class="definition" data-terms="dominates (eventually)">
<p>Let <span class="math inline">\(f, g : \N \to \R^{\ge 0}\)</span>. We say that <span class="math inline">\(g\)</span> <strong>is eventually dominated by</strong> <span class="math inline">\(f\)</span> when there exists <span class="math inline">\(n_0 \in \R^+\)</span> such that <span class="math inline">\(\forall n \in \N\)</span>, if <span class="math inline">\(n \geq n_0\)</span> then <span class="math inline">\(g(n) \leq f(n)\)</span>.</p>
</div>
<div class="example">
<p>Let <span class="math inline">\(f(n) = n^2\)</span> and <span class="math inline">\(g(n) = n + 90\)</span>. Prove that <span class="math inline">\(g\)</span> is eventually dominated by <span class="math inline">\(f\)</span>.</p>
<div class="translation">
<p><span class="math display">\[\exists n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \IMP g(n) \leq f(n).\]</span></p>
</div>
<div class="discussion">
<p>Okay, so rather than finding a constant to scale up <span class="math inline">\(f\)</span>, we need to argue that for “large enough” values of <span class="math inline">\(n\)</span>, <span class="math inline">\(n + 90 \leq n^2\)</span>. How do we know that value of <span class="math inline">\(n\)</span> is “large enough?”</p>
<p>Since this is a quadratic inequality, it is actually possible to solve it directly using factoring or the quadratic formula. But thats not really the point of this example, so instead well take advantage of the fact that <em>we</em> get to choose the value of <span class="math inline">\(n_0\)</span> to pick one which is large enough.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(n_0 = 90\)</span>, let <span class="math inline">\(n \in \N\)</span>, and assume <span class="math inline">\(n \geq n_0\)</span>. We want to prove that <span class="math inline">\(n + 90 \leq n^2\)</span>.</p>
<p>We will start with the left-hand side and obtain a chain of inequalities that lead to the right-hand side. <span class="math display">\[\begin{align*}
n + 90 &amp;\leq n + n \tag{since $n \geq 90$} \\
&amp;= 2n \\
&amp;\leq n \cdot n \tag{since $n \geq 2$} \\
&amp;= n^2
\end{align*}\]</span></p>
</div>
</div>
<p>Intuitively, this definition allows us to ignore “small” values of <span class="math inline">\(n\)</span> and focus on the long term, or asymptotic, behaviour of the function. This is particularly important for ignoring the influence of slow-growing terms in a function, which may affect the function values for “small” <span class="math inline">\(n\)</span>, but eventually are overshadowed by the faster-growing terms. In the above example, we knew that <span class="math inline">\(n^2\)</span> grows faster than <span class="math inline">\(n\)</span>, but because an extra <span class="math inline">\(+ 90\)</span> was added to the latter function, it took a while for the faster growth rate of <span class="math inline">\(n^2\)</span> to “catch up” to <span class="math inline">\(n + 90\)</span>.</p>
<p>Our final definition combines both of the previous ones, enabling us to ignore both <em>constant factors</em> and <em>small values of <span class="math inline">\(n\)</span></em> when comparing functions.</p>
<div class="definition" data-terms="Big-O">
<p>Let <span class="math inline">\(f, g: \N \to \R^{\ge 0}\)</span>. We say that <span class="math inline">\(g\)</span> <strong>is eventually dominated by <span class="math inline">\(f\)</span> up to a constant factor</strong> when there exist <span class="math inline">\(c, n_0 \in \R^+\)</span>, such that for all <span class="math inline">\(n \in \N\)</span>, if <span class="math inline">\(n \geq n_0\)</span> then <span class="math inline">\(g(n) \leq c \cdot f(n)\)</span>.</p>
<p>In this case, we also say that <strong><span class="math inline">\(g\)</span> is Big-O of <span class="math inline">\(f\)</span></strong>, and write <span class="math inline">\(g \in \cO(f)\)</span>.</p>
<p>We use the notation “<span class="math inline">\(\in \cO(f)\)</span>” here because we formally define <span class="math inline">\(\cO(f)\)</span> to be the <em>set</em> of functions that are eventually dominated by <span class="math inline">\(f\)</span> up to a constant factor: <span class="math display">\[\cO(f) = \{g \mid g: \N \to \R^{\ge 0},~\text{and}~\exists c, n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \IMP g(n) \leq c \cdot f(n)\}.\]</span></p>
</div>
<div class="example">
<p>Let <span class="math inline">\(f(n) = n^3\)</span> and <span class="math inline">\(g(n) = n^3 + 100n + 5000\)</span>. Prove that <span class="math inline">\(g \in \cO(f)\)</span>.<label for="sn-3-dec297549b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-dec297549b" class="margin-toggle"/><span class="sidenote">We can also express this statement as “<span class="math inline">\(n^3 + 100n + 5000 \in \cO(n^3)\)</span>”.</span></p>
<div class="translation">
<p><span class="math display">\[\exists c, n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \IMP n^3 + 100n + 5000 \leq c n^3.\]</span></p>
</div>
<div class="discussion">
<p>Its worth pointing out that in this case, <span class="math inline">\(g\)</span> is neither eventually dominated by <span class="math inline">\(f\)</span> nor dominated by <span class="math inline">\(f\)</span> up to a constant factor.<label for="sn-4-dec297549b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-dec297549b" class="margin-toggle"/><span class="sidenote"> Exercise: prove this!</span> So well really need to make use of both constants <span class="math inline">\(c\)</span> and <span class="math inline">\(n_0\)</span>. Theyre both existentially-quantified, so we have a lot of freedom in how to choose them!</p>
<p>Heres an idea: lets split up the inequality <span class="math inline">\(n^3 + 100n + 5000 \leq c n^3\)</span> into three simpler ones: <span class="math display">\[\begin{align*}
n^3 &amp;\leq c_1 n^3 \\
100n &amp;\leq c_2 n^3 \\
5000 &amp;\leq c_3 n^3
\end{align*}\]</span></p>
<p>If we can make these three inequalities true, adding them together will give us our desired result (setting <span class="math inline">\(c = c_1 + c_2 + c_3\)</span>). Each of these inequalities is simple enough that we can “solve” them by inspection. Moreover, because we have freedom in how we choose <span class="math inline">\(n_0\)</span> and <span class="math inline">\(c\)</span>, there are many different ways to satisfy these inequalities! To illustrate this, well look at two different approaches here.</p>
<p><strong>Approach 1</strong>: focus on choosing <span class="math inline">\(n_0\)</span>.</p>
<p>It turns out we can satisfy the three inequalities even if <span class="math inline">\(c_1 = c_2 = c_3 = 1\)</span>:</p>
<ul>
<li><span class="math inline">\(n^3 \leq n^3\)</span> is always true (so for all <span class="math inline">\(n \geq 0\)</span>).</li>
<li><span class="math inline">\(100n \leq n^3\)</span> when <span class="math inline">\(n \geq 10\)</span>.</li>
<li><span class="math inline">\(5000 \leq n^3\)</span> when <span class="math inline">\(n \geq \sqrt[3]{5000} \approx 17.1\)</span></li>
</ul>
<p>We can pick <span class="math inline">\(n_0\)</span> to be the largest of the lower bounds on <span class="math inline">\(n\)</span>, <span class="math inline">\(\sqrt[3]{5000}\)</span>, and then these three inequalities will be satisfied!</p>
<p><strong>Approach 2</strong>: focus on choosing <span class="math inline">\(c\)</span>.</p>
<p>Another approach is to pick <span class="math inline">\(c_1\)</span>, <span class="math inline">\(c_2\)</span>, and <span class="math inline">\(c_3\)</span> to make the right-hand sides large enough to satisfy the inequalities.</p>
<ul>
<li><span class="math inline">\(n^3 \leq c_1 n^3\)</span> when <span class="math inline">\(c_1 = 1\)</span>.</li>
<li><span class="math inline">\(100n \leq c_2 n^3\)</span> when <span class="math inline">\(c_2 = 100\)</span>.</li>
<li><span class="math inline">\(5000 \leq c_3 n^3\)</span> when <span class="math inline">\(c_3 = 5000\)</span>, <em>as long as <span class="math inline">\(n \geq 1\)</span></em>.</li>
</ul>
</div>
<div class="proof">
<p>(<em>Using Approach 1</em>) Let <span class="math inline">\(c = 3\)</span> and <span class="math inline">\(n_0 = \sqrt[3]{5000}\)</span>. Let <span class="math inline">\(n \in \N\)</span>, and assume that <span class="math inline">\(n \geq n_0\)</span>. We want to show that <span class="math inline">\(n^3 + 100n + 5000 \leq c n^3\)</span>.</p>
<p>First, we prove three simpler inequalities:</p>
<ul>
<li><span class="math inline">\(n^3 \leq n^3\)</span> (since the two quantities are equal).</li>
<li>Since <span class="math inline">\(n \geq n_0 \geq 10\)</span>, we know that <span class="math inline">\(n^2 \geq 100\)</span>, and so <span class="math inline">\(n^3 \geq 100n\)</span>.</li>
<li>Since <span class="math inline">\(n \geq n_0\)</span>, we know that <span class="math inline">\(n^3 \geq n_0^3 = 5000\)</span>.</li>
</ul>
<p>Adding these three inequalities gives us: <span class="math display">\[n^3 + 100n + 5000 \leq n^3 + n^3 + n^3 = c n^3.\]</span></p>
</div>
<div class="proof">
<p>(<em>Using Approach 2</em>) Let <span class="math inline">\(c = 5101\)</span> and <span class="math inline">\(n_0 = 1\)</span>. Let <span class="math inline">\(n \in \N\)</span>, and assume that <span class="math inline">\(n \geq n_0\)</span>. We want to show that <span class="math inline">\(n^3 + 100n + 5000 \leq c n^3\)</span>.</p>
<p>First, we prove three simpler inequalities:</p>
<ul>
<li><span class="math inline">\(n^3 \leq n^3\)</span> (since the two quantities are equal).</li>
<li>Since <span class="math inline">\(n \in \N\)</span>, we know that <span class="math inline">\(n \leq n^3\)</span>, and so <span class="math inline">\(100n \leq 100n^3\)</span>.</li>
<li>Since <span class="math inline">\(1 \leq n\)</span>, we know that <span class="math inline">\(1 \leq n^3\)</span>, and then multiplying both sides by 5000 gives us <span class="math inline">\(5000 \leq 5000n^3\)</span>.</li>
</ul>
<p>Adding these three inequalities gives us: <span class="math display">\[n^3 + 100n + 5000 \leq n^3 + 100n^3 + 5000n^3 = 5101 n^3 = c n^3.\]</span></p>
</div>
</div>
<!--div exercise>
<div questions data-series="chapter5">
\item
Let $f: \N \to \R^{\ge 0}$, and let $y \in \R^+$ be an arbitrary positive real
number.
Prove that if $f \in \cO(y)$, then $f \in \cO(1)$ (this is why we write
$\cO(1)$ and usually never see $\cO(2)$ or $\cO(110)$).
</div>
</div-->
</section> <br/> <a id="anchor-08-03"></a>
<header id="title-block-header-a075c2eedb">
<h1 class="title">8.3 Big-O, Omega, and Theta</h1>
</header>
<section>
<p>Big-O is a useful way of describing the long-term growth behaviour of functions, but its definition is limited in that it is not required to be an exact description of growth. After all, the key inequality <span class="math inline">\(g(n) \leq c f(n)\)</span> can be satisfied even if <span class="math inline">\(f\)</span> grows much, <em>much</em> faster than <span class="math inline">\(g\)</span>. For example, we could say that <span class="math inline">\(n + 10 \in \cO(n^{100})\)</span> according to our definition, but this is not necessarily informative.</p>
<p>In other words, the definition of Big-O allows us to express <em>upper bounds</em> on the growth of a function, but does not allow us to distinguish between an upper bound that is tight and one that vastly overestimates the rate of growth.</p>
<p>In this section, we will introduce the final new pieces of notation for this chapter, which allow us to express tight bounds on the growth of a function.</p>
<h2 id="omega-and-theta-a075c2eedb">Omega and Theta</h2>
<div class="definition">
<p>Let <span class="math inline">\(f, g : \N \TO \R^{\ge 0}\)</span>. We say that <strong><span class="math inline">\(g\)</span> is Omega of <span class="math inline">\(f\)</span></strong> when there exist constants <span class="math inline">\(c, n_0 \in \R^+\)</span> such that for all <span class="math inline">\(n \in \N\)</span>, if <span class="math inline">\(n \geq n_0\)</span>, then <span class="math inline">\(g(n) \geq c \cdot f(n)\)</span>. In this case, we can also write <span class="math inline">\(g \in \Omega(f)\)</span>.</p>
</div>
<p>You can think of Omega as the dual of Big-O: when <span class="math inline">\(g \in \Omega(f)\)</span>, then <span class="math inline">\(f\)</span> is a <em>lower</em> bound on the growth rate of <span class="math inline">\(g\)</span>. For example, we can use the definition to prove that <span class="math inline">\(n^2 - n \in \Omega(n)\)</span>.</p>
<p>We can now express a bound that is tight for a functions growth rate quite elegantly by combining Big-O and Omega: if <span class="math inline">\(f\)</span> is asymptotically both a lower and upper bound for <span class="math inline">\(g\)</span>, then <span class="math inline">\(g\)</span> must grow at the same rate as <span class="math inline">\(f\)</span>.</p>
<div class="definition" data-terms="Omega, Theta">
<p>Let <span class="math inline">\(f, g : \N \TO \R^{\ge 0}\)</span>. We say that <strong><span class="math inline">\(g\)</span> is Theta of <span class="math inline">\(f\)</span></strong> when <span class="math inline">\(g\)</span> is both Big-O of <span class="math inline">\(f\)</span> and Omega of <span class="math inline">\(f\)</span>. In this case, we can write <span class="math inline">\(g \in \Theta(f)\)</span>, and say that <span class="math inline">\(f\)</span> is a <strong>tight bound</strong> on <span class="math inline">\(g\)</span>.<label for="sn-0-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-a075c2eedb" class="margin-toggle"/><span class="sidenote">Most of the time, when people say “Big-O” they actually mean Theta, i.e., a Big-O upper bound is meant to be the tight one, because we rarely say upper bounds that overestimate the rate of growth. However, in this course we will always use <span class="math inline">\(\Theta\)</span> when we mean tight bounds, because we will see some cases where coming up with tight bounds isnt easy.</span></p>
<p>Equivalently, <span class="math inline">\(g\)</span> is Theta of <span class="math inline">\(f\)</span> when there exist constants <span class="math inline">\(c_1, c_2, n_0 \in \R^+\)</span> such that for all <span class="math inline">\(n \in \N\)</span>, if <span class="math inline">\(n \geq n_0\)</span> then <span class="math inline">\(c_1 f(n) \leq g(n) \leq c_2 f(n)\)</span>.</p>
</div>
<p>When we are comparing function growth rates, we typically look for a “Theta bound”, as this means that the two functions have the same approximate rate of growth, not just that one is larger than the other. For example, it is possible to prove that <span class="math inline">\(10n + 5 \in \Theta(n)\)</span>, but <span class="math inline">\(10n + 5 \notin \Theta(n^2)\)</span>.<label for="sn-1-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-a075c2eedb" class="margin-toggle"/><span class="sidenote"> Both of these are good exercises to prove, using the above definitions!</span></p>
<!-- <div class="example">
Let $f(n) = n^2$ and $g(n) = n + 10$. Then $g \in \cO(f)$, but
$g \notin \Theta(f)$. That is, $f$ is an upper bound for the growth
rate of $g$, but it is not a tight upper bound.
</div>
<div exercise>
<div questions data-series="chapter5">
\item
Prove the statement in the previous example.
Note that the correct translation uses an **AND**, so you'll actually need to prove two different statements here.
</div>
</div> -->
<h2 id="a-special-case-co1-omega1-and-theta1-a075c2eedb">A special case: <span class="math inline">\(\cO(1)\)</span>, <span class="math inline">\(\Omega(1)\)</span>, and <span class="math inline">\(\Theta(1)\)</span></h2>
<p>So far, we have seen Big-O expressions like <span class="math inline">\(\cO(n)\)</span> and <span class="math inline">\(\cO(n^2)\)</span>, where the function in parentheses has grown to infinity. However, not every function takes on larger and larger values as its input grows. Some functions are <em>bounded</em>, meaning they never take on a value larger than some fixed constant.</p>
<p>For example, consider the constant function <span class="math inline">\(f(n) = 1\)</span>, which always outputs the value <span class="math inline">\(1\)</span>, regardless of the value of <span class="math inline">\(n\)</span>. What would it mean to say that a function <span class="math inline">\(g\)</span> is Big-O of this <span class="math inline">\(f\)</span>? Lets unpack the definition of Big-O to find out.</p>
<p><span class="math display">\[\begin{align*}
&amp; g \in \cO(f) \\
&amp; \exists c, n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \IMP g(n) \leq c \cdot f(n) \\
&amp; \exists c, n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \IMP g(n) \leq c \tag{since $f(n) = 1$}
\end{align*}\]</span></p>
<p>In other words, there exists a constant <span class="math inline">\(c\)</span> such that <span class="math inline">\(g(n)\)</span> is eventually always less than or equal to <span class="math inline">\(c\)</span>. We say that such functions <span class="math inline">\(g\)</span> are <strong>asymptotically bounded</strong> with respect to their input, and write <span class="math inline">\(g \in \cO(1)\)</span> to represent this.</p>
<p>Similarly, we use <span class="math inline">\(g \in \Omega(1)\)</span> to express that functions are greater than or equal to some constant <span class="math inline">\(c\)</span>. You might wonder why we would ever say this—dont all functions satisfy this property? While the functions well be studying in later chapters in this section are generally going to be <span class="math inline">\(\geq 1\)</span>, this is not true for all mathematical functions. For example, the function <span class="math inline">\(g(n) = \frac{1}{n + 1}\)</span> is <span class="math inline">\(\cO(1)\)</span>, but <em>not</em> <span class="math inline">\(\Omega(1)\)</span>.<label for="sn-2-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-a075c2eedb" class="margin-toggle"/><span class="sidenote"> More generally, any function <span class="math inline">\(g\)</span> where <span class="math inline">\(\lim_{n \to \infty} g(n) = 0\)</span> is not <span class="math inline">\(\Omega(1)\)</span>.</span></p>
<p>On the other hand, the function <span class="math inline">\(g(n) = n^2\)</span> is <span class="math inline">\(\Omega(1)\)</span> but not <span class="math inline">\(\cO(1)\)</span>. So we reserve <span class="math inline">\(\Theta(1)\)</span> to refer to the functions that are both <span class="math inline">\(\cO(1)\)</span> and <span class="math inline">\(\Omega(1)\)</span>.</p>
<h2 id="section:asymptotic-properties-a075c2eedb">Properties of Big-O, Omega, and Theta</h2>
<p>If we had you always write chains of inequalities to prove that one function is Big-O/Omega/Theta of another, that would get quite tedious rather quickly. Instead, in this section we will prove some properties of this definition which are extremely useful for combining functions together under this definition. These properties can save you quite a lot of work in the long run. Well illustrate the proof of one of these properties here; most of the others can be proved in a similar manner, while a few are most easily proved using some techniques from calculus.<label for="sn-3-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-a075c2eedb" class="margin-toggle"/><span class="sidenote">We discuss the connection between calculus and asymptotic notation in the following section, but this is <em>not</em> a required part of CSC110.</span></p>
<h3 id="elementary-functions-a075c2eedb">Elementary functions</h3>
<p>The following theorem tells us how to compare four different types of “elementary” functions: constant functions, logarithms, powers of <span class="math inline">\(n\)</span>, and exponential functions.</p>
<div id="elementary-function-hierarchy-a075c2eedb" class="theorem" data-label="Elementary function hierarchy">
<p>(<em>Elementary function growth hierarchy</em>)</p>
<p>For all <span class="math inline">\(a, b \in \R^+\)</span>, the following statements are true:</p>
<ol type="1">
<li>If <span class="math inline">\(a &gt; 1\)</span> and <span class="math inline">\(b &gt; 1\)</span>, then <span class="math inline">\(\log_a n \in \Theta(\log_b n)\)</span>.</li>
<li>If <span class="math inline">\(a &lt; b\)</span>, then <span class="math inline">\(n^a \in \cO(n^b)\)</span> and <span class="math inline">\(n^a \notin \Omega(n^b)\)</span>.</li>
<li>If <span class="math inline">\(a &lt; b\)</span>, then <span class="math inline">\(a^n \in \cO(b^n)\)</span> and <span class="math inline">\(a^n \notin \Omega(b^n)\)</span>.</li>
<li>If <span class="math inline">\(a &gt; 1\)</span>, then <span class="math inline">\(1 \in \cO(\log_a n)\)</span> and <span class="math inline">\(1 \notin \Omega(\log_a n)\)</span>.</li>
<li><span class="math inline">\(\log_a n \in \cO(n^b)\)</span> and <span class="math inline">\(\log_a n \notin \Omega(n^b)\)</span>.</li>
<li>If <span class="math inline">\(b &gt; 1\)</span>, then <span class="math inline">\(n^a \in \cO(b^n)\)</span> and <span class="math inline">\(n^a \notin \Omega(b^n)\)</span>.</li>
</ol>
</div>
<p>And here is a handy figure to show the progression of functions toward longer running times:</p>
<p><img src="images/elementary_function_hierarchy.png" /></p>
<h3 id="basic-properties-a075c2eedb">Basic properties</h3>
<div class="theorem" data-label="Reflexivity">
<p>For all <span class="math inline">\(f : \N \to \R^{\geq 0}\)</span>, <span class="math inline">\(f \in \Theta(f)\)</span>.</p>
</div>
<div class="theorem" data-label="Quasi-symmetry">
<p>For all <span class="math inline">\(f, g : \N \to \R^{\geq 0}\)</span>, <span class="math inline">\(g \in \cO(f)\)</span> if and only if <span class="math inline">\(f \in \Omega(g)\)</span>.<label for="sn-4-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-a075c2eedb" class="margin-toggle"/><span class="sidenote">As a consequence of this, <span class="math inline">\(g \in \Theta(f)\)</span> if and only if <span class="math inline">\(f \in \Theta(g)\)</span>.</span></p>
</div>
<div class="theorem" data-label="Transitivity">
<p>For all <span class="math inline">\(f, g, h : \N \to \R^{\geq 0}\)</span>:</p>
<ul>
<li>If <span class="math inline">\(f \in \cO(g)\)</span> and <span class="math inline">\(g \in \cO(h)\)</span>, then <span class="math inline">\(f \in \cO(h)\)</span>.</li>
<li>If <span class="math inline">\(f \in \Omega(g)\)</span> and <span class="math inline">\(g \in \Omega(h)\)</span>, then <span class="math inline">\(f \in \Omega(h)\)</span>.</li>
<li>If <span class="math inline">\(f \in \Theta(g)\)</span> and <span class="math inline">\(g \in \Theta(h)\)</span>, then <span class="math inline">\(f \in \Theta(h)\)</span>.<label for="sn-5-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-a075c2eedb" class="margin-toggle"/><span class="sidenote"> Exercise: prove this using the first two.</span></li>
</ul>
</div>
<h3 id="operations-on-functions-a075c2eedb">Operations on functions</h3>
<div class="definition" data-terms="sum of functions">
<p>Let <span class="math inline">\(f, g : \N \TO \R^{\ge 0}\)</span>. We can define the <strong>sum of <span class="math inline">\(f\)</span> and <span class="math inline">\(g\)</span></strong> as the function <span class="math inline">\(f + g : \N \TO \R^{\ge 0}\)</span> such that <span class="math display">\[\forall n \in \N,~ (f + g)(n) = f(n) + g(n).\]</span></p>
</div>
<div class="theorem" data-label="Sum of functions">
<p> For all <span class="math inline">\(f, g, h : \N \to \R^{\geq 0}\)</span>, the following hold:</p>
<ol type="1">
<li>If <span class="math inline">\(f \in \cO(h)\)</span> and <span class="math inline">\(g \in \cO(h)\)</span>, then <span class="math inline">\(f + g \in \cO(h)\)</span>.</li>
<li>If <span class="math inline">\(f \in \Omega(h)\)</span>, then <span class="math inline">\(f + g \in \Omega(h)\)</span>.</li>
<li>If <span class="math inline">\(f \in \Theta(h)\)</span> and <span class="math inline">\(g \in \cO(h)\)</span>, then <span class="math inline">\(f + g \in \Theta(h)\)</span>.<label for="sn-6-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-a075c2eedb" class="margin-toggle"/><span class="sidenote"> Exercise: prove this using the first two.</span></li>
</ol>
<p>Well prove the first of these statements.</p>
<div class="translation">
<p><span class="math display">\[\forall f, g, h : \N \TO \R^{\ge 0},~ \big(f \in \cO(h) \AND g \in \cO(h)\big) \IMP f + g \in \cO(h).\]</span></p>
</div>
<div class="discussion">
<p>This is similar in spirit to the divisibility proofs we did in <a href="../06-proofs/02-number-theory-proofs.html">Section 6.2</a>, which used a term (divisibility) that contained a quantifier.<label for="sn-7-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7-a075c2eedb" class="margin-toggle"/><span class="sidenote">The definition of Big-O here has <em>three</em> quantifiers, but the idea is the same.</span> Here, we need to assume that <span class="math inline">\(f\)</span> and <span class="math inline">\(g\)</span> are both Big-O of <span class="math inline">\(h\)</span>, and prove that <span class="math inline">\(f + g\)</span> is also Big-O of <span class="math inline">\(h\)</span>.</p>
<p>Assuming <span class="math inline">\(f \in \cO(h)\)</span> tells us there exist positive real numbers <span class="math inline">\(c_1\)</span> and <span class="math inline">\(n_1\)</span> such that for all <span class="math inline">\(n \in \N\)</span>, if <span class="math inline">\(n \geq n_1\)</span> then <span class="math inline">\(f(n) \leq c_1 \cdot h(n)\)</span>. There similarly exist <span class="math inline">\(c_2\)</span> and <span class="math inline">\(n_2\)</span> such that <span class="math inline">\(g(n) \leq c_2 \cdot h(n)\)</span> whenever <span class="math inline">\(n \geq n_2\)</span>. <em>Warning:</em> we cant assume that <span class="math inline">\(c_1 = c_2\)</span> or <span class="math inline">\(n_1 = n_2\)</span>, or any other relationship between these two sets of variables.</p>
<p>We want to prove that there exist <span class="math inline">\(c, n_0 \in \R^+\)</span> such that for all <span class="math inline">\(n \in \N\)</span>, if <span class="math inline">\(n \geq n_0\)</span> then <span class="math inline">\(f(n) + g(n) \leq c \cdot h(n)\)</span>.</p>
<p>The forms of the inequalities we can assume—<span class="math inline">\(f(n) \leq c_1 h(n)\)</span>, <span class="math inline">\(g(n) \leq c_2 h(n)\)</span>—and the final inequality are identical, and in particular the left-hand side suggests that we just need to add the two given inequalities together to get the third. We just need to make sure that both given inequalities hold by choosing <span class="math inline">\(n_0\)</span> to be large enough, and let <span class="math inline">\(c\)</span> be large enough to take into account both <span class="math inline">\(c_1\)</span> and <span class="math inline">\(c_2\)</span>.</p>
</div>
<div class="proof">
<p>Let <span class="math inline">\(f, g, h : \N \TO \R^{\ge 0}\)</span>, and assume <span class="math inline">\(f \in \cO(h)\)</span> and <span class="math inline">\(g \in \cO(h)\)</span>. By these assumptions, there exist <span class="math inline">\(c_1, c_2, n_1, n_2 \in \R^+\)</span> such that for all <span class="math inline">\(n \in \N\)</span>,</p>
<ul>
<li>if <span class="math inline">\(n \geq n_1\)</span>, then <span class="math inline">\(f(n) \leq c_1 \cdot h(n)\)</span>, and</li>
<li>if <span class="math inline">\(n \geq n_2\)</span>, then <span class="math inline">\(g(n) \leq c_2 \cdot h(n)\)</span>.</li>
</ul>
<p>We want to prove that <span class="math inline">\(f + g \in \cO(h)\)</span>, i.e., that there exist <span class="math inline">\(c, n_0 \in \R^+\)</span> such that for all <span class="math inline">\(n \in \N\)</span>, if <span class="math inline">\(n \geq n_0\)</span> then <span class="math inline">\(f(n) + g(n) \leq c \cdot h(n)\)</span>.</p>
<p>Let <span class="math inline">\(n_0 = \max \{n_1, n_2\}\)</span> and <span class="math inline">\(c = c_1 + c_2\)</span>. Let <span class="math inline">\(n \in \N\)</span>, and assume that <span class="math inline">\(n \geq n_0\)</span>. We now want to prove that <span class="math inline">\(f(n) + g(n) \leq c \cdot h(n)\)</span>.</p>
<p>Since <span class="math inline">\(n_0 \geq n_1\)</span> and <span class="math inline">\(n_0 \geq n_2\)</span>, we know that <span class="math inline">\(n\)</span> is greater than or equal to <span class="math inline">\(n_1\)</span> and <span class="math inline">\(n_2\)</span> as well. Then using the Big-O assumptions, <span class="math display">\[\begin{align*}
f(n) &amp;\leq c_1 \cdot h(n) \\
g(n) &amp;\leq c_2 \cdot h(n)
\end{align*}\]</span></p>
<p>Adding these two inequalities together yields</p>
<p><span class="math display">\[f(n) + g(n) \leq c_1 h(n) + c_2 h(n) = (c_1 + c_2) h(n) = c \cdot h(n).\]</span></p>
</div>
</div>
<div class="theorem" data-label="Multiplication by a constant">
<p>For all <span class="math inline">\(f : \N \to \R^{\geq 0}\)</span> and all <span class="math inline">\(a \in \R^+\)</span>, <span class="math inline">\(a \cdot f \in \Theta(f)\)</span>.</p>
</div>
<div class="theorem" data-label="Product of functions">
<p>For all <span class="math inline">\(f_1, f_2, g_1, g_2 : \N \to \R^{\geq 0}\)</span>, if <span class="math inline">\(g_1 \in \cO(f_1)\)</span> and <span class="math inline">\(g_2 \in \cO(f_2)\)</span>, then <span class="math inline">\(g_1 \cdot g_2 \in \cO(f_1 \cdot f_2)\)</span>. <em>Moreover</em>, the statement is still true if you replace Big-O with Omega, or if you replace Big-O with Theta.</p>
</div>
<div class="theorem" data-label="Floor and ceiling">
<p>For all <span class="math inline">\(f : \N \to \R^{\geq 0}\)</span>, if <span class="math inline">\(f(n)\)</span> is eventually greater than or equal to <span class="math inline">\(1\)</span>, then <span class="math inline">\(\floor{f} \in \Theta(f)\)</span> and <span class="math inline">\(\ceil{f} \in \Theta(f)\)</span>.</p>
</div>
<h3 id="properties-from-calculus-a075c2eedb">Properties from calculus</h3>
<p>[<em>Note: this subsection is <strong>not</strong> part of the require course material for CSC110. It is presented mainly for the nice connection between Big-O notation and calculus.</em>]</p>
<p>Our asymptotic notation of <span class="math inline">\(\cO\)</span>, <span class="math inline">\(\Omega\)</span>, and <span class="math inline">\(\Theta\)</span> are concerned with the comparing the <em>long-term behaviour</em> of two functions. It turns out that the concept of “long-term behaviour” is captured in another object of mathematical study, familiar to us from calculus: the <em>limit</em> of the function as its input approaches infinity.</p>
<p>Let <span class="math inline">\(f: \N \to \R\)</span> and <span class="math inline">\(L \in \R\)</span>. We have the following two definitions:<label for="sn-8-a075c2eedb" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-8-a075c2eedb" class="margin-toggle"/><span class="sidenote">Were restricting our attention here to functions with domain <span class="math inline">\(\N\)</span> because thats our focus in computer science.</span> <span class="math display">\[
\lim_{n \to \infty} f(n) = L:~ \forall \epsilon \in \R^+,~ \exists n_0 \in \N,~ \forall n \in \N,~ n \geq n_0 \IMP |f(n) - L| &lt; \epsilon
\]</span> <span class="math display">\[
\lim_{n \to \infty} f(n) = \infty:~ \forall M \in \R^+,~ \exists n_0 \in \N,~ \forall n \in \N,~ n \geq n_0 \IMP f(n) &gt; M
\]</span></p>
<p>Using just these definitions and the definitions of our asymptotic symbols <span class="math inline">\(\cO\)</span>, <span class="math inline">\(\Omega\)</span>, and <span class="math inline">\(\Theta\)</span>, we can prove the following pretty remarkable results:</p>
<div class="theorem" data-label="Limits and Big-O">
<p>For all <span class="math inline">\(f, g: \N \to \R^{\geq 0}\)</span>, if <span class="math inline">\(g(n) \neq 0\)</span> for all <span class="math inline">\(n \in \N\)</span>, then the following statements hold:</p>
<ol type="i">
<li>If there exists <span class="math inline">\(L \in \R^+\)</span> such that <span class="math inline">\(\lim_{n \to \infty} f(n)/g(n) = L\)</span>, then <span class="math inline">\(g \in \Omega(f)\)</span> and <span class="math inline">\(g \in \cO(f)\)</span>. (In other words, <span class="math inline">\(g \in \Theta(f)\)</span>.)</li>
<li>If <span class="math inline">\(\lim_{n \to \infty} f(n)/g(n) = 0\)</span>, then <span class="math inline">\(f \in \cO(g)\)</span> and <span class="math inline">\(g \notin \cO(f)\)</span>.</li>
<li>If <span class="math inline">\(\lim_{n \to \infty} f(n)/g(n) = \infty\)</span>, then <span class="math inline">\(g \in \cO(f)\)</span> and <span class="math inline">\(f \notin \cO(g)\)</span>.</li>
</ol>
</div>
<p>Proving this theorem is actually a very good (lengthy) exercise for a CSC110 student; they involve keeping track of variables and manipulating inequalities, two key skills youre developing in this course! And they do tend to be useful in practice (although again, not for this course) to proving asymptotic bounds like <span class="math inline">\(n^2 \in \cO(1.01^n)\)</span>. But note that the converse of these statements is not true; for example, it is possible (and another nice exercise) to find functions <span class="math inline">\(f\)</span> and <span class="math inline">\(g\)</span> such that <span class="math inline">\(g \in \Theta(f)\)</span>, but <span class="math inline">\(\lim_{n \to \infty} f(n)/g(n)\)</span> is undefined.</p>
</section>
<br/> <a id="anchor-08-04"></a>
<header id="title-block-header-575113cd9d">
<h1 class="title">8.4 Analyzing Algorithm Running Time</h1>
</header>
<section>
<p>Let us consider a very similar function to <code>print_integers</code> from the beginning of the chapter:</p>
<div class="sourceCode" id="cb1-575113cd9d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-575113cd9d"><a href="#cb1-1-575113cd9d"></a><span class="kw">def</span> print_items(lst: <span class="bu">list</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-2-575113cd9d"><a href="#cb1-2-575113cd9d"></a> <span class="cf">for</span> item <span class="kw">in</span> lst:</span>
<span id="cb1-3-575113cd9d"><a href="#cb1-3-575113cd9d"></a> <span class="bu">print</span>(item)</span></code></pre></div>
<p>Here, <code>print_items</code> takes a list as input instead, and so <span class="math inline">\(n\)</span> is equivalent to <code>len(lst)</code>.<label for="sn-0-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-575113cd9d" class="margin-toggle"/><span class="sidenote"> For the remainder of this course, we will assume input size for a list is always its length, unless something else is specified.</span> How can we use our asymptotic notation to help us analyze the running time of this algorithm? Earlier, we said that the call to <code>print</code> took 1 “basic operation”, but is that true? The answer is, it doesnt matter. By using asymptotic notation, we no longer need to worry about the constants involved, and so dont need to worry about whether a single call to <code>print</code> counts as one or ten “basic operations”.</p>
<p>Just as switching from measuring real time to counting “basic operations” allows us to ignore the computing environment in which the program runs, switching from an exact step count to asymptotic notation allows us to ignore machine- and programming language-dependent constants involved in the execution of the code. Having ignored all these external factors, our analysis will concentrate on how the <strong>size of the input</strong> influences the running time of a program, where we measure running time just using asymptotic notation, and not exact expressions.</p>
<p><strong>Warning</strong>: the “size” of the input to a program can mean different things depending on the type of input, or even depending on the program itself. Whenever you perform a running time analysis, be sure to clearly state how you are measuring and representing input size.</p>
<p>Because constants dont matter, we will use a very coarse measure of “basic operation” to make our analysis as simple as possible. For our purposes, a basic operation (or step) is <strong>any block of code whose running time does not depend on the size of the input</strong>.<label for="sn-1-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-575113cd9d" class="margin-toggle"/><span class="sidenote">To belabour the point a little, this depends on how we define input size. For integers, we usually will assume they have a fixed size in memory (e.g., 32 bits), which is why arithmetic operations take constant time. But of course if we allow numbers to grow infinitely, this is no longer true, and performing arithmetic operations will no longer take constant time.</span></p>
<p>This includes all primitive language operations like most assignment statements, arithmetic calculations, and list and string indexing. The one major statement type which does not fit in this category is a function call—the running time of such statements depends on how long that particular function takes to run. Well revisit this in more detail later.</p>
<h2 id="the-runtime-function-575113cd9d">The runtime function</h2>
<p>The running time of <code>print_items</code> depends <em>only</em> on the size of the input list, and not the contents of the list. That is, we expect that <code>print_items</code> takes the same amount of time on every list of length <span class="math inline">\(100\)</span>. We can make this a little more clear by introducing one piece of notation that will come in handy for the rest of the chapter.</p>
<div class="definition" data-terms="input sets">
<p>Let <code>func</code> be an algorithm. For every <span class="math inline">\(n \in \N\)</span>, we define the set <span class="math inline">\(\cI_{func, n}\)</span> to be the set of allowed inputs to <code>func</code> of size <span class="math inline">\(n\)</span>.</p>
</div>
<p>For example, <span class="math inline">\(\cI_{print\_items, 100}\)</span> is simply the set of all lists of length 100. <span class="math inline">\(\cI_{print\_items, 0}\)</span> is the set containing just one input: the empty list.</p>
<p>We can restate our observation about <code>print_items</code> in terms of these sets: for all <span class="math inline">\(n \in \N\)</span>, every element of <span class="math inline">\(\cI_{print\_items, n}\)</span> has the <em>same</em> runtime when passed to <code>print_items</code>.</p>
<div class="definition" data-terms="runtime function">
<p>Let <code>func</code> be an algorithm whose runtime depends <em>only</em> on its input size. We define the <strong>running time function of <code>func</code></strong> as <span class="math inline">\(RT_{func}: \N \to \R^{\geq 0}\)</span>, where <span class="math inline">\(RT_{func}(n)\)</span> is equal to the running time of <code>func</code> when given an input of size <span class="math inline">\(n\)</span>.</p>
<p>The goal of a <em>running time analysis</em> for <code>func</code> is to find a function <span class="math inline">\(f\)</span> (typically a simple elementary function) such that <span class="math inline">\(RT_{func} \in \Theta(f)\)</span>.</p>
</div>
<p>Our first technique for performing this runtime analysis follows four steps:</p>
<ol type="1">
<li>Identify the blocks of code which can be counted as a single basic operation, because they dont depend on the input size.</li>
<li>Identify any loops in the code, which cause basic operations to repeat. Youll need to figure out how many times those loops run, based on the size of the input. Be <em>exact</em> when counting loop iterations.</li>
<li>Use your observations from the previous two steps to come up with an expression for the number of basic operations used in this algorithm—i.e., find an exact expression for <span class="math inline">\(RT_{func}(n)\)</span>.</li>
<li>Use the properties of asymptotic notation to find an elementary function <span class="math inline">\(f\)</span> such that <span class="math inline">\(RT_{func} \in \Theta(f(n))\)</span>.</li>
</ol>
<p>Because Theta expressions depend only on the fastest-growing term in a sum, <em>and</em> ignores constants, we dont even need an exact, “correct” expression for the number of basic operations. This allows us to be rough with our analysis, but still get the correct Theta expression.</p>
<div class="example">
<p>Consider the function <code>print_items</code>. We define input size to be the <em>number of items of the input list</em>. Perform a runtime analysis of <code>print_items</code>.</p>
<div class="sourceCode" id="cb2-575113cd9d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-575113cd9d"><a href="#cb2-1-575113cd9d"></a><span class="kw">def</span> print_items(lst: <span class="bu">list</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-2-575113cd9d"><a href="#cb2-2-575113cd9d"></a> <span class="cf">for</span> item <span class="kw">in</span> lst:</span>
<span id="cb2-3-575113cd9d"><a href="#cb2-3-575113cd9d"></a> <span class="bu">print</span>(item)</span></code></pre></div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input list <code>lst</code>.</p>
<p>For this algorithm, each iteration of the loop can be counted as a single operation, because nothing in it (including the call to <code>print</code>) depends on the size of the input list.<label for="sn-2-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-575113cd9d" class="margin-toggle"/><span class="sidenote">This is actually a little subtle. If we consider the size of individual list elements, it could be the case that some take a much longer time to print than others (imagine printing a string of one-thousand characters vs. the number <span class="math inline">\(5\)</span>). But by defining input size purely as the number of items, we are implicitly ignoring the size of the individual items. The running time of a call to <code>print</code> does <em>not</em> depend on the length of the input list.</span></p>
<p>So the running time depends on the number of loop iterations. Since this is a for loop over the <code>lst</code> argument.</p>
<p>Thus the total number of basic operations performed is <span class="math inline">\(n\)</span>, and so the running time is <span class="math inline">\(RT_{print\_items}(n) = n\)</span>, which is <span class="math inline">\(\Theta(n)\)</span>.</p>
</div>
</div>
<p>Here is a second example, which has a similar structure to our first example, but also features slightly more code, using the familiar loop accumulator pattern.</p>
<div class="example">
<p>Analyse the running time of the following function.</p>
<div class="sourceCode" id="cb3-575113cd9d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-575113cd9d"><a href="#cb3-1-575113cd9d"></a><span class="kw">def</span> my_sum(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-575113cd9d"><a href="#cb3-2-575113cd9d"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb3-3-575113cd9d"><a href="#cb3-3-575113cd9d"></a></span>
<span id="cb3-4-575113cd9d"><a href="#cb3-4-575113cd9d"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb3-5-575113cd9d"><a href="#cb3-5-575113cd9d"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> number</span>
<span id="cb3-6-575113cd9d"><a href="#cb3-6-575113cd9d"></a></span>
<span id="cb3-7-575113cd9d"><a href="#cb3-7-575113cd9d"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input list (i.e., <code>numbers</code>).</p>
<p>This function body consists of three statements (with the middle statement, the for loop, itself containing more statements). To analyse the total running time of the function, we need to count each statement separately:</p>
<ul>
<li>The assignment statement <code>sum_so_far = 0</code> counts as 1 step, as its running time does not depend on the length of <code>numbers</code>.</li>
<li>The for loop takes <span class="math inline">\(n\)</span> steps: it has <span class="math inline">\(n\)</span> iterations, and each iteration takes 1 step.<label for="sn-3-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-575113cd9d" class="margin-toggle"/><span class="sidenote"> Remember that were treating all arithmetic operations as constant time here.</span></li>
<li>The return statement counts as 1 step: it, too, has running time that does not depend on the length of <code>numbers</code>.</li>
</ul>
<p>The total running time is the sum of these three parts: <span class="math inline">\(1 + n + 1 = n + 2\)</span>, which is <span class="math inline">\(\Theta(n)\)</span>.</p>
</div>
</div>
<h2 id="nested-loops-575113cd9d">Nested loops</h2>
<p>It is quite possible to have nested loops in a function body, and analyze the running time in the same fashion. The simplest method of tackling such functions is to count the number of repeated basic operations in a loop starting with the <em>innermost</em> loop and working your way out.</p>
<div class="example">
<p>Consider the following function.</p>
<div class="sourceCode" id="cb4-575113cd9d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-575113cd9d"><a href="#cb4-1-575113cd9d"></a><span class="kw">def</span> print_sums(lst: <span class="bu">list</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb4-2-575113cd9d"><a href="#cb4-2-575113cd9d"></a> <span class="cf">for</span> item1 <span class="kw">in</span> lst:</span>
<span id="cb4-3-575113cd9d"><a href="#cb4-3-575113cd9d"></a> <span class="cf">for</span> item2 <span class="kw">in</span> lst:</span>
<span id="cb4-4-575113cd9d"><a href="#cb4-4-575113cd9d"></a> <span class="bu">print</span>(item1 <span class="op">+</span> item2)</span></code></pre></div>
<p>Perform a runtime analysis of <code>print_sums</code>.</p>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of <code>lst</code>.</p>
<p>The inner loop (<code>for item2 in lst</code>) runs <span class="math inline">\(n\)</span> times (once per item in <code>lst</code>), and each iteration is just a single basic operation.</p>
<p>But the entire inner loop is itself repeated, since it is inside another loop. The outer loop runs <span class="math inline">\(n\)</span> times as well, and each of its iterations takes <span class="math inline">\(n\)</span> operations.</p>
<p>So then the total number of basic operations is <span class="math display">\[\begin{align*}
RT_{print\_sums}(n)
&amp;= \text{steps for the inner loop} \times \text{number of times inner loop is repeated} \\
&amp;= n \times n \\
&amp;= n^2
\end{align*}\]</span></p>
<p>So the running time of this algorithm is <span class="math inline">\(\Theta(n^2)\)</span>.</p>
</div>
</div>
<p>Students often make the mistake, however, that the number of nested loops should always be the exponent of <span class="math inline">\(n\)</span> in the Big-O expression.<label for="sn-4-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-575113cd9d" class="margin-toggle"/><span class="sidenote">E.g., two levels of nested loops always becomes <span class="math inline">\(\Theta(n^2)\)</span>.</span> However, things are not that simple, and in particular, not every loop takes <span class="math inline">\(n\)</span> iterations.</p>
<div class="example">
<p>Consider the following function:</p>
<div class="sourceCode" id="cb5-575113cd9d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-575113cd9d"><a href="#cb5-1-575113cd9d"></a><span class="kw">def</span> f(lst: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb5-2-575113cd9d"><a href="#cb5-2-575113cd9d"></a> <span class="cf">for</span> item <span class="kw">in</span> lst:</span>
<span id="cb5-3-575113cd9d"><a href="#cb5-3-575113cd9d"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">10</span>):</span>
<span id="cb5-4-575113cd9d"><a href="#cb5-4-575113cd9d"></a> <span class="bu">print</span>(item <span class="op">+</span> i)</span></code></pre></div>
<p>Perform a runtime analysis of this function.</p>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input list <code>lst</code>. The inner loop repeats 10 times, and each iteration is again a single basic operation, for a total of 10 basic operations. The outer loop repeats <span class="math inline">\(n\)</span> times, and each iteration takes 10 steps, for a total of <span class="math inline">\(10n\)</span> steps. So the running time of this function is <span class="math inline">\(\Theta(n)\)</span>. (Even though it has a nested loop!)</p>
<p><em>Alternative, more concise analysis</em>. The inner loops running time doesnt depend on the number of items in the input list, so we can count it as a single basic operation.</p>
<p>The outer loop runs <span class="math inline">\(n\)</span> times, and each iteration takes <span class="math inline">\(1\)</span> step, for a total of <span class="math inline">\(n\)</span> steps, which is <span class="math inline">\(\Theta(n)\)</span>.</p>
</div>
</div>
<p>When we are analyzing the running time of two blocks of code executed in sequence (one after the other), we add together their individual running times. The sum theorems are particularly helpful here, as it tells us that we can simply compute Theta expressions for the blocks individually, and then combine them just by taking the fastest-growing one. Because Theta expressions are a simplification of exact mathematical function expressions, taking this approach is often easier and faster than trying to count an exact number steps for the entire function.<label for="sn-5-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-575113cd9d" class="margin-toggle"/><span class="sidenote">E.g., <span class="math inline">\(\Theta(n^2)\)</span> is simpler than <span class="math inline">\(10n^2 + 0.001n + 165\)</span>.</span></p>
<div class="example">
<p>Analyze the running time of the following function, which is a combination of two previous functions.</p>
<div class="sourceCode" id="cb6-575113cd9d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-575113cd9d"><a href="#cb6-1-575113cd9d"></a><span class="kw">def</span> combined(lst: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-2-575113cd9d"><a href="#cb6-2-575113cd9d"></a> <span class="co"># Loop 1</span></span>
<span id="cb6-3-575113cd9d"><a href="#cb6-3-575113cd9d"></a> <span class="cf">for</span> item <span class="kw">in</span> lst:</span>
<span id="cb6-4-575113cd9d"><a href="#cb6-4-575113cd9d"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">10</span>):</span>
<span id="cb6-5-575113cd9d"><a href="#cb6-5-575113cd9d"></a> <span class="bu">print</span>(item <span class="op">+</span> i)</span>
<span id="cb6-6-575113cd9d"><a href="#cb6-6-575113cd9d"></a></span>
<span id="cb6-7-575113cd9d"><a href="#cb6-7-575113cd9d"></a> <span class="co"># Loop 2</span></span>
<span id="cb6-8-575113cd9d"><a href="#cb6-8-575113cd9d"></a> <span class="cf">for</span> item1 <span class="kw">in</span> lst:</span>
<span id="cb6-9-575113cd9d"><a href="#cb6-9-575113cd9d"></a> <span class="cf">for</span> item2 <span class="kw">in</span> lst:</span>
<span id="cb6-10-575113cd9d"><a href="#cb6-10-575113cd9d"></a> <span class="bu">print</span>(item1 <span class="op">+</span> item2)</span></code></pre></div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of <code>lst</code>. We have already seen that the first loop runs in time <span class="math inline">\(\Theta(n)\)</span>, while the second loop runs in time <span class="math inline">\(\Theta(n^2)\)</span>.<label for="sn-6-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-575113cd9d" class="margin-toggle"/><span class="sidenote">By “runs in time <span class="math inline">\(\Theta(n)\)</span>,” we mean that the number of basic operations of the second loop is a function <span class="math inline">\(f(n) \in \Theta(n)\)</span>.</span></p>
<p>By the <em>Sum of Functions</em> theorem from the previous section, we can conclude that <code>combined</code> runs in time <span class="math inline">\(\Theta(n^2)\)</span>. (Since <span class="math inline">\(n \in \cO(n^2)\)</span>.)</p>
</div>
</div>
<h3 id="loop-iterations-with-changing-costs-575113cd9d">Loop iterations with changing costs</h3>
<p>Now lets look at one last example in this section, which is a function that prints out the sum of all distinct pairs of integers from a given list.</p>
<div class="example">
<p>Analyze the running time of the following function</p>
<div class="sourceCode" id="cb7-575113cd9d"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-575113cd9d"><a href="#cb7-1-575113cd9d"></a><span class="kw">def</span> all_pairs(lst: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb7-2-575113cd9d"><a href="#cb7-2-575113cd9d"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="bu">len</span>(lst)):</span>
<span id="cb7-3-575113cd9d"><a href="#cb7-3-575113cd9d"></a> <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, i):</span>
<span id="cb7-4-575113cd9d"><a href="#cb7-4-575113cd9d"></a> <span class="bu">print</span>(lst[i] <span class="op">+</span> lst[j])</span></code></pre></div>
<div class="discussion">
<p>Like previous examples, this function has a nested loop. However, unlike those examples, here the inner loops running time depends on the current value of <code>i</code>, i.e., which iteration of the outer loop were on.</p>
<p>This means we cannot take the previous approach of calculating the cost of the inner loop, and multiplying it by the number of iterations of the outer loop; this only works if the cost of each outer loop iteration is the same.</p>
<p>So instead, we need to manually add up the cost of each iteration of the outer loop, which depends on the number of iterations of the inner loop. More specifically, since <span class="math inline">\(j\)</span> goes from <span class="math inline">\(0\)</span> to <span class="math inline">\(i-1\)</span>, the number of iterations of the inner loop is <span class="math inline">\(i\)</span>, and each iteration of the inner loop counts as one basic operation.</p>
<p>Lets see how to do this in a formal analysis.</p>
</div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input list.</p>
<p>We start by analysing the running time of the inner loop for a <em>fixed</em> iteration of the outer loop, and a fixed value of <span class="math inline">\(i\)</span>.</p>
<ul>
<li>The inner loop iterates <span class="math inline">\(i\)</span> times (for <span class="math inline">\(j\)</span> going from 0 to <span class="math inline">\(i - 1\)</span>), and each iteration takes one step (constant time).<label for="sn-7-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7-575113cd9d" class="margin-toggle"/><span class="sidenote">Here, list indexing is counted as constant time—well explore this more a bit later this chapter.</span> Therefore the cost of the inner loop is <span class="math inline">\(i\)</span> steps, for one iteration of the outer loop.</li>
</ul>
<p>Now, the outer loop iterates <span class="math inline">\(n\)</span> times for <span class="math inline">\(i\)</span> going from 0 to <span class="math inline">\(n - 1\)</span>. But here the cost of each iteration is not constant. Instead, the cost of iteration <span class="math inline">\(i\)</span> is <span class="math inline">\(i\)</span> steps, and so the total cost of the outer loop is:</p>
<p><span class="math display">\[\sum_{i=0}^{n-1} i = \frac{n(n - 1)}{2}\]</span></p>
<p>Here we used the summation formula for the sum of the first <span class="math inline">\(n\)</span> natural numbers, which is reviewed in <a href="../C-math-reference/01-summations-products.html">Appendix C.1</a>.</p>
<p>And so the total number of steps taken by <code>all_pairs</code> is <span class="math inline">\(\frac{n(n - 1)}{2}\)</span>, which is <span class="math inline">\(\Theta(n^2)\)</span>.<label for="sn-8-575113cd9d" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-8-575113cd9d" class="margin-toggle"/><span class="sidenote"> Note that we can write <span class="math inline">\(\frac{n(n - 1)}{2} = \frac{1}{2} n^2 - \frac{1}{2} n\)</span>.</span></p>
</div>
</div>
</section>
<br/> <a id="anchor-08-05"></a>
<header id="title-block-header-f773b452a3">
<h1 class="title">8.5 Analyzing Comprehensions and While Loops</h1>
</header>
<section>
<p>In the previous section, we began our study of algorithm running time analysis by looking at functions that are implemented using for loops. We chose for loops as a starting point because they make explicit the <em>repeated statements</em> that occur when we execute a function body, while also being relatively straightforward to analyze because of their predicable iteration patterns.</p>
<p>In this section, well extend what we learned about for loops to two different kinds of Python code: comprehension expressions and while loop. Well see how all three obey similar patterns when it comes to repeating code, but while loops offer both more flexibility and more complexity in what they can do.</p>
<h2 id="comprehensions-f773b452a3">Comprehensions</h2>
<p>Consider the following function:</p>
<div class="sourceCode" id="cb1-f773b452a3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-f773b452a3"><a href="#cb1-1-f773b452a3"></a><span class="kw">def</span> square_all(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">int</span>]:</span>
<span id="cb1-2-f773b452a3"><a href="#cb1-2-f773b452a3"></a> <span class="co">&quot;&quot;&quot;Return a new list containing the squares of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb1-3-f773b452a3"><a href="#cb1-3-f773b452a3"></a> <span class="cf">return</span> [x <span class="op">**</span> <span class="dv">2</span> <span class="cf">for</span> x <span class="kw">in</span> numbers]</span></code></pre></div>
<div class="analysis">
<p>How do we analyze the running time of this code? It turns out that we do so in the same way as a for loop:</p>
<ol type="1">
<li>We determine the number of steps required to evaluate the leftmost expression in the comprehension. In this case, evaluating <code>x ** 2</code> takes 1 step (i.e., is constant time).</li>
<li>The collection that acts as the source of the comprehension (in our example, <code>numbers</code>), determines how many times the leftmost expression is evaluated.</li>
</ol>
<p>So let <span class="math inline">\(n\)</span> be the length of the input list <code>numbers</code>. The comprehension expression takes <span class="math inline">\(n\)</span> steps (1 step per element of <code>numbers</code>). So the running time of <code>square_all</code> is <span class="math inline">\(n\)</span> steps, which is <span class="math inline">\(\Theta(n)\)</span>.</p>
</div>
<p>Importantly, the fact that a comprehension is creating a new collection (in our above example, a list) does <em>not</em> count as additional time when analysing the cost of a comprehension. This is true for all three of list, set, and dictionary comprehensions, and so the same analysis would hold in the above function if we had used a set or dictionary comprehension instead.</p>
<h2 id="while-loops-f773b452a3">While loops</h2>
<p>Analysing the running time of code involving while loops follows the same principle using for loops: we calculate the sum of the different loop iterations, either using multiplication (when the iteration running time is constant) or a summation (when the iterations have different running times). There is one subtle twist, though: a while loop requires that we write statements to initialize the loop variable(s) before the loop, and update the loop variable(s) inside the loop body. We must be careful to count the cost of these statements as well, just like we did for statements involving loop accumulators in the previous section.</p>
<p>To keep things simple, our first example is a simple rewriting of an earlier example using a while loop instead of a for loop.</p>
<div class="example">
<p>Analyse the running time of the following function.</p>
<div class="sourceCode" id="cb2-f773b452a3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-f773b452a3"><a href="#cb2-1-f773b452a3"></a><span class="kw">def</span> my_sum_v2(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb2-2-f773b452a3"><a href="#cb2-2-f773b452a3"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb2-3-f773b452a3"><a href="#cb2-3-f773b452a3"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb2-4-f773b452a3"><a href="#cb2-4-f773b452a3"></a> i <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb2-5-f773b452a3"><a href="#cb2-5-f773b452a3"></a></span>
<span id="cb2-6-f773b452a3"><a href="#cb2-6-f773b452a3"></a> <span class="cf">while</span> i <span class="op">&lt;</span> <span class="bu">len</span>(numbers):</span>
<span id="cb2-7-f773b452a3"><a href="#cb2-7-f773b452a3"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[i]</span>
<span id="cb2-8-f773b452a3"><a href="#cb2-8-f773b452a3"></a> i <span class="op">=</span> i <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb2-9-f773b452a3"><a href="#cb2-9-f773b452a3"></a></span>
<span id="cb2-10-f773b452a3"><a href="#cb2-10-f773b452a3"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input <code>numbers</code>.</p>
<p>In this function, we now have both an accumulator and the loop variable to worry about. We can still divide up the function into three parts, and compute the cost of each part separately.</p>
<ol type="1">
<li><p>The cost of the assignment statements <code>sum_so_far = 0</code> and <code>i = 0</code> is constant time. Well count this as a constant-time block of code, which is just <em>1</em> step.<label for="sn-0-f773b452a3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-f773b452a3" class="margin-toggle"/><span class="sidenote"> This might be a bit surprising, because they are two lines of code and look like two separate “actions”. The power of our asymptotic notation is that whether we count this block of code as 1 step or 2, we get the same Theta bound in the end! And so we just go with the simpler one here, but youre welcome to count this as “two steps” in your own analyses if you find that more intuitive.</span></p></li>
<li><p>To analyse the while loop, we need to determine the cost of each iteration and the total number of iterations, just like a for loop.</p>
<ul>
<li>Each iteration is constant time, so well count that as one step.</li>
<li>There are <span class="math inline">\(n\)</span> iterations, since <code>i</code> starts at 0 and increases by 1 until it reaches <span class="math inline">\(n\)</span>. Note that this is less obvious than the for loop version! Here we need to look at three different places in the code: how <code>i</code> is initialized, how <code>i</code> is updated inside the loop body, and how <code>i</code> is used in the loop condition.</li>
</ul></li>
<li><p>The return statement again takes constant time, and so counts as 1 step.</p></li>
</ol>
<p>So the total running time is <span class="math inline">\(1 + n + 1 = n + 2\)</span>, which is <span class="math inline">\(\Theta(n)\)</span>.</p>
</div>
</div>
<p>Now, the previous example was a little contrived because we could have implemented the same function more simply using a for loop. Here is another example, which uses a while loop to compute powers of two to act as indexes into a list.</p>
<div class="example">
<p>Analyse the running time of the following function.</p>
<div class="sourceCode" id="cb3-f773b452a3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-f773b452a3"><a href="#cb3-1-f773b452a3"></a><span class="kw">def</span> my_sum_powers_of_two(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb3-2-f773b452a3"><a href="#cb3-2-f773b452a3"></a> <span class="co">&quot;&quot;&quot;Return the sum of the given numbers whose indexes are powers of 2.</span></span>
<span id="cb3-3-f773b452a3"><a href="#cb3-3-f773b452a3"></a></span>
<span id="cb3-4-f773b452a3"><a href="#cb3-4-f773b452a3"></a><span class="co"> That is, return numbers[1] + numbers[2] + numbers[4] + numbers[8] + ...</span></span>
<span id="cb3-5-f773b452a3"><a href="#cb3-5-f773b452a3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-6-f773b452a3"><a href="#cb3-6-f773b452a3"></a> sum_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb3-7-f773b452a3"><a href="#cb3-7-f773b452a3"></a> i <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb3-8-f773b452a3"><a href="#cb3-8-f773b452a3"></a></span>
<span id="cb3-9-f773b452a3"><a href="#cb3-9-f773b452a3"></a> <span class="cf">while</span> i <span class="op">&lt;</span> <span class="bu">len</span>(numbers):</span>
<span id="cb3-10-f773b452a3"><a href="#cb3-10-f773b452a3"></a> sum_so_far <span class="op">=</span> sum_so_far <span class="op">+</span> numbers[i]</span>
<span id="cb3-11-f773b452a3"><a href="#cb3-11-f773b452a3"></a> i <span class="op">=</span> i <span class="op">*</span> <span class="dv">2</span></span>
<span id="cb3-12-f773b452a3"><a href="#cb3-12-f773b452a3"></a></span>
<span id="cb3-13-f773b452a3"><a href="#cb3-13-f773b452a3"></a> <span class="cf">return</span> sum_so_far</span></code></pre></div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input list <code>numbers</code>.</p>
<p>This code has much of the same structure as <code>my_sum_v2</code>, and we can reuse most of the same analysis here. In particular, well still count the initial assignment statements as 1 step, and the return statement as 1 step. To analyse the loop, we still need the number of steps per iteration and the total number of iterations. Each iteration still takes constant time (1 step), same as <code>my_sum_v2</code>. It is the number of loop iterations that is most challenging.</p>
<p>To determine the number of loop iterations, we need to take into account the initial value of <code>i</code>, how <code>i</code> is updated, and how <code>i</code> is used in the while loop condition. More formally, we follow these steps:</p>
<ol type="1">
<li><p>Find a pattern for how <code>i</code> changes at each loop iteration, and a general formula formula for <span class="math inline">\(i_k\)</span>, the value of <code>i</code> after <span class="math inline">\(k\)</span> iterations. For relatively simple updates, we can find a pattern by writing a small loop tracing table, showing the value of the loop variable at the <em>end</em> of the iteration.</p>
<div class="reference-table">
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Iteration</th>
<th>Value of <code>i</code></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">0</td>
<td>1</td>
</tr>
<tr class="even">
<td style="text-align: left;">1</td>
<td>2</td>
</tr>
<tr class="odd">
<td style="text-align: left;">2</td>
<td>4</td>
</tr>
<tr class="even">
<td style="text-align: left;">3</td>
<td>8</td>
</tr>
<tr class="odd">
<td style="text-align: left;">4</td>
<td>16</td>
</tr>
</tbody>
</table>
</div>
<p>So we find that after <span class="math inline">\(k\)</span> iterations, <span class="math inline">\(i_k = 2^k\)</span>.<label for="sn-1-f773b452a3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-f773b452a3" class="margin-toggle"/><span class="sidenote"> Note that we havent <em>proved</em> that this formula is true; a formal proof would require a proof by induction, which you may have already seen in your math classes.</span></p></li>
<li><p>We know the while loop continues while <code>i &lt; len(numbers)</code>. Another way to phrase this is that the while loop continues <em>until</em> <code>i &gt;= len(numbers)</code>.</p>
<p>So to find the number of iterations, we need to find the smallest value of <span class="math inline">\(k\)</span> such that <span class="math inline">\(i_k \geq n\)</span> (making the loop condition False). This is where our formula for <span class="math inline">\(i_k\)</span> comes in:</p>
<p><span class="math display">\[\begin{align*}
i_k &amp;\geq n \\
2^k &amp;\geq n \\
k &amp;\geq \log_2 n
\end{align*}\]</span> So we need to find the smallest value of <span class="math inline">\(k\)</span> such that <span class="math inline">\(k \geq \log_2 n\)</span>. This is exactly the definition of the ceiling function, and so the smallest value of <span class="math inline">\(k\)</span> is <span class="math inline">\(\ceil{\log_2 n}\)</span>.</p></li>
</ol>
<p>So the while loop iterates <span class="math inline">\(\ceil{\log_2 n}\)</span> times, with 1 step per iteration, for a total of <span class="math inline">\(\ceil{\log_2 n}\)</span> steps.</p>
<p>Putting it all together, the function <code>my_sum_powers_of_two</code> has a running time of <span class="math inline">\(1 + \ceil{\log_2 n} + 1 = \ceil{\log_2 n} + 2\)</span>, which is <span class="math inline">\(\Theta(\log n)\)</span>.<label for="sn-2-f773b452a3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-f773b452a3" class="margin-toggle"/><span class="sidenote"> Note that our convention is to drop the base of the log when writing a Theta expression, since all bases <span class="math inline">\(&gt; 1\)</span> are equivalent to each other in Theta bounds.</span></p>
</div>
</div>
<h2 id="a-trickier-example-f773b452a3">A trickier example</h2>
<p>It turns out that the extreme flexibility of while loops can make analysing their running time much more subtle than it might appear. Our next example considers a standard loop, with a twist in how the loop variable changes at each iteration.</p>
<div class="sourceCode" id="cb4-f773b452a3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-f773b452a3"><a href="#cb4-1-f773b452a3"></a><span class="kw">def</span> twisty(n: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb4-2-f773b452a3"><a href="#cb4-2-f773b452a3"></a> <span class="co">&quot;&quot;&quot;Return the number of iterations it takes for this special loop to stop</span></span>
<span id="cb4-3-f773b452a3"><a href="#cb4-3-f773b452a3"></a><span class="co"> for the given n.</span></span>
<span id="cb4-4-f773b452a3"><a href="#cb4-4-f773b452a3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-5-f773b452a3"><a href="#cb4-5-f773b452a3"></a> iterations_so_far <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb4-6-f773b452a3"><a href="#cb4-6-f773b452a3"></a> x <span class="op">=</span> n</span>
<span id="cb4-7-f773b452a3"><a href="#cb4-7-f773b452a3"></a> <span class="cf">while</span> x <span class="op">&gt;</span> <span class="dv">1</span>:</span>
<span id="cb4-8-f773b452a3"><a href="#cb4-8-f773b452a3"></a> <span class="cf">if</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb4-9-f773b452a3"><a href="#cb4-9-f773b452a3"></a> x <span class="op">=</span> x <span class="op">/</span> <span class="dv">2</span></span>
<span id="cb4-10-f773b452a3"><a href="#cb4-10-f773b452a3"></a> <span class="cf">else</span>:</span>
<span id="cb4-11-f773b452a3"><a href="#cb4-11-f773b452a3"></a> x <span class="op">=</span> <span class="dv">2</span> <span class="op">*</span> x <span class="op">-</span> <span class="dv">2</span></span>
<span id="cb4-12-f773b452a3"><a href="#cb4-12-f773b452a3"></a> iterations_so_far <span class="op">=</span> iterations_so_far <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb4-13-f773b452a3"><a href="#cb4-13-f773b452a3"></a></span>
<span id="cb4-14-f773b452a3"><a href="#cb4-14-f773b452a3"></a> <span class="cf">return</span> iterations_so_far</span></code></pre></div>
<p>Even though the individual lines of code in this example are simple, they combine to form a pretty complex situation. The challenge with analyzing the runtime of this function is that, unlike previous examples, here the loop variable <code>x</code> does not always get closer to the loop stopping condition; sometimes it does (when divided by two), and sometimes it increases!</p>
<p>The key insight into analyzing the runtime of this function is that we dont just need to look at what happens after a single loop iteration, but instead perform a more sophisticated analysis based on <em>multiple</em> iterations.<label for="sn-3-f773b452a3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-f773b452a3" class="margin-toggle"/><span class="sidenote"> As preparation, try tracing <code>twisty</code> on inputs <span class="math inline">\(7\)</span>, <span class="math inline">\(9\)</span>, and <span class="math inline">\(11\)</span>.</span> More concretely, well prove the following claim.</p>
<div class="claim">
<p>For any integer value of <code>x</code> greater than <span class="math inline">\(2\)</span>, after <em>two</em> iterations of the loop in <code>twisty</code> the value of <code>x</code> decreases by at least one.</p>
<div class="proof">
<p>Let <span class="math inline">\(x_0\)</span> be the value of variable <code>x</code> at some iteration of the loop, and assume <span class="math inline">\(x_0 &gt; 2\)</span>. Let <span class="math inline">\(x_1\)</span> be the value of <span class="math inline">\(x\)</span> after one loop iteration, and <span class="math inline">\(x_2\)</span> the value of <span class="math inline">\(x\)</span> after two loop iterations. We want to prove that <span class="math inline">\(x_2 \leq x_0 - 1\)</span>.</p>
<p>We divide up this proof into four cases, based on the remainder of <span class="math inline">\(x_0\)</span> when dividing by four.<label for="sn-4-f773b452a3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-f773b452a3" class="margin-toggle"/><span class="sidenote">The intuition for these cases is that this determines whether <span class="math inline">\(x_0\)</span> is even/odd, and whether <span class="math inline">\(x_1\)</span> is even/odd.</span> Well only do two cases here to illustrate the main idea, and leave the last two cases as an exercise.</p>
<p><strong>Case 1</strong>: Assume <span class="math inline">\(4 \DIV x_0\)</span>, i.e., <span class="math inline">\(\exists k \in \Z,~ x_0 = 4k\)</span>.</p>
<p>In this case, <span class="math inline">\(x_0\)</span> is even, so the <code>if</code> branch executes in the first loop iteration, and so <span class="math inline">\(x_1 = \frac{x_0}{2} = 2k\)</span>. And so then <span class="math inline">\(x_1\)</span> is also even, and so the <code>if</code> branch executes again: <span class="math inline">\(x_2 = \frac{x_1}{2} = k\)</span>.</p>
<p>So then <span class="math inline">\(x_2 = \frac{1}{4}x_0 \leq x_0 - 1\)</span> (since <span class="math inline">\(x_0 \geq 4\)</span>), as required.</p>
<p><strong>Case 2</strong>: Assume <span class="math inline">\(4 \DIV x_0 - 1\)</span>, i.e., <span class="math inline">\(\exists k \in \Z,~ x_0 = 4k + 1\)</span>.</p>
<p>In this case, <span class="math inline">\(x_0\)</span> is odd, so the <code>else</code> branch executes in the first loop iteration, and so <span class="math inline">\(x_1 = 2x_0 - 2 = 8k\)</span>. Then <span class="math inline">\(x_1\)</span> is even, and so <span class="math inline">\(x_2 = \frac{x_1}{2} = 4k\)</span>.</p>
<p>So then <span class="math inline">\(x_2 = 4k = x_0 - 1\)</span>, as required.</p>
<p><strong>Cases 3 and 4</strong>: left as exercises.</p>
</div>
</div>
<p>Now lets see how take this claim and use it to formally analyse the running time of <code>twisty</code>.</p>
<div class="analysis">
<p>(<em>Analysis of <code>twisty</code></em>)</p>
<p>As before, we count the variable initializations before the while loop as 1 step, and the return statement as 1 step.</p>
<p>For the while loop:</p>
<ul>
<li><p>The loop body also takes 1 step, since all of the code consists of operations that do not depend on the size of the input <span class="math inline">\(n\)</span>.</p></li>
<li><p>To count the number of loop iterations, we first observe that <span class="math inline">\(x\)</span> starts at <span class="math inline">\(n\)</span> and the loop terminates when <span class="math inline">\(x\)</span> reaches 1 or less. The <em>Claim</em> tells us that after every two iterations, the value of <span class="math inline">\(x\)</span> decreases by at least one.</p>
<p>So then after 2 iterations, <span class="math inline">\(x \leq n - 1\)</span>, after 4 iterations, <span class="math inline">\(x \leq n - 2\)</span>, and in general, after <span class="math inline">\(2k\)</span> iterations, <span class="math inline">\(x \leq n - k\)</span>. This tells us that after <span class="math inline">\(2(n - 1)\)</span> loop iterations, <span class="math inline">\(x \leq n - (n - 1) = 1\)</span>, and so the loop must stop.</p></li>
</ul>
<p>This analysis tells us that the loop iterations <em>at most</em> <span class="math inline">\(2(n - 1)\)</span> times, and so takes <em>at most</em> <span class="math inline">\(2(n - 1)\)</span> steps (remember that each iteration takes 1 step).</p>
<p>So the total running time of <code>twisty</code> is <em>at most</em> <span class="math inline">\(1 + 2(n - 1) + 1 = 2n\)</span> steps, which is <span class="math inline">\(\cO(n)\)</span>.</p>
</div>
<p>Something funny happened at the end of the above analysis: we did not actually compute the exact number of steps the function <code>twisty</code> takes, only an <em>upper bound</em> on the number of steps (signalled by our use of the phrase “at most”). This means that we were only able to conclude a Big-O bound, and not a Theta bound, on the running time of this function: its running time is <em>at most</em> <span class="math inline">\(\cO(n)\)</span>, but we dont know whether this bound is tight.</p>
<p>In fact, it isnt! It is possible to prove something pretty remarkable about what happens to the variable <code>x</code> after <em>three</em> iterations of the twisty loop.</p>
<div class="claim">
<p>(<em>Improved claim</em>)</p>
<p>For any integer value of <code>x</code> greater than <span class="math inline">\(2\)</span>, let <span class="math inline">\(x_0\)</span> be the initial value of <code>x</code> and let <span class="math inline">\(x_3\)</span> be the value of <code>x</code> after <em>three</em> loop iterations. Then <span class="math inline">\(\frac{1}{8} x_0 \leq x_3 \leq \frac{1}{2} x_0\)</span>.</p>
</div>
<p>It is a good exercise to prove this claim<label for="sn-5-f773b452a3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-f773b452a3" class="margin-toggle"/><span class="sidenote"> Hint: you can use the same approach as the previous claim, but consider remainders when you divide by 8 instead of 4.</span> and then use this claim to conduct a more detailed running time analysis of <code>twisty</code>. When you do so, you should be able to show that the running time of <code>twisty</code> is both <span class="math inline">\(\cO(\log n)\)</span> and <span class="math inline">\(\Omega(\log n)\)</span>, and hence conclude that its running time is actually <span class="math inline">\(\Theta(\log n)\)</span>, not just <span class="math inline">\(\cO(n)\)</span>!</p>
<!-- <div exercise>
<div questions data-series="chapter5">
\item
The analysis we performed in the previous example is incomplete for a few reasons; our goal with this set of exercises is to complete it here.
(a) Complete the last two cases in the proof of the claim.
(b) State and prove an analogous statement for how much $x$ must decrease by after *three* loop iterations.
(c) Find an exact upper bound on the number of loop iterations taken by this algorithm. Your upper bound should be smaller (and therefore more accurate) than the one given in the example.
(d) Finally, find, with proof, a good *lower bound* on the number of loop iterations taken by this algorithm.
</div>
</div> -->
</section>
<br/> <a id="anchor-08-06"></a>
<header id="title-block-header-7c3d4f22d6">
<h1 class="title">8.6 Analyzing Built-In Data Type Operations</h1>
</header>
<section>
<p>So far in our study of running time, we have looked at algorithms that use only primitive numeric data types or loops/comprehensions over collections. In this section, were going to study the running time of operations on built-in collection data types (e.g., lists, sets, dictionaries), and the custom data classes that we create. Because a single instance of these compound data types can be very large (e.g., a list of one trillion elements!), the natural question we will ask is, “what operations will take longer when called on very large data structures?” Well also study <em>why</em> this is the case for Python lists by studying how they are stored in computer memory. For the other compound data types, however, their implementations are more complex and so well only touch on them in this course.</p>
<h2 id="timing-operations-7c3d4f22d6">Timing operations</h2>
<p>Python provides a module (called <code>timeit</code>) that can tell us how long Python code takes to execute on our machine. Heres an example showing how to import the module and use it:</p>
<div class="sourceCode" id="cb1-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-7c3d4f22d6"><a href="#cb1-1-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">from</span> timeit <span class="im">import</span> timeit</span>
<span id="cb1-2-7c3d4f22d6"><a href="#cb1-2-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;5 + 15&#39;</span>, number<span class="op">=</span><span class="dv">1000</span>)</span>
<span id="cb1-3-7c3d4f22d6"><a href="#cb1-3-7c3d4f22d6"></a><span class="fl">1.9799976143985987e-05</span></span></code></pre></div>
<p>The call to <code>timeit</code> will perform the operation <code>5 + 15</code> (which we passed in as a string) one thousand times. The function returned the total time elapsed, in seconds, to perform all thousand operations. The return value in the notes is specific to one machine—try the code on your own machine to see how you compare!</p>
<p>Next, lets create two lists with different lengths for comparison: 1,000 and 1,000,000:</p>
<div class="sourceCode" id="cb2-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-7c3d4f22d6"><a href="#cb2-1-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> lst_1k <span class="op">=</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">10</span> <span class="op">**</span> <span class="dv">3</span>))</span>
<span id="cb2-2-7c3d4f22d6"><a href="#cb2-2-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> lst_1m <span class="op">=</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">10</span> <span class="op">**</span> <span class="dv">6</span>))</span></code></pre></div>
<p>We know that there are several operations available to lists. For example, we can search the list using the <code>in</code> operator. Or we could lookup an element at a specific index in the list. Or we could mutate the list by inserting or deleting. Lets compare the time it takes to access the first element of the list:</p>
<div class="sourceCode" id="cb3-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-7c3d4f22d6"><a href="#cb3-1-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;lst_1k[0]&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb3-2-7c3d4f22d6"><a href="#cb3-2-7c3d4f22d6"></a><span class="fl">5.80001506023109e-06</span></span>
<span id="cb3-3-7c3d4f22d6"><a href="#cb3-3-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;lst_1m[0]&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb3-4-7c3d4f22d6"><a href="#cb3-4-7c3d4f22d6"></a><span class="fl">5.599984433501959e-06</span></span></code></pre></div>
<p>The length of the list does not seem to impact the time it takes to retrieve an element from this specific index. Lets compare the time it takes to insert a new element at the front of the list:</p>
<div class="sourceCode" id="cb4-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-7c3d4f22d6"><a href="#cb4-1-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;list.insert(lst_1k, 0, -1)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb4-2-7c3d4f22d6"><a href="#cb4-2-7c3d4f22d6"></a><span class="fl">0.00014379998901858926</span></span>
<span id="cb4-3-7c3d4f22d6"><a href="#cb4-3-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;list.insert(lst_1m, 0, -1)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb4-4-7c3d4f22d6"><a href="#cb4-4-7c3d4f22d6"></a><span class="fl">0.1726928999996744</span></span></code></pre></div>
<p>There is a clear difference in time (by several orders of magnitude) between searching a list with one-thousand elements versus one-million elements.</p>
<p>Indeed, every list operation has its own implementation whose running time we can analyze, using the same techniques we studied earlier in this chapter. But in order to fully understand why these implementations work the way they do, we need to dive deeper into how Python lists really work.</p>
<h2 id="how-python-lists-are-stored-in-memory-7c3d4f22d6">How Python lists are stored in memory</h2>
<p>Recall that a Python <code>list</code> object represents an ordered sequence of other objects, which we call its elements. When we studied the object-based memory model in Chapter 5, we drew diagrams like this to represent a <code>list</code>:</p>
<div class="fullwidth">
<p><img src="images/list_memory_model.png" alt="Memory model diagram of a list" /><br />
</p>
</div>
<p>Our memory-model diagrams are an abstraction. In reality, all data used by a program are stored in blocks of computer memory, which are labeled by numbers called <em>memory addresses</em>, so that the program can keep track of where each piece of data is stored.</p>
<p>Here is the key idea for how the Python interpreter stores lists in memory. For every Python <code>list</code> object, the references to its elements are stored in a <em>contiguous</em> block of memory. For example, here is how we could picture the same list as in the previous diagram, now stored in blocks of computer memory:</p>
<div class="text-align: center">
<p><img src="./images/list_memory_layout.png" style="width:70.0%" alt="Diagram of a list in memory" /><br />
</p>
</div>
<p>As before, our list stores four integers. In memory, the four consecutive blocks 400403 store references to the actual integer values. Of course, even this diagram is a simplification of whats actually going on in computer memory, but it illustrates the main point: the references to each list elements are always stored consecutively. This type of list implementation is used by the Python interpreter and many other programming languages, and is called an <strong>array-based list implementation</strong>.</p>
<h3 id="fast-list-indexing-7c3d4f22d6">Fast list indexing</h3>
<p>The primary reason Python uses an array-based list implementation is that it makes list indexing fast. Because the list element references are stored in consecutive memory locations, accessing the <em>i</em>-th element can be done with simple arithmetic: take the memory address where the list starts, and then increase it by <em>i</em> blocks to obtain the the location of the <em>i</em>-th element reference.<label for="sn-0-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-7c3d4f22d6" class="margin-toggle"/><span class="sidenote"> Think about it like this: suppose youre walking down a hallway with numbered rooms on just one side and room numbers going up by one. If you see that the first room number is 11, and youre looking for room 15, you can be confident that it is the fifth room down the hall.</span> More precisely, this means that list indexing is a <em>constant-time</em> operation: its running time does not depend on the size of the list or the index <em>i</em> being accessed. So even with a very long list or a very large index, we expect list indexing to take the same amount of time (and e very fast!).</p>
<p>This is true for both evaluating a list indexing expression or assigning to a list index, e.g. <code>lst[1] = 100</code>. In the latter case, the Python interpreter takes constant time to calculate the memory address where the <code>lst[1]</code> reference is stored and modify it to refer to a new object.</p>
<h3 id="mutating-contiguous-memory-7c3d4f22d6">Mutating contiguous memory</h3>
<p>Array-based lists have constant time indexing, but as well see again and again in our study of data types, fast operations almost always come at the cost of slow ones. In order for Python to be able to calculate the address of an arbitrary list index, these references must always be stores in a contiguous block of memory; there cant be any “gaps”.</p>
<p>Maintaining this contiguity has implications for how insertion and deletion in a Python list works. When a list element to be deleted, all items after it have to be moved back one memory block to fill the gap.</p>
<div class="text-align: center">
<p><img src="images/list_memory_animation_deletion.gif" style="width:70.0%" alt="Animation of deletion in the middle of a list" /><br />
</p>
</div>
<p>Similarly, when a list element is inserted somewhere in the list, all items after it moved forward one block.</p>
<div class="text-align: center">
<p><img src="images/list_memory_animation_insertion.gif" style="width:70.0%" alt="Animation of insertion in the middle of the list" /><br />
</p>
</div>
<p>In general, suppose we have a list <code>lst</code> of length <span class="math inline">\(n\)</span> and we wish to remove the element at index <span class="math inline">\(i\)</span> in the list, where <span class="math inline">\(0 \leq i &lt; n\)</span>. Then <span class="math inline">\(n - i - 1\)</span> elements must be moved, and the number of “basic operations” this requires is <span class="math inline">\(\Theta(n - i)\)</span>.<label for="sn-1-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-7c3d4f22d6" class="margin-toggle"/><span class="sidenote"> Here were counting moving the contents of one memory block to another as a basic operation.</span> Similarly, if we want to insert an element into a list of length <span class="math inline">\(n\)</span> at index <span class="math inline">\(i\)</span>, <span class="math inline">\(n - i\)</span> elements must be moved, and so the running time of this operation is <span class="math inline">\(\Theta(n - i)\)</span>.</p>
<p>At the extremes, this means that inserting/deleting at the front of a Python list (<span class="math inline">\(i = 0\)</span>) takes <span class="math inline">\(\Theta(n)\)</span> time, i.e., proportional to the length of list; on the other hand, inserting/deleting at the back of a Python list (<span class="math inline">\(i = n - 1\)</span>) is a constant-time operation. We can see evidence of this in the following <code>timeit</code> comparisons:</p>
<div class="sourceCode" id="cb5-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-7c3d4f22d6"><a href="#cb5-1-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;list.append(lst_1k, 123)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb5-2-7c3d4f22d6"><a href="#cb5-2-7c3d4f22d6"></a><span class="fl">1.0400000064691994e-05</span></span>
<span id="cb5-3-7c3d4f22d6"><a href="#cb5-3-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;list.append(lst_1m, 123)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb5-4-7c3d4f22d6"><a href="#cb5-4-7c3d4f22d6"></a><span class="fl">1.3099999932819628e-05</span></span>
<span id="cb5-5-7c3d4f22d6"><a href="#cb5-5-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;list.insert(lst_1k, 0, 123)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb5-6-7c3d4f22d6"><a href="#cb5-6-7c3d4f22d6"></a><span class="fl">4.520000015872938e-05</span></span>
<span id="cb5-7-7c3d4f22d6"><a href="#cb5-7-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;list.insert(lst_1m, 0, 123)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb5-8-7c3d4f22d6"><a href="#cb5-8-7c3d4f22d6"></a><span class="fl">0.011574500000051557</span></span></code></pre></div>
<div class="center reference-table">
<table>
<caption>Summary of list operation asymptotic running times (<span class="math inline">\(n\)</span> is the list size)</caption>
<thead>
<tr class="header">
<th>Operation</th>
<th>Running time (<span class="math inline">\(n\)</span> = <code>len(lst)</code>)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>List indexing (<code>lst[i]</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="even">
<td>List index assignment (<code>lst[i]</code> = …)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="odd">
<td>List insertion at end (<code>list.append(lst, ...)</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="even">
<td>List deletion at end (<code>list.pop(lst)</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="odd">
<td>List insertion at index (<code>list.insert(lst, i, ...)</code>)</td>
<td><span class="math inline">\(\Theta(n - i)\)</span></td>
</tr>
<tr class="even">
<td>List deletion at index (<code>list.pop(lst, i)</code>)</td>
<td><span class="math inline">\(\Theta(n - i)\)</span></td>
</tr>
</tbody>
</table>
</div>
<h3 id="when-space-runs-out-7c3d4f22d6">When space runs out</h3>
<p>Finally, we should point out one subtle assumption weve just made in our analysis of list insertion: that there will always be free memory blocks at the end of the list for the list to expand into. In practice, this is almost always true, and so for the purposes of this course well stick with this assumption. But in <em>CSC263/265 (Data Structures and Analysis)</em>, youll learn about how programming languages handle array-based list implementations to take into account whether there is “free space” or not, and how these operations still provide the running times weve presented in this section.</p>
<h2 id="running-time-analysis-with-list-operations-7c3d4f22d6">Running-time analysis with list operations</h2>
<p>Now that weve learned about the running time of basic list operations, lets see how to apply this knowledge to analysing the running time of algorithms that use these operations. Well look at two different examples.</p>
<div class="example">
<p>Analyse the running time of the following function.</p>
<div class="sourceCode" id="cb6-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-7c3d4f22d6"><a href="#cb6-1-7c3d4f22d6"></a><span class="kw">def</span> squares(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">int</span>]:</span>
<span id="cb6-2-7c3d4f22d6"><a href="#cb6-2-7c3d4f22d6"></a> <span class="co">&quot;&quot;&quot;Return a list containing the squares of the given numbers.&quot;&quot;&quot;</span></span>
<span id="cb6-3-7c3d4f22d6"><a href="#cb6-3-7c3d4f22d6"></a> squares_so_far <span class="op">=</span> []</span>
<span id="cb6-4-7c3d4f22d6"><a href="#cb6-4-7c3d4f22d6"></a></span>
<span id="cb6-5-7c3d4f22d6"><a href="#cb6-5-7c3d4f22d6"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb6-6-7c3d4f22d6"><a href="#cb6-6-7c3d4f22d6"></a> <span class="bu">list</span>.append(squares_so_far, number <span class="op">**</span> <span class="dv">2</span>)</span>
<span id="cb6-7-7c3d4f22d6"><a href="#cb6-7-7c3d4f22d6"></a></span>
<span id="cb6-8-7c3d4f22d6"><a href="#cb6-8-7c3d4f22d6"></a> <span class="cf">return</span> squares_so_far</span></code></pre></div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input list (i.e., <code>numbers</code>).<label for="sn-2-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-7c3d4f22d6" class="margin-toggle"/><span class="sidenote">Note the similarities between this analysis and our analysis of <code>sum_so_far</code> in <a href="04-basic-algorithm-analysis.html">Section 8.4</a>.</span></p>
<p>This function body consists of three statements (with the middle statement, the for loop, itself containing more statements). To analyse the total running time of the function, we need to count each statement separately:</p>
<ul>
<li>The assignment statement <code>squares_so_far = 0</code> counts as 1 step, as its running time does not depend on the length of <code>numbers</code>.</li>
<li>The for loop:
<ul>
<li>Takes <span class="math inline">\(n\)</span> iterations</li>
<li>Inside the loop body, we call <code>list.append(squares_so_far, number ** 2)</code>. Based on our discussion of the previous section, this call to <code>list.append</code> takes <em>constant time</em> (<span class="math inline">\(\Theta(1)\)</span> steps), and so the entire loop body counts as 1 step.</li>
<li>This means the for loop takes <span class="math inline">\(n \cdot 1 = n\)</span> steps total.</li>
</ul></li>
<li>The return statement counts as 1 step: it, too, has running time that does not depend on the length of <code>numbers</code>.</li>
</ul>
<p>The total running time is the sum of these three parts: <span class="math inline">\(1 + n + 1 = n + 2\)</span>, which is <span class="math inline">\(\Theta(n)\)</span>.</p>
</div>
</div>
<p>In our above analysis, we had to take into account the running of calling <code>list.append</code>, but this quantity did not depend on the length of the input list. Our second example will look very similar to the first, but now we use a different <code>list</code> method that results in a dramatic difference in running time:</p>
<div class="sourceCode" id="cb7-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-7c3d4f22d6"><a href="#cb7-1-7c3d4f22d6"></a><span class="kw">def</span> squares_reversed(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">list</span>[<span class="bu">int</span>]:</span>
<span id="cb7-2-7c3d4f22d6"><a href="#cb7-2-7c3d4f22d6"></a> <span class="co">&quot;&quot;&quot;Return a list containing the squares of the given numbers, in reverse order.&quot;&quot;&quot;</span></span>
<span id="cb7-3-7c3d4f22d6"><a href="#cb7-3-7c3d4f22d6"></a> squares_so_far <span class="op">=</span> []</span>
<span id="cb7-4-7c3d4f22d6"><a href="#cb7-4-7c3d4f22d6"></a></span>
<span id="cb7-5-7c3d4f22d6"><a href="#cb7-5-7c3d4f22d6"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb7-6-7c3d4f22d6"><a href="#cb7-6-7c3d4f22d6"></a> <span class="co"># Now, insert number ** 2 at the START of squares_so_far</span></span>
<span id="cb7-7-7c3d4f22d6"><a href="#cb7-7-7c3d4f22d6"></a> <span class="bu">list</span>.insert(squares_so_far, <span class="dv">0</span>, number <span class="op">**</span> <span class="dv">2</span>)</span>
<span id="cb7-8-7c3d4f22d6"><a href="#cb7-8-7c3d4f22d6"></a></span>
<span id="cb7-9-7c3d4f22d6"><a href="#cb7-9-7c3d4f22d6"></a> <span class="cf">return</span> squares_so_far</span></code></pre></div>
<div class="analysis">
<p>Let <span class="math inline">\(n\)</span> be the length of the input list (i.e., <code>numbers</code>).</p>
<p>This function body consists of three statements (with the middle statement, the for loop, itself containing more statements). To analyse the total running time of the function, we need to count each statement separately:</p>
<ul>
<li>The assignment statement <code>squares_so_far = 0</code> counts as 1 step, as its running time does not depend on the length of <code>numbers</code>.</li>
<li>The for loop:
<ul>
<li><p>Takes <span class="math inline">\(n\)</span> iterations</p></li>
<li><p>Inside the loop body, we call <code>list.insert(squares_so_far, 0, n ** 2)</code>. As we discussed above, inserting at the front of a Python list causes all of its current elements to be shifted over, taking time proportional to the size of the list. Therefore this call takes <span class="math inline">\(\Theta(k)\)</span> time, where <span class="math inline">\(k\)</span> is the current length of <code>squares_so_far</code>.<label for="sn-3-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-7c3d4f22d6" class="margin-toggle"/><span class="sidenote"> We cant use <span class="math inline">\(n\)</span> here, because <span class="math inline">\(n\)</span> already refers to the length of <code>numbers</code>!</span></p>
<p>For the purpose of our analysis, we count a function call with <span class="math inline">\(\Theta(k)\)</span> running time as taking <span class="math inline">\(k\)</span> steps, i.e., ignoring the “eventually” and “constant factors” part of the definition of Theta. And so we say that the loop body takes <span class="math inline">\(k\)</span> steps.</p></li>
<li><p>In order to calculate the total running time of the loop, we need to add the running times of every iteration. We know that <code>squares_so_far</code> starts as empty, and then increases in length by <code>1</code> at each iteration. So then <span class="math inline">\(k\)</span> (the current length of <code>squares_so_far</code>) takes on the values <span class="math inline">\(0, 1, 2, \dots, n - 1\)</span>, and we can calculate the total running time of the for loop using a summation:</p>
<p><span class="math display">\[\sum_{k=0}^{n-1} k = \frac{(n-1)n}{2}\]</span></p></li>
</ul></li>
<li>The return statement counts as 1 step: it, too, has running time that does not depend on the length of <code>numbers</code>.</li>
</ul>
<p>The total running time is the sum of these three parts: <span class="math inline">\(1 + \frac{(n-1)n}{2} + 1 = \frac{(n-1)n}{2} + 2\)</span>, which is <span class="math inline">\(\Theta(n^2)\)</span>.</p>
</div>
<p>To summarize, this single line of code change (from <code>list.append</code> to <code>list.insert</code> at index 0) causes the running time to change dramatically, from <span class="math inline">\(\Theta(n)\)</span> to <span class="math inline">\(\Theta(n^2)\)</span>. When calling functions and performing operations on data types, we must always be conscious of which functions/operations were using and their running times. It is easy to skim over a function call because it takes up so little visual space, but that one call might make the difference between running times of <span class="math inline">\(\Theta(n)\)</span>, <span class="math inline">\(\Theta(n^2)\)</span>, or even <span class="math inline">\(\Theta(2^n)\)</span>!<label for="sn-4-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-7c3d4f22d6" class="margin-toggle"/><span class="sidenote"> Lastly, you might be curious how we could speed up <code>squares_reversed</code>. It turns out that Python has a built-in method <code>list.reverse</code> that mutates a list by reversing it, and this method has a <span class="math inline">\(\Theta(n)\)</span> running time. So we could accumulate the squares by using <code>list.append</code>, and then call <code>list.reverse</code> on the final result.</span></p>
<h2 id="sets-and-dictionaries-7c3d4f22d6">Sets and dictionaries</h2>
<p>It turns out that how Python implements sets and dictionaries is very similar, and so well discuss them together in this section. Both of them are implemented using a more primitive data structure called a <em>hash table</em>, which youll also learn about in CSC263/265. The benefit of using hash tables is that they allow <em>constant-time lookup, insertion, and removal</em> of elements (for a set) and key-value pairs (for a dictionary)!<label for="sn-5-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5-7c3d4f22d6" class="margin-toggle"/><span class="sidenote"> This is actually a simplification of how hash tables are implemented. So while well treat all these operations as constant-time in this course, this relies on some technical assumptions which hold in most, but not all, cases.</span></p>
<p>But of course, there is a catch. The trade-off of how Python uses hash tables is the elements of a set and the keys of a dictionary cannot be mutable data types, a restriction we discussed earlier in the course. This can be inconvenient, but in general is seen as a small price to pay for the speed of their operations.</p>
<p>So if you only care about set operations like “element of”, it is more efficient to use a <code>set</code> than a <code>list</code>:<label for="sn-6-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6-7c3d4f22d6" class="margin-toggle"/><span class="sidenote"> Youll notice that we havent formally discussed the running time of the list <code>in</code> operation in this section. Well study it in the next section.</span></p>
<div class="sourceCode" id="cb8-7c3d4f22d6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-7c3d4f22d6"><a href="#cb8-1-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> lst1M <span class="op">=</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">10</span> <span class="op">**</span> <span class="dv">6</span>))</span>
<span id="cb8-2-7c3d4f22d6"><a href="#cb8-2-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> set1M <span class="op">=</span> <span class="bu">set</span>(<span class="bu">range</span>(<span class="dv">10</span> <span class="op">**</span> <span class="dv">6</span>))</span>
<span id="cb8-3-7c3d4f22d6"><a href="#cb8-3-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;5000000 in lst1M&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb8-4-7c3d4f22d6"><a href="#cb8-4-7c3d4f22d6"></a><span class="fl">0.16024739999556914</span></span>
<span id="cb8-5-7c3d4f22d6"><a href="#cb8-5-7c3d4f22d6"></a><span class="op">&gt;&gt;&gt;</span> timeit(<span class="st">&#39;5000000 in set1M&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb8-6-7c3d4f22d6"><a href="#cb8-6-7c3d4f22d6"></a><span class="fl">4.6000059228390455e-06</span></span></code></pre></div>
<h2 id="data-classes-7c3d4f22d6">Data classes</h2>
<p>It turns out that data classes (and in fact all Python data types) store their instance attributes using a dictionary that maps attribute names to their corresponding values. This means that data classes benefit from the constant-time dictionary operations that we discussed above.</p>
<p>Explicitly, the two operations that we can perform on a data class instance are looking up an attribute value (e.g., <code>david.age</code>) and mutating the instance by assigning to an attribute (e.g., <code>david.age = 99</code>). Both of these operations take constant time, independent of how many instance attributes the data class has or what values are stored for those attributes.</p>
<div class="center reference-table">
<table>
<caption>Summary of set, dictionary, and data class operations</caption>
<thead>
<tr class="header">
<th>Operation</th>
<th>Running time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Set/dict Search (<code>in</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="even">
<td><code>set.add</code>/<code>set.remove</code></td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="odd">
<td>Dictionary key lookup (<code>d[k]</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="even">
<td>Dictionary key assignment (<code>d[k] = ...</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="odd">
<td>Data class attribute access (<code>obj.attr</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
<tr class="even">
<td>Data class attribute assignment (<code>obj.attr = ...</code>)</td>
<td><span class="math inline">\(\Theta(1)\)</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="aggregation-functions-7c3d4f22d6">Aggregation functions</h2>
<p>Finally, well briefly discuss a few built-in aggregation functions weve seen so far in this course.</p>
<p><code>sum</code>, <code>max</code>, <code>min</code> have a <em>linear</em> running time (<span class="math inline">\(\Theta(n)\)</span>), proportional to the size of the input collection. This should be fairly intuitive, as each element of the collection must be processed in order to calculate each of these values.</p>
<p><code>len</code> is a bit surprising: it has a <em>constant</em> running time (<span class="math inline">\(\Theta(1)\)</span>), independent of the size of the input collection. In order words, the Python interpreter does <em>not</em> need to process each element of a collection when calculating the collections size! Instead, each of these collection data types stores a special attribute referring to the size of that collection. And as we discussed for data classes, accessing attributes takes constant time.<label for="sn-7-7c3d4f22d6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7-7c3d4f22d6" class="margin-toggle"/><span class="sidenote"> There is one technical difference between data class attributes and these collection “size” attributes: we cant access the latter directly in Python code using dot notation, only through calling <code>len</code> on the collection. This is a result of how the Python language implements these built-in collection data types.</span></p>
<p><code>any</code> and <code>all</code> are a bit different. Intuitively, they may need to check ever element of their input collection, just like <code>sum</code> or <code>max</code>, but they can also <em>short-circuit</em> (stopping before checking every element), just like the logical <code>or</code> and <code>and</code> operators. This means their running time isnt a fixed function of the input size, but rather a possible range of values, depending on whether this short-circuiting happens or not. Well discuss how to formally analyse the running time of such functions in the next section.</p>
</section>
<!--
### Searching Contiguous Memory
While contiguous memory helps us find elements at a specific *index*, it does not help with searching elements for a specific *value*.
The value being searched for could be at any index (address).
The typical algorithm to approach a search is a *linear search*:
start at the very first index and check if the value has been found.
If not, check the next index and repeat as necessary.
We can see that this will take O(n) time, hence why the `in` operator took more time with `lst1M` than `lst1K`.
-->
<br/> <a id="anchor-08-07"></a>
<header id="title-block-header-a484943552">
<h1 class="title">8.7 Worst-Case Running Time Analysis</h1>
</header>
<section>
<p>In Section 8.3, we saw how to use asymptotic notation to characterize the <em>rate of growth</em> of the number of “basic operations” as a way of analyzing the running time of an algorithm. This approach allows us to ignore details of the computing environment in which the algorithm is run, and machine- and language-dependent implementations of primitive operations, and instead characterize the relationship between the input size and number of basic operations performed.</p>
<p>However, this focus on just the input size is a little too restrictive. Even though we can define input size differently for each algorithm we analyze, we tend not to stray too far from the “natural” definitions (e.g., length of list). In practice, though, algorithms often depend on the actual value of the input, not just its size. For example, consider the following function, which searches for an even number in a list of integers.<label for="sn-0-a484943552" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-a484943552" class="margin-toggle"/><span class="sidenote"> This is very similar to how the <code>in</code> operator is implemented for Python lists.</span></p>
<div class="sourceCode" id="cb1-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-a484943552"><a href="#cb1-1-a484943552"></a><span class="kw">def</span> has_even(numbers: <span class="bu">list</span>[<span class="bu">int</span>]) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-a484943552"><a href="#cb1-2-a484943552"></a> <span class="co">&quot;&quot;&quot;Return whether numbers contains an even element.&quot;&quot;&quot;</span></span>
<span id="cb1-3-a484943552"><a href="#cb1-3-a484943552"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers:</span>
<span id="cb1-4-a484943552"><a href="#cb1-4-a484943552"></a> <span class="cf">if</span> number <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb1-5-a484943552"><a href="#cb1-5-a484943552"></a> <span class="cf">return</span> <span class="va">True</span></span>
<span id="cb1-6-a484943552"><a href="#cb1-6-a484943552"></a> <span class="cf">return</span> <span class="va">False</span></span></code></pre></div>
<p>Because this function returns as soon as it finds an even number in the list, its running time is not necessarily proportional to the length of the input list.</p>
<p><strong>The running time of a function can vary even when the input size is fixed.</strong> Or using the notation we learned earlier this chapter, the inputs in <span class="math inline">\(\cI_{has\_even, 10}\)</span> do <em>not</em> all have the same runtime. The question “what is <em>the</em> running time of <code>has_even</code> on an input of length <span class="math inline">\(n\)</span>?” does not make sense, as for a given input the runtime depends not just on its length but on which of its elements are even. We illustrate in the following plot, which shows the results of using <code>timeit</code> to measure the running time of <code>has_evens</code> on randomly-chosen lists. While every timing experiment has some inherent uncertainty in the results, the spread of running times cannot be explained by that alone!</p>
<p><img src="images/has_evens_plotly.png" style="width:100.0%" alt="Running time plot for has_evens." /><br />
</p>
<p>Because our asymptotic notation is used to describe the growth rate of <em>functions</em>, we cannot use it to describe the growth of a whole range of values with respect to increasing input sizes. A natural approach to fix this problem is to focus on the <em>maximum</em> of this range, which corresponds to the <em>slowest</em> the algorithm could run for a given input size.</p>
<div class="definition" data-terms="worst-case runtime">
<p>Let <code>func</code> be a program. We define the function <span class="math inline">\(WC_{func}: \N \to \N\)</span>, called the <strong>worst-case running time function of <code>func</code></strong>, as follows:<label for="sn-1-a484943552" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-a484943552" class="margin-toggle"/><span class="sidenote">Here, “running time” is measured in exact number of basic operations. We are taking the maximum of a set of numbers, <em>not</em> a set of asymptotic expressions.</span> <span class="math display">\[
WC_{func}(n) = \max \big\{ \text{running time of executing $func(x)$} \mid x \in \cI_{func, n} \big\}
\]</span></p>
</div>
<p>Note that <span class="math inline">\(WC_{func}\)</span> is a function, not a (constant) number: it returns the maximum possible running time for an input of size <span class="math inline">\(n\)</span>, for every natural number <span class="math inline">\(n\)</span>. And because it is a function, we can use asymptotic notation to describe it, saying things like “the worst-case running time of this function is <span class="math inline">\(\Theta(n^2)\)</span>.”</p>
<p>The goal of a <em>worst-case runtime analysis</em> for <code>func</code> is to find an elementary function <span class="math inline">\(f\)</span> such that <span class="math inline">\(WC_{func} \in \Theta(f)\)</span>.</p>
<p>However, it takes a bit more work to obtain tight bounds on a worst-case running time than on the runtime functions of the previous section. It is difficult to compute the <em>exact maximum</em> number of basic operations performed by this algorithm for every input size, which requires that we identify an input for each input size, count its maximum number of basic operations, and then prove that every input of this size takes at most this number of operations. Instead, we will generally take a two-pronged approach: proving matching <em>upper</em> and <em>lower bounds</em> on the worst-case running time of our algorithm.</p>
<h3 id="upper-bounds-on-the-worst-case-runtime-a484943552">Upper bounds on the worst-case runtime</h3>
<div class="definition" data-terms="upper bound on worst-case runtime">
<p>Let <code>func</code> be a program, and <span class="math inline">\(WC_{func}\)</span> its worst-case runtime function. We say that a function <span class="math inline">\(f: \N \to \R^{\geq 0}\)</span> is an <strong>upper bound on the worst-case runtime</strong> when <span class="math inline">\(WC_{func} \in \cO(f)\)</span>.</p>
</div>
<p>To get some intuition about what an upper bound on the worst-case running means, suppose we use absolute dominance rather than Big-O. In this case, theres a very intuitive way to expand the phrase “<span class="math inline">\(WC_{func}\)</span> is absolutely dominated by <span class="math inline">\(f\)</span>”:</p>
<p><span class="math display">\[\begin{align*}
&amp;\forall n \in \N,~ WC_{func}(n) \leq f(n) \\
\Longleftrightarrow \, &amp;\forall n \in \N,~ \max \big\{ \text{running time of executing $func(x)$} \mid x \in \cI_{func, n} \big\} \leq f(n) \\
\Longleftrightarrow \, &amp;\forall n \in \N,~ \forall x \in \cI_{func, n},~ \text{running time of executing $func(x)$} \leq f(n)
\end{align*}\]</span></p>
<p>The last line comes from the fact that if we know the maximum of a set of numbers is less than some value <span class="math inline">\(K\)</span>, then <em>all</em> numbers in that set must be less than <span class="math inline">\(K\)</span>. Thus an upper bound on the worst-case runtime is equivalent to an upper bound on the runtimes of <em>all</em> inputs.</p>
<p>Now when we apply the definition of Big-O instead of absolute dominance, we get the following translation of <span class="math inline">\(WC_{func} \in \cO(f)\)</span>:</p>
<p><span class="math display">\[
\exists c, n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \Rightarrow \big(\forall x \in \cI_{func, n},~ \text{running time of executing $func(x)$} \leq c \cdot f(n) \big)
\]</span></p>
</div>
<p>To approach an analysis of an upper bound on the worst-case, we typically find a function <span class="math inline">\(g\)</span> such that <span class="math inline">\(WC_{func}\)</span> is absolutely dominated by <span class="math inline">\(g\)</span>, and then find a simple function <span class="math inline">\(f\)</span> such that <span class="math inline">\(g \in \cO(f)\)</span>. But how do we find such a <span class="math inline">\(g\)</span>? And what does it mean to upper bound <em>all</em> runtimes of a given input size? Well illustrate the technique in our next example.</p>
<div id="example:worst_case_upper_bound-a484943552" class="example">
<p>Find an asymptotic upper bound on the worst-case running time of <code>has_even</code>.</p>
<div class="discussion">
<p>The intuitive translation using absolute dominance is usually enough for an upper bound analysis. In particular, the <span class="math inline">\(\forall n \in \N,~ \forall x \in \cI_{func, n}\)</span> begins with two universal quantifiers, and just knowing this alone should anticipate how well start our proof, using the same techniques of proof we learned earlier!</p>
</div>
<div class="analysis">
<p><em>(Upper bound on worst-case)</em></p>
<p>First, let <span class="math inline">\(n \in \N\)</span> and let <code>numbers</code> be an <em>arbitrary</em> list of length <span class="math inline">\(n\)</span>.</p>
<p>Now well analyse the running time of <code>has_even</code>, except we <em>cant</em> assume anything about the values inside <code>numbers</code>, because its an aribtrary list. But we can still find an <em>upper bound</em> on the running time:</p>
<ul>
<li><p>The loop (<code>for number in numbers</code>) iterates <em>at most</em> <span class="math inline">\(n\)</span> times. Each loop iteration counts as a single step (because it is constant time), so the loop takes <em>at most</em> <span class="math inline">\(n \cdot 1 = n\)</span> steps in total.</p></li>
<li><p>The <code>return False</code> statement (if it is executed) counts as <span class="math inline">\(1\)</span> basic operation.</p></li>
</ul>
<p>Therefore the running time is <em>at most <span class="math inline">\(n + 1\)</span></em>, and <span class="math inline">\(n + 1 \in \cO(n)\)</span>. So we can conclude that the worst-case running time of <code>has_even</code> is <span class="math inline">\(\cO(n)\)</span>.</p>
</div>
</div>
<p>Note that we did <em>not</em> prove that <code>has_even(numbers)</code> takes exactly <span class="math inline">\(n + 1\)</span> basic operations for an arbitrary input <code>numbers</code> (this is false); we only proved an <em>upper bound</em> on the number of operations. And in fact, we dont even care that much about the exact number: what we ultimately care about is the asymptotic growth rate, which is linear for <span class="math inline">\(n + 1\)</span>. This allowed us to conclude that the worst-case running time of <code>has_even</code> is <span class="math inline">\(\cO(n)\)</span>.</p>
<p>But because we calculated an upper bound rather than an exact number of steps, we can only conclude a Big-O, not Theta bound: we dont yet know that this upper bound is tight.<label for="sn-2-a484943552" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-a484943552" class="margin-toggle"/><span class="sidenote">If this is surprising, note that we could have done the above proof but replaced <span class="math inline">\(n+1\)</span> by <span class="math inline">\(5000n + 110\)</span> and it would still have been mathematically valid.</span></p>
<h3 id="lower-bounds-on-the-worst-case-runtime-a484943552">Lower bounds on the worst-case runtime</h3>
<p>So how do we prove our upper bound is tight? Since weve just shown that <span class="math inline">\(WC_{has\_even}(n) \in \cO(n)\)</span>, we need to prove the corresponding lower bound <span class="math inline">\(WC_{has\_even}(n) \in \Omega(n)\)</span>. But what does it mean to prove a lower bound on the maximum of a set of numbers? Suppose we have a set of numbers <span class="math inline">\(S\)</span>, and say that “the maximum of <span class="math inline">\(S\)</span> is at least <span class="math inline">\(50\)</span>.” This doesnt tell us what the maximum of <span class="math inline">\(S\)</span> actually is, but it does give us one piece of information: there has to be a number in <span class="math inline">\(S\)</span> which is at least <span class="math inline">\(50\)</span>.</p>
<p>The key insight is that the converse is also true—if I tell you that <span class="math inline">\(S\)</span> contains the number <span class="math inline">\(50\)</span>, then you can conclude that the maximum of <span class="math inline">\(S\)</span> is at least <span class="math inline">\(50\)</span>. <span class="math display">\[\max(S) \geq 50 \IFF (\exists x \in S,~ x \geq 50)\]</span> Using this idea, well give a formal definition for a lower bound on the worst-case runtime of an algorithm.</p>
<div class="definition" data-terms="lower bound on worst-case runtime">
<p>Let <code>func</code> be a program, and <span class="math inline">\(WC_{func}\)</span> is worst-case runtime function. We say that a function <span class="math inline">\(f: \N \to \R^{\geq 0}\)</span> is a <strong>lower bound on the worst-case runtime</strong> when <span class="math inline">\(WC_{func} \in \Omega(f)\)</span>.</p>
<p>In an analogous fashion to the upper bound, we unpack this definition first by using absolute dominance: <span class="math display">\[\begin{align*}
&amp; \forall n \in \N,~ WC_{func}(n) \geq f(n) \\
\Longleftrightarrow \, &amp;\forall n \in \N,~ \max \big\{ \text{running time of executing $func(x)$} \mid x \in \cI_{func, n} \big\} \geq f(n) \\
\Longleftrightarrow \, &amp;\forall n \in \N,~ \exists x \in \cI_{func, n},~ \text{running time of executing $func(x)$} \geq f(n)
\end{align*}\]</span></p>
<p>And then using Omega:</p>
<p><span class="math display">\[
\exists c, n_0 \in \R^+,~ \forall n \in \N,~ n \geq n_0 \Rightarrow
\big(\exists x \in \cI_{func, n},~ \text{running time of executing $func(x)$} \geq c \cdot f(n) \big)
\]</span></p>
</div>
<p>Remarkably, the crucial difference between this definition and the one for upper bounds is a change of quantifier: now the input <span class="math inline">\(x\)</span> is existentially quantified, meaning we get to pick it. Or really, our goal is to find an <strong>input family</strong>—a <em>set</em> of inputs, one per input size <span class="math inline">\(n\)</span>—whose runtime is asymptotically larger than our target lower bound.</p>
<p>For example, in <code>has_even</code> we want to prove that the worst-case running time is <span class="math inline">\(\Omega(n)\)</span> to match the <span class="math inline">\(\cO(n)\)</span> upper bound, and so we want to find and input family where the number of steps taken is <span class="math inline">\(\Omega(n)\)</span>. Lets do that now.</p>
<div id="example:worst_case_lower_bound-a484943552" class="example">
<p>Find an asymptotic lower bound on the worst-case running time of <code>has_even</code>.</p>
<div class="discussion">
<p>Again, well just remind you of the quantifiers from the intuitive “absolute dominance” version of the lower bound definition: <span class="math inline">\(\forall n \in \N,~ \exists x \in \cI_{n}\)</span>. This will inform how we start our proof.</p>
</div>
<div class="analysis">
<p><em>(Lower bound on worst-case)</em></p>
<p>Let <span class="math inline">\(n \in \N\)</span>. Let <code>numbers</code> be the list of length <span class="math inline">\(n\)</span> consisting of all <span class="math inline">\(1\)</span>s. Now well analyse the (exact) running time of <code>has_even</code> on this input.</p>
<p>In this case, the <code>if</code> condition in the loop is always false, so the loop never stops early. Therefore it iterates exactly <span class="math inline">\(n\)</span> times (once per item in the list), with each iteration taking one step.</p>
<p>Finally, the <code>return False</code> statement executes, which is one step. So the total number of steps for this input is <span class="math inline">\(n + 1\)</span>, which is <span class="math inline">\(\Omega(n)\)</span>.</p>
</div>
</div>
<h3 id="putting-it-all-together-a484943552">Putting it all together</h3>
<p>Finally, we can combine our upper and lower bounds on <span class="math inline">\(WC_{has\_even}\)</span> to obtain a tight asymptotic bound.</p>
<div class="example">
<p>Find a <em>tight</em> bound on the worst-case running time of <code>has_even</code>.</p>
<div class="analysis">
<p>Since weve proved that <span class="math inline">\(WC_{has\_even}\)</span> is <span class="math inline">\(\cO(n)\)</span> and <span class="math inline">\(\Omega(n)\)</span>, it is <span class="math inline">\(\Theta(n)\)</span>.</p>
</div>
</div>
<p>To summarize, to obtain a tight bound on the worst-case running time of a function, we need to do two things:</p>
<ul>
<li><p>Use the properties of the code to obtain an <em>asymptotic upper bound</em> on the worst-case running time. We would say something like <span class="math inline">\(WC_{func} \in \cO(f)\)</span>.</p></li>
<li><p>Find a family of inputs whose running time is <span class="math inline">\(\Omega(f)\)</span>.<label for="sn-3-a484943552" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-a484943552" class="margin-toggle"/><span class="sidenote"> Almost always we find an input family whose running time is <span class="math inline">\(\Theta(f)\)</span>, but strictly speaking only <span class="math inline">\(\Omega(f)\)</span> is required.</span> This will prove that <span class="math inline">\(WC_{func} \in \Omega(f)\)</span>.</p></li>
<li><p>After showing that <span class="math inline">\(WC_{func} \in \cO(f)\)</span> and <span class="math inline">\(WC_{func} \in \Omega(f)\)</span>, we can conclude that <span class="math inline">\(WC_f \in \Theta(f)\)</span>.</p></li>
</ul>
<h3 id="a-note-about-best-case-runtime-a484943552">A note about best-case runtime</h3>
<p>In this section, we focused on worst-case runtime, the result of taking the <em>maximum</em> runtime for every input size. It is also possible to define a best-case runtime function by taking the minimum possible runtimes, and obtain tight bounds on the best case through an analysis that is completely analogous to the one we just performed. In practice, however, the best-case runtime of an algorithm is usually not as useful to know—we care far more about knowing just how <em>slow</em> an algorithm is than how fast it can be.</p>
<h2 id="early-returning-in-python-built-ins-a484943552">Early returning in Python built-ins</h2>
<p>Weve encountered a few different Python functions and methods whose running time depends on more than just the size of their inputs. We alluded to one at the start of this chapter: the list search operation using the keyword <code>in</code>:</p>
<div class="sourceCode" id="cb2-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-a484943552"><a href="#cb2-1-a484943552"></a><span class="op">&gt;&gt;&gt;</span> lst <span class="op">=</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">1000000</span>))</span>
<span id="cb2-2-a484943552"><a href="#cb2-2-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;0 in lst&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb2-3-a484943552"><a href="#cb2-3-a484943552"></a><span class="fl">8.299997716676444e-06</span></span>
<span id="cb2-4-a484943552"><a href="#cb2-4-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;-1 in lst&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb2-5-a484943552"><a href="#cb2-5-a484943552"></a><span class="fl">0.17990550000104122</span></span></code></pre></div>
<p>In the first <code>timeit</code> expression, <code>0</code> appears as the first element of <code>lst</code>, and so is found immediately when the search occurs. In the second, <code>-1</code> does not appear in <code>lst</code> at all, and so all one-million elements of <code>lst</code> must be checked, resulting in a running-time that is proportional to the length of the list. <em>The worst-case running time of the <code>in</code> operation for lists is <span class="math inline">\(\Theta(n)\)</span>, where <span class="math inline">\(n\)</span> is the length of the list.</em></p>
<p>We have also seen two more functions that are implemented using an early return: <code>any</code> and <code>all</code>. Because <code>any</code> searches for a single <code>True</code> in a collection, it stops the first time it finds one. Similarly, because <code>all</code> requires that all elements of a collection be <code>True</code>, it stops the first time it finds a <code>False</code> value.</p>
<div class="sourceCode" id="cb3-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-a484943552"><a href="#cb3-1-a484943552"></a><span class="op">&gt;&gt;&gt;</span> all_trues <span class="op">=</span> [<span class="va">True</span>] <span class="op">*</span> <span class="dv">1000000</span></span>
<span id="cb3-2-a484943552"><a href="#cb3-2-a484943552"></a><span class="op">&gt;&gt;&gt;</span> all_falses <span class="op">=</span> [<span class="va">False</span>] <span class="op">*</span> <span class="dv">1000000</span></span>
<span id="cb3-3-a484943552"><a href="#cb3-3-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;any(all_trues)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb3-4-a484943552"><a href="#cb3-4-a484943552"></a><span class="fl">8.600000001024455e-06</span></span>
<span id="cb3-5-a484943552"><a href="#cb3-5-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;any(all_falses)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb3-6-a484943552"><a href="#cb3-6-a484943552"></a><span class="fl">0.10643419999905745</span></span>
<span id="cb3-7-a484943552"><a href="#cb3-7-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;all(all_trues)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb3-8-a484943552"><a href="#cb3-8-a484943552"></a><span class="fl">0.10217570000168053</span></span>
<span id="cb3-9-a484943552"><a href="#cb3-9-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;all(all_falses)&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb3-10-a484943552"><a href="#cb3-10-a484943552"></a><span class="fl">6.300000677583739e-06</span></span></code></pre></div>
<p>So in the above example:</p>
<ul>
<li><code>any(all_trues)</code> returns <code>True</code> immediately after checking the first list element.</li>
<li><code>any(all_falses)</code> returns <code>False</code> only after checking all one-million list elements.</li>
<li><code>all(all_trues)</code> returns <code>True</code> only after checking all one-million list elements.</li>
<li><code>all(all_falses)</code> returns <code>False</code> immediately after checking the first list element.</li>
</ul>
<p>So <code>any</code> and <code>all</code> have a worst-case running time of <span class="math inline">\(\Theta(n)\)</span>, where <span class="math inline">\(n\)</span> is the size of the input collection. But in practice they can be much faster if they encounter the “right” boolean value early on!</p>
<h3 id="any-all-and-comprehensions-a484943552"><code>any</code>, <code>all</code>, and comprehensions</h3>
<p>There is one subtlety that often catches students by surprise when they attempt to call <code>any</code>/<code>all</code> on a comprehension and expect a quick result. Lets see a simple example:</p>
<div class="sourceCode" id="cb4-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-a484943552"><a href="#cb4-1-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;any([x == 0 for x in range(0, 1000000)])&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb4-2-a484943552"><a href="#cb4-2-a484943552"></a><span class="fl">0.7032962000012049</span></span></code></pre></div>
<p>Thats a lot slower than we would expect, given that the first element checked is <code>x = 0</code>! The result is similar if we try to use a set comprehension instead of a list comprehension:</p>
<div class="sourceCode" id="cb5-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-a484943552"><a href="#cb5-1-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;any({x == 0 for x in range(0, 1000000)})&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb5-2-a484943552"><a href="#cb5-2-a484943552"></a><span class="fl">0.6538308000017423</span></span></code></pre></div>
<p>The subtlety here is that in both cases, <em>the full comprehension is evaluated before <code>any</code> is called</em>. As we discussed in <a href="05-more-runtime.html">8.5 Analyzing Comprehensions and While Loops</a>, the running time of evaluating a comprehension is proportional to the size of the source collection of the comprehension—in our example, thats <code>range(0, 1000000)</code>, which contains one-million numbers.</p>
<p>But all is not lost! In practice, Python programmers <em>do</em> use <code>any</code>/<code>all</code> with comprehensions, but they do so by writing the comprehension expression in the function call without any surrounding square brackets or curly braces:</p>
<div class="sourceCode" id="cb6-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-a484943552"><a href="#cb6-1-a484943552"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">any</span>(x <span class="op">==</span> <span class="dv">0</span> <span class="cf">for</span> x <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">1000000</span>))</span>
<span id="cb6-2-a484943552"><a href="#cb6-2-a484943552"></a><span class="va">True</span></span></code></pre></div>
<p>This is called a <strong>generator comprehension</strong>, and is used to produce a special Python collection data type called a <strong>generator</strong>. We wont use generators or generator comprehensions very much at all in this course, but what we want you to know about them here is that unlike set/list comprehensions, generator comprehensions do not evaluate their elements all at once, but instead only when they are needed by the function being called. This means that our above <code>any</code> call achieves the fast running time we initially expected:</p>
<div class="sourceCode" id="cb7-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-a484943552"><a href="#cb7-1-a484943552"></a><span class="op">&gt;&gt;&gt;</span> timeit.timeit(<span class="st">&#39;any(x == 0 for x in range(0, 1000000))&#39;</span>, number<span class="op">=</span><span class="dv">10</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb7-2-a484943552"><a href="#cb7-2-a484943552"></a><span class="fl">4.050000279676169e-05</span></span></code></pre></div>
<p>Now, only the <code>x = 0</code> value from the generator comprehension gets evaluated; none of the other possible values (<code>x = 1, 2, ..., 999999</code>) are ever checked by the <code>any</code> call!</p>
<h2 id="dont-assume-bounds-are-tight-a484943552">Dont assume bounds are tight!</h2>
<p>It is likely unsatisfying to hear that upper and lower bounds really are distinct things that must be computed separately. Our intuition here pulls us towards the bounds being “obviously” the same, but this is really a side effect of the examples we have studied so far in this course being rather straightforward. But this wont always be the case: the study of more complex algorithms and data structures exhibits quite a few situations where obtaining an upper bound on the running time involves a completely different analysis than the lower bound.</p>
<p>Lets look at one such example that deals with manipulating strings.</p>
<div class="example">
<p>We say that a string is a <strong>palindrome</strong> when it can be read the same forwards and backwards; example of palindromes are “abba”, “racecar”, and “z”.<label for="sn-4-a484943552" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4-a484943552" class="margin-toggle"/><span class="sidenote">Every string of length 1 is a palindrome.</span> We say that a string <span class="math inline">\(s_1\)</span> is a <strong>prefix</strong> of another string <span class="math inline">\(s_2\)</span> when <span class="math inline">\(s_1\)</span> is a substring of <span class="math inline">\(s_2\)</span> that starts at index 0 of <span class="math inline">\(s_2\)</span>. For example, the string “abc” is a prefix of “abcdef”.</p>
<p>The algorithm below takes a non-empty string as input, and returns the length of the longest prefix of that string that is a palindrome. For example, the string “attack” has two non-empty prefixes that are palindromes, “a” and “atta”, and so our algorithm will return 4.</p>
<div class="sourceCode" id="cb8-a484943552"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-a484943552"><a href="#cb8-1-a484943552"></a><span class="kw">def</span> palindrome_prefix(s: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">int</span>:</span>
<span id="cb8-2-a484943552"><a href="#cb8-2-a484943552"></a> n <span class="op">=</span> <span class="bu">len</span>(s)</span>
<span id="cb8-3-a484943552"><a href="#cb8-3-a484943552"></a> <span class="cf">for</span> prefix_length <span class="kw">in</span> <span class="bu">range</span>(n, <span class="dv">0</span>, <span class="op">-</span><span class="dv">1</span>): <span class="co"># goes from n down to 1</span></span>
<span id="cb8-4-a484943552"><a href="#cb8-4-a484943552"></a> <span class="co"># Check whether s[0:prefix_length] is a palindrome</span></span>
<span id="cb8-5-a484943552"><a href="#cb8-5-a484943552"></a> is_palindrome <span class="op">=</span> <span class="bu">all</span>(s[i] <span class="op">==</span> s[prefix_length <span class="op">-</span> <span class="dv">1</span> <span class="op">-</span> i]</span>
<span id="cb8-6-a484943552"><a href="#cb8-6-a484943552"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, prefix_length))</span>
<span id="cb8-7-a484943552"><a href="#cb8-7-a484943552"></a></span>
<span id="cb8-8-a484943552"><a href="#cb8-8-a484943552"></a> <span class="co"># If a palindrome prefix is found, return the current length.</span></span>
<span id="cb8-9-a484943552"><a href="#cb8-9-a484943552"></a> <span class="cf">if</span> is_palindrome:</span>
<span id="cb8-10-a484943552"><a href="#cb8-10-a484943552"></a> <span class="cf">return</span> prefix_length</span></code></pre></div>
<p>There are a few interesting details to note about this algorithm:</p>
<ul>
<li>The for loop iterable is <code>range(n, 0, -1)</code>—the third argument <code>-1</code> causes the loop variable to <em>start</em> at <code>n</code> and decrease by 1 at each iteration. In other words, this loop is checking the possible prefixes starting with the longest prefix (length <code>n</code>) and working its way to the shortest prefix (length 1).</li>
<li>The call to <code>all</code> checks pairs of characters starting at either end of the current prefix. It uses a <em>generator comprehension</em> (like we discussed above) so that it can stop early as soon as it encounters a mismatch (i.e., when <code>s[i] != s[prefix_length - 1 - i]</code>).</li>
<li>Even though the only return statement is inside the <code>for</code> loop, this algorithm is guaranteed to find a palindrome prefix, since the first letter of <code>s</code> by itself is a palindrome.</li>
</ul>
<p>The code presented here is structurally simple. Indeed, it is not too hard to show that the worst-case runtime of this function is <span class="math inline">\(\cO(n^2)\)</span>, where <span class="math inline">\(n\)</span> is the length of the input string. What is harder, however, is showing that the worst-case runtime is <span class="math inline">\(\Omega(n^2)\)</span>. To do so, we must find an input family whose runtime is <span class="math inline">\(\Omega(n^2)\)</span>. There are two points in the code that can lead to fewer than the maximum loop iterations occurring, and we want to find an input family that avoids both of these.</p>
<p>The difficulty is that these two points are caused by different types of inputs! The call to <code>all</code> can stop as soon as the algorithm detects that a prefix is <em>not</em> a palindrome, while the <code>return</code> statement occurs when the algorithm has determined that a prefix <em>is</em> a palindrome! To make this tension more explicit, lets consider two extreme input families that seem plausible at first glance, but which do not have a runtime that is <span class="math inline">\(\Omega(n^2)\)</span>.</p>
<ul>
<li>The entire string <span class="math inline">\(s\)</span> is a palindrome of length <span class="math inline">\(n\)</span>. In this case, in the first iteration of the loop, the entire string is checked. The <code>all</code> call checks all pairs of characters, but unfortunately this means that <code>is_palindrome = True</code>, and the loop returns during its very first iteration. Since the <code>all</code> call takes <span class="math inline">\(n\)</span> steps, this input family takes <span class="math inline">\(\Theta(n)\)</span> time to run.</li>
<li>The entire string <span class="math inline">\(s\)</span> consists of <span class="math inline">\(n\)</span> different letters. In this case, the only palindrome prefix is just the first letter of <span class="math inline">\(s\)</span> itself. This means that the loop will run for all <span class="math inline">\(n\)</span> iterations, only returning in its last iteration (when <code>prefix_length == 1</code>). However, the <code>all</code> call will always stop after just one step, since it starts by comparing the first letter of <span class="math inline">\(s\)</span> with another letter, which is guaranteed to be different by our choice of input family. This again leads to a <span class="math inline">\(\Theta(n)\)</span> running time.</li>
</ul>
<p>The key idea is that we want to choose an input family that <em>doesnt</em> contain a long palindrome (so the loop runs for many iterations), but whose prefixes are close to being palindromes like palindromes (so the <code>all</code> call checks many pairs of letters). Let <span class="math inline">\(n \in \Z^+\)</span>. We define the input <span class="math inline">\(s_n\)</span> as follows:</p>
<ul>
<li><span class="math inline">\(s_n[\ceil{n/2}] = b\)</span></li>
<li>Every other character in <span class="math inline">\(s_n\)</span> is equal to <span class="math inline">\(a\)</span>.</li>
</ul>
<p>For example, <span class="math inline">\(s_4 = aaba\)</span> and <span class="math inline">\(s_{11} = aaaaaabaaa\)</span>. Note that <span class="math inline">\(s_n\)</span> is very close to being a palindrome: if that single character <span class="math inline">\(b\)</span> were changed to an <span class="math inline">\(a\)</span>, then <span class="math inline">\(s_n\)</span> would be the all-<span class="math inline">\(a\)</span>s string, which is certainly a palindrome. But by making the centre character a <span class="math inline">\(b\)</span>, we not only ensure that the longest palindrome of <span class="math inline">\(s_n\)</span> has length roughly <span class="math inline">\(n/2\)</span> (so the loop iterates roughly <span class="math inline">\(n/2\)</span> times), but also that the “outer” characters of each prefix of <span class="math inline">\(s_n\)</span> containing more than <span class="math inline">\(n/2\)</span> characters are all the same (so the <code>all</code> call checks many pairs to find the mismatch between <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span>). It turns out that this input family does indeed have an <span class="math inline">\(\Omega(n^2)\)</span> runtime! Well leave the details as an exercise.</p>
</div>
</section>
<br/> <a id="anchor-08-08"></a>
<header id="title-block-header-0c23335a56">
<h1 class="title">8.8 Testing Functions IV: Efficiency</h1>
</header>
<section>
<p>We hope that the number of sections of these notes dedicated to testing demonstrates its importance in the process of software development. What is perhaps surprising is that testing is not limited to correctness. In fact, strict efficiency constraints are the norm in several domains. For example, a Playstation controller must send wireless signals at the touch of a button or the move of a joystick—if the function for doing so were correct, but took 10 seconds, players would not be happy. Similarly, a search on Google that sifts through terabytes of data must also be fast.<label for="sn-0-0c23335a56" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-0c23335a56" class="margin-toggle"/><span class="sidenote"> Check it out: each search you do on Google reports how many results were found in how many fractions of a second.</span> In this section, we will discuss how to write tests for efficiency of functions.</p>
<!-- Even more surprising than performance constraints, the performance of the tests themselves are incredibly important in well-designed software projects.
The test suite itself can be quite large, and each time a developer fixes a bug (hopefully) or adds a new feature the tests must be re-run.
The faster the test suite runs, the better software can reach its internal (e.g., alpha, beta) and external release deadlines.
In this section, we will discuss how to setup tests for performance constraints for both functions and tests (which, coincidentally, are also functions). -->
<h2 id="an-efficiency-test-0c23335a56">An efficiency test</h2>
<p>Earlier we saw how to use the <code>timeit</code> module to measure the time taken to execute a piece of Python code. Lets see how we might setup a performance constraint using <code>timeit</code> and our implementation of <code>is_prime</code>:</p>
<div class="sourceCode" id="cb1-0c23335a56"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-0c23335a56"><a href="#cb1-1-0c23335a56"></a><span class="im">from</span> math <span class="im">import</span> floor, sqrt</span>
<span id="cb1-2-0c23335a56"><a href="#cb1-2-0c23335a56"></a><span class="im">from</span> timeit <span class="im">import</span> timeit</span>
<span id="cb1-3-0c23335a56"><a href="#cb1-3-0c23335a56"></a></span>
<span id="cb1-4-0c23335a56"><a href="#cb1-4-0c23335a56"></a></span>
<span id="cb1-5-0c23335a56"><a href="#cb1-5-0c23335a56"></a><span class="kw">def</span> is_prime(p: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-6-0c23335a56"><a href="#cb1-6-0c23335a56"></a> <span class="co">&quot;&quot;&quot;Return whether p is prime.&quot;&quot;&quot;</span></span>
<span id="cb1-7-0c23335a56"><a href="#cb1-7-0c23335a56"></a> possible_divisors <span class="op">=</span> <span class="bu">range</span>(<span class="dv">2</span>, floor(sqrt(p)) <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb1-8-0c23335a56"><a href="#cb1-8-0c23335a56"></a> <span class="cf">return</span> (</span>
<span id="cb1-9-0c23335a56"><a href="#cb1-9-0c23335a56"></a> p <span class="op">&gt;</span> <span class="dv">1</span> <span class="kw">and</span></span>
<span id="cb1-10-0c23335a56"><a href="#cb1-10-0c23335a56"></a> <span class="bu">all</span>(<span class="kw">not</span> p <span class="op">%</span> d <span class="op">==</span> <span class="dv">0</span> <span class="cf">for</span> d <span class="kw">in</span> possible_divisors)</span>
<span id="cb1-11-0c23335a56"><a href="#cb1-11-0c23335a56"></a> )</span>
<span id="cb1-12-0c23335a56"><a href="#cb1-12-0c23335a56"></a></span>
<span id="cb1-13-0c23335a56"><a href="#cb1-13-0c23335a56"></a></span>
<span id="cb1-14-0c23335a56"><a href="#cb1-14-0c23335a56"></a><span class="kw">def</span> test_is_prime_performance() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-15-0c23335a56"><a href="#cb1-15-0c23335a56"></a> <span class="co">&quot;&quot;&quot;Test the efficiency of is_prime.&quot;&quot;&quot;</span></span>
<span id="cb1-16-0c23335a56"><a href="#cb1-16-0c23335a56"></a> numbers_to_test <span class="op">=</span> <span class="bu">range</span>(<span class="dv">2</span>, <span class="dv">1000</span>)</span>
<span id="cb1-17-0c23335a56"><a href="#cb1-17-0c23335a56"></a> <span class="cf">for</span> number <span class="kw">in</span> numbers_to_test:</span>
<span id="cb1-18-0c23335a56"><a href="#cb1-18-0c23335a56"></a> time <span class="op">=</span> timeit(<span class="ss">f&#39;is_prime(</span><span class="sc">{</span>number<span class="sc">}</span><span class="ss">)&#39;</span>, number<span class="op">=</span><span class="dv">100</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb1-19-0c23335a56"><a href="#cb1-19-0c23335a56"></a> <span class="cf">assert</span> time <span class="op">&lt;</span> <span class="fl">0.001</span>, <span class="st">&#39;Failed performance constraint of 0.001s.&#39;</span></span></code></pre></div>
<p>There are several issues here that we need to keep in mind. The performance constraint of 0.001 seconds is for the total runtime of 100 calls to <code>is_prime</code> for only one number in <code>numbers_to_test</code> (there will be as many assertions as there are elements in <code>numbers_to_test</code>). Where did the argument <code>number=100</code> come from? Should it be more or less? An important thing to remember is a computer system is not at all like a science experiment you would setup in a chemistry or biology lab. There are too many external factors (i.e., background processes being run) that can impact the results. To avoid this issue, several samples of an experiment (i.e., measurements of time) need to be taken. The field of statistics can help inform us on whether or not 100 samples is sufficient for this test.</p>
<p>Next, where did <code>0.001</code> seconds come from? The number is most certainly arbitrary in this example. Computer systems are very different from one another, in terms of both hardware and software. While the assertions may hold for all <code>numbers_to_test</code> on one computer, they may not hold on another. The <code>0.001</code> seconds may be tuned over time in the testing suite. Or it can help identify the minimum hardware requirements for running a piece of software.</p>
<p>While it is easy to write the Python code that checks for performance, coming up with the actual parameters (number of function calls, inputs to the function, total acceptable runtime) is quite challenging, and often domain-dependent. For example, in user interfaces, a great deal of research has gone into how fast actions should be; a so-called “instantaneous” action in a user interface should complete in <a href="https://www.nngroup.com/articles/response-times-3-important-limits/">0.1 seconds</a>. Other domains, such as embedded systems, have a series of functions that must meet hard deadlines in order for the computer system to function properly (e.g., in a spaceship).</p>
<p>But what about domains where there are no guidelines or standards? Runtime constraints that are tuned over time can still be useful in discovering changes in program efficiency due to bug fixes or new features. When a code change causes an efficiency test to fail, the programmers can decide whether to the efficiency constraint or explore alternative code changes. Without efficiency tests in place, the change in performance might not have been found until it impacted a real user of the software!</p>
<!-- ## Timing Out on Tests
The result of a test can be unpredictable.
So far, we have assumed that a test can either pass or fail.
But what if a test never ends?
For example, a specific set of inputs could cause the function being tested to enter an infinite loop.
In this scenario, the test does not know that the function is in an infinite loop, and so cannot raise an assertion error.
In a less extreme example, a recent change in the code has increased the complexity of the function from logarithmic to quadratic.
An large input that was tested earlier in seconds could now be taking minutes.
Both of the examples above motivate the need for a maximum time that each test should take.
When the maximum time is exceeded, the test is said to have *timed out*.
You may have seen this type of error before while browsing the internet.
Sometimes, a server is unable to process a request within a reasonable amount of time, and your browser displays an error such as "connection timed out".
Setting up timeouts for our tests is useful to ensure that all tests will complete.
We can add timeouts to our functions in pytest through the `timeout_decorator` Python module.
The module provides access to a decorator: `@timeout`.
We have seen decorators before when we introduced `@dataclass` before defining a new `class`.
In this scenario, we place the `@timeout` decorator before defining a new test function:
```python
import timeout_decorator
@timeout_decorator.timeout(1)
def test_is_prime_large_number() -> None:
assert is_prime(32443) is True
```
Much like with performance constraints, we must specify how long (in seconds) a test should take.
In this scenario, we timeout after `1` second.
The decision on how many seconds is, similarly, a tuning exercise.
To give you a very relevant example, your undergraduate programming classes choose timeouts based on a few parameters.
How generous do the professors want to be with inefficient implementations?
How much of a load will the test suite put on the servers?
How long can the professors wait before getting the grades back?
You can imagine that some submissions may timeout on several tests---if a 30 minute timeout is used, then a single submission could take several hours to test! -->
</section>
<br/>
<!--
[8.5 Revisting Cryptographic Algorithms](08-runtime/05-crypto-algorithm-analysis.html) <br/>
-->
<h2 class="unnumbered" id="abstraction-classes-and-software-design">9. Abstraction, Classes, and Software Design</h2>
<a id="anchor-09-01"></a>
<header id="title-block-header-a54b5a486e">
<h1 class="title">9.1 An Introduction to Abstraction</h1>
</header>
<section>
<p>Abstraction is fundamental to our everyday lives, not just in computing. Loosely, abstraction is about understanding how to use something without knowing how it works. Consider your refrigerator—how does it work? Does it matter? We know that we can open a fridge door, place something (probably food) inside, and the fridge will keep it cold. So our notion of a fridge is really quite abstract; there are many thousands of refrigerator types, each one designed and built by different companies and people around the world. But this is irrelevant: when you go to a friends house, you can use their fridge just as you would your own, without any extra help.</p>
<p>There are several examples of abstraction in the real world. It doesnt matter how a watch was built, so long as we can use it to tell time. It doesnt matter how a cup was made or what materials it was made out of, so long as we can use it to hold liquid. Divorcing the nitty gritty details of how something works with how to use it is abstraction. And it is abstraction that has allowed for ingenuity and creativity to advance technology (i.e., how something works) without having to re-educate the entire world on how to use a cup.<label for="sn-0-a54b5a486e" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-a54b5a486e" class="margin-toggle"/><span class="sidenote"> Of course, humans have also creatively improved how we use things, like attaching a handle to a cup meant to contain hot coffee.</span></p>
<p>We can think of abstraction as allowing for the separation of two groups of people with different goals: the <em>creators</em> of an entity, and the <em>users</em> (or <em>clients</em>) of that entity. Sometimes theres overlap between these two groups, but much of the time—especially as technology and systems have grown more complex—these two groups are fairly separate. Creators are responsible for designing, building, and implementing an entity, and users are responsible for, well, using it.</p>
<p>The <strong>interface</strong> of an entity is the boundary between creator and user: it is the set of rules (implicit or explicit) governing how users can interact with that entity. We call an interface the <em>public</em> side of an entity; it is the part of the creators work that everyone can interact it. Creators are responsible for the design of the interface, while users are responsible for learning the interface in order to interact with the entity. For example, the interface of a cup is how you use it: where to put liquid and where to hold it when taking a drink.</p>
<h2 id="abstraction-in-computer-science-a54b5a486e">Abstraction in computer science</h2>
<p>Abstraction and interfaces are incredibly useful concepts in computer science because of the complexity of programming languages, algorithms, and computer hardware that come with modern technology. Weve been using abstraction all the way through this course, playing the role of creator in some cases, and users in others:</p>
<ul>
<li><p>We are <em>users</em> of the Python programming language itself, which provides an interface that hides the details of our computer hardware, processor instructions, memory, storage, and graphics.<label for="sn-1-a54b5a486e" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-a54b5a486e" class="margin-toggle"/><span class="sidenote"> This isnt unique to Python, of course: <em>every</em> programming language is an interface between the programmer and their computer.</span> While we have learned some details about how the Python interpreter works (like our discussion of its array-based list implementation in the previous chapter), weve barely scratched the surface of this large and complex software.</p></li>
<li><p>We are <em>users</em> of built-in Python functions, data types, and modules. We dont know how the creators of the Python programming language have implemented these built-ins, but have learned how to <em>use</em> them to write useful programs.</p></li>
<li><p>We are <em>creators</em> of new Python functions, data types and modules. Each time you have followed the function or data class design recipe, you have created an interface.</p>
<p>For a <em>function</em>, its interface is its header and docstring: these specify how to call the function, the arguments it expects, and what the function does. The function body, is the implementation of the function, and are not part of its interface—someone who wants to use our function should not have to look a the function body to determine what it does.</p>
<p>For a <em>data class</em>, its interface is the name of the data class and the names and types of its attributes, and the class docstring. In other words, <em>every</em> part of what we write to define a new data class is part of its interface! How data classes are actually implemented has been hidden from us in the <code>@dataclass</code> decorator, though well begin learning about how this implementation works in the next section.</p>
<p>Finally, the interface of a Python <em>module</em> is simply the collection of interfaces of the functions and data types defined in that module, plus any additional documentation in the module docstring. For every Python file youve written so far, youve created a module that could be used by other programmers.</p></li>
<li><p>When studying mathematical statements, we have acted as both <em>users</em> and <em>creators</em>. Every time we write a proof, we act as a creator of knowledge, providing airtight evidence that a statement is True.<label for="sn-2-a54b5a486e" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-a54b5a486e" class="margin-toggle"/><span class="sidenote"> You can view a proof as an “implementation” of a statement. Rather than acting as a set of instructions to execute to complete a task, a proof is a set of statements that assert the truth of a statement.</span> Every time we use an “external statement” in a proof, like the Quotient-Remainder Theorem or Fermats Little Theorem, we are acting as <em>users</em> of these statements, and do not worry about how they have been proved.</p></li>
</ul>
<h2 id="interfaces-are-contracts-a54b5a486e">Interfaces are contracts</h2>
<p>As we work with more and more programming interfaces—different functions, data types, modules, and even programming languages—we see just how challenging designing interfaces can be. Every interface is a contract between creator and user: while creators have control over how they design an interface, they have the responsibility to make that interface easy and intuitive for users. Good interfaces are simple and strive to minimize the cognitive load on users; bad interfaces are cumbersome, ambiguous, and require the user to keep track of many unrelated details. Because interfaces are public, as creators we put a lot of effort into designing good interfaces, a topic well discuss in this year but that youll explore far more in future courses.</p>
<p>Moreover, because interfaces are contracts, they are hard to change once released—made public to users—as any change will have ramifications on every user. We have been the users used several Python modules so far, such as <code>timeit</code>, <code>pytest</code>, and <code>doctest</code>. What would happen if the creators of one of these modules decided to make a change to that interface, like changing the <code>timeit</code> function name to <code>time_it</code>? This one character change would cause all code that uses the <code>timeit.timeit</code> function to no longer work! As clients of the <code>timeit</code> module, we would not be very happy.</p>
<p>There are two sides to every contract. Just as creators are beholden to keep the interface they provide, users are limited to that interface as well. When we act as the creators of a function or module, we are free to modify their implementations in any way we wish, as long as we do not change the public interface. We can fix a bug, simplify the code, or use a more efficient algorithm, all to improve our implementation <em>without</em> affecting our users. In software engineering, it is important to clearly define what the public interface of a piece of code actually is, so that its creators know precisely what they must preserve and what they are free to change.</p>
<p>Over the next two chapters, well explore the concepts of abstraction, public interfaces, and private implementations in more detail. Well study how we can build our own Python data types from scratch (without relying on <code>@dataclass</code>) to gain full control over defining a data types public interface. Well create implementations of abstract data types and models of real-world domains, using the ideas weve introduced here to define clear public interfaces for every part of what we do.</p>
</section>
<br/> <a id="anchor-09-02"></a>
<header id="title-block-header-9b469a7b5a">
<h1 class="title">9.2 Defining Our Own Data Types, Part 3</h1>
</header>
<section>
<p>All the way back in <a href="../04-complex-data/02-data-classes-1.html">Chapter 4</a>, we learned how to create our own simple data types in Python using the <code>@dataclass</code> decorator. While data classes are very useful, they are just one particular form of classes in Python. The <code>@dataclass</code> decorator takes our data class declaration—its <em>public interface</em>—and automatically creates an implementation of class. This makes it very simple to set up data classes, at the cost of flexibility of implementation.</p>
<p>In this section, well learn about how to create a Python data type from scratch, without the automatic implementation that <code>@dataclass</code> provides. In future sections, well apply what weve learned to defining new Python data types to solve various computational problems.</p>
<h2 id="what-if-we-just-remove-the-dataclass-9b469a7b5a">What if we just remove the <code>@dataclass</code>?</h2>
<p>To start with, recall the <code>Person</code> data class example we used when we first introduced data classes:</p>
<div class="sourceCode" id="cb1-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-9b469a7b5a"><a href="#cb1-1-9b469a7b5a"></a><span class="at">@dataclass</span></span>
<span id="cb1-2-9b469a7b5a"><a href="#cb1-2-9b469a7b5a"></a><span class="kw">class</span> Person:</span>
<span id="cb1-3-9b469a7b5a"><a href="#cb1-3-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;A custom data type that represents data for a person.&quot;&quot;&quot;</span></span>
<span id="cb1-4-9b469a7b5a"><a href="#cb1-4-9b469a7b5a"></a> given_name: <span class="bu">str</span></span>
<span id="cb1-5-9b469a7b5a"><a href="#cb1-5-9b469a7b5a"></a> family_name: <span class="bu">str</span></span>
<span id="cb1-6-9b469a7b5a"><a href="#cb1-6-9b469a7b5a"></a> age: <span class="bu">int</span></span>
<span id="cb1-7-9b469a7b5a"><a href="#cb1-7-9b469a7b5a"></a> address: <span class="bu">str</span></span></code></pre></div>
<p>We were able to use this data class to create and display an instance of the class and access its attributes:</p>
<div class="sourceCode" id="cb2-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-9b469a7b5a"><a href="#cb2-1-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Liu&#39;</span>, <span class="dv">100</span>, <span class="st">&#39;40 St. George Street&#39;</span>)</span>
<span id="cb2-2-9b469a7b5a"><a href="#cb2-2-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david</span>
<span id="cb2-3-9b469a7b5a"><a href="#cb2-3-9b469a7b5a"></a>Person(given_name<span class="op">=</span><span class="st">&#39;David&#39;</span>, family_name<span class="op">=</span><span class="st">&#39;Liu&#39;</span>, age<span class="op">=</span><span class="dv">100</span>, address<span class="op">=</span><span class="st">&#39;40 St. George Street&#39;</span>)</span>
<span id="cb2-4-9b469a7b5a"><a href="#cb2-4-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david.given_name</span>
<span id="cb2-5-9b469a7b5a"><a href="#cb2-5-9b469a7b5a"></a><span class="co">&#39;David&#39;</span></span>
<span id="cb2-6-9b469a7b5a"><a href="#cb2-6-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david.family_name</span>
<span id="cb2-7-9b469a7b5a"><a href="#cb2-7-9b469a7b5a"></a><span class="co">&#39;Liu&#39;</span></span>
<span id="cb2-8-9b469a7b5a"><a href="#cb2-8-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david.age</span>
<span id="cb2-9-9b469a7b5a"><a href="#cb2-9-9b469a7b5a"></a><span class="dv">100</span></span>
<span id="cb2-10-9b469a7b5a"><a href="#cb2-10-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david.address</span>
<span id="cb2-11-9b469a7b5a"><a href="#cb2-11-9b469a7b5a"></a><span class="co">&#39;40 St. George Street&#39;</span></span></code></pre></div>
<p>Now lets see what happens if we remove the <code>@dataclass</code> decorator from our class definition. This is indeed valid Python syntax, but with perhaps an unexpected consequence.</p>
<div class="sourceCode" id="cb3-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-9b469a7b5a"><a href="#cb3-1-9b469a7b5a"></a><span class="co"># @dataclass (We&#39;ve commented out this line)</span></span>
<span id="cb3-2-9b469a7b5a"><a href="#cb3-2-9b469a7b5a"></a><span class="kw">class</span> Person:</span>
<span id="cb3-3-9b469a7b5a"><a href="#cb3-3-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;A custom data type that represents data for a person.&quot;&quot;&quot;</span></span>
<span id="cb3-4-9b469a7b5a"><a href="#cb3-4-9b469a7b5a"></a> given_name: <span class="bu">str</span></span>
<span id="cb3-5-9b469a7b5a"><a href="#cb3-5-9b469a7b5a"></a> family_name: <span class="bu">str</span></span>
<span id="cb3-6-9b469a7b5a"><a href="#cb3-6-9b469a7b5a"></a> age: <span class="bu">int</span></span>
<span id="cb3-7-9b469a7b5a"><a href="#cb3-7-9b469a7b5a"></a> address: <span class="bu">str</span></span>
<span id="cb3-8-9b469a7b5a"><a href="#cb3-8-9b469a7b5a"></a></span>
<span id="cb3-9-9b469a7b5a"><a href="#cb3-9-9b469a7b5a"></a></span>
<span id="cb3-10-9b469a7b5a"><a href="#cb3-10-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Liu&#39;</span>, <span class="dv">100</span>, <span class="st">&#39;40 St. George Street&#39;</span>)</span>
<span id="cb3-11-9b469a7b5a"><a href="#cb3-11-9b469a7b5a"></a><span class="pp">TypeError</span>: Person() takes no arguments</span></code></pre></div>
<p>Okay, something went wrong. Even though our class declaration still contains attribute names and type annotations, we cannot call <code>Person</code> and pass in values for those attributes. According to the error message, <code>Person() takes no arguments</code>. So what happens when we try to create an instance of <code>Person</code> and pass in zero arguments?</p>
<div class="sourceCode" id="cb4-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-9b469a7b5a"><a href="#cb4-1-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person()</span>
<span id="cb4-2-9b469a7b5a"><a href="#cb4-2-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(david)</span>
<span id="cb4-3-9b469a7b5a"><a href="#cb4-3-9b469a7b5a"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;Person&#39;</span><span class="op">&gt;</span></span></code></pre></div>
<p>We successfully created an instance of the <code>Person</code> class. But what happens when we try to access the instance attributes?</p>
<div class="sourceCode" id="cb5-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-9b469a7b5a"><a href="#cb5-1-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david.given_name</span>
<span id="cb5-2-9b469a7b5a"><a href="#cb5-2-9b469a7b5a"></a><span class="pp">AttributeError</span>: <span class="st">&#39;Person&#39;</span> <span class="bu">object</span> has no attribute <span class="st">&#39;given_name&#39;</span></span></code></pre></div>
<p>This should make sense: by just calling <code>Person()</code> with no arguments, we havent specified values for any of the instance attributes, so we shouldnt expect to see a value when we access <code>david.given_name</code>.</p>
<h2 id="defining-an-initializer-9b469a7b5a">Defining an initializer</h2>
<p>When we execute the statement <code>david = Person()</code>, all we have in memory is this:</p>
<p><img src="images/empty-person.png" alt="An empty instance of Person" /><br />
</p>
<p>A <code>Person</code> object has been created, but it has no attributes. To fix this (without using <code>@dataclass</code>), we need to define a new method for <code>Person</code> called the <strong>initializer</strong>. The initializer method of a class is called when an instance of the class is created in Python. As its name suggests, the purpose of this method it to initialize all of the instance attributes for the new object. To distinguish it from regular functions, Python always uses the name <code>__init__</code> for the initializer method.</p>
<p>When we use the <code>@dataclass</code> decorator, the Python interpreter automatically creates an initializer method for the class. So lets start by seeing what this “automatic” code for the initializer looks like.</p>
<div class="sourceCode" id="cb6-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-9b469a7b5a"><a href="#cb6-1-9b469a7b5a"></a><span class="kw">class</span> Person:</span>
<span id="cb6-2-9b469a7b5a"><a href="#cb6-2-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;A custom data type that represents data for a person.&quot;&quot;&quot;</span></span>
<span id="cb6-3-9b469a7b5a"><a href="#cb6-3-9b469a7b5a"></a> given_name: <span class="bu">str</span></span>
<span id="cb6-4-9b469a7b5a"><a href="#cb6-4-9b469a7b5a"></a> family_name: <span class="bu">str</span></span>
<span id="cb6-5-9b469a7b5a"><a href="#cb6-5-9b469a7b5a"></a> age: <span class="bu">int</span></span>
<span id="cb6-6-9b469a7b5a"><a href="#cb6-6-9b469a7b5a"></a> address: <span class="bu">str</span></span>
<span id="cb6-7-9b469a7b5a"><a href="#cb6-7-9b469a7b5a"></a></span>
<span id="cb6-8-9b469a7b5a"><a href="#cb6-8-9b469a7b5a"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, given_name: <span class="bu">str</span>, family_name: <span class="bu">str</span>, age: <span class="bu">int</span>, address: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-9-9b469a7b5a"><a href="#cb6-9-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;Initialize a new Person object.&quot;&quot;&quot;</span></span>
<span id="cb6-10-9b469a7b5a"><a href="#cb6-10-9b469a7b5a"></a> <span class="va">self</span>.given_name <span class="op">=</span> given_name</span>
<span id="cb6-11-9b469a7b5a"><a href="#cb6-11-9b469a7b5a"></a> <span class="va">self</span>.family_name <span class="op">=</span> family_name</span>
<span id="cb6-12-9b469a7b5a"><a href="#cb6-12-9b469a7b5a"></a> <span class="va">self</span>.age <span class="op">=</span> age</span>
<span id="cb6-13-9b469a7b5a"><a href="#cb6-13-9b469a7b5a"></a> <span class="va">self</span>.address <span class="op">=</span> address</span></code></pre></div>
<p>Since all methods are functions, it should not surprise you to learn that we define methods using the same keyword (<code>def</code>) as other functions. However, there are two key differences between this method definition and all top-level function definitions weve studied so far. The first is that this method definition is <em>indented</em> so that it is inside the body of the <code>class Person</code> definition. This is how we signal that the function being defined is a method for the <code>Person</code> class.</p>
<p>The second difference is the presence of the parameter <code>self</code>. Every initializer has a first parameter that refers to the instance that has just been created and is to be initialized. By convention, we always call it <code>self</code>. This is such a strong Python convention that most code checkers will complain if you dont follow it.<label for="sn-0-9b469a7b5a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-9b469a7b5a" class="margin-toggle"/><span class="sidenote"> This name is the reason we refer to attributes as <code>self.&lt;attr&gt;</code> in class representation invariants.</span> In fact, this convention is so strong that we also typically omit the type annotation for <code>self</code>. We could have written <code>self: Person</code>, but because the type of <code>self</code> should <em>always</em> be the class that the initializer belongs to, this is considered redundant in Python!</p>
<p>To understand how <code>self</code> works, lets examine how we use the initializer:</p>
<div class="sourceCode" id="cb7-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-9b469a7b5a"><a href="#cb7-1-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Person(<span class="st">&#39;David&#39;</span>, <span class="st">&#39;Liu&#39;</span>, <span class="dv">100</span>, <span class="st">&#39;40 St. George Street&#39;</span>)</span></code></pre></div>
<p>Notice that we never mention the initializer <code>__init__</code> by name; it is called automatically, and the values in parentheses are passed to it. Also notice that we pass four values to the initializer, even though it has five parameters. We never have to pass a value for <code>self</code>; Python automatically sets it to the instance that is to be initialized. So this is what is happening in memory at the beginning of the initializer:</p>
<p><img src="images/person-initializer-start.png" alt="Memory at the start of Person.__init__" /><br />
</p>
<p>The initializers job is to create and initialize the instance attributes. To do this, we use one assignment statement per instance attribute. This uses the same dot notation syntax that we saw in Chapter 5 for assigning to instance attributes: <code>self.given_name = given_name</code>, for example. Note that <code>given_name</code> and <code>self.given_name</code> are two different expressions! <code>given_name</code> is a <em>parameter</em> of the initialize, while <code>self.given_name</code> is an <em>instance attribute</em>.<label for="sn-1-9b469a7b5a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-9b469a7b5a" class="margin-toggle"/><span class="sidenote"> Some other programming languages like Java allow you to refer to instance attributes without using dot notation. In Python, however, dot notation is <em>mandatory</em> for accessing and assigning to instance attributes.</span> We can illustrate this distinction by showing the state of memory after all attributes have been initialized, immediately before the initializer returns:</p>
<p><img src="images/person-initializer-end.png" alt="Memory at the end of Person.__init__" /><br />
</p>
<h3 id="what-really-happens-when-we-create-a-new-object-9b469a7b5a">What really happens when we create a new object</h3>
<p>You may have noticed that the initializer return type is <code>None</code>, and that the body of the function does not actually return anything. This is a bit strange, since when we evaluate <code>david = Person('David', 'Liu', 100, '40 St. George Street')</code>, a <code>Person</code> object is definitely returned from the function call and assigned to the variable <code>david</code>.</p>
<p><img src="images/person-initializer-after-return.png" alt="Memory after Person.__init__ returns" /><br />
</p>
<p>Whats going on? It turns out that calling <code>Person</code> doesnt just cause <code>__init__</code> to be called. It actually does three things:<label for="sn-2-9b469a7b5a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-9b469a7b5a" class="margin-toggle"/><span class="sidenote">Of course, this is true not just for our <code>Person</code> class, but in fact <em>every</em> class in Python.</span></p>
<ol type="1">
<li>Create a new <code>Person</code> object behind the scenes.</li>
<li>Call <code>__init__</code> with the new object passed to the parameter <code>self</code>, along with the other arguments.</li>
<li>Return the new object. This step is where the object is returned, not directly from the call to <code>__init__</code> in Step 2.</li>
</ol>
<p>So in fact, <code>__init__</code> is a <em>helper function</em> in the object creation process. Its task is only to initialize attributes for an object; Python handles both creating the object beforehand, and returning the new object after <code>__init__</code> has been called.</p>
<h2 id="methods-as-part-of-a-data-type-interface-9b469a7b5a">Methods as part of a data type interface</h2>
<p>It is certainly possible to accomplish everything that we would ever want to do with our <code>Person</code> class by writing top-level functions, and this is the approach weve taken with data classes up to this point. An alternate and commonly-used approach is to define <em>methods</em> for a data type, which become part of the interface of that data type. Remember that methods are just functions that belong to a data type—but this “belonging to” is not just an abstract relationship, but creates concrete consequences for how the Python interpreter handles them. When we define a data class and top-level functions, the interface of a data class itself only consists of its attributes; we have to remember to import those functions separately in order to use them. When we define a class with methods, those methods are <em>always</em> bundled with the class, and so any instance of the class can use those methods, without needing to import them separately.</p>
<p>We have seen one example of a method definition already: the initializer, <code>__init__</code>. More generally, any function that operates on an instance of a class can be converted into a method by doing the following:</p>
<ul>
<li>Indent the function so that it is part of the class body, underneath the innstance attributes.</li>
<li>Ensure that the first parameter of the function is an instance of the class, and name this parameter <code>self</code>.</li>
</ul>
<p>For example, suppose we had the following function to increase a persons age:</p>
<div class="sourceCode" id="cb8-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-9b469a7b5a"><a href="#cb8-1-9b469a7b5a"></a><span class="kw">def</span> increase_age(person: Person, years: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb8-2-9b469a7b5a"><a href="#cb8-2-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;Add the given number of years to the given person&#39;s age.</span></span>
<span id="cb8-3-9b469a7b5a"><a href="#cb8-3-9b469a7b5a"></a></span>
<span id="cb8-4-9b469a7b5a"><a href="#cb8-4-9b469a7b5a"></a><span class="co"> &gt;&gt;&gt; david = Person(&#39;David&#39;, &#39;Liu&#39;, 100, &#39;40 St. George Street&#39;)</span></span>
<span id="cb8-5-9b469a7b5a"><a href="#cb8-5-9b469a7b5a"></a><span class="co"> &gt;&gt;&gt; increase_age(david, 10)</span></span>
<span id="cb8-6-9b469a7b5a"><a href="#cb8-6-9b469a7b5a"></a><span class="co"> &gt;&gt;&gt; david.age</span></span>
<span id="cb8-7-9b469a7b5a"><a href="#cb8-7-9b469a7b5a"></a><span class="co"> 110</span></span>
<span id="cb8-8-9b469a7b5a"><a href="#cb8-8-9b469a7b5a"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb8-9-9b469a7b5a"><a href="#cb8-9-9b469a7b5a"></a> person.age <span class="op">=</span> person.age <span class="op">+</span> years</span></code></pre></div>
<p>We can turn <code>increase_age</code> into a <code>Person</code> method as follows:</p>
<div class="sourceCode" id="cb9-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-9b469a7b5a"><a href="#cb9-1-9b469a7b5a"></a><span class="kw">class</span> Person:</span>
<span id="cb9-2-9b469a7b5a"><a href="#cb9-2-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;A custom data type that represents data for a person.&quot;&quot;&quot;</span></span>
<span id="cb9-3-9b469a7b5a"><a href="#cb9-3-9b469a7b5a"></a> given_name: <span class="bu">str</span></span>
<span id="cb9-4-9b469a7b5a"><a href="#cb9-4-9b469a7b5a"></a> family_name: <span class="bu">str</span></span>
<span id="cb9-5-9b469a7b5a"><a href="#cb9-5-9b469a7b5a"></a> age: <span class="bu">int</span></span>
<span id="cb9-6-9b469a7b5a"><a href="#cb9-6-9b469a7b5a"></a> address: <span class="bu">str</span></span>
<span id="cb9-7-9b469a7b5a"><a href="#cb9-7-9b469a7b5a"></a></span>
<span id="cb9-8-9b469a7b5a"><a href="#cb9-8-9b469a7b5a"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, given_name: <span class="bu">str</span>, family_name: <span class="bu">str</span>, age: <span class="bu">int</span>, address: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb9-9-9b469a7b5a"><a href="#cb9-9-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;Initialize a new Person object.&quot;&quot;&quot;</span></span>
<span id="cb9-10-9b469a7b5a"><a href="#cb9-10-9b469a7b5a"></a> <span class="va">self</span>.given_name <span class="op">=</span> given_name</span>
<span id="cb9-11-9b469a7b5a"><a href="#cb9-11-9b469a7b5a"></a> <span class="va">self</span>.family_name <span class="op">=</span> family_name</span>
<span id="cb9-12-9b469a7b5a"><a href="#cb9-12-9b469a7b5a"></a> <span class="va">self</span>.age <span class="op">=</span> age</span>
<span id="cb9-13-9b469a7b5a"><a href="#cb9-13-9b469a7b5a"></a> <span class="va">self</span>.address <span class="op">=</span> address</span>
<span id="cb9-14-9b469a7b5a"><a href="#cb9-14-9b469a7b5a"></a></span>
<span id="cb9-15-9b469a7b5a"><a href="#cb9-15-9b469a7b5a"></a> <span class="kw">def</span> increase_age(<span class="va">self</span>, years: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb9-16-9b469a7b5a"><a href="#cb9-16-9b469a7b5a"></a> <span class="co">&quot;&quot;&quot;Add the given number of years to this person&#39;s age.</span></span>
<span id="cb9-17-9b469a7b5a"><a href="#cb9-17-9b469a7b5a"></a></span>
<span id="cb9-18-9b469a7b5a"><a href="#cb9-18-9b469a7b5a"></a><span class="co"> &gt;&gt;&gt; david = Person(&#39;David&#39;, &#39;Liu&#39;, 100, &#39;40 St. George Street&#39;)</span></span>
<span id="cb9-19-9b469a7b5a"><a href="#cb9-19-9b469a7b5a"></a><span class="co"> &gt;&gt;&gt; Person.increase_age(david, 10)</span></span>
<span id="cb9-20-9b469a7b5a"><a href="#cb9-20-9b469a7b5a"></a><span class="co"> &gt;&gt;&gt; david.age</span></span>
<span id="cb9-21-9b469a7b5a"><a href="#cb9-21-9b469a7b5a"></a><span class="co"> 110</span></span>
<span id="cb9-22-9b469a7b5a"><a href="#cb9-22-9b469a7b5a"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb9-23-9b469a7b5a"><a href="#cb9-23-9b469a7b5a"></a> <span class="va">self</span>.age <span class="op">=</span> <span class="va">self</span>.age <span class="op">+</span> years</span></code></pre></div>
<p>Notice that we now use parameter <code>self</code> (without a type annotation) to access instance attributes, just as we did in the initializer. In our function docstring, the phrase “the given person” changes to “this person”,<label for="sn-3-9b469a7b5a" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-9b469a7b5a" class="margin-toggle"/><span class="sidenote"> We typically use the word “this” in a method docstring to refer to the object instance that <code>self</code> refers to. In fact, some other programming languages also use <code>this</code> instead of <code>self</code> as a variable or keyword to refer to this object in code.</span> and our doctest example changes the call to <code>increase_age</code> to <code>Person.increase_age</code>.</p>
<h3 id="shortcut-syntax-for-method-calls-9b469a7b5a">Shortcut syntax for method calls</h3>
<p>Now that we are starting to define our own custom classes and methods, we are ready to see a shorthand for calling methods in Python. Lets take a look at the method call from our doctest above:</p>
<div class="sourceCode" id="cb10-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-9b469a7b5a"><a href="#cb10-1-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> Person.increase_age(david, <span class="dv">10</span>)</span></code></pre></div>
<p>This uses dot notation to access the <code>increase_age</code> method of the <code>Person</code> class, calling it with the two arguments <code>david</code> and <code>10</code>, which get assigned to parameters <code>self</code> and <code>years</code>, respectively.</p>
<p>The alternate form for calling the <code>increase_age</code> method is to use dot notation <em>with the <code>Person</code> instance directly</em>:</p>
<div class="sourceCode" id="cb11-9b469a7b5a"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-9b469a7b5a"><a href="#cb11-1-9b469a7b5a"></a><span class="op">&gt;&gt;&gt;</span> david.increase_age(<span class="dv">10</span>)</span></code></pre></div>
<p>When we call <code>david.increase_age(10)</code>, the Python interpreter does the following:</p>
<ol type="1">
<li>It looks up the class of <code>david</code>, which is <code>Person</code>.</li>
<li>It looks up the <code>increase_age</code> method of the <code>Person</code> class.</li>
<li>It calls <code>Person.increase_age</code> on <code>david</code> and <code>10</code>. In other words, the interpreter <em>automatically</em> passes the value to the left of the dot (in this case, the object <code>david</code> refers to) as the methods first parameter <code>self</code>.</li>
</ol>
<p>This works not just for our custom class <code>Person</code>, but all built-in data types as well. For example, <code>list.append(lst, 10)</code> can be written as <code>lst.append(10)</code>, and <code>str.lower(s)</code> as simply <code>s.lower()</code>. More generally, a method call of the form <code>obj.method(x1, x2, ..., xn)</code> is equivalent to <code>type(obj).method(obj, x1, x2, ..., xn)</code>.</p>
<p>Though weve been using the more explicit “class dot notation” style (<code>Person.increase_age</code>) so far in this course, well switch over to the “object dot notation” style (<code>david.increase_age</code>) starting in this chapter, as this is the much more common style in Python programming. There are two primary reasons why the latter style is standard:</p>
<ol type="1">
<li><p>It matches other languages with an <em>object-oriented</em> style of programming, where the object being operated own is of central importance. Because we read from left to right, every time we use dot notation with the instance object on the left, we are reminded that it is an object we are working with, whether we are accessing a piece of data bundled with that object or performing an operation on that object.</p>
<p>We read <code>david.age</code> as “access <code>david</code>s age” and <code>david.increase_age(10)</code> as “increase <code>david</code>s age by 10”. In both cases, <code>david</code> is the most important object in the code expression.</p></li>
<li><p>Only the “object dot notation” style of method call supports <em>inheritance</em>, which is a technical feature of classes that well discuss in the next chapter.</p></li>
</ol>
</section>
<br/> <a id="anchor-09-03"></a>
<header id="title-block-header-2f79a07983">
<h1 class="title">9.3 Data Types, Abstract and Concrete</h1>
</header>
<section>
<p>So far in this course, weve used the term <em>data type</em> to actually mean two different things. Most of the time, we use it to mean a data type in the Python programming language, like <code>int</code> or <code>list</code> or a data class weve defined. When we use the term “data type” in this way, it is synonymous with the term <em>Python class</em>, which is the name the Python language gives to all of its data types. Well now call refer to these Python classes as <strong>concrete data types</strong>, since they have a concrete implementation in Python code. This is true for both built-in data types, data classes that we define, and the more general classes we learned about in <a href="02-classes.html">Section 9.2</a>.</p>
<p>However, theres another way weve used the term “data type” that goes all the way back to <a href="../01-working-with-data/01-data-types.html">1.1 The Different Types of Data</a>: as abstract representations of data that transcend any one specific programming language. For example, the Python <code>list</code> class is implemented differently than the Java <code>ArrayList</code> or JavaScript <code>Array</code>, but all three share some common expectations of what list operations they support. We can describe these common, language-independent list operations by defining an <strong>abstract data type (ADT)</strong>, which defines an entity that stores some kind of data and the operations that can be performed on it. Using the terminology from [Section 9.1], an abstract data type is a pure interface it is concerned only with the <em>what</em>—what data is stored, what we can do with this data—and not the <em>how</em>—how a computer actually stores this data or implements these operations.</p>
<h2 id="familiar-abstract-data-types-2f79a07983">Familiar abstract data types</h2>
<p>Lets take a moment here to review some of the collection-based abstract data types weve seen already in this course.<label for="sn-0-2f79a07983" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-2f79a07983" class="margin-toggle"/><span class="sidenote"> One caveat with this list: while computer scientists generally agree on what the “main” abstract data types are, they often disagree on what operations each one actually supports. Youll notice here that weve taken a fairly conservative approach for specifying operations, limiting ourselves to the most basic ones.</span></p>
<ul>
<li><p><strong>Set</strong></p>
<ul>
<li>Data: a collection of unique elements</li>
<li>Operations: get size, insert a value (without introducing duplicates), remove a specified value, check membership in the set.</li>
</ul></li>
<li><p><strong>List</strong></p>
<ul>
<li>Data: an ordered sequence of elements (which may or may not be unique)</li>
<li>Operations: get size, access element by index, insert a value at a given index, remove a value at a given index</li>
</ul></li>
<li><p><strong>Mapping</strong></p>
<ul>
<li>Data: a collection of key-value pairs, where each key is unique and associated with a single value</li>
<li>Operations: get size, lookup a value for a given key, insert a new key-value pair, remove a key-value pair, update the value associated with a given key</li>
</ul></li>
<li><p><strong>Iterable</strong></p>
<ul>
<li>Data: a collection of values (may or may not be unique)</li>
<li>Operations: iterate through the elements of the collection one at a time.</li>
</ul></li>
</ul>
<p>There are a few more foundational abstract data types in computer science that well cover in this chapter, and in future courses. We have discussed many of these throughout the semester so far, and have used many in Python. But the true power of ADTs is that they are abstract enough to transcend any individual program or even programming languages. ADTs like lists, sets, and maps form a common vocabulary that is necessary to being a professional computer scientist.</p>
<h2 id="abstract-vs.-concrete-data-types-2f79a07983">Abstract vs. concrete data types</h2>
<p>Abstract data types form a high-level interface between a computer scientist and how the computer stores program data. A concrete data type is an implementation of an abstract data type: unlike abstract data types, they <em>are</em> actually concerned with how the data is stored and how their operations are implemented. The creators of the Python programming language took various abstract data types and created a set of built-in concrete data types (classes), making careful decisions about how each class would store its data and implement its methods. Indeed, as Python programmers we benefit from all the work theyve put in to create classes that not just support common ADTs, but to make their implementations extremely fast using clever programming techniques.<label for="sn-1-2f79a07983" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-2f79a07983" class="margin-toggle"/><span class="sidenote"> Youll learn about some of these techniques in CSC263/265!</span></p>
<p>So a <code>dict</code>, for instance, is not itself an abstract data type. But the <code>dict</code> data type is an obvious implementation of the Mapping ADT. However, <em>there is NOT a one-to-one correspondence between abstract data types and concrete data types</em>, in Python or any other programming language. A single abstract data type can be implemented by many different concrete data types. For example, although the Python <code>dict</code> is a natural implementation of the Mapping ADT, we could implement the Mapping ADT instead with a <code>list</code>, where each element is a tuple storing a key-value pair:</p>
<div class="sourceCode" id="cb1-2f79a07983"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-2f79a07983"><a href="#cb1-1-2f79a07983"></a><span class="co"># A Map using a Python dict</span></span>
<span id="cb1-2-2f79a07983"><a href="#cb1-2-2f79a07983"></a>{<span class="dv">0</span>: <span class="st">&#39;hello&#39;</span>, <span class="dv">1</span>: <span class="dv">42</span>, <span class="dv">2</span>: <span class="st">&#39;goodbye&#39;</span>}</span>
<span id="cb1-3-2f79a07983"><a href="#cb1-3-2f79a07983"></a></span>
<span id="cb1-4-2f79a07983"><a href="#cb1-4-2f79a07983"></a><span class="co"># A Map using a Python list</span></span>
<span id="cb1-5-2f79a07983"><a href="#cb1-5-2f79a07983"></a>[(<span class="dv">0</span>, <span class="st">&#39;hello&#39;</span>), (<span class="dv">1</span>, <span class="dv">42</span>), (<span class="dv">2</span>, <span class="st">&#39;goodbye&#39;</span>)]</span></code></pre></div>
<p>Conversely, every concrete data type can be used to implement multiple ADTs. The Python <code>list</code> can be used to implement not just the List ADT, but each of the other above ADTs as well. For instance, think about how you would implement the Set ADT with a <code>list</code>, and in particular, how you would avoid duplicates.<label for="sn-2-2f79a07983" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-2f79a07983" class="margin-toggle"/><span class="sidenote"> Though just because something is possible doesnt mean it is a good idea in practice. Beginning Python programmers often implement use a <code>list</code> when all they need is the Set ADTs operations. As we discussed in <a href="../08-runtime/09-data-types-runtime.html">Section 8.6</a>, this leads to slower programs, and so should be avoided.</span> A <code>dict</code> could also implement any of the ADTs above, and the same is true of the new data structures you will learn in this course.</p>
<p>You might be wondering what is the point of making this distinction—so what if <code>list</code>s can implement the Mapping ADT, wed never use this in “real” Python code when we have a <code>dict</code> instead. And thats true! But what this distinction reminds us is that we always have <em>choices</em> when implementing an interface. Rather than saying “its not possible to implement a Map using <code>list</code>”, we instead say “it is possible to implement a Map using <code>list</code>, but this choice is worse than using <code>dict</code>”.</p>
<p>Any idea why is a <code>dict</code> better than <code>list</code> at implementing the Mapping ADT? If we ignore the fact that weve been using <code>dict</code> for this purpose all along, the answer is not obvious! It comes down to <em>efficiency</em>: though <code>dict</code> and <code>list</code> can both be used to implement the Map ADT, the implementation of <code>dict</code> makes the Mapping operations much faster than how we would (straightforwardly) implement the Mapping ADT using a <code>list</code>. As well see a few times this chapter, running time analysis is one of the key ways to evaluate and compare different implementations of an ADT.</p>
</section>
<br/> <a id="anchor-09-04"></a>
<header id="title-block-header-5209fcad86">
<h1 class="title">9.4 Stacks</h1>
</header>
<section>
<p>Over the next few sections of this chapter, well learn about three new abstract data types: Stack, Queue, and Priority Queue. All three of these ADTs store a collection of items, and support operations to add an item and remove an item. However, unlike a Set or List, in which users may specify which item to remove (by value or by index, respectively), these three ADTs remove and return their items in a fixed order—client code is allowed no choice. This might seem restrictive and simplistic, but youll soon learn how the power of these ADTs lies in their simplicity. Once you learn about them, youll start seeing them everywhere, and be able to effectively communicate about these ADTs to any other computer scientist.</p>
<h2 id="the-stack-adt-5209fcad86">The Stack ADT</h2>
<p>The <strong>Stack</strong> ADT is very simple. A stack contains zero or more items. When you add an item, it goes “on the top” of the stack (we call this “pushing” onto the stack) and when you remove an item, it is removed from the top also (we call this “popping” from the stack).<label for="sn-0-5209fcad86" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-5209fcad86" class="margin-toggle"/><span class="sidenote"> The name “stack” is a deliberate metaphor for a stack of books on a table.</span> The net effect is that the first item added to the stack is the last item removed. We call this <em>Last-In-First-Out (LIFO)</em> behaviour. To summarize:</p>
<ul>
<li><p><strong>Stack</strong></p>
<ul>
<li>Data: a collection of items</li>
<li>Operations: determine whether the stack is empty, add an item (<em>push</em>), remove the most recently-added item (<em>pop</em>)</li>
</ul></li>
</ul>
<p>In code:</p>
<div class="sourceCode" id="cb1-5209fcad86"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-5209fcad86"><a href="#cb1-1-5209fcad86"></a><span class="kw">class</span> Stack:</span>
<span id="cb1-2-5209fcad86"><a href="#cb1-2-5209fcad86"></a> <span class="co">&quot;&quot;&quot;A last-in-first-out (LIFO) stack of items.</span></span>
<span id="cb1-3-5209fcad86"><a href="#cb1-3-5209fcad86"></a></span>
<span id="cb1-4-5209fcad86"><a href="#cb1-4-5209fcad86"></a><span class="co"> Stores data in last-in, first-out order. When removing an item from the</span></span>
<span id="cb1-5-5209fcad86"><a href="#cb1-5-5209fcad86"></a><span class="co"> stack, the most recently-added item is the one that is removed.</span></span>
<span id="cb1-6-5209fcad86"><a href="#cb1-6-5209fcad86"></a></span>
<span id="cb1-7-5209fcad86"><a href="#cb1-7-5209fcad86"></a><span class="co"> Sample usage:</span></span>
<span id="cb1-8-5209fcad86"><a href="#cb1-8-5209fcad86"></a></span>
<span id="cb1-9-5209fcad86"><a href="#cb1-9-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s = Stack()</span></span>
<span id="cb1-10-5209fcad86"><a href="#cb1-10-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.is_empty()</span></span>
<span id="cb1-11-5209fcad86"><a href="#cb1-11-5209fcad86"></a><span class="co"> True</span></span>
<span id="cb1-12-5209fcad86"><a href="#cb1-12-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.push(&#39;hello&#39;)</span></span>
<span id="cb1-13-5209fcad86"><a href="#cb1-13-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.is_empty()</span></span>
<span id="cb1-14-5209fcad86"><a href="#cb1-14-5209fcad86"></a><span class="co"> False</span></span>
<span id="cb1-15-5209fcad86"><a href="#cb1-15-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.push(&#39;goodbye&#39;)</span></span>
<span id="cb1-16-5209fcad86"><a href="#cb1-16-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.pop()</span></span>
<span id="cb1-17-5209fcad86"><a href="#cb1-17-5209fcad86"></a><span class="co"> &#39;goodbye&#39;</span></span>
<span id="cb1-18-5209fcad86"><a href="#cb1-18-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-19-5209fcad86"><a href="#cb1-19-5209fcad86"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-20-5209fcad86"><a href="#cb1-20-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Initialize a new empty stack.&quot;&quot;&quot;</span></span>
<span id="cb1-21-5209fcad86"><a href="#cb1-21-5209fcad86"></a></span>
<span id="cb1-22-5209fcad86"><a href="#cb1-22-5209fcad86"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-23-5209fcad86"><a href="#cb1-23-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Return whether this stack contains no items.</span></span>
<span id="cb1-24-5209fcad86"><a href="#cb1-24-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-25-5209fcad86"><a href="#cb1-25-5209fcad86"></a></span>
<span id="cb1-26-5209fcad86"><a href="#cb1-26-5209fcad86"></a> <span class="kw">def</span> push(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-27-5209fcad86"><a href="#cb1-27-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Add a new element to the top of this stack.</span></span>
<span id="cb1-28-5209fcad86"><a href="#cb1-28-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-29-5209fcad86"><a href="#cb1-29-5209fcad86"></a></span>
<span id="cb1-30-5209fcad86"><a href="#cb1-30-5209fcad86"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb1-31-5209fcad86"><a href="#cb1-31-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Remove and return the element at the top of this stack.</span></span>
<span id="cb1-32-5209fcad86"><a href="#cb1-32-5209fcad86"></a></span>
<span id="cb1-33-5209fcad86"><a href="#cb1-33-5209fcad86"></a><span class="co"> Preconditions:</span></span>
<span id="cb1-34-5209fcad86"><a href="#cb1-34-5209fcad86"></a><span class="co"> - not self.is_empty()</span></span>
<span id="cb1-35-5209fcad86"><a href="#cb1-35-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>At this point, you may be wondering how we fill in the method bodies, picturing perhaps a <code>list</code> instance attribute to store the items in the stack. But remember, thinking about implementation is irrelevant when you are using an ADT. At this point, you should picture a pile of objects stacked on top of each other—this is enough to understand each of the doctest examples in the above code. Abstraction allows us to separate our understanding of what the Stack ADT is from how it is implemented.</p>
<h2 id="applications-of-stacks-5209fcad86">Applications of stacks</h2>
<p>Because they have so few methods, it may seem like stacks are not that powerful. But in fact, stacks are useful for many things. For instance, they can be used to check for balanced parentheses in a mathematical expression. And consider the execution of a Python program. We have talked about frames that store the names available at a given moment in its execution. What happens when <code>f</code> calls <code>g</code>, which calls <code>h</code>? When <code>h</code> is over, we go back to <code>g</code> and when <code>g</code> is over we go back to <code>f</code>. To make this happen, our frames go on a stack! Hence the names <em>call stack</em> and <em>stack frame</em> from our memory model.</p>
<p>As a more “real world” example, consider the undo feature in many different applications. When we perform an action by mistake and want to undo it, we want to undo <em>the most recent</em> action, and so the Stack ADT is the perfect abstract data type for keeping track of the history of our actions so that we can undo them. A similar application lies in how web browsers store page visits so that we can go back to the most recently-visited page.</p>
<h2 id="implementing-the-stack-adt-using-lists-5209fcad86">Implementing the Stack ADT using lists</h2>
<p>Next, well now implement the Stack ADT using a built-in Python data structure: the <code>list</code>. Weve chosen to use the <em>end</em> of the list to represent the top of the stack.</p>
<div class="sourceCode" id="cb2-5209fcad86"><pre class="sourceCode python fullwidth"><code class="sourceCode python"><span id="cb2-1-5209fcad86"><a href="#cb2-1-5209fcad86"></a><span class="kw">class</span> Stack1:</span>
<span id="cb2-2-5209fcad86"><a href="#cb2-2-5209fcad86"></a> <span class="co">&quot;&quot;&quot;A last-in-first-out (LIFO) stack of items.</span></span>
<span id="cb2-3-5209fcad86"><a href="#cb2-3-5209fcad86"></a></span>
<span id="cb2-4-5209fcad86"><a href="#cb2-4-5209fcad86"></a><span class="co"> Stores data in first-in, last-out order. When removing an item from the</span></span>
<span id="cb2-5-5209fcad86"><a href="#cb2-5-5209fcad86"></a><span class="co"> stack, the most recently-added item is the one that is removed.</span></span>
<span id="cb2-6-5209fcad86"><a href="#cb2-6-5209fcad86"></a></span>
<span id="cb2-7-5209fcad86"><a href="#cb2-7-5209fcad86"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb2-8-5209fcad86"><a href="#cb2-8-5209fcad86"></a><span class="co"> - items: The items stored in the stack. The end of the list represents</span></span>
<span id="cb2-9-5209fcad86"><a href="#cb2-9-5209fcad86"></a><span class="co"> the top of the stack.</span></span>
<span id="cb2-10-5209fcad86"><a href="#cb2-10-5209fcad86"></a></span>
<span id="cb2-11-5209fcad86"><a href="#cb2-11-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s = Stack1()</span></span>
<span id="cb2-12-5209fcad86"><a href="#cb2-12-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.is_empty()</span></span>
<span id="cb2-13-5209fcad86"><a href="#cb2-13-5209fcad86"></a><span class="co"> True</span></span>
<span id="cb2-14-5209fcad86"><a href="#cb2-14-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.push(&#39;hello&#39;)</span></span>
<span id="cb2-15-5209fcad86"><a href="#cb2-15-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.is_empty()</span></span>
<span id="cb2-16-5209fcad86"><a href="#cb2-16-5209fcad86"></a><span class="co"> False</span></span>
<span id="cb2-17-5209fcad86"><a href="#cb2-17-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.push(&#39;goodbye&#39;)</span></span>
<span id="cb2-18-5209fcad86"><a href="#cb2-18-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.pop()</span></span>
<span id="cb2-19-5209fcad86"><a href="#cb2-19-5209fcad86"></a><span class="co"> &#39;goodbye&#39;</span></span>
<span id="cb2-20-5209fcad86"><a href="#cb2-20-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-21-5209fcad86"><a href="#cb2-21-5209fcad86"></a> items: <span class="bu">list</span></span>
<span id="cb2-22-5209fcad86"><a href="#cb2-22-5209fcad86"></a></span>
<span id="cb2-23-5209fcad86"><a href="#cb2-23-5209fcad86"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-24-5209fcad86"><a href="#cb2-24-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Initialize a new empty stack.</span></span>
<span id="cb2-25-5209fcad86"><a href="#cb2-25-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-26-5209fcad86"><a href="#cb2-26-5209fcad86"></a> <span class="va">self</span>.items <span class="op">=</span> []</span>
<span id="cb2-27-5209fcad86"><a href="#cb2-27-5209fcad86"></a></span>
<span id="cb2-28-5209fcad86"><a href="#cb2-28-5209fcad86"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-29-5209fcad86"><a href="#cb2-29-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Return whether this stack contains no items.</span></span>
<span id="cb2-30-5209fcad86"><a href="#cb2-30-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-31-5209fcad86"><a href="#cb2-31-5209fcad86"></a> <span class="cf">return</span> <span class="va">self</span>.items <span class="op">==</span> []</span>
<span id="cb2-32-5209fcad86"><a href="#cb2-32-5209fcad86"></a></span>
<span id="cb2-33-5209fcad86"><a href="#cb2-33-5209fcad86"></a> <span class="kw">def</span> push(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-34-5209fcad86"><a href="#cb2-34-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Add a new element to the top of this stack.</span></span>
<span id="cb2-35-5209fcad86"><a href="#cb2-35-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-36-5209fcad86"><a href="#cb2-36-5209fcad86"></a> <span class="va">self</span>.items.append(item)</span>
<span id="cb2-37-5209fcad86"><a href="#cb2-37-5209fcad86"></a></span>
<span id="cb2-38-5209fcad86"><a href="#cb2-38-5209fcad86"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb2-39-5209fcad86"><a href="#cb2-39-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Remove and return the element at the top of this stack.</span></span>
<span id="cb2-40-5209fcad86"><a href="#cb2-40-5209fcad86"></a></span>
<span id="cb2-41-5209fcad86"><a href="#cb2-41-5209fcad86"></a><span class="co"> Preconditions:</span></span>
<span id="cb2-42-5209fcad86"><a href="#cb2-42-5209fcad86"></a><span class="co"> - not self.is_empty()</span></span>
<span id="cb2-43-5209fcad86"><a href="#cb2-43-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-44-5209fcad86"><a href="#cb2-44-5209fcad86"></a> <span class="cf">return</span> <span class="va">self</span>.items.pop()</span></code></pre></div>
<h2 id="attributes-and-the-class-interface-5209fcad86">Attributes and the class interface</h2>
<p>Our current <code>Stack1</code> class is correct, but has one subtle difference with the Stack ADT it is supposed to implement. While a user can create a new <code>Stack1</code> object and call its methods <code>push</code> and <code>pop</code> to interact with it, they can also do one more thing: access the <code>items</code> instance attribute. This means that any user of a <code>Stack1</code> object can access any item in the stack at any time, or even mutate <code>items</code> to modify the contents of the stack in unexpected ways.</p>
<p>You might wonder why this is an issue—if a user wants to change the <code>items</code> attribute, let them! And indeed this is a common and valid approach in programming, particularly in favour with many Python developers. However, it is not the only approach. Another school of thought is that a data types interface should communicate not just how to use it, but also how <em>not</em> to use it. For our current <code>Stack1</code> implementation, the instance attribute <code>items</code> is part of the class interface, and so all users can reasonably expect to use it.</p>
<p>To make an instance attribute that <em>isnt</em> part of a class interface, we prefix its name with an underscore <code>_</code>. We refer to attributes whose names begin with an underscore as <strong>private instance attributes</strong>, and those without the underscore (all the attributes weve seen so far) as <strong>public instance attributes</strong>. These names suggest how theyre interpreted when it comes to a class interface: all public instance attributes are part of the interface, and all private ones arent.</p>
<p>Heres how we could modify our <code>Stack1</code> implementation to make <code>items</code> a private attribute instead.</p>
<div class="sourceCode" id="cb3-5209fcad86"><pre class="sourceCode python fullwidth"><code class="sourceCode python"><span id="cb3-1-5209fcad86"><a href="#cb3-1-5209fcad86"></a><span class="kw">class</span> Stack1:</span>
<span id="cb3-2-5209fcad86"><a href="#cb3-2-5209fcad86"></a> <span class="co">&quot;&quot;&quot;A last-in-first-out (LIFO) stack of items.</span></span>
<span id="cb3-3-5209fcad86"><a href="#cb3-3-5209fcad86"></a></span>
<span id="cb3-4-5209fcad86"><a href="#cb3-4-5209fcad86"></a><span class="co"> Stores data in first-in, last-out order. When removing an item from the</span></span>
<span id="cb3-5-5209fcad86"><a href="#cb3-5-5209fcad86"></a><span class="co"> stack, the most recently-added item is the one that is removed.</span></span>
<span id="cb3-6-5209fcad86"><a href="#cb3-6-5209fcad86"></a></span>
<span id="cb3-7-5209fcad86"><a href="#cb3-7-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s = Stack1()</span></span>
<span id="cb3-8-5209fcad86"><a href="#cb3-8-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.is_empty()</span></span>
<span id="cb3-9-5209fcad86"><a href="#cb3-9-5209fcad86"></a><span class="co"> True</span></span>
<span id="cb3-10-5209fcad86"><a href="#cb3-10-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.push(&#39;hello&#39;)</span></span>
<span id="cb3-11-5209fcad86"><a href="#cb3-11-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.is_empty()</span></span>
<span id="cb3-12-5209fcad86"><a href="#cb3-12-5209fcad86"></a><span class="co"> False</span></span>
<span id="cb3-13-5209fcad86"><a href="#cb3-13-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.push(&#39;goodbye&#39;)</span></span>
<span id="cb3-14-5209fcad86"><a href="#cb3-14-5209fcad86"></a><span class="co"> &gt;&gt;&gt; s.pop()</span></span>
<span id="cb3-15-5209fcad86"><a href="#cb3-15-5209fcad86"></a><span class="co"> &#39;goodbye&#39;</span></span>
<span id="cb3-16-5209fcad86"><a href="#cb3-16-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-17-5209fcad86"><a href="#cb3-17-5209fcad86"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb3-18-5209fcad86"><a href="#cb3-18-5209fcad86"></a> <span class="co"># - _items: The items stored in the stack. The end of the list represents</span></span>
<span id="cb3-19-5209fcad86"><a href="#cb3-19-5209fcad86"></a> <span class="co"># the top of the stack.</span></span>
<span id="cb3-20-5209fcad86"><a href="#cb3-20-5209fcad86"></a> _items: <span class="bu">list</span></span>
<span id="cb3-21-5209fcad86"><a href="#cb3-21-5209fcad86"></a></span>
<span id="cb3-22-5209fcad86"><a href="#cb3-22-5209fcad86"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-23-5209fcad86"><a href="#cb3-23-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Initialize a new empty stack.</span></span>
<span id="cb3-24-5209fcad86"><a href="#cb3-24-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-25-5209fcad86"><a href="#cb3-25-5209fcad86"></a> <span class="va">self</span>._items <span class="op">=</span> []</span>
<span id="cb3-26-5209fcad86"><a href="#cb3-26-5209fcad86"></a></span>
<span id="cb3-27-5209fcad86"><a href="#cb3-27-5209fcad86"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb3-28-5209fcad86"><a href="#cb3-28-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Return whether this stack contains no items.</span></span>
<span id="cb3-29-5209fcad86"><a href="#cb3-29-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-30-5209fcad86"><a href="#cb3-30-5209fcad86"></a> <span class="cf">return</span> <span class="va">self</span>._items <span class="op">==</span> []</span>
<span id="cb3-31-5209fcad86"><a href="#cb3-31-5209fcad86"></a></span>
<span id="cb3-32-5209fcad86"><a href="#cb3-32-5209fcad86"></a> <span class="kw">def</span> push(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-33-5209fcad86"><a href="#cb3-33-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Add a new element to the top of this stack.</span></span>
<span id="cb3-34-5209fcad86"><a href="#cb3-34-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-35-5209fcad86"><a href="#cb3-35-5209fcad86"></a> <span class="va">self</span>._items.append(item)</span>
<span id="cb3-36-5209fcad86"><a href="#cb3-36-5209fcad86"></a></span>
<span id="cb3-37-5209fcad86"><a href="#cb3-37-5209fcad86"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb3-38-5209fcad86"><a href="#cb3-38-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Remove and return the element at the top of this stack.</span></span>
<span id="cb3-39-5209fcad86"><a href="#cb3-39-5209fcad86"></a></span>
<span id="cb3-40-5209fcad86"><a href="#cb3-40-5209fcad86"></a><span class="co"> Preconditions:</span></span>
<span id="cb3-41-5209fcad86"><a href="#cb3-41-5209fcad86"></a><span class="co"> - not self.is_empty()</span></span>
<span id="cb3-42-5209fcad86"><a href="#cb3-42-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-43-5209fcad86"><a href="#cb3-43-5209fcad86"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop()</span></code></pre></div>
<p>Other than renaming the attribute from <code>items</code> to <code>_items</code>, the only change is in how we document this attribute. Weve kept the same format, but now moved the description from the class docstring to comments in the class body. By doing so, there is now no mention of this attribute when we call <code>help</code> on our class:</p>
<div class="sourceCode" id="cb4-5209fcad86"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-5209fcad86"><a href="#cb4-1-5209fcad86"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">help</span>(Stack1)</span>
<span id="cb4-2-5209fcad86"><a href="#cb4-2-5209fcad86"></a><span class="kw">class</span> Stack1(builtins.<span class="bu">object</span>)</span>
<span id="cb4-3-5209fcad86"><a href="#cb4-3-5209fcad86"></a> <span class="op">|</span> Stack1() <span class="op">-&gt;</span> <span class="va">None</span></span>
<span id="cb4-4-5209fcad86"><a href="#cb4-4-5209fcad86"></a> <span class="op">|</span></span>
<span id="cb4-5-5209fcad86"><a href="#cb4-5-5209fcad86"></a> <span class="op">|</span> A last<span class="op">-</span><span class="kw">in</span><span class="op">-</span>first<span class="op">-</span>out (LIFO) stack of items.</span>
<span id="cb4-6-5209fcad86"><a href="#cb4-6-5209fcad86"></a> <span class="op">|</span></span>
<span id="cb4-7-5209fcad86"><a href="#cb4-7-5209fcad86"></a> <span class="op">|</span> Stores data <span class="kw">in</span> a last<span class="op">-</span><span class="kw">in</span>, first<span class="op">-</span>out order. When removing an item <span class="im">from</span> the</span>
<span id="cb4-8-5209fcad86"><a href="#cb4-8-5209fcad86"></a> <span class="op">|</span> stack, the most recently<span class="op">-</span>added item <span class="kw">is</span> the one that <span class="kw">is</span> removed.</span>
<span id="cb4-9-5209fcad86"><a href="#cb4-9-5209fcad86"></a> <span class="op">|</span></span>
<span id="cb4-10-5209fcad86"><a href="#cb4-10-5209fcad86"></a> <span class="op">|</span> <span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> Stack1()</span>
<span id="cb4-11-5209fcad86"><a href="#cb4-11-5209fcad86"></a> <span class="op">|</span> <span class="op">&gt;&gt;&gt;</span> s.is_empty()</span>
<span id="cb4-12-5209fcad86"><a href="#cb4-12-5209fcad86"></a> <span class="op">|</span> <span class="va">True</span></span>
<span id="cb4-13-5209fcad86"><a href="#cb4-13-5209fcad86"></a> <span class="op">|</span> <span class="op">&gt;&gt;&gt;</span> s.push(<span class="st">&#39;hello&#39;</span>)</span>
<span id="cb4-14-5209fcad86"><a href="#cb4-14-5209fcad86"></a> <span class="op">|</span> <span class="op">&gt;&gt;&gt;</span> s.is_empty()</span>
<span id="cb4-15-5209fcad86"><a href="#cb4-15-5209fcad86"></a> <span class="op">|</span> <span class="va">False</span></span>
<span id="cb4-16-5209fcad86"><a href="#cb4-16-5209fcad86"></a> <span class="op">|</span> <span class="op">&gt;&gt;&gt;</span> s.push(<span class="st">&#39;goodbye&#39;</span>)</span>
<span id="cb4-17-5209fcad86"><a href="#cb4-17-5209fcad86"></a> <span class="op">|</span> <span class="op">&gt;&gt;&gt;</span> s.pop()</span>
<span id="cb4-18-5209fcad86"><a href="#cb4-18-5209fcad86"></a> <span class="op">|</span> <span class="st">&#39;goodbye&#39;</span></span>
<span id="cb4-19-5209fcad86"><a href="#cb4-19-5209fcad86"></a> <span class="op">|</span></span>
<span id="cb4-20-5209fcad86"><a href="#cb4-20-5209fcad86"></a> <span class="op">|</span> [The rest <span class="kw">is</span> omitted]</span>
<span id="cb4-21-5209fcad86"><a href="#cb4-21-5209fcad86"></a> <span class="op">|</span></span></code></pre></div>
<h3 id="warning-private-attributes-can-be-accessed-5209fcad86">Warning: private attributes can be accessed!</h3>
<p>One of the distinctive features of Python that separates it from many other programming languages is that private instance attributes can still be accessed from outside the class.</p>
<div class="sourceCode" id="cb5-5209fcad86"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-5209fcad86"><a href="#cb5-1-5209fcad86"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> Stack1()</span>
<span id="cb5-2-5209fcad86"><a href="#cb5-2-5209fcad86"></a><span class="op">&gt;&gt;&gt;</span> s.push(<span class="dv">10</span>)</span>
<span id="cb5-3-5209fcad86"><a href="#cb5-3-5209fcad86"></a><span class="op">&gt;&gt;&gt;</span> s.push(<span class="dv">20</span>)</span>
<span id="cb5-4-5209fcad86"><a href="#cb5-4-5209fcad86"></a><span class="op">&gt;&gt;&gt;</span> s._items</span>
<span id="cb5-5-5209fcad86"><a href="#cb5-5-5209fcad86"></a>[<span class="dv">10</span>, <span class="dv">20</span>]</span></code></pre></div>
<p>This is a design choice made by the creators of the Python programming language to prefer <em>flexibility</em> over <em>restriction</em> when it comes to accessing attributes. But does this mean private attributes are meaningless? <em>No!</em> By making an instance attribute private, we are communicating that client code should <em>not</em> access this attribute: it is not an expected way of interacting with this class. As a result, we reduce the cognitive load on the client (one less attribute to think about when using the class), and also give flexibility to the designer of the class to change or even remove a private attribute if they want to update their implementation of the class, without affecting the class public interface.</p>
<h2 id="analyzing-efficiency-5209fcad86">Analyzing efficiency</h2>
<p>We implemented <code>Stack1</code> using the back of the <code>_items</code> list to represent the top of the stack. You might wonder why we didnt use the front of <code>_items</code> instead. Indeed, the implemention wouldnt have to change much:</p>
<div class="sourceCode" id="cb6-5209fcad86"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-5209fcad86"><a href="#cb6-1-5209fcad86"></a><span class="kw">class</span> Stack2:</span>
<span id="cb6-2-5209fcad86"><a href="#cb6-2-5209fcad86"></a> <span class="co"># Duplicated code from Stack1 omitted. Only push and pop are different.</span></span>
<span id="cb6-3-5209fcad86"><a href="#cb6-3-5209fcad86"></a></span>
<span id="cb6-4-5209fcad86"><a href="#cb6-4-5209fcad86"></a> <span class="kw">def</span> push(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-5-5209fcad86"><a href="#cb6-5-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Add a new element to the top of this stack.</span></span>
<span id="cb6-6-5209fcad86"><a href="#cb6-6-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb6-7-5209fcad86"><a href="#cb6-7-5209fcad86"></a> <span class="va">self</span>._items.insert(<span class="dv">0</span>, item)</span>
<span id="cb6-8-5209fcad86"><a href="#cb6-8-5209fcad86"></a></span>
<span id="cb6-9-5209fcad86"><a href="#cb6-9-5209fcad86"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb6-10-5209fcad86"><a href="#cb6-10-5209fcad86"></a> <span class="co">&quot;&quot;&quot;Remove and return the element at the top of this stack.</span></span>
<span id="cb6-11-5209fcad86"><a href="#cb6-11-5209fcad86"></a></span>
<span id="cb6-12-5209fcad86"><a href="#cb6-12-5209fcad86"></a><span class="co"> Preconditions:</span></span>
<span id="cb6-13-5209fcad86"><a href="#cb6-13-5209fcad86"></a><span class="co"> - not self.is_empty()</span></span>
<span id="cb6-14-5209fcad86"><a href="#cb6-14-5209fcad86"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb6-15-5209fcad86"><a href="#cb6-15-5209fcad86"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop(<span class="dv">0</span>)</span></code></pre></div>
<p>The key difference between <code>Stack1</code> and <code>Stack2</code> is not their code complexity but their <em>efficiency</em>. In Chapter 8, we learned that Python uses an array-based implementation for lists. Because of this, the <code>list.append</code> operation for an array-based list is <span class="math inline">\(\Theta(1)\)</span>, therefore <code>Stack1.push</code> is also <span class="math inline">\(\Theta(1)\)</span>. In contrast, <code>list.insert</code> has complexity <span class="math inline">\(\Theta(n - i)\)</span>, where <span class="math inline">\(i\)</span> is the index argument passed to <code>list.insert</code>. In <code>Stack2.push</code>, <span class="math inline">\(i = 0\)</span> and so the method has complexity <span class="math inline">\(\Theta(n)\)</span>. So the <code>push</code> operation for stacks is more efficient when we treat the end of an array-based list as the top of the stack.</p>
<p>Similarly, removing the last element of an array-based list using <code>list.pop</code> is also <span class="math inline">\(\Theta(1)\)</span>, and so the running time of <code>Stack1.pop</code> is <span class="math inline">\(\Theta(1)\)</span>. However, <code>Stack2.pop</code> uses passes an index of 0 to <code>list.pop</code>, which causes the method to have a <span class="math inline">\(\Theta(n)\)</span> running time.</p>
<p>The decision of which implementation has superior efficiency is clear: <code>Stack1</code> will always be more efficient than <code>Stack2</code>. Having such a clear-cut winner is actually quite rare. There are almost always trade-offs associated with choosing one implementation over another. We will see one such trade-off when we introduce our next ADT: queues.</p>
</section>
<!--
If a client creates a `Stack` object in their code, they know
there are exactly three operations that can be performed on it:
checking whether it's empty, pushing an item onto it, and popping an item from it.
This reduces cognitive load for the programmer dramatically.
Modern, complex software would be impossible otherwise.
-->
<br/> <a id="anchor-09-05"></a>
<header id="title-block-header-97e9e07b9b">
<h1 class="title">9.5 Exceptions as a Part of the Public Interface</h1>
</header>
<section>
<p>The stack implementations we studied in the previous section included a precondition on their <code>pop</code> method specifying that the stack must not be empty. Preconditions are used to rule out erroneous situations like attempting to remove an item from an empty stack, but they come with one drawback: every precondition we add increases the complexity of the functions interface. A precondition becomes the responsibility of the <em>user</em> of the function to check, for example, with code like</p>
<div class="sourceCode" id="cb1-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-97e9e07b9b"><a href="#cb1-1-97e9e07b9b"></a><span class="cf">if</span> <span class="kw">not</span> my_stack.is_empty():</span>
<span id="cb1-2-97e9e07b9b"><a href="#cb1-2-97e9e07b9b"></a> top_item <span class="op">=</span> my_stack.pop()</span></code></pre></div>
<p>Sometimes these checks are straightforward, but depending on the preconditions we specify, they can be onerous as well. In this section, well introduce an alternate mechanism for signaling an erroneous state from within a function call.</p>
<h2 id="warm-up-letting-an-error-happen-97e9e07b9b">Warm-up: letting an error happen</h2>
<p>Consider this version of <code>Stack.pop</code>, which removes the precondition but keeps the same implementation:</p>
<div class="sourceCode" id="cb2-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-97e9e07b9b"><a href="#cb2-1-97e9e07b9b"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb2-2-97e9e07b9b"><a href="#cb2-2-97e9e07b9b"></a> <span class="co">&quot;&quot;&quot;Remove and return the element at the top of this stack.</span></span>
<span id="cb2-3-97e9e07b9b"><a href="#cb2-3-97e9e07b9b"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-4-97e9e07b9b"><a href="#cb2-4-97e9e07b9b"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop()</span></code></pre></div>
<p>When we call <code>pop</code> on an empty stack, we encounter the following error:</p>
<div class="sourceCode" id="cb3-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-97e9e07b9b"><a href="#cb3-1-97e9e07b9b"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> Stack()</span>
<span id="cb3-2-97e9e07b9b"><a href="#cb3-2-97e9e07b9b"></a><span class="op">&gt;&gt;&gt;</span> s.pop()</span>
<span id="cb3-3-97e9e07b9b"><a href="#cb3-3-97e9e07b9b"></a>Traceback (most recent call last):</span>
<span id="cb3-4-97e9e07b9b"><a href="#cb3-4-97e9e07b9b"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb3-5-97e9e07b9b"><a href="#cb3-5-97e9e07b9b"></a> File <span class="st">&quot;...&quot;</span>, line <span class="dv">58</span>, <span class="kw">in</span> pop</span>
<span id="cb3-6-97e9e07b9b"><a href="#cb3-6-97e9e07b9b"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop()</span>
<span id="cb3-7-97e9e07b9b"><a href="#cb3-7-97e9e07b9b"></a><span class="pp">IndexError</span>: pop <span class="im">from</span> empty <span class="bu">list</span></span></code></pre></div>
<p>As we saw earlier in the course, when an exception is raised Python stops the normal control flow of the currently running program. From the perspective of the client code, it is good to see an exception to know that something has gone wrong, but bad that the exceptions report refers to a list (<code>IndexError: pop from empty list</code>) and a private attribute (<code>self._items</code>) that the client code should have no knowledge of.</p>
<h2 id="custom-exceptions-97e9e07b9b">Custom exceptions</h2>
<p>A better solution is to raise a custom exception that is descriptive, yet does not reveal any implementation details. We can achieve this very easily in Python: we define our own type of error by defining a new class:</p>
<div class="sourceCode" id="cb4-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-97e9e07b9b"><a href="#cb4-1-97e9e07b9b"></a><span class="kw">class</span> EmptyStackError(<span class="pp">Exception</span>):</span>
<span id="cb4-2-97e9e07b9b"><a href="#cb4-2-97e9e07b9b"></a> <span class="co">&quot;&quot;&quot;Exception raised when calling pop on an empty stack.&quot;&quot;&quot;</span></span></code></pre></div>
<p>There is some slightly new syntax here: the <code>(Exception)</code> that follows the class name. For now, it is enough to know that this will properly create a new type of exception. The technical mechanism used, <em>inheritance</em>, is one well cover later in this chapter.</p>
<p>Heres how well use <code>EmptyStackError</code> in our <code>pop</code> method:</p>
<div class="sourceCode" id="cb5-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-97e9e07b9b"><a href="#cb5-1-97e9e07b9b"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb5-2-97e9e07b9b"><a href="#cb5-2-97e9e07b9b"></a> <span class="co">&quot;&quot;&quot;Remove and return the element at the top of this stack.</span></span>
<span id="cb5-3-97e9e07b9b"><a href="#cb5-3-97e9e07b9b"></a></span>
<span id="cb5-4-97e9e07b9b"><a href="#cb5-4-97e9e07b9b"></a><span class="co"> Raise an EmptyStackError if this stack is empty.</span></span>
<span id="cb5-5-97e9e07b9b"><a href="#cb5-5-97e9e07b9b"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-6-97e9e07b9b"><a href="#cb5-6-97e9e07b9b"></a> <span class="cf">if</span> <span class="va">self</span>.is_empty():</span>
<span id="cb5-7-97e9e07b9b"><a href="#cb5-7-97e9e07b9b"></a> <span class="cf">raise</span> EmptyStackError</span>
<span id="cb5-8-97e9e07b9b"><a href="#cb5-8-97e9e07b9b"></a> <span class="cf">else</span>:</span>
<span id="cb5-9-97e9e07b9b"><a href="#cb5-9-97e9e07b9b"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop()</span></code></pre></div>
<p>There are two important changes in this version of <code>pop</code>. First, in the method docstring there is a new sentence which names both the type of exception and the scenario that will cause that exception to be raised. This exception is now part of the <em>public interface</em> of <code>Stack.pop</code>, meaning users of this class will be expected to take note of this exception. Second, this implementation now uses a new Python keyword, <code>raise</code>, which unsurprisingly raises an exception.<label for="sn-0-97e9e07b9b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-97e9e07b9b" class="margin-toggle"/><span class="sidenote"> Even though were using our custom exception class here, <code>raise</code> works with any exception type, such as <code>IndexError</code> and <code>AttributeError</code>.</span> A raise statement can be used anywhere in our code to raise exceptions, even ones that weve defined ourselves. Lets see what happens now when we call <code>pop</code> on an empty stack:</p>
<div class="sourceCode" id="cb6-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-97e9e07b9b"><a href="#cb6-1-97e9e07b9b"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> Stack()</span>
<span id="cb6-2-97e9e07b9b"><a href="#cb6-2-97e9e07b9b"></a><span class="op">&gt;&gt;&gt;</span> s.pop()</span>
<span id="cb6-3-97e9e07b9b"><a href="#cb6-3-97e9e07b9b"></a>Traceback (most recent call last):</span>
<span id="cb6-4-97e9e07b9b"><a href="#cb6-4-97e9e07b9b"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb6-5-97e9e07b9b"><a href="#cb6-5-97e9e07b9b"></a> File <span class="st">&quot;...&quot;</span>, line <span class="dv">60</span>, <span class="kw">in</span> pop</span>
<span id="cb6-6-97e9e07b9b"><a href="#cb6-6-97e9e07b9b"></a> <span class="cf">raise</span> EmptyStackError</span>
<span id="cb6-7-97e9e07b9b"><a href="#cb6-7-97e9e07b9b"></a>EmptyStackError</span></code></pre></div>
<p>As before, an exception is raised. But now the line shown is just this simple <code>raise</code> statement; it doesnt mention any implementation details of the class. And it specifies that an <code>EmptyStackError</code> was the problem, as was documented in the method docstring.</p>
<h3 id="custom-exception-messages-97e9e07b9b">Custom exception messages</h3>
<p>One current limitation of the above approach is that simply the name of the exception class does not convey a lot of meaning. To provide a custom exception message, we can define a new special method with the name <code>__str__</code> in our exception class:<label for="sn-1-97e9e07b9b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-97e9e07b9b" class="margin-toggle"/><span class="sidenote"> Like <code>__init__</code>, the name <code>__str__</code> has special meaning in Python. Well study it and more methods like it later in the course.</span></p>
<div class="sourceCode" id="cb7-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-97e9e07b9b"><a href="#cb7-1-97e9e07b9b"></a><span class="kw">class</span> EmptyStackError(<span class="pp">Exception</span>):</span>
<span id="cb7-2-97e9e07b9b"><a href="#cb7-2-97e9e07b9b"></a> <span class="co">&quot;&quot;&quot;Exception raised when calling pop on an empty stack.&quot;&quot;&quot;</span></span>
<span id="cb7-3-97e9e07b9b"><a href="#cb7-3-97e9e07b9b"></a></span>
<span id="cb7-4-97e9e07b9b"><a href="#cb7-4-97e9e07b9b"></a> <span class="kw">def</span> <span class="fu">__str__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb7-5-97e9e07b9b"><a href="#cb7-5-97e9e07b9b"></a> <span class="co">&quot;&quot;&quot;Return a string representation of this error.&quot;&quot;&quot;</span></span>
<span id="cb7-6-97e9e07b9b"><a href="#cb7-6-97e9e07b9b"></a> <span class="cf">return</span> <span class="st">&#39;pop may not be called on an empty stack&#39;</span></span>
<span id="cb7-7-97e9e07b9b"><a href="#cb7-7-97e9e07b9b"></a></span>
<span id="cb7-8-97e9e07b9b"><a href="#cb7-8-97e9e07b9b"></a></span>
<span id="cb7-9-97e9e07b9b"><a href="#cb7-9-97e9e07b9b"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> Stack()</span>
<span id="cb7-10-97e9e07b9b"><a href="#cb7-10-97e9e07b9b"></a><span class="op">&gt;&gt;&gt;</span> s.pop()</span>
<span id="cb7-11-97e9e07b9b"><a href="#cb7-11-97e9e07b9b"></a>Traceback (most recent call last):</span>
<span id="cb7-12-97e9e07b9b"><a href="#cb7-12-97e9e07b9b"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb7-13-97e9e07b9b"><a href="#cb7-13-97e9e07b9b"></a> File <span class="st">&quot;...&quot;</span>, line <span class="dv">60</span>, <span class="kw">in</span> pop</span>
<span id="cb7-14-97e9e07b9b"><a href="#cb7-14-97e9e07b9b"></a> <span class="cf">raise</span> EmptyStackError</span>
<span id="cb7-15-97e9e07b9b"><a href="#cb7-15-97e9e07b9b"></a>EmptyStackError: pop may <span class="kw">not</span> be called on an empty stack</span></code></pre></div>
<h2 id="testing-exceptions-97e9e07b9b">Testing exceptions</h2>
<p>Because we include <code>EmptyStackError</code> as part of the public interface of the <code>Stack.pop</code> method, we should write tests to check that this behaviour occurs as expected. But unlike the tests weve written so far, we cannot simply call <code>pop</code> on an empty stack and check the return value or the state of the stack after <code>pop</code> returns. Raising an error interrupts the regular control flow of a Python program—and this includes test cases!</p>
<p>The <code>pytest</code> module<label for="sn-2-97e9e07b9b" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-97e9e07b9b" class="margin-toggle"/><span class="sidenote"> It is also possible to write doctests that check for exceptions. See <a href="../B-Python-libraries/01-doctest.html">Appendix B.1</a> for details.</span> allows us to write tests that expects an exception to occur using a function <code>pytest.raises</code> together with the <code>with</code> keyword: Here is an example of a test case to check that calling <code>Stack.pop</code> on an empty stack raises an <code>EmptyStackError</code>.</p>
<div class="sourceCode" id="cb8-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-97e9e07b9b"><a href="#cb8-1-97e9e07b9b"></a><span class="co"># Assuming our stack implementation is contained in a file stack.py.</span></span>
<span id="cb8-2-97e9e07b9b"><a href="#cb8-2-97e9e07b9b"></a><span class="im">from</span> stack <span class="im">import</span> Stack, EmptyStackError</span>
<span id="cb8-3-97e9e07b9b"><a href="#cb8-3-97e9e07b9b"></a><span class="im">import</span> pytest</span>
<span id="cb8-4-97e9e07b9b"><a href="#cb8-4-97e9e07b9b"></a></span>
<span id="cb8-5-97e9e07b9b"><a href="#cb8-5-97e9e07b9b"></a></span>
<span id="cb8-6-97e9e07b9b"><a href="#cb8-6-97e9e07b9b"></a><span class="kw">def</span> test_empty_stack_error():</span>
<span id="cb8-7-97e9e07b9b"><a href="#cb8-7-97e9e07b9b"></a> <span class="co">&quot;&quot;&quot;Test that popping from an empty stack raises an exception.&quot;&quot;&quot;</span></span>
<span id="cb8-8-97e9e07b9b"><a href="#cb8-8-97e9e07b9b"></a> s <span class="op">=</span> Stack()</span>
<span id="cb8-9-97e9e07b9b"><a href="#cb8-9-97e9e07b9b"></a></span>
<span id="cb8-10-97e9e07b9b"><a href="#cb8-10-97e9e07b9b"></a> <span class="cf">with</span> pytest.raises(EmptyStackError):</span>
<span id="cb8-11-97e9e07b9b"><a href="#cb8-11-97e9e07b9b"></a> s.pop()</span></code></pre></div>
<p>The <code>with</code> keyword acts as an assertion, expecting an <code>EmptyStackError</code> to be raised by the body of the <code>with</code> block, the function call <code>s.pop()</code>. The test <em>passes</em> when that exception is raised, and <em>fails</em> when that exception is not raised (this includes the case when a different exception is raised instead of the expected one).</p>
<h2 id="handling-exceptions-97e9e07b9b">Handling exceptions</h2>
<p>Weve said repeatedly that when an exception is raised, the normal execution of the program is stopped, and the exception is reported to the user. However, <code>pytest.raises</code> seems to circumvent this: after an <code>EmptyStackError</code> is raised in our test, the test simply <em>passes</em> and execution proceeds to the next test. How does <code>pytest.raises</code> achieve this?</p>
<p>Python provides a compound statement, the <strong>try-except</strong> statement, to execute a block of code and handle a case where one or more pre-specified exceptions are raised in that block. Here is the simplest form of a try-except statement:</p>
<div class="sourceCode" id="cb9-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-97e9e07b9b"><a href="#cb9-1-97e9e07b9b"></a><span class="cf">try</span>:</span>
<span id="cb9-2-97e9e07b9b"><a href="#cb9-2-97e9e07b9b"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb9-3-97e9e07b9b"><a href="#cb9-3-97e9e07b9b"></a> ...</span>
<span id="cb9-4-97e9e07b9b"><a href="#cb9-4-97e9e07b9b"></a><span class="cf">except</span> <span class="op">&lt;</span>ExceptionClass<span class="op">&gt;</span>:</span>
<span id="cb9-5-97e9e07b9b"><a href="#cb9-5-97e9e07b9b"></a> <span class="op">&lt;</span>statement<span class="op">&gt;</span></span>
<span id="cb9-6-97e9e07b9b"><a href="#cb9-6-97e9e07b9b"></a> ...</span></code></pre></div>
<p>When a try-except statement is executed:</p>
<ol type="1">
<li><p>First, the block of code indented within the <code>try</code> is executed.</p></li>
<li><p>If no exception occurs when executing this block, the <code>except</code> part is skipped, and the Python interpreter continues to the next statement after the try-except.</p></li>
<li><p>If an exception occurs when executing this block:</p>
<ul>
<li><p>If the exception has type <code>&lt;ExceptionClass&gt;</code>, the block under the <code>except</code> is executed, and then after that the Python interpreter continues executing the next statement after the try-except.</p>
<p>Importantly, in this case the program does <em>not</em> immediately halt!</p></li>
<li><p>However, if the exception is a different type, this does stop the normal program execution.</p></li>
</ul></li>
</ol>
<p>In practice, client code often uses try-except statements to call functions that may raise an error as part of their public interface. This shields users from seeing errors that they should never see, and allows the rest of the program to continue.</p>
<p>For example, here is how we could implement a function that takes a stack and returns the second item from the top of the stack.</p>
<div class="sourceCode" id="cb10-97e9e07b9b"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-97e9e07b9b"><a href="#cb10-1-97e9e07b9b"></a><span class="kw">def</span> second_from_top(s: Stack) <span class="op">-&gt;</span> Optional[<span class="bu">str</span>]:</span>
<span id="cb10-2-97e9e07b9b"><a href="#cb10-2-97e9e07b9b"></a> <span class="co">&quot;&quot;&quot;Return the item that is second from the top of s.</span></span>
<span id="cb10-3-97e9e07b9b"><a href="#cb10-3-97e9e07b9b"></a></span>
<span id="cb10-4-97e9e07b9b"><a href="#cb10-4-97e9e07b9b"></a><span class="co"> If there is no such item in the Stack, returns None.</span></span>
<span id="cb10-5-97e9e07b9b"><a href="#cb10-5-97e9e07b9b"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb10-6-97e9e07b9b"><a href="#cb10-6-97e9e07b9b"></a> <span class="cf">try</span>:</span>
<span id="cb10-7-97e9e07b9b"><a href="#cb10-7-97e9e07b9b"></a> hold1 <span class="op">=</span> s.pop()</span>
<span id="cb10-8-97e9e07b9b"><a href="#cb10-8-97e9e07b9b"></a> <span class="cf">except</span> EmptyStackError:</span>
<span id="cb10-9-97e9e07b9b"><a href="#cb10-9-97e9e07b9b"></a> <span class="co"># In this case, s is empty. We can return None.</span></span>
<span id="cb10-10-97e9e07b9b"><a href="#cb10-10-97e9e07b9b"></a> <span class="cf">return</span> <span class="va">None</span></span>
<span id="cb10-11-97e9e07b9b"><a href="#cb10-11-97e9e07b9b"></a></span>
<span id="cb10-12-97e9e07b9b"><a href="#cb10-12-97e9e07b9b"></a> <span class="cf">try</span>:</span>
<span id="cb10-13-97e9e07b9b"><a href="#cb10-13-97e9e07b9b"></a> hold2 <span class="op">=</span> s.pop()</span>
<span id="cb10-14-97e9e07b9b"><a href="#cb10-14-97e9e07b9b"></a> <span class="cf">except</span> EmptyStackError:</span>
<span id="cb10-15-97e9e07b9b"><a href="#cb10-15-97e9e07b9b"></a> <span class="co"># In this case, s had only one element.</span></span>
<span id="cb10-16-97e9e07b9b"><a href="#cb10-16-97e9e07b9b"></a> <span class="co"># We restore s to its original state and return None.</span></span>
<span id="cb10-17-97e9e07b9b"><a href="#cb10-17-97e9e07b9b"></a> s.push(hold1)</span>
<span id="cb10-18-97e9e07b9b"><a href="#cb10-18-97e9e07b9b"></a> <span class="cf">return</span> <span class="va">None</span></span>
<span id="cb10-19-97e9e07b9b"><a href="#cb10-19-97e9e07b9b"></a></span>
<span id="cb10-20-97e9e07b9b"><a href="#cb10-20-97e9e07b9b"></a> <span class="co"># If we reach this point, both of the previous s.pop() calls succeeded.</span></span>
<span id="cb10-21-97e9e07b9b"><a href="#cb10-21-97e9e07b9b"></a> <span class="co"># In this case, we restore s to its original state and return the second item.</span></span>
<span id="cb10-22-97e9e07b9b"><a href="#cb10-22-97e9e07b9b"></a> s.push(hold2)</span>
<span id="cb10-23-97e9e07b9b"><a href="#cb10-23-97e9e07b9b"></a> s.push(hold1)</span>
<span id="cb10-24-97e9e07b9b"><a href="#cb10-24-97e9e07b9b"></a></span>
<span id="cb10-25-97e9e07b9b"><a href="#cb10-25-97e9e07b9b"></a> <span class="cf">return</span> hold2</span></code></pre></div>
<h2 id="references-97e9e07b9b">References</h2>
<ul>
<li>CSC108 videos: Exceptions (<a href="https://youtu.be/mhsu6mRKRdE?list=PLfMGJf6SEIv4qYogjAyLyfv3h_NUEKbWd">video</a>)</li>
</ul>
</section>
<br/> <a id="anchor-09-06"></a>
<header id="title-block-header-08117c64fa">
<h1 class="title">9.6 Queues</h1>
</header>
<section>
<p>Picture a lineup at a fast food restaurant. The first person in line is the first one served, then the next person in line, and so forth. As new people join the line, they join at the back, so that everyone who joined before them are served before them. This is the exact opposite of a stack: in this lineup situation, people leave the line in the <em>same</em> order they joined it.</p>
<p>In this section, well introduce a new abstract data type to represent this type of collection, see how to implement it in Python, and analyze our implementations take a close look at the operations a queue supports, how we might implement one in Python, and how efficient our implementation is.</p>
<h2 id="the-queue-adt-08117c64fa">The Queue ADT</h2>
<p>A <strong>queue</strong> is another collection of data that, like a stack, adds and removes items in a fixed order. Unlike a stack, items come out of a queue in the order in which they entered. We call this behaviour <em>First-In-First-Out (FIFO)</em>.</p>
<ul>
<li><p><strong>Queue</strong></p>
<ul>
<li>Data: a collection of items</li>
<li>Operations: determine whether the queue is empty, add an item (<em>enqueue</em>), remove the least recently-added item (<em>dequeue</em>)</li>
</ul></li>
</ul>
<p>In code:</p>
<div class="sourceCode" id="cb1-08117c64fa"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-08117c64fa"><a href="#cb1-1-08117c64fa"></a><span class="kw">class</span> Queue:</span>
<span id="cb1-2-08117c64fa"><a href="#cb1-2-08117c64fa"></a> <span class="co">&quot;&quot;&quot;A first-in-first-out (FIFO) queue of items.</span></span>
<span id="cb1-3-08117c64fa"><a href="#cb1-3-08117c64fa"></a></span>
<span id="cb1-4-08117c64fa"><a href="#cb1-4-08117c64fa"></a><span class="co"> Stores data in a first-in, first-out order. When removing an item from the</span></span>
<span id="cb1-5-08117c64fa"><a href="#cb1-5-08117c64fa"></a><span class="co"> queue, the most recently-added item is the one that is removed.</span></span>
<span id="cb1-6-08117c64fa"><a href="#cb1-6-08117c64fa"></a></span>
<span id="cb1-7-08117c64fa"><a href="#cb1-7-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q = Queue()</span></span>
<span id="cb1-8-08117c64fa"><a href="#cb1-8-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.is_empty()</span></span>
<span id="cb1-9-08117c64fa"><a href="#cb1-9-08117c64fa"></a><span class="co"> True</span></span>
<span id="cb1-10-08117c64fa"><a href="#cb1-10-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.enqueue(&#39;hello&#39;)</span></span>
<span id="cb1-11-08117c64fa"><a href="#cb1-11-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.is_empty()</span></span>
<span id="cb1-12-08117c64fa"><a href="#cb1-12-08117c64fa"></a><span class="co"> False</span></span>
<span id="cb1-13-08117c64fa"><a href="#cb1-13-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.enqueue(&#39;goodbye&#39;)</span></span>
<span id="cb1-14-08117c64fa"><a href="#cb1-14-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.dequeue()</span></span>
<span id="cb1-15-08117c64fa"><a href="#cb1-15-08117c64fa"></a><span class="co"> &#39;hello&#39;</span></span>
<span id="cb1-16-08117c64fa"><a href="#cb1-16-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.dequeue()</span></span>
<span id="cb1-17-08117c64fa"><a href="#cb1-17-08117c64fa"></a><span class="co"> &#39;goodbye&#39;</span></span>
<span id="cb1-18-08117c64fa"><a href="#cb1-18-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.is_empty()</span></span>
<span id="cb1-19-08117c64fa"><a href="#cb1-19-08117c64fa"></a><span class="co"> True</span></span>
<span id="cb1-20-08117c64fa"><a href="#cb1-20-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-21-08117c64fa"><a href="#cb1-21-08117c64fa"></a></span>
<span id="cb1-22-08117c64fa"><a href="#cb1-22-08117c64fa"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-23-08117c64fa"><a href="#cb1-23-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Initialize a new empty queue.&quot;&quot;&quot;</span></span>
<span id="cb1-24-08117c64fa"><a href="#cb1-24-08117c64fa"></a></span>
<span id="cb1-25-08117c64fa"><a href="#cb1-25-08117c64fa"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-26-08117c64fa"><a href="#cb1-26-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Return whether this queue contains no items.</span></span>
<span id="cb1-27-08117c64fa"><a href="#cb1-27-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-28-08117c64fa"><a href="#cb1-28-08117c64fa"></a></span>
<span id="cb1-29-08117c64fa"><a href="#cb1-29-08117c64fa"></a> <span class="kw">def</span> enqueue(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-30-08117c64fa"><a href="#cb1-30-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Add &lt;item&gt; to the back of this queue.</span></span>
<span id="cb1-31-08117c64fa"><a href="#cb1-31-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-32-08117c64fa"><a href="#cb1-32-08117c64fa"></a></span>
<span id="cb1-33-08117c64fa"><a href="#cb1-33-08117c64fa"></a> <span class="kw">def</span> dequeue(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb1-34-08117c64fa"><a href="#cb1-34-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Remove and return the item at the front of this queue.</span></span>
<span id="cb1-35-08117c64fa"><a href="#cb1-35-08117c64fa"></a></span>
<span id="cb1-36-08117c64fa"><a href="#cb1-36-08117c64fa"></a><span class="co"> Raise an EmptyQueueError if this queue is empty.</span></span>
<span id="cb1-37-08117c64fa"><a href="#cb1-37-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-38-08117c64fa"><a href="#cb1-38-08117c64fa"></a></span>
<span id="cb1-39-08117c64fa"><a href="#cb1-39-08117c64fa"></a></span>
<span id="cb1-40-08117c64fa"><a href="#cb1-40-08117c64fa"></a><span class="kw">class</span> EmptyQueueError(<span class="pp">Exception</span>):</span>
<span id="cb1-41-08117c64fa"><a href="#cb1-41-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Exception raised when calling dequeue on an empty queue.&quot;&quot;&quot;</span></span>
<span id="cb1-42-08117c64fa"><a href="#cb1-42-08117c64fa"></a></span>
<span id="cb1-43-08117c64fa"><a href="#cb1-43-08117c64fa"></a> <span class="kw">def</span> <span class="fu">__str__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb1-44-08117c64fa"><a href="#cb1-44-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Return a string representation of this error.&quot;&quot;&quot;</span></span>
<span id="cb1-45-08117c64fa"><a href="#cb1-45-08117c64fa"></a> <span class="cf">return</span> <span class="st">&#39;dequeue may not be called on an empty queue&#39;</span></span></code></pre></div>
<p>Much like a stack, we can also picture implementing this with a Python list. And, once again, we need to decide which end of the list is considered the front. Unlike the stack, we will see that there is a trade-off in choosing which end of the list is considered a front. Before reading the rest of the section, try to informally reason with yourself why this might be, taking into account that a queue is a FIFO.</p>
<h2 id="list-based-implementation-of-the-queue-adt-08117c64fa">List-based implementation of the Queue ADT</h2>
<p>In the following implementation, we use a Python list that is hidden from the client. We have decided that the beginning of the list (i.e., index 0) is the front of the queue. This means that new items that are enqueued will be added at the end of the list, and items that are dequeued are removed from the beginning of the list.</p>
<div class="sourceCode" id="cb2-08117c64fa"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-08117c64fa"><a href="#cb2-1-08117c64fa"></a><span class="kw">class</span> Queue:</span>
<span id="cb2-2-08117c64fa"><a href="#cb2-2-08117c64fa"></a> <span class="co">&quot;&quot;&quot;A first-in-first-out (FIFO) queue of items.</span></span>
<span id="cb2-3-08117c64fa"><a href="#cb2-3-08117c64fa"></a></span>
<span id="cb2-4-08117c64fa"><a href="#cb2-4-08117c64fa"></a><span class="co"> Stores data in a first-in, first-out order. When removing an item from the</span></span>
<span id="cb2-5-08117c64fa"><a href="#cb2-5-08117c64fa"></a><span class="co"> queue, the most recently-added item is the one that is removed.</span></span>
<span id="cb2-6-08117c64fa"><a href="#cb2-6-08117c64fa"></a></span>
<span id="cb2-7-08117c64fa"><a href="#cb2-7-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q = Queue()</span></span>
<span id="cb2-8-08117c64fa"><a href="#cb2-8-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.is_empty()</span></span>
<span id="cb2-9-08117c64fa"><a href="#cb2-9-08117c64fa"></a><span class="co"> True</span></span>
<span id="cb2-10-08117c64fa"><a href="#cb2-10-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.enqueue(&#39;hello&#39;)</span></span>
<span id="cb2-11-08117c64fa"><a href="#cb2-11-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.is_empty()</span></span>
<span id="cb2-12-08117c64fa"><a href="#cb2-12-08117c64fa"></a><span class="co"> False</span></span>
<span id="cb2-13-08117c64fa"><a href="#cb2-13-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.enqueue(&#39;goodbye&#39;)</span></span>
<span id="cb2-14-08117c64fa"><a href="#cb2-14-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.dequeue()</span></span>
<span id="cb2-15-08117c64fa"><a href="#cb2-15-08117c64fa"></a><span class="co"> &#39;hello&#39;</span></span>
<span id="cb2-16-08117c64fa"><a href="#cb2-16-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.dequeue()</span></span>
<span id="cb2-17-08117c64fa"><a href="#cb2-17-08117c64fa"></a><span class="co"> &#39;goodbye&#39;</span></span>
<span id="cb2-18-08117c64fa"><a href="#cb2-18-08117c64fa"></a><span class="co"> &gt;&gt;&gt; q.is_empty()</span></span>
<span id="cb2-19-08117c64fa"><a href="#cb2-19-08117c64fa"></a><span class="co"> True</span></span>
<span id="cb2-20-08117c64fa"><a href="#cb2-20-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-21-08117c64fa"><a href="#cb2-21-08117c64fa"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb2-22-08117c64fa"><a href="#cb2-22-08117c64fa"></a> <span class="co"># - _items: The items stored in this queue. The front of the list represents</span></span>
<span id="cb2-23-08117c64fa"><a href="#cb2-23-08117c64fa"></a> <span class="co"># the front of the queue.</span></span>
<span id="cb2-24-08117c64fa"><a href="#cb2-24-08117c64fa"></a> _items: <span class="bu">list</span></span>
<span id="cb2-25-08117c64fa"><a href="#cb2-25-08117c64fa"></a></span>
<span id="cb2-26-08117c64fa"><a href="#cb2-26-08117c64fa"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-27-08117c64fa"><a href="#cb2-27-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Initialize a new empty queue.&quot;&quot;&quot;</span></span>
<span id="cb2-28-08117c64fa"><a href="#cb2-28-08117c64fa"></a> <span class="va">self</span>._items <span class="op">=</span> []</span>
<span id="cb2-29-08117c64fa"><a href="#cb2-29-08117c64fa"></a></span>
<span id="cb2-30-08117c64fa"><a href="#cb2-30-08117c64fa"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-31-08117c64fa"><a href="#cb2-31-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Return whether this queue contains no items.</span></span>
<span id="cb2-32-08117c64fa"><a href="#cb2-32-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-33-08117c64fa"><a href="#cb2-33-08117c64fa"></a> <span class="cf">return</span> <span class="va">self</span>._items <span class="op">==</span> []</span>
<span id="cb2-34-08117c64fa"><a href="#cb2-34-08117c64fa"></a></span>
<span id="cb2-35-08117c64fa"><a href="#cb2-35-08117c64fa"></a> <span class="kw">def</span> enqueue(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-36-08117c64fa"><a href="#cb2-36-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Add &lt;item&gt; to the back of this queue.</span></span>
<span id="cb2-37-08117c64fa"><a href="#cb2-37-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-38-08117c64fa"><a href="#cb2-38-08117c64fa"></a> <span class="va">self</span>._items.append(item)</span>
<span id="cb2-39-08117c64fa"><a href="#cb2-39-08117c64fa"></a></span>
<span id="cb2-40-08117c64fa"><a href="#cb2-40-08117c64fa"></a> <span class="kw">def</span> dequeue(<span class="va">self</span>) <span class="op">-&gt;</span> Optional[Any]:</span>
<span id="cb2-41-08117c64fa"><a href="#cb2-41-08117c64fa"></a> <span class="co">&quot;&quot;&quot;Remove and return the item at the front of this queue.</span></span>
<span id="cb2-42-08117c64fa"><a href="#cb2-42-08117c64fa"></a></span>
<span id="cb2-43-08117c64fa"><a href="#cb2-43-08117c64fa"></a><span class="co"> Raise an EmptyQueueError if this queue is empty.</span></span>
<span id="cb2-44-08117c64fa"><a href="#cb2-44-08117c64fa"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-45-08117c64fa"><a href="#cb2-45-08117c64fa"></a> <span class="cf">if</span> <span class="va">self</span>.is_empty():</span>
<span id="cb2-46-08117c64fa"><a href="#cb2-46-08117c64fa"></a> <span class="cf">raise</span> EmptyQueueError</span>
<span id="cb2-47-08117c64fa"><a href="#cb2-47-08117c64fa"></a> <span class="cf">else</span>:</span>
<span id="cb2-48-08117c64fa"><a href="#cb2-48-08117c64fa"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop(<span class="dv">0</span>)</span></code></pre></div>
<h2 id="implementation-efficiency-08117c64fa">Implementation efficiency</h2>
<p>Our <code>Queue.enqueue</code> calls <code>list.append</code>, which we know takes constant (<span class="math inline">\(\Theta(1)\)</span>) time. However, the <code>Queue.dequeue</code> calls <code>self._items.pop(0)</code>, which takes <span class="math inline">\(\Theta(n)\)</span> time (where <span class="math inline">\(n\)</span> is the number of items stored in the queue). If we changed things around so that the front of the queue is the end of the list (rather than the beginning), we simply swap these running times. This presents a trade-off; using an array-based list, we can <em>either</em> have an efficient enqueue or an efficient dequeue operation.</p>
<p>Is there, perhaps, another data structure we can use instead of a list to improve efficiency? Unfortunately, both <code>dict</code> and <code>set</code> are unordered data structures, but queues need to maintain (and remember) a very specific order. One interesting programming challenge is to implement a queue using two stacks, which can be done correctly but is not always more efficient. Eventually you will learn about even more interesting data structures, and it may be a good idea to revisit the Queue ADT and see how to use your new arsenal of data structures instead of a Python list. And because of abstraction (i.e., <code>_items</code> is a private attribute), you can modify your <code>Queue</code> implementation however you like without having to change any client code that uses it!</p>
</section>
<br/> <a id="anchor-09-07"></a>
<header id="title-block-header-9957b03a9c">
<h1 class="title">9.7 Priority Queues</h1>
</header>
<section>
<p>Not all lineups work the same way. While the lineup at a McDonalds restaurant serves customers in a first-in-first-out order, the emergency room at a hospital does not see patients in the order that they arrive. Instead, the medical team perform an initial assessment of each patient for the severity of their illness, and patients with more life-threatening issues are seen earlier than others, regardless of when they arrived. In other words, patients are <em>prioritized</em> based on their condition.</p>
<h2 id="the-priority-queue-adt-9957b03a9c">The Priority Queue ADT</h2>
<p>The <strong>Priority Queue ADT</strong> is similar to the Queue ADT, except that every item has some measure of its “priority”. Items are removed from a Priority Queue in order of their priority, and ties are broken in FIFO order. To summarize:</p>
<ul>
<li><strong>Priority Queue</strong>
<ul>
<li>Data: a collection of items and their priorities</li>
<li>Operations: determine whether the priority queue is empty, add an item with a priority (<em>enqueue</em>), remove the highest priority item (<em>dequeue</em>)</li>
</ul></li>
</ul>
<p>One subtlety with our definition of this ADT is in how we represent priorities. For this section, well simply represent priorities as integers, with larger integers representing higher priorities. Well see a different way of representing priorites in the next chapter.</p>
<p>Here is the public interface of a <code>PriorityQueue</code> class.</p>
<div class="sourceCode" id="cb1-9957b03a9c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-9957b03a9c"><a href="#cb1-1-9957b03a9c"></a><span class="kw">class</span> PriorityQueue:</span>
<span id="cb1-2-9957b03a9c"><a href="#cb1-2-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;A collection items that are be removed in priority order.</span></span>
<span id="cb1-3-9957b03a9c"><a href="#cb1-3-9957b03a9c"></a></span>
<span id="cb1-4-9957b03a9c"><a href="#cb1-4-9957b03a9c"></a><span class="co"> When removing an item from the queue, the highest-priority item is the one</span></span>
<span id="cb1-5-9957b03a9c"><a href="#cb1-5-9957b03a9c"></a><span class="co"> that is removed.</span></span>
<span id="cb1-6-9957b03a9c"><a href="#cb1-6-9957b03a9c"></a></span>
<span id="cb1-7-9957b03a9c"><a href="#cb1-7-9957b03a9c"></a><span class="co"> &gt;&gt;&gt; pq = PriorityQueue()</span></span>
<span id="cb1-8-9957b03a9c"><a href="#cb1-8-9957b03a9c"></a><span class="co"> &gt;&gt;&gt; pq.is_empty()</span></span>
<span id="cb1-9-9957b03a9c"><a href="#cb1-9-9957b03a9c"></a><span class="co"> True</span></span>
<span id="cb1-10-9957b03a9c"><a href="#cb1-10-9957b03a9c"></a><span class="co"> &gt;&gt;&gt; pq.enqueue(1, &#39;hello&#39;)</span></span>
<span id="cb1-11-9957b03a9c"><a href="#cb1-11-9957b03a9c"></a><span class="co"> &gt;&gt;&gt; pq.is_empty()</span></span>
<span id="cb1-12-9957b03a9c"><a href="#cb1-12-9957b03a9c"></a><span class="co"> False</span></span>
<span id="cb1-13-9957b03a9c"><a href="#cb1-13-9957b03a9c"></a><span class="co"> &gt;&gt;&gt; pq.enqueue(5, &#39;goodbye&#39;)</span></span>
<span id="cb1-14-9957b03a9c"><a href="#cb1-14-9957b03a9c"></a><span class="co"> &gt;&gt;&gt; pq.enqueue(2, &#39;hi&#39;)</span></span>
<span id="cb1-15-9957b03a9c"><a href="#cb1-15-9957b03a9c"></a><span class="co"> &gt;&gt;&gt; pq.dequeue()</span></span>
<span id="cb1-16-9957b03a9c"><a href="#cb1-16-9957b03a9c"></a><span class="co"> &#39;goodbye&#39;</span></span>
<span id="cb1-17-9957b03a9c"><a href="#cb1-17-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-18-9957b03a9c"><a href="#cb1-18-9957b03a9c"></a></span>
<span id="cb1-19-9957b03a9c"><a href="#cb1-19-9957b03a9c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-20-9957b03a9c"><a href="#cb1-20-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Initialize a new and empty priority queue.&quot;&quot;&quot;</span></span>
<span id="cb1-21-9957b03a9c"><a href="#cb1-21-9957b03a9c"></a></span>
<span id="cb1-22-9957b03a9c"><a href="#cb1-22-9957b03a9c"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-23-9957b03a9c"><a href="#cb1-23-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Return whether this priority queue contains no items.</span></span>
<span id="cb1-24-9957b03a9c"><a href="#cb1-24-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-25-9957b03a9c"><a href="#cb1-25-9957b03a9c"></a></span>
<span id="cb1-26-9957b03a9c"><a href="#cb1-26-9957b03a9c"></a> <span class="kw">def</span> enqueue(<span class="va">self</span>, priority: <span class="bu">int</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-27-9957b03a9c"><a href="#cb1-27-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Add the given item with the given priority to this priority queue.</span></span>
<span id="cb1-28-9957b03a9c"><a href="#cb1-28-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-29-9957b03a9c"><a href="#cb1-29-9957b03a9c"></a></span>
<span id="cb1-30-9957b03a9c"><a href="#cb1-30-9957b03a9c"></a> <span class="kw">def</span> dequeue(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb1-31-9957b03a9c"><a href="#cb1-31-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Remove and return the item with the highest priority.</span></span>
<span id="cb1-32-9957b03a9c"><a href="#cb1-32-9957b03a9c"></a></span>
<span id="cb1-33-9957b03a9c"><a href="#cb1-33-9957b03a9c"></a><span class="co"> Raise an EmptyPriorityQueueError when the priority queue is empty.</span></span>
<span id="cb1-34-9957b03a9c"><a href="#cb1-34-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-35-9957b03a9c"><a href="#cb1-35-9957b03a9c"></a></span>
<span id="cb1-36-9957b03a9c"><a href="#cb1-36-9957b03a9c"></a></span>
<span id="cb1-37-9957b03a9c"><a href="#cb1-37-9957b03a9c"></a><span class="kw">class</span> EmptyPriorityQueueError(<span class="pp">Exception</span>):</span>
<span id="cb1-38-9957b03a9c"><a href="#cb1-38-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Exception raised when calling pop on an empty stack.&quot;&quot;&quot;</span></span>
<span id="cb1-39-9957b03a9c"><a href="#cb1-39-9957b03a9c"></a></span>
<span id="cb1-40-9957b03a9c"><a href="#cb1-40-9957b03a9c"></a> <span class="kw">def</span> <span class="fu">__str__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb1-41-9957b03a9c"><a href="#cb1-41-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Return a string representation of this error.&quot;&quot;&quot;</span></span>
<span id="cb1-42-9957b03a9c"><a href="#cb1-42-9957b03a9c"></a> <span class="cf">return</span> <span class="st">&#39;You called dequeue on an empty priority queue.&#39;</span></span></code></pre></div>
<h2 id="list-based-implementation-of-the-priority-queue-adt-9957b03a9c">List-based implementation of the Priority Queue ADT</h2>
<p>Unlike with the Stack and Queue ADTs, it is not clear if we can use a list here. Somehow we need to not only store items, but also keep track of which one has the largest priority, and in the case of ties, which one was inserted first.</p>
<p>Our implementation idea here is to use a private attribute that is a <em>list of tuples</em>, where each tuple is a <code>(priority, item)</code> pair. Our list will also be <em>sorted</em> with respect to priority (breaking ties by insertion order), so that the <em>last</em> element in the list is always the next item to be removed from the priority queue.</p>
<p>With this idea, three of the four <code>PriorityQueue</code> methods are straightforward to implement:</p>
<div class="sourceCode" id="cb2-9957b03a9c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-9957b03a9c"><a href="#cb2-1-9957b03a9c"></a><span class="im">from</span> typing <span class="im">import</span> Any</span>
<span id="cb2-2-9957b03a9c"><a href="#cb2-2-9957b03a9c"></a></span>
<span id="cb2-3-9957b03a9c"><a href="#cb2-3-9957b03a9c"></a></span>
<span id="cb2-4-9957b03a9c"><a href="#cb2-4-9957b03a9c"></a><span class="kw">class</span> PriorityQueue:</span>
<span id="cb2-5-9957b03a9c"><a href="#cb2-5-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;A queue of items that can be dequeued in priority order.</span></span>
<span id="cb2-6-9957b03a9c"><a href="#cb2-6-9957b03a9c"></a></span>
<span id="cb2-7-9957b03a9c"><a href="#cb2-7-9957b03a9c"></a><span class="co"> When removing an item from the queue, the highest-priority item is the one</span></span>
<span id="cb2-8-9957b03a9c"><a href="#cb2-8-9957b03a9c"></a><span class="co"> that is removed.</span></span>
<span id="cb2-9-9957b03a9c"><a href="#cb2-9-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-10-9957b03a9c"><a href="#cb2-10-9957b03a9c"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb2-11-9957b03a9c"><a href="#cb2-11-9957b03a9c"></a> <span class="co"># - _items: a list of the items in this priority queue</span></span>
<span id="cb2-12-9957b03a9c"><a href="#cb2-12-9957b03a9c"></a> _items: <span class="bu">list</span>[<span class="bu">tuple</span>[<span class="bu">int</span>, Any]]</span>
<span id="cb2-13-9957b03a9c"><a href="#cb2-13-9957b03a9c"></a></span>
<span id="cb2-14-9957b03a9c"><a href="#cb2-14-9957b03a9c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-15-9957b03a9c"><a href="#cb2-15-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Initialize a new and empty priority queue.&quot;&quot;&quot;</span></span>
<span id="cb2-16-9957b03a9c"><a href="#cb2-16-9957b03a9c"></a> <span class="va">self</span>._items <span class="op">=</span> []</span>
<span id="cb2-17-9957b03a9c"><a href="#cb2-17-9957b03a9c"></a></span>
<span id="cb2-18-9957b03a9c"><a href="#cb2-18-9957b03a9c"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-19-9957b03a9c"><a href="#cb2-19-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Return whether this priority queue contains no items.</span></span>
<span id="cb2-20-9957b03a9c"><a href="#cb2-20-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-21-9957b03a9c"><a href="#cb2-21-9957b03a9c"></a> <span class="cf">return</span> <span class="va">self</span>._items <span class="op">==</span> []</span>
<span id="cb2-22-9957b03a9c"><a href="#cb2-22-9957b03a9c"></a></span>
<span id="cb2-23-9957b03a9c"><a href="#cb2-23-9957b03a9c"></a> <span class="kw">def</span> dequeue(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb2-24-9957b03a9c"><a href="#cb2-24-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Remove and return the item with the highest priority.</span></span>
<span id="cb2-25-9957b03a9c"><a href="#cb2-25-9957b03a9c"></a></span>
<span id="cb2-26-9957b03a9c"><a href="#cb2-26-9957b03a9c"></a><span class="co"> Raise an EmptyPriorityQueueError when the priority queue is empty.</span></span>
<span id="cb2-27-9957b03a9c"><a href="#cb2-27-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-28-9957b03a9c"><a href="#cb2-28-9957b03a9c"></a> <span class="cf">if</span> <span class="va">self</span>.is_empty():</span>
<span id="cb2-29-9957b03a9c"><a href="#cb2-29-9957b03a9c"></a> <span class="cf">raise</span> EmptyPriorityQueueError</span>
<span id="cb2-30-9957b03a9c"><a href="#cb2-30-9957b03a9c"></a> <span class="cf">else</span>:</span>
<span id="cb2-31-9957b03a9c"><a href="#cb2-31-9957b03a9c"></a> _priority, item <span class="op">=</span> <span class="va">self</span>._items.pop()</span>
<span id="cb2-32-9957b03a9c"><a href="#cb2-32-9957b03a9c"></a> <span class="cf">return</span> item</span></code></pre></div>
<p>As an exercise, well leave you to show that each of these operations also runs in <span class="math inline">\(\Theta(1)\)</span> time. But what about <code>PriorityQueue.enqueue</code>? An initial approach might be to first insert the new priority and item into the list, and then sort the list by priority. But this is a bit inefficient: we shouldnt need to re-sort the entire list, if we start with a sorted list and are simply inserting one new item.<label for="sn-0-9957b03a9c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-9957b03a9c" class="margin-toggle"/><span class="sidenote"> We make this observation precise by observing that the worst-case running time of <code>list.sort</code> is <span class="math inline">\(\Theta(n \log n)\)</span>. Well study sorting algorithms in detail later on this year.</span> So instead, our <code>enqueue</code> implementation will search for the right index in the list to add the new item. For example, suppose we want to insert the item <code>'hi'</code> with priority <code>5</code> into the priority queue with <code>self._items</code> equal to <code>[(1, 'a'), (4, 'b'), (6, 'c'), (10, 'd')]</code>. We need to insert <code>(5, 'hi')</code> into index 2 in this list:</p>
<p><img src="./images/priority_queue_enqueue.png" alt="A diagram of priority queue enqueue" /><br />
</p>
<p>Here is our implementation of <code>enqueue</code>:</p>
<div class="sourceCode" id="cb3-9957b03a9c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-9957b03a9c"><a href="#cb3-1-9957b03a9c"></a><span class="kw">class</span> PriorityQueue:</span>
<span id="cb3-2-9957b03a9c"><a href="#cb3-2-9957b03a9c"></a> ...</span>
<span id="cb3-3-9957b03a9c"><a href="#cb3-3-9957b03a9c"></a></span>
<span id="cb3-4-9957b03a9c"><a href="#cb3-4-9957b03a9c"></a> <span class="kw">def</span> enqueue(<span class="va">self</span>, priority: <span class="bu">int</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-5-9957b03a9c"><a href="#cb3-5-9957b03a9c"></a> <span class="co">&quot;&quot;&quot;Add the given item with the given priority to this priority queue.</span></span>
<span id="cb3-6-9957b03a9c"><a href="#cb3-6-9957b03a9c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-7-9957b03a9c"><a href="#cb3-7-9957b03a9c"></a> i <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb3-8-9957b03a9c"><a href="#cb3-8-9957b03a9c"></a> <span class="cf">while</span> i <span class="op">&lt;</span> <span class="bu">len</span>(<span class="va">self</span>._items) <span class="kw">and</span> <span class="va">self</span>._items[i][<span class="dv">0</span>] <span class="op">&lt;</span> priority:</span>
<span id="cb3-9-9957b03a9c"><a href="#cb3-9-9957b03a9c"></a> <span class="co"># Loop invariant: all items in self._items[0:i]</span></span>
<span id="cb3-10-9957b03a9c"><a href="#cb3-10-9957b03a9c"></a> <span class="co"># have a lower priority than &lt;priority&gt;.</span></span>
<span id="cb3-11-9957b03a9c"><a href="#cb3-11-9957b03a9c"></a> i <span class="op">=</span> i <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb3-12-9957b03a9c"><a href="#cb3-12-9957b03a9c"></a></span>
<span id="cb3-13-9957b03a9c"><a href="#cb3-13-9957b03a9c"></a> <span class="va">self</span>._items.insert(i, (priority, item))</span></code></pre></div>
<p>In the second part of the loop condition, you might wonder about the <code>&lt;</code>: could we do <code>self._items[i][0] &lt;= priority</code> instead? Does it make a difference? It turns out that switching <code>&lt;</code> for <code>&lt;=</code> in the second part of the condition does make a difference when it comes to breaking ties. Well leave it as an exercise for you to work this out: try tracing an <code>enqueue</code> operation for the item <code>'hi'</code> with priority <code>5</code> into the priority queue with <code>self._items</code> equal to <code>[(1, 'a'), (5, 'b'), (5, 'c'), (10, 'd')]</code>.</p>
<p>And finally, what is the running time of this implementation of <code>PriorityQueue.enqueue</code>, for a priority queue with <span class="math inline">\(n\)</span> elements? The loop here is a bit tricky to analyze because the number of iterations is not a fixed number in terms of <span class="math inline">\(n\)</span>. Here is one analysis:</p>
<ul>
<li><p>The while loop takes <em>at most</em> <span class="math inline">\(n\)</span> iterations, since <code>i</code> starts at 0 and increases by 1 at each iteration, and the loop must stop when <code>i</code> reaches <span class="math inline">\(n\)</span> (if it hasnt stopped earlier).</p>
<p>Since each loop iteration takes 1 step, in total the while loop takes at most <span class="math inline">\(n\)</span> steps.</p></li>
<li><p>We know from our study of array-based lists that <code>list.insert</code> takes at most <span class="math inline">\(n\)</span> steps, where <span class="math inline">\(n\)</span> is the length of the list being inserted into.</p></li>
<li><p>Adding up these two quantities, the total running time of this algorithm is at most <span class="math inline">\(n + n = 2n\)</span> steps, which is <span class="math inline">\(\cO(n)\)</span>.</p></li>
</ul>
<p>Of course, we shouldnt be satisfied with just an upper bound on the running time! It turns out that we can do better by incorporating the value of variable <code>i</code> in our calculation. Let <span class="math inline">\(I\)</span> be the value of variable <code>i</code> <em>after</em> the loop finishes. Then:</p>
<ul>
<li>We now know that the while loop takes <em>exactly</em> <span class="math inline">\(I\)</span> iterations, for a total of <span class="math inline">\(I\)</span> steps (1 step per iteration).</li>
<li>We know that calling <code>list.insert</code> on a list of length <span class="math inline">\(n\)</span> to insert an item at index <span class="math inline">\(I\)</span> takes <span class="math inline">\(n - I\)</span> steps.</li>
<li>So the total running time is actually <span class="math inline">\(I + (n - I) = n\)</span> steps, which is <span class="math inline">\(\Theta(n)\)</span>.</li>
</ul>
<p>In other words, weve shown that <em>every</em> call to this implementation of <code>PriorityQueue.enqueue</code> will take <span class="math inline">\(\Theta(n)\)</span> time, regardless of the priority being inserted.</p>
<h3 id="using-an-unsorted-list-9957b03a9c">Using an unsorted list</h3>
<p>Our implementation of <code>PriorityQueue</code> has a constant-time <code>dequeue</code> but a linear-time <code>enqueue</code>. You might naturally wonder if we can do better: what if we used an unsorted list of tuples instead? This would allow us to have <span class="math inline">\(\Theta(1)\)</span> <code>enqueue</code> operations, simply by appending a new <code>(priority, item)</code> tuple to the end of <code>self._items</code>. However, we have simply shifted the work over to the <code>dequeue</code> operation. Specifically, we must search for the highest priority item in a list of unsorted items, which would take <span class="math inline">\(\Theta(n)\)</span> time. Yet another trade-off!</p>
<h3 id="looking-ahead-heaps-9957b03a9c">Looking ahead: heaps</h3>
<p>In CSC263/CSC265, youll learn about the <em>heap</em>, a data structure which is commonly used to implement the Priority Queue ADT in practice. We can use this data structure to implement both <code>PriorityQueue.enqueue</code> and <code>PriorityQueue.dequeue</code> with a worst-case running time of <span class="math inline">\(\Theta(\log n)\)</span>.<label for="sn-1-9957b03a9c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-9957b03a9c" class="margin-toggle"/><span class="sidenote"> This is actually the approach taken by Pythons built-in <a href="https://docs.python.org/3/library/heapq.html"><code>heapq</code> module</a>. Pretty neat!</span></p>
</section>
<br/> <a id="anchor-09-08"></a>
<header id="title-block-header-8747233902">
<h1 class="title">9.8 Defining a Shared Public Interface with Inheritance</h1>
</header>
<section>
<p>In this chapter, we have learned that an abstract data type can have multiple implementations, and seen this first-hand with a variety of ADTs. For example, in <a href="04-stacks.html">9.4 Stacks</a> we saw that the Stack ADT can be implemented using a Python list in two different ways, storing the top of the stack at the end of the list (<code>Stack1</code>) or the front of the list (<code>Stack2</code>). Though these two classes had different implementations, they shared the same <em>public interface</em> of the Stack ADT.</p>
<p>One limitation of the code we wrote for these two classes is that the only way to tell that <code>Stack1</code> and <code>Stack2</code> had the same interface was from their method names and docstrings. In this section, well see how to create a special kind of Python class that is used to define a public interface that can be implemented by other classes, using a Python language feature known as <em>inheritance</em>.</p>
<h2 id="the-stack-abstract-class-8747233902">The Stack abstract class</h2>
<p>Let us begin by defining a <code>Stack</code> class that consists only of the <em>public interface</em> of the Stack ADT.</p>
<div class="sourceCode" id="cb1-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-8747233902"><a href="#cb1-1-8747233902"></a><span class="kw">class</span> Stack:</span>
<span id="cb1-2-8747233902"><a href="#cb1-2-8747233902"></a> <span class="co">&quot;&quot;&quot;A last-in-first-out (LIFO) stack of items.</span></span>
<span id="cb1-3-8747233902"><a href="#cb1-3-8747233902"></a></span>
<span id="cb1-4-8747233902"><a href="#cb1-4-8747233902"></a><span class="co"> This is an abstract class. Only subclasses should be instantiated.</span></span>
<span id="cb1-5-8747233902"><a href="#cb1-5-8747233902"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-6-8747233902"><a href="#cb1-6-8747233902"></a></span>
<span id="cb1-7-8747233902"><a href="#cb1-7-8747233902"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-8-8747233902"><a href="#cb1-8-8747233902"></a> <span class="co">&quot;&quot;&quot;Return whether this stack contains no items.</span></span>
<span id="cb1-9-8747233902"><a href="#cb1-9-8747233902"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-10-8747233902"><a href="#cb1-10-8747233902"></a> <span class="cf">raise</span> <span class="pp">NotImplementedError</span></span>
<span id="cb1-11-8747233902"><a href="#cb1-11-8747233902"></a></span>
<span id="cb1-12-8747233902"><a href="#cb1-12-8747233902"></a> <span class="kw">def</span> push(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-13-8747233902"><a href="#cb1-13-8747233902"></a> <span class="co">&quot;&quot;&quot;Add a new element to the top of this stack.</span></span>
<span id="cb1-14-8747233902"><a href="#cb1-14-8747233902"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-15-8747233902"><a href="#cb1-15-8747233902"></a> <span class="cf">raise</span> <span class="pp">NotImplementedError</span></span>
<span id="cb1-16-8747233902"><a href="#cb1-16-8747233902"></a></span>
<span id="cb1-17-8747233902"><a href="#cb1-17-8747233902"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb1-18-8747233902"><a href="#cb1-18-8747233902"></a> <span class="co">&quot;&quot;&quot;Remove and return the element at the top of this stack.</span></span>
<span id="cb1-19-8747233902"><a href="#cb1-19-8747233902"></a></span>
<span id="cb1-20-8747233902"><a href="#cb1-20-8747233902"></a><span class="co"> Raise an EmptyStackError if this stack is empty.</span></span>
<span id="cb1-21-8747233902"><a href="#cb1-21-8747233902"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-22-8747233902"><a href="#cb1-22-8747233902"></a> <span class="cf">raise</span> <span class="pp">NotImplementedError</span></span>
<span id="cb1-23-8747233902"><a href="#cb1-23-8747233902"></a></span>
<span id="cb1-24-8747233902"><a href="#cb1-24-8747233902"></a></span>
<span id="cb1-25-8747233902"><a href="#cb1-25-8747233902"></a><span class="kw">class</span> EmptyStackError(<span class="pp">Exception</span>):</span>
<span id="cb1-26-8747233902"><a href="#cb1-26-8747233902"></a> <span class="co">&quot;&quot;&quot;Exception raised when calling pop on an empty stack.&quot;&quot;&quot;</span></span></code></pre></div>
<p>In Python, we mark a method as unimplemented by having its body raise a special exception, <code>NotImplementedError</code>. We say that a method is <strong>abstract</strong> when it is not implemented and raises this error; we say that a <em>class</em> is <strong>abstract</strong> when at least one of its methods is abstract (i.e., not implemented). A <strong>concrete class</strong> is a class that is not abstract; so far in this course, weve been dealing with concrete classes, and called them concrete data types.<label for="sn-0-8747233902" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-8747233902" class="margin-toggle"/><span class="sidenote"> The terminology here is a bit confusing because of the multiple uses of certain terms. A concrete Python class is the same as a concrete data type. However, an abstract Python class is <em>not</em> the same thing as an abstract data type; the former has a technical meaning specific to the Python programming language, while the latter is the name given to an abstract description of a data type that is programming language-independent.</span></p>
<p>Now, you might wonder what the purpose of an abstract class is. Indeed, a programmer who creates a <code>Stack</code> object will quickly find it is useless, because calling the Stack ADT operations cause errors:</p>
<div class="sourceCode" id="cb2-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-8747233902"><a href="#cb2-1-8747233902"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> Stack()</span>
<span id="cb2-2-8747233902"><a href="#cb2-2-8747233902"></a><span class="op">&gt;&gt;&gt;</span> s.push(<span class="dv">30</span>)</span>
<span id="cb2-3-8747233902"><a href="#cb2-3-8747233902"></a>Traceback...</span>
<span id="cb2-4-8747233902"><a href="#cb2-4-8747233902"></a><span class="pp">NotImplementedError</span></span>
<span id="cb2-5-8747233902"><a href="#cb2-5-8747233902"></a><span class="op">&gt;&gt;&gt;</span> s.pop()</span>
<span id="cb2-6-8747233902"><a href="#cb2-6-8747233902"></a>Traceback...</span>
<span id="cb2-7-8747233902"><a href="#cb2-7-8747233902"></a><span class="pp">NotImplementedError</span></span></code></pre></div>
<p>If we cant use the <code>Stack</code> object for any of the Stack ADT operations, what was the point in creating it? The answer is very much based on abstraction, hence the name abstract class. The <code>Stack</code> class we have defined is a direct translation of the Stack ADT: an <strong>interface</strong> that describes the methods that a concrete class that wants to implement the Stack ADT <em>must</em> define. Python gives us a way to describe the relationship between an abstract class and a concrete class that implements its methods directly in the code.</p>
<h2 id="inheriting-the-stack-abstract-class-8747233902">Inheriting the Stack abstract class</h2>
<p>Earlier in this chapter, we defined two new types: <code>Stack1</code> and <code>Stack2</code>. However, despite the two types sharing the same method names, the code did not indicate that the types were related in any way. Now that we have the abstract class <code>Stack</code>, we can indicate this relationship in the code through <strong>inheritance</strong>:</p>
<div class="sourceCode" id="cb3-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-8747233902"><a href="#cb3-1-8747233902"></a><span class="kw">class</span> Stack1(Stack):</span>
<span id="cb3-2-8747233902"><a href="#cb3-2-8747233902"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-3-8747233902"><a href="#cb3-3-8747233902"></a> <span class="co">&quot;&quot;&quot;Initialize a new empty stack.</span></span>
<span id="cb3-4-8747233902"><a href="#cb3-4-8747233902"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-5-8747233902"><a href="#cb3-5-8747233902"></a> <span class="va">self</span>._items <span class="op">=</span> []</span>
<span id="cb3-6-8747233902"><a href="#cb3-6-8747233902"></a></span>
<span id="cb3-7-8747233902"><a href="#cb3-7-8747233902"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb3-8-8747233902"><a href="#cb3-8-8747233902"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-9-8747233902"><a href="#cb3-9-8747233902"></a> <span class="cf">return</span> <span class="va">self</span>._items <span class="op">==</span> []</span>
<span id="cb3-10-8747233902"><a href="#cb3-10-8747233902"></a></span>
<span id="cb3-11-8747233902"><a href="#cb3-11-8747233902"></a> <span class="kw">def</span> push(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-12-8747233902"><a href="#cb3-12-8747233902"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-13-8747233902"><a href="#cb3-13-8747233902"></a> <span class="va">self</span>._items.append(item)</span>
<span id="cb3-14-8747233902"><a href="#cb3-14-8747233902"></a></span>
<span id="cb3-15-8747233902"><a href="#cb3-15-8747233902"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb3-16-8747233902"><a href="#cb3-16-8747233902"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-17-8747233902"><a href="#cb3-17-8747233902"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop()</span>
<span id="cb3-18-8747233902"><a href="#cb3-18-8747233902"></a></span>
<span id="cb3-19-8747233902"><a href="#cb3-19-8747233902"></a></span>
<span id="cb3-20-8747233902"><a href="#cb3-20-8747233902"></a><span class="kw">class</span> Stack2(Stack):</span>
<span id="cb3-21-8747233902"><a href="#cb3-21-8747233902"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-22-8747233902"><a href="#cb3-22-8747233902"></a> <span class="co">&quot;&quot;&quot;Initialize a new empty stack.</span></span>
<span id="cb3-23-8747233902"><a href="#cb3-23-8747233902"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-24-8747233902"><a href="#cb3-24-8747233902"></a> <span class="va">self</span>._items <span class="op">=</span> []</span>
<span id="cb3-25-8747233902"><a href="#cb3-25-8747233902"></a></span>
<span id="cb3-26-8747233902"><a href="#cb3-26-8747233902"></a> <span class="kw">def</span> is_empty(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb3-27-8747233902"><a href="#cb3-27-8747233902"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-28-8747233902"><a href="#cb3-28-8747233902"></a> <span class="cf">return</span> <span class="va">self</span>._items <span class="op">==</span> []</span>
<span id="cb3-29-8747233902"><a href="#cb3-29-8747233902"></a></span>
<span id="cb3-30-8747233902"><a href="#cb3-30-8747233902"></a> <span class="kw">def</span> push(<span class="va">self</span>, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-31-8747233902"><a href="#cb3-31-8747233902"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-32-8747233902"><a href="#cb3-32-8747233902"></a> <span class="va">self</span>._items.insert(<span class="dv">0</span>, item)</span>
<span id="cb3-33-8747233902"><a href="#cb3-33-8747233902"></a></span>
<span id="cb3-34-8747233902"><a href="#cb3-34-8747233902"></a> <span class="kw">def</span> pop(<span class="va">self</span>) <span class="op">-&gt;</span> Any:</span>
<span id="cb3-35-8747233902"><a href="#cb3-35-8747233902"></a> <span class="co">&quot;&quot;&quot;...&quot;&quot;&quot;</span></span>
<span id="cb3-36-8747233902"><a href="#cb3-36-8747233902"></a> <span class="cf">return</span> <span class="va">self</span>._items.pop(<span class="dv">0</span>)</span></code></pre></div>
<p>In the class header <code>class Stack1(Stack)</code> and <code>class Stack2(Stack)</code>, the syntax <code>(Stack)</code> indicates that <code>Stack1</code> and <code>Stack2</code> inherit from <code>Stack</code>. There are specific words we use to talk about these relationships:</p>
<ul>
<li><code>Stack</code>: base class, superclass, and parent class are synonyms.</li>
<li><code>Stack1</code>, <code>Stack2</code>: subclass, child class, and derived class are synonyms.</li>
</ul>
<p>For example, we can say that “<code>Stack</code> is the parent class of <code>Stack1</code>” or “<code>Stack2</code> is a subclass of <code>Stack</code>”.</p>
<p><img src="images/stacks_inheritance_diagram.png" /></p>
<p>When one class in Python inherits from another, there are two important consequences. First, the Python interpreter treats every instance of the subclass as an instance of the superclass as well.</p>
<div class="sourceCode" id="cb4-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-8747233902"><a href="#cb4-1-8747233902"></a><span class="op">&gt;&gt;&gt;</span> s1 <span class="op">=</span> Stack1()</span>
<span id="cb4-2-8747233902"><a href="#cb4-2-8747233902"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">isinstance</span>(s1, Stack1)</span>
<span id="cb4-3-8747233902"><a href="#cb4-3-8747233902"></a><span class="va">True</span></span>
<span id="cb4-4-8747233902"><a href="#cb4-4-8747233902"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">isinstance</span>(s1, Stack)</span>
<span id="cb4-5-8747233902"><a href="#cb4-5-8747233902"></a><span class="va">True</span></span>
<span id="cb4-6-8747233902"><a href="#cb4-6-8747233902"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">isinstance</span>(s1, Stack2)</span>
<span id="cb4-7-8747233902"><a href="#cb4-7-8747233902"></a><span class="va">False</span></span></code></pre></div>
<p>Second, when the superclass is abstract, the subclass must implement all abstract methods from the superclass, without changing the public interface of those methods. Just like preconditions and representation invariants, inheritance serves as another form of <em>contract</em>:</p>
<ul>
<li>The implementor of the subclass must implement the methods from the abstract superclass.</li>
<li>Any user of the subclass may assume that they can call the superclass methods on instances of the subclass.</li>
</ul>
<p>So for example, if we say that <code>Stack1</code> is a subclass of <code>Stack</code>, then any user of <code>Stack1</code> can expect to be able to call <code>push</code>, <code>pop</code>, and <code>is_empty</code> on <code>Stack1</code> instances. And of course the same applies to <code>Stack2</code> as well.</p>
<p>It is this expectation that allows us to use inheritance in Python to express a <em>shared public interface</em> between multiples classes. In our example, because <code>Stack1</code> and <code>Stack2</code> are both subclasses of <code>Stack</code>, we expect them implement all the stack methods. They might also implement additional methods that are unique to each subclass (<em>not</em> shared), but this is not required.</p>
<h2 id="writing-polymorphic-code-using-inheritance-8747233902">Writing polymorphic code using inheritance</h2>
<p>Suppose we are writing code that operations on a stack, like in the following function:</p>
<div class="sourceCode" id="cb5-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-8747233902"><a href="#cb5-1-8747233902"></a><span class="kw">def</span> push_and_pop(s: ..., item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb5-2-8747233902"><a href="#cb5-2-8747233902"></a> <span class="co">&quot;&quot;&quot;Push and pop the given item onto the stack s.&quot;&quot;&quot;</span></span>
<span id="cb5-3-8747233902"><a href="#cb5-3-8747233902"></a> s.push(item)</span>
<span id="cb5-4-8747233902"><a href="#cb5-4-8747233902"></a> s.pop()</span></code></pre></div>
<p>What type annotation would be appropriate for <code>s</code>? If we use a concrete stack implementation like <code>Stack1</code>, this would rule out other stack implementations for this function. Instead, we use the abstract class <code>Stack</code> as the type annotation, to indicate that our function <code>push_and_pop</code> can be called with <em>any</em> instance of any <code>Stack</code> subclass.</p>
<div class="sourceCode" id="cb6-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-8747233902"><a href="#cb6-1-8747233902"></a><span class="kw">def</span> push_and_pop(s: Stack, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb6-2-8747233902"><a href="#cb6-2-8747233902"></a> <span class="co">&quot;&quot;&quot;Push and pop the given item onto the stack s.&quot;&quot;&quot;</span></span>
<span id="cb6-3-8747233902"><a href="#cb6-3-8747233902"></a> s.push(item)</span>
<span id="cb6-4-8747233902"><a href="#cb6-4-8747233902"></a> s.pop()</span></code></pre></div>
<p>Remember that <code>Stack</code> defines a public interface that is shared between all of its subclasses: the body of <code>push_and_pop</code> only needs to call methods from that interface (<code>pop</code> and <code>push</code>), and doesnt worry about how those methods are implemented. This allows us to pass to the <code>push_and_pop</code> function a <code>Stack1</code> or <code>Stack2</code> object, which both inherit from <code>Stack</code>.</p>
<div class="sourceCode" id="cb7-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-8747233902"><a href="#cb7-1-8747233902"></a><span class="op">&gt;&gt;&gt;</span> s1 <span class="op">=</span> Stack1()</span>
<span id="cb7-2-8747233902"><a href="#cb7-2-8747233902"></a><span class="op">&gt;&gt;&gt;</span> push_and_pop(s1) <span class="co"># This works!</span></span>
<span id="cb7-3-8747233902"><a href="#cb7-3-8747233902"></a><span class="op">&gt;&gt;&gt;</span> s2 <span class="op">=</span> Stack2()</span>
<span id="cb7-4-8747233902"><a href="#cb7-4-8747233902"></a><span class="op">&gt;&gt;&gt;</span> push_and_pop(s2) <span class="co"># This also works!</span></span></code></pre></div>
<p>You might notice that there are actually three versions of <code>push</code> in our code: <code>Stack.push</code>, <code>Stack1.push</code>, and <code>Stack2.push</code>. So which method does the Python interpreter choose when the <code>push_and_pop</code> function is called? This is how it works for <code>s.push(item)</code> (<code>s.pop()</code> is handled similarly):</p>
<ol type="1">
<li>When the Python interpreter evaluates <code>s.push(item)</code>, it first computes <code>type(s)</code>. The result will depend on the argument we passed in—in our above example, <code>type(s1)</code> is <code>Stack1</code>, and <code>type(s2)</code> is <code>Stack2</code>.</li>
<li>The Python interpreter then looks in that class for a <code>push</code> method and calls it, passing in <code>s</code> for the <code>self</code> argument.<label for="sn-1-8747233902" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-8747233902" class="margin-toggle"/><span class="sidenote">There are instances with inheritance where a subclass might not implement a particular method from the superclass. Well look at some examples of this in the next section.</span></li>
</ol>
<p>We say that the Python interpreter <em>dynamically looks up (or resolves) the <code>s.push</code>/<code>.pop</code> method</em>, because the actual method called by <code>s.push</code>/<code>s.pop</code> changes depending on the argument passed to <code>push_and_pop</code>.</p>
<p>We say that the <code>push_and_pop</code> function is <strong>polymorphic</strong>, meaning it can take as inputs values of different concrete data type and select a specific method based on the type of input. This support for polymorphism is also why the “object dot notation” style of method call is preferred to the “class dot notation” style weve been using up to this point. Consider the following two alternate implementations of <code>push_and_pop</code>:</p>
<div class="sourceCode" id="cb8-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-8747233902"><a href="#cb8-1-8747233902"></a><span class="kw">def</span> push_and_pop_alt1(s: Stack, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb8-2-8747233902"><a href="#cb8-2-8747233902"></a> <span class="co">&quot;&quot;&quot;Push and pop the given item onto the stack s.&quot;&quot;&quot;</span></span>
<span id="cb8-3-8747233902"><a href="#cb8-3-8747233902"></a> Stack.push(s, item)</span>
<span id="cb8-4-8747233902"><a href="#cb8-4-8747233902"></a> Stack.pop(s)</span>
<span id="cb8-5-8747233902"><a href="#cb8-5-8747233902"></a></span>
<span id="cb8-6-8747233902"><a href="#cb8-6-8747233902"></a></span>
<span id="cb8-7-8747233902"><a href="#cb8-7-8747233902"></a><span class="kw">def</span> push_and_pop_alt2(s: Stack, item: Any) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb8-8-8747233902"><a href="#cb8-8-8747233902"></a> <span class="co">&quot;&quot;&quot;Push and pop the given item onto the stack s.&quot;&quot;&quot;</span></span>
<span id="cb8-9-8747233902"><a href="#cb8-9-8747233902"></a> Stack1.push(s, item)</span>
<span id="cb8-10-8747233902"><a href="#cb8-10-8747233902"></a> Stack1.pop(s)</span></code></pre></div>
<p>The first version (<code>alt1</code>) explicitly calls the <code>Stack.push</code> and <code>Stack.pop</code> methods, both of which are unimplemented and would raise a <code>NotImplementedError</code>. The second version (<code>alt2</code>) calls concrete methods <code>Stack1.push</code> and <code>Stack1.pop</code>, which assumes a specific stack implementation (<code>Stack1</code>), and so <code>push_and_pop</code> would only be guaranteed to work on <code>Stack1</code> instances, but not any other <code>Stack</code> subclass. This makes <code>push_and_pop</code> no longer polymorphic: the correct type annotation for <code>s</code> would be <code>Stack1</code>, not <code>Stack</code>.</p>
<h3 id="application-running-timing-experiments-on-stack-implementation-8747233902">Application: running timing experiments on stack implementation</h3>
<p>Because both <code>Stack1</code> and <code>Stack2</code> are different implementations of the same interface, we can use polymorphism to help us measure the performance of each. Below, we time the <code>push_and_pop</code> function, first with a <code>Stack1</code> object and second with a <code>Stack2</code> object.</p>
<div class="sourceCode" id="cb9-8747233902"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-8747233902"><a href="#cb9-1-8747233902"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb9-2-8747233902"><a href="#cb9-2-8747233902"></a> <span class="co"># Import the main timing function.</span></span>
<span id="cb9-3-8747233902"><a href="#cb9-3-8747233902"></a> <span class="im">from</span> timeit <span class="im">import</span> timeit</span>
<span id="cb9-4-8747233902"><a href="#cb9-4-8747233902"></a></span>
<span id="cb9-5-8747233902"><a href="#cb9-5-8747233902"></a> <span class="co"># The stack sizes we want to try.</span></span>
<span id="cb9-6-8747233902"><a href="#cb9-6-8747233902"></a> STACK_SIZES <span class="op">=</span> [<span class="dv">1000</span>, <span class="dv">10000</span>, <span class="dv">100000</span>, <span class="dv">1000000</span>, <span class="dv">10000000</span>]</span>
<span id="cb9-7-8747233902"><a href="#cb9-7-8747233902"></a> <span class="cf">for</span> stack_size <span class="kw">in</span> STACK_SIZES:</span>
<span id="cb9-8-8747233902"><a href="#cb9-8-8747233902"></a> stack1 <span class="op">=</span> Stack1()</span>
<span id="cb9-9-8747233902"><a href="#cb9-9-8747233902"></a> stack2 <span class="op">=</span> Stack2()</span>
<span id="cb9-10-8747233902"><a href="#cb9-10-8747233902"></a></span>
<span id="cb9-11-8747233902"><a href="#cb9-11-8747233902"></a> <span class="co"># Bypass the Stack interface to create a stack of size &lt;stack_size&gt;.</span></span>
<span id="cb9-12-8747233902"><a href="#cb9-12-8747233902"></a> <span class="co"># This speeds up the experiment, but we know this violates</span></span>
<span id="cb9-13-8747233902"><a href="#cb9-13-8747233902"></a> <span class="co"># encapsulation!</span></span>
<span id="cb9-14-8747233902"><a href="#cb9-14-8747233902"></a> stack1._items <span class="op">=</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">0</span>, stack_size))</span>
<span id="cb9-15-8747233902"><a href="#cb9-15-8747233902"></a> stack2._items <span class="op">=</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">0</span>, stack_size))</span>
<span id="cb9-16-8747233902"><a href="#cb9-16-8747233902"></a></span>
<span id="cb9-17-8747233902"><a href="#cb9-17-8747233902"></a> <span class="co"># Call push_and_pop(stack1) 1000 times, and store the time taken.</span></span>
<span id="cb9-18-8747233902"><a href="#cb9-18-8747233902"></a> t1 <span class="op">=</span> timeit(<span class="st">&#39;push_and_pop(stack1, 10)&#39;</span>, number<span class="op">=</span><span class="dv">1000</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb9-19-8747233902"><a href="#cb9-19-8747233902"></a> t2 <span class="op">=</span> timeit(<span class="st">&#39;push_and_pop(stack2, 10)&#39;</span>, number<span class="op">=</span><span class="dv">1000</span>, <span class="bu">globals</span><span class="op">=</span><span class="bu">globals</span>())</span>
<span id="cb9-20-8747233902"><a href="#cb9-20-8747233902"></a></span>
<span id="cb9-21-8747233902"><a href="#cb9-21-8747233902"></a> <span class="bu">print</span>(<span class="ss">f&#39;Stack size </span><span class="sc">{</span>stack_size<span class="sc">:&gt;8}</span><span class="ss">; Stack1 time </span><span class="sc">{t1}</span><span class="ss">; Stack2 time </span><span class="sc">{t2}</span><span class="ss">&#39;</span>)</span></code></pre></div>
<p>If we have several implementations of an ADT, each inheriting from the same base class, then we can quickly run experiments on all of them but only need to remember a single interface. This creates a rule of thumb: when indicating the type of an object (e.g., through a type contract), choose the most generic type possible. Following this rule of thumb means that the client code is not constrained to one particular implementation (such as <code>Stack1</code>) and can readily change the underlying object so long as the new object type shares the same public interface.</p>
<p>Many software applications follow the same principle. For example, you may have used software with “plugins”:<label for="sn-2-8747233902" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-8747233902" class="margin-toggle"/><span class="sidenote">Like PyCharm!</span> each plugin implements a shared public interface, allowing the software to use it without knowing any of the details. For example, Adobe develops the powerful Photoshop application for image editing. David comes along and discovers a feature he really wants is missing. Rather than asking Adobe to implement the new feature, he can implement it himself as a plugin. Thus, Adobe has allowed independent developers to <em>extend the functionality</em> of their software after it has been released and without any employees of their own. Behold, the power of abstraction!</p>
</section>
<!--
otherwise, Python next searches for `push` in the superclass of the type of `s`.^[
And then the superclass of the superclass, etc., until it either finds a definition of `push` or it has exhausted all possibilities, in which case it raises an `AttributeError`.
]
This is why, if `Stack1` does not implement the `push` method, Python can still find `push` method if `Stack1.push` is called (the one inherited from `Stack` that raises a `NotImplementedError`).
However, if `Stack1` does implement the `push` method, then its implementation **overrides** the implementation in the parent class.
In other words, Python is following a "chain of responsibility" until it finds the person (class) responsible for the implementation.
-->
<br/> <a id="anchor-09-09"></a>
<header id="title-block-header-cc466c2a3c">
<h1 class="title">9.9 The <code>object</code> Superclass</h1>
</header>
<section>
<p>In our very first chapter, we described every piece of data as an <em>object</em>, and have continued to use this term throughout this course. It turns out that “object” is not merely a theoretical concept, but made explicit in the Python language. Python has a special class called <code>object</code>, which is an <em>ancestor class</em><label for="sn-0-cc466c2a3c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-cc466c2a3c" class="margin-toggle"/><span class="sidenote">By “ancestor” we mean either a parent class, or a parent of a parent class, etc.</span> of every other class, both built-in classes like <code>int</code> or our custom data classes and the classes weve defined in this chapter. And this includes abstract classes like <code>Stack</code>!</p>
<p>By default, whenever we define a new class (including data classes), if we do not specify a superclass in parentheses, <code>object</code> is the <em>implicit</em> superclass, which is why we can write <code>class Stack:</code> instead of <code>class Stack(object):</code>.</p>
<p><img src="images/object_inheritance_diagram.png" /></p>
<h2 id="the-object-special-methods-cc466c2a3c">The <code>object</code> special methods</h2>
<p>This <code>object</code> class defines several special methods as part of its shared public interface, including:<label for="sn-1-cc466c2a3c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-cc466c2a3c" class="margin-toggle"/><span class="sidenote"> The Python convention is to name methods that have a special purpose with double underscores. These are sometimes called “dunder” methods (<strong>d</strong>ouble <strong>under</strong>score).</span></p>
<ul>
<li><code>__init__(self, ...)</code>, the initializer</li>
<li><code>__str__(self)</code>, which returns a <code>str</code> representation of the object.</li>
</ul>
<h3 id="method-inheritance-cc466c2a3c">Method inheritance</h3>
<p>Unlike our <code>Stack</code> abstract class earlier this chapter, the <code>object</code> class is actually <em>not abstract</em>, and implements each of these methods. We can use this to illustrate a different form of inheritance, where the superclass is a concrete class. In this case, inheritance is used not just to define a shared public interface, but also to provide <em>default implementations</em> for each method in the interface.</p>
<p>For example, suppose we create a dummy class with a completely empty body:</p>
<div class="sourceCode" id="cb1-cc466c2a3c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-cc466c2a3c"><a href="#cb1-1-cc466c2a3c"></a><span class="kw">class</span> Donut:</span>
<span id="cb1-2-cc466c2a3c"><a href="#cb1-2-cc466c2a3c"></a> <span class="co">&quot;&quot;&quot;A donut, because why not?&quot;</span></span></code></pre></div>
<p>This class inherits the <code>object.__init__</code> method, which allows us to create new <code>Donut</code> instances.</p>
<div class="sourceCode" id="cb2-cc466c2a3c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-cc466c2a3c"><a href="#cb2-1-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> donut <span class="op">=</span> Donut()</span>
<span id="cb2-2-cc466c2a3c"><a href="#cb2-2-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">type</span>(donut)</span>
<span id="cb2-3-cc466c2a3c"><a href="#cb2-3-cc466c2a3c"></a><span class="op">&lt;</span><span class="kw">class</span> <span class="st">&#39;__main__.Donut&#39;</span><span class="op">&gt;</span></span></code></pre></div>
<p>Similarly, this class inherits the <code>object.__str__</code> method, which returns a string that states the class name and memory location of the object:</p>
<div class="sourceCode" id="cb3-cc466c2a3c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-cc466c2a3c"><a href="#cb3-1-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> d <span class="op">=</span> Donut()</span>
<span id="cb3-2-cc466c2a3c"><a href="#cb3-2-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> d.<span class="fu">__str__</span>()</span>
<span id="cb3-3-cc466c2a3c"><a href="#cb3-3-cc466c2a3c"></a><span class="co">&#39;&lt;__main__.Donut object at 0x7fc299d7b588&gt;&#39;</span></span></code></pre></div>
<p>We can use the built-in <code>dir</code> function to see all of the special methods that <code>Donut</code> has inherited from <code>object</code>:<label for="sn-2-cc466c2a3c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-cc466c2a3c" class="margin-toggle"/><span class="sidenote">Though this list includes few special attributes set directly by the Python interpreter, which are beyond the scope of this course.</span></p>
<div class="sourceCode" id="cb4-cc466c2a3c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-cc466c2a3c"><a href="#cb4-1-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">dir</span>(Donut)</span>
<span id="cb4-2-cc466c2a3c"><a href="#cb4-2-cc466c2a3c"></a>[<span class="st">&#39;__class__&#39;</span>, <span class="st">&#39;__delattr__&#39;</span>, <span class="st">&#39;__dict__&#39;</span>, <span class="st">&#39;__dir__&#39;</span>, <span class="st">&#39;__doc__&#39;</span>, <span class="st">&#39;__eq__&#39;</span>, <span class="st">&#39;__format__&#39;</span>, <span class="st">&#39;__ge__&#39;</span>, <span class="st">&#39;__getattribute__&#39;</span>, <span class="st">&#39;__gt__&#39;</span>, <span class="st">&#39;__hash__&#39;</span>, <span class="st">&#39;__init__&#39;</span>, <span class="st">&#39;__init_subclass__&#39;</span>, <span class="st">&#39;__le__&#39;</span>, <span class="st">&#39;__lt__&#39;</span>, <span class="st">&#39;__module__&#39;</span>, <span class="st">&#39;__ne__&#39;</span>, <span class="st">&#39;__new__&#39;</span>, <span class="st">&#39;__reduce__&#39;</span>, <span class="st">&#39;__reduce_ex__&#39;</span>, <span class="st">&#39;__repr__&#39;</span>, <span class="st">&#39;__setattr__&#39;</span>, <span class="st">&#39;__sizeof__&#39;</span>, <span class="st">&#39;__str__&#39;</span>, <span class="st">&#39;__subclasshook__&#39;</span>, <span class="st">&#39;__weakref__&#39;</span>]</span></code></pre></div>
<p>There is another reason these methods are special beyond simply being inherited from the <code>object</code> superclass: they are often called by other functions or parts of Python syntax. For example, we have already seen how the <code>__init__</code> method is called when a new object is initialized.</p>
<p>The <code>__str__</code> method is called when we attempt to convert an object to a string by calling <code>str</code> on it:</p>
<div class="sourceCode" id="cb5-cc466c2a3c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-cc466c2a3c"><a href="#cb5-1-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> d <span class="op">=</span> Donut()</span>
<span id="cb5-2-cc466c2a3c"><a href="#cb5-2-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> d.<span class="fu">__str__</span>()</span>
<span id="cb5-3-cc466c2a3c"><a href="#cb5-3-cc466c2a3c"></a><span class="co">&#39;&lt;__main__.Donut object at 0x7fc299d7b588&gt;&#39;</span></span>
<span id="cb5-4-cc466c2a3c"><a href="#cb5-4-cc466c2a3c"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>(d)</span>
<span id="cb5-5-cc466c2a3c"><a href="#cb5-5-cc466c2a3c"></a><span class="co">&#39;&lt;__main__.Donut object at 0x7fc299d7b588&gt;&#39;</span></span></code></pre></div>
<p>Similarly, the built-in <code>print</code> function actually first converts its arguments into strings using their <code>__str__</code> methods, and then prints out the resulting text.</p>
<h3 id="method-overriding-cc466c2a3c">Method overriding</h3>
<p>Now, even though the <code>object</code> superclass contains default implementations of <code>__init__</code> and <code>__str__</code>, in practice we often want to define our own custom implementations of these methods.</p>
<p>Every time weve defined our own <code>__init__</code> in a class, we have <strong>overridden</strong> the <code>object.__init__</code> method. Formally, we say that a class <code>C</code> <strong>overrides</strong> a method <code>m</code> when the method <code>m</code> is defined in the superclass of <code>C</code>, and is also given a concrete implementation in the body of <code>C</code>.<label for="sn-3-cc466c2a3c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3-cc466c2a3c" class="margin-toggle"/><span class="sidenote"> This definition applies whether the superclass of <code>C</code> has <code>m</code> as an abstract or concrete method. For example, we could say that <code>Stack1</code> overrides the <code>push</code> and <code>pop</code> method from its abstract superclass <code>Stack</code>.</span></p>
<p>Similarly, when we defined a custom exception class in <a href="05-section.html">Section 9.5</a>,</p>
<div class="sourceCode" id="cb6-cc466c2a3c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-cc466c2a3c"><a href="#cb6-1-cc466c2a3c"></a><span class="kw">class</span> EmptyStackError(<span class="pp">Exception</span>):</span>
<span id="cb6-2-cc466c2a3c"><a href="#cb6-2-cc466c2a3c"></a> <span class="co">&quot;&quot;&quot;Exception raised when calling pop on an empty stack.&quot;&quot;&quot;</span></span>
<span id="cb6-3-cc466c2a3c"><a href="#cb6-3-cc466c2a3c"></a></span>
<span id="cb6-4-cc466c2a3c"><a href="#cb6-4-cc466c2a3c"></a> <span class="kw">def</span> <span class="fu">__str__</span>(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="bu">str</span>:</span>
<span id="cb6-5-cc466c2a3c"><a href="#cb6-5-cc466c2a3c"></a> <span class="co">&quot;&quot;&quot;Return a string representation of this error.&quot;&quot;&quot;</span></span>
<span id="cb6-6-cc466c2a3c"><a href="#cb6-6-cc466c2a3c"></a> <span class="cf">return</span> <span class="st">&#39;pop may not be called on an empty stack&#39;</span></span></code></pre></div>
<p>this class <em>overrode</em> the <code>__str__</code> method to use its own string representation, which is displayed when this exception is raised.</p>
</section>
<br/>
<h2 class="unnumbered" id="case-study-building-a-simulation">10. Case Study: Building a Simulation</h2>
<a id="anchor-10-01"></a>
<header id="title-block-header-c4d89fc288">
<h1 class="title">10.1 The Problem Domain: Food Delivery Networks</h1>
</header>
<section>
<p>We do not write software in a vacuum; we study computer science to learn how to use vast computational power to solve real-world problems. As professionals in industry and academia, the programs we create serve a purpose, whether to satisfy a need from a client, to improve individual lives and society, or to advance human knowledge and technology. In the previous chapters of these course notes, we have learned about the fundamentals of programming, mathematical proof, and algorithm analysis. We have focused on developed the knowledge and skills required to create and analyse programs.</p>
<p>In this final chapter of the course, we will take what weve learned and apply it to design and implement a large program to solve a real-world problem. As a first step to this, well learn about how to approach a new domain to understand how we can apply computer science techniques to both represent and solve problems in that domain.</p>
<h2 id="what-is-a-problem-domain-c4d89fc288">What is a problem domain?</h2>
<p>A <strong>problem domain</strong> is collection of knowledge<label for="sn-0-c4d89fc288" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-c4d89fc288" class="margin-toggle"/><span class="sidenote"> We use the term <em>domain-specific</em> knowledge to refer to knowledge about a particular domain. Society often uses the term <em>domain experts</em> to refer to people who have a great deal of knowledge in a particular domain.</span> about a specific field, phenomenon, or discipline, and an understanding of the goals, problems, deficiencies, and/or desired improvements within that area. Each problem domains encompass many different kinds of knowledge, including terminology and definitions, concepts and skills, and context and history. Through your lectures, tutorials, and assignments, youve touched on a wide array of problem domains, such as tracking marriage records in the City of Toronto, modelling the spread of infectious diseases, generating course timetables as U of T students, and cryptography.</p>
<p>Lets unpack how we explored the domain of cryptography in Chapter 7. We first introduced the key scenario of two people communicating securely so that their messages could not be deciphered by an eavesdropper. As we dove into cryptography, we learned about:</p>
<ul>
<li>terminology and definitions (e.g., symmetric-key and public-key cryptosystems, encryption and decryption, various existing cryptosystems)</li>
<li>concepts and skills (e.g., proving that a cryptosystem is correct; justifying the security of a cryptosystem based on the presumed hardness of mathematical problems like Integer Factorization)</li>
<li>the context and history (e.g., ancient cryptosystems, how cryptography is applied to Internet communciations)</li>
</ul>
<p>Our previous study of programming enabled us to write programs, but we had to learn all about the domain of cryptography before being able to implement cryptographic algorithms ourselves. Our knowledge of Python programming alone might have been sufficient to explain what operations are performed on what data in, for example, <code>rsa_generate_key</code>, <code>rsa_encrypt</code>, and <code>rsa_decrypt</code>. But it was the domain-specific knowledge we learned that explained <em>how</em> we came up with these algorithms and why they are correct.</p>
<h2 id="introducing-hercules-c4d89fc288">Introducing Hercules</h2>
<p>Now, well introduce a new problem domain that we will spend the rest of this chapter studying.</p>
<p>Consider a person or household self-quarantining during the pandemic. One of the main logistical challenges they have to face is how to arrange for food during their quarantine. To help address this need, you have founded <em>Hercules Ltd.</em>, a non-profit organization that allows people under quarantine to order groceries and meals from grocery stores and restaurants, and arranges for couriers to make deliveries right to their front doors. You are incredibly excited and cant wait to launch a Hercules app. Your friend is a bit more cautious, and wonders how many couriers will be needed to make grocery and meal deliveries in a timely manner, which of course will depend on how many people use the app. You and your friend decide to put the computational skills youve learned in this course to help answer this question.</p>
<p>This problem domain is likely a familiar one; the idea of having food delivered to your doorstep has existed for a long time. The preceding paragraph uses some familiar terminology, such as couriers and deliveries. You may even be familiar with existing apps that already do this, such as <em>UberEats</em>, <em>Skip the Dishes</em>, or <em>Instacart</em>. When thinking about designing and implementing this app, you are probably considering:</p>
<ul>
<li>how restaurants will register with the app and post menus</li>
<li>how customers will register with the app to browse restaurants and place orders</li>
<li>how couriers will register with the app to claim orders and deliver them from restaurants to customers</li>
<li>…and more</li>
</ul>
<h3 id="food-delivery-as-a-system-c4d89fc288">Food delivery as a system</h3>
<p>We can view food delivery in Toronto as a <strong>system</strong>, which is a group of entities (or agents) that interact with each other over time. Systems modeling is frequently used to conceptualize how an organization operates. The first part of creating a computational model for such a system is to design and implement the various entities in the system—in the case of the Hercules Ltd., these are entities like couriers and the customers placing orders.</p>
<p>The entities in a system are not static; they change over time. New people sign up and place food orders; couriers pick up meals from restaurants and deliver them to clients. For a live app, these events are driven by real humans interacting with the app in real-time. In this chapter, however, were going to look at another way of driving change in our food delivery system over time. The second part of our computational model is a <em>simulation</em> that uses randomness to generate events that cause the system to change over time. For example, our food delivery simulation will specify how often customers place an order, taking into account that some times of day are busier than others.</p>
<p>Computational simulations are a powerful tool because they harness the speed and reliability of your computer to perform complex calculations and produce results that can be analysed and visualized. But simulations are reliant on the accuracy of their underlying mathematical models, and are ultimately approximations of the real world. A well-designed simulation allows the programmer to start with a simple model and extend and tweak it in response to new domain-specific knowledge.</p>
<h3 id="chapter-roadmap-c4d89fc288">Chapter roadmap</h3>
<p>Over the course of this chapter, well study how to design and implement both of these parts of a computational model for our food delivery platform, Hercules. This case study will also give us an opportunity to explore the design of a relatively complex software system. Well use what weve learned about classes to model the entities in a food delivery network, and study a specific kind of simulation known as the <em>discrete-event simulation</em>. We hope youre excited. Hercules is counting on you!</p>
</section>
<br/> <a id="anchor-10-02"></a>
<header id="title-block-header-9daaec5a41">
<h1 class="title">10.2 Object-Oriented Modelling of Our Problem Domain</h1>
</header>
<section>
<p>In the previous section, we said that a system is a collection of entities that interact with each other over time. In this section, we will explore what data should be a part of our problem domain—a food delivery system—and how that data might change over time. Well introduce an object-oriented approach to modelling this data in Python, using both data classes and general classes to represent different entities.</p>
<p>One thing to keep in mind as we proceed through this section (and the rest of the chapter) is that just like in the “real world”, the scope of our problem domain is not fixed and can change over time. We are interested in the minimum set of data needed for our system to be meaningful, keeping the scope small at first with the potential to expand over time. Throughout this section, well point out places where we make <em>simplifying assumptions</em> that reduce the complexity of our system, which can serve as potential avenues for your own independent explorations after working through this chapter.</p>
<h2 id="entities-in-a-food-delivery-system-9daaec5a41">Entities in a food delivery system</h2>
<p>A good first step in modelling our problem domain is to identify the relevant entities in the domain. Here is our initial description of <em>Hercules</em> from the previous section:</p>
<blockquote>
<p>Consider a person or household doing a self-quarantine during the pandemic. One of the main logistical challenges they have to face is how to arrange for food during their quarantine. To help address this need, you have founded <em>Hercules Ltd.</em>, a non-profit organization that allows people under quarantine to order groceries and meals from grocery stores and restaurants, and arranges for couriers to make deliveries right to their front doors.</p>
</blockquote>
<p>We use two strategies for picking out relevant entities from an English description like this one:</p>
<ol type="1">
<li>Identify different roles that people/groups play in the domain. Each “role” is likely an entity: e.g., <em>customer</em>, <em>courier</em>, and <em>restaurant</em> are three distinct roles in the system.</li>
<li>Identify a bundle of data that makes sense as a logical unit. Each “bundle” is likely an entity: e.g., an <em>order</em> is a bundle of related information about a users food request.</li>
</ol>
<p>In an object-oriented design, a standard approach is to create a class to represent each of these entities. Should we make a data class or a general class for each one? There are no easy answers to this question, but a good strategy to use is to <em>start</em> with a data class, since data classes are easier to create, and turn it into a general class if we need a more complex design (e.g., to add methods, including the initializer, or mark attributes as private).</p>
<div class="sourceCode" id="cb1-9daaec5a41"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-9daaec5a41"><a href="#cb1-1-9daaec5a41"></a><span class="at">@dataclass</span></span>
<span id="cb1-2-9daaec5a41"><a href="#cb1-2-9daaec5a41"></a><span class="kw">class</span> Restaurant:</span>
<span id="cb1-3-9daaec5a41"><a href="#cb1-3-9daaec5a41"></a> <span class="co">&quot;&quot;&quot;A place that serves food.&quot;&quot;&quot;</span></span>
<span id="cb1-4-9daaec5a41"><a href="#cb1-4-9daaec5a41"></a></span>
<span id="cb1-5-9daaec5a41"><a href="#cb1-5-9daaec5a41"></a><span class="at">@dataclass</span></span>
<span id="cb1-6-9daaec5a41"><a href="#cb1-6-9daaec5a41"></a><span class="kw">class</span> Customer:</span>
<span id="cb1-7-9daaec5a41"><a href="#cb1-7-9daaec5a41"></a> <span class="co">&quot;&quot;&quot;A person who orders food.&quot;&quot;&quot;</span></span>
<span id="cb1-8-9daaec5a41"><a href="#cb1-8-9daaec5a41"></a></span>
<span id="cb1-9-9daaec5a41"><a href="#cb1-9-9daaec5a41"></a><span class="at">@dataclass</span></span>
<span id="cb1-10-9daaec5a41"><a href="#cb1-10-9daaec5a41"></a><span class="kw">class</span> Courier:</span>
<span id="cb1-11-9daaec5a41"><a href="#cb1-11-9daaec5a41"></a> <span class="co">&quot;&quot;&quot;A person who delivers food orders from restaurants to customers.&quot;&quot;&quot;</span></span>
<span id="cb1-12-9daaec5a41"><a href="#cb1-12-9daaec5a41"></a></span>
<span id="cb1-13-9daaec5a41"><a href="#cb1-13-9daaec5a41"></a><span class="at">@dataclass</span></span>
<span id="cb1-14-9daaec5a41"><a href="#cb1-14-9daaec5a41"></a><span class="kw">class</span> Order:</span>
<span id="cb1-15-9daaec5a41"><a href="#cb1-15-9daaec5a41"></a> <span class="co">&quot;&quot;&quot;A food order from a customer.&quot;&quot;&quot;</span></span></code></pre></div>
<p>Once we have identified the classes representing the entities in the system, we now dive into the details of the system to identify appropriate <em>attributes</em> for each of these data classes. Well discuss our process for two of these data classes in this section, and leave the other two to lecture this week.</p>
<h2 id="designing-the-restaurant-data-class-9daaec5a41">Designing the <code>Restaurant</code> data class</h2>
<p>Let us consider how we might design a restaurant data class. What would a restaurant need to have stored as data? It is useful to envision how a user might interact with the app. A user might want to browse a list of restaurants available, and so we need a way to identify each restaurant: its <em>name</em>. After selecting a restaurant, a user needs to see what food is available to order, so we need to store a <em>food menu</em> for each restaurant. Finally, couriers need to know where restaurants are in order to pick up food orders, and so we need to store a <em>location</em> for each restaurant.</p>
<p>Each of these three pieces of information—restaurant name, food menu, and location—are appropriate <em>attributes</em> for the restaurant. Now we have to decide what data types to use to represent this data. You have much practice doing this, stretching back to all the way to the beginning of this course! Yet as well see, there are design decisions to be made even when choosing individual attributes.</p>
<ul>
<li><p>The restaurant <em>name</em> is fairly straightforward: well use a <code>str</code> to represent it.</p></li>
<li><p>The restaurant <em>menu</em> has a few different options. For this section, well use a <code>dict</code> that maps the names of dishes (<code>str</code>s) to their price (<code>float</code>s).</p></li>
<li><p>There are many ways to represent a restaurants location. For example, we could store its address, as a <code>str</code>. Or we could improve the precision of our data and store the latitude and longitude (a tuple of <code>float</code>s), which would be useful for displaying restaurants on maps.</p>
<p>For now, well store both address and latitude/longitude information for each restaurant. It may be that both representations are useful, and should be stored by our application.</p></li>
</ul>
<div class="sourceCode" id="cb2-9daaec5a41"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-9daaec5a41"><a href="#cb2-1-9daaec5a41"></a><span class="at">@dataclass</span></span>
<span id="cb2-2-9daaec5a41"><a href="#cb2-2-9daaec5a41"></a><span class="kw">class</span> Restaurant:</span>
<span id="cb2-3-9daaec5a41"><a href="#cb2-3-9daaec5a41"></a> <span class="co">&quot;&quot;&quot;A place that serves food.</span></span>
<span id="cb2-4-9daaec5a41"><a href="#cb2-4-9daaec5a41"></a></span>
<span id="cb2-5-9daaec5a41"><a href="#cb2-5-9daaec5a41"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb2-6-9daaec5a41"><a href="#cb2-6-9daaec5a41"></a><span class="co"> - name: the name of the restaurant</span></span>
<span id="cb2-7-9daaec5a41"><a href="#cb2-7-9daaec5a41"></a><span class="co"> - address: the address of the restaurant</span></span>
<span id="cb2-8-9daaec5a41"><a href="#cb2-8-9daaec5a41"></a><span class="co"> - menu: the menu of the restaurant with the name of the dish mapping to</span></span>
<span id="cb2-9-9daaec5a41"><a href="#cb2-9-9daaec5a41"></a><span class="co"> the price</span></span>
<span id="cb2-10-9daaec5a41"><a href="#cb2-10-9daaec5a41"></a><span class="co"> - location: the location of the restaurant as (latitude, longitude)</span></span>
<span id="cb2-11-9daaec5a41"><a href="#cb2-11-9daaec5a41"></a></span>
<span id="cb2-12-9daaec5a41"><a href="#cb2-12-9daaec5a41"></a><span class="co"> Representation Invariants:</span></span>
<span id="cb2-13-9daaec5a41"><a href="#cb2-13-9daaec5a41"></a><span class="co"> - all(self.menu[item] &gt;= 0 for item in self.menu)</span></span>
<span id="cb2-14-9daaec5a41"><a href="#cb2-14-9daaec5a41"></a><span class="co"> - -90 &lt;= self.location[0] &lt;= 90</span></span>
<span id="cb2-15-9daaec5a41"><a href="#cb2-15-9daaec5a41"></a><span class="co"> - -180 &lt;= self.location[1] &lt;= 180</span></span>
<span id="cb2-16-9daaec5a41"><a href="#cb2-16-9daaec5a41"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-17-9daaec5a41"><a href="#cb2-17-9daaec5a41"></a> name: <span class="bu">str</span></span>
<span id="cb2-18-9daaec5a41"><a href="#cb2-18-9daaec5a41"></a> address: <span class="bu">str</span></span>
<span id="cb2-19-9daaec5a41"><a href="#cb2-19-9daaec5a41"></a> menu: <span class="bu">dict</span>[<span class="bu">str</span>, <span class="bu">float</span>]</span>
<span id="cb2-20-9daaec5a41"><a href="#cb2-20-9daaec5a41"></a> location: <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">float</span>]</span></code></pre></div>
<p>There is one other subtlety with this design before we move on. The menu is a compound data type, and we chose to represent it using one of Pythons built-in data structures. But another approach would have been to create a completely separate <code>Menu</code> data class. That is certainly a viable option, but we were wary of falling into the trap of creating too many classes in our simulation. Each new class we create introduces a little more complexity into our program, and for a relatively simple class for a menu, we did not think this additional complexity was worth it.</p>
<p>On the flip side, we could have used a dictionary to represent a restaurant instead of a <code>Restaurant</code> data class. This would have reduced on area of complexity (the number of classes to keep track of), but introduced another (the “valid” keys of a dictionary used to represent a restaurant). There is always a trade-off in design, and when evaluating trade-offs one should never forget cognitive load on the programmer.</p>
<h2 id="designing-the-order-data-class-9daaec5a41">Designing the <code>Order</code> data class</h2>
<p>Now lets discuss a data class thats a bit more abstract: a single order. An order must track the <em>customer</em> who placed the order, the <em>restaurant</em> where the food is being ordered from, and the <em>food items</em> that are being ordered. We can also imagine that an order should have an associated courier who has been assigned to deliver the order. Well also keep track of when the order was created, and when the order is completed.</p>
<p>Theres one subtlety with two of these attributes: the associated courier and the time when the order is completed might only be assigned values after the order has been created. So we use a default value <code>None</code> to assign to these two instance attributes when an <code>Order</code> is first created. We could implement this by converting the data class to a general class and writing our own <code>__init__</code> method, but instead well take advantage of a new feature with data classes: the ability to specify default values for an instance attribute after the type annotation.</p>
<div class="sourceCode" id="cb3-9daaec5a41"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-9daaec5a41"><a href="#cb3-1-9daaec5a41"></a><span class="at">@dataclass</span></span>
<span id="cb3-2-9daaec5a41"><a href="#cb3-2-9daaec5a41"></a><span class="kw">class</span> Order:</span>
<span id="cb3-3-9daaec5a41"><a href="#cb3-3-9daaec5a41"></a> <span class="co">&quot;&quot;&quot;A food order from a customer.</span></span>
<span id="cb3-4-9daaec5a41"><a href="#cb3-4-9daaec5a41"></a></span>
<span id="cb3-5-9daaec5a41"><a href="#cb3-5-9daaec5a41"></a><span class="co"> Attributes:</span></span>
<span id="cb3-6-9daaec5a41"><a href="#cb3-6-9daaec5a41"></a><span class="co"> - customer: the name of the customer who placed this order</span></span>
<span id="cb3-7-9daaec5a41"><a href="#cb3-7-9daaec5a41"></a><span class="co"> - restaurant: the name of the restaurant the order is placed for</span></span>
<span id="cb3-8-9daaec5a41"><a href="#cb3-8-9daaec5a41"></a><span class="co"> - food_items: a mapping from names of food to the quantity being ordered</span></span>
<span id="cb3-9-9daaec5a41"><a href="#cb3-9-9daaec5a41"></a><span class="co"> - start_time: the time the order was placed</span></span>
<span id="cb3-10-9daaec5a41"><a href="#cb3-10-9daaec5a41"></a><span class="co"> - courier: the courier assigned to this order (initially None)</span></span>
<span id="cb3-11-9daaec5a41"><a href="#cb3-11-9daaec5a41"></a><span class="co"> - end_time: the time the order was completed by the courier (initially None)</span></span>
<span id="cb3-12-9daaec5a41"><a href="#cb3-12-9daaec5a41"></a></span>
<span id="cb3-13-9daaec5a41"><a href="#cb3-13-9daaec5a41"></a><span class="co"> Representation Invariants:</span></span>
<span id="cb3-14-9daaec5a41"><a href="#cb3-14-9daaec5a41"></a><span class="co"> - self.food_items != []</span></span>
<span id="cb3-15-9daaec5a41"><a href="#cb3-15-9daaec5a41"></a><span class="co"> - all(self.food_items[i][1] &gt; 0 for i in range(len(self.food_items)))</span></span>
<span id="cb3-16-9daaec5a41"><a href="#cb3-16-9daaec5a41"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-17-9daaec5a41"><a href="#cb3-17-9daaec5a41"></a> customer: Customer</span>
<span id="cb3-18-9daaec5a41"><a href="#cb3-18-9daaec5a41"></a> restaurant: Restaurant</span>
<span id="cb3-19-9daaec5a41"><a href="#cb3-19-9daaec5a41"></a> food_items: <span class="bu">dict</span>[<span class="bu">str</span>, <span class="bu">int</span>]</span>
<span id="cb3-20-9daaec5a41"><a href="#cb3-20-9daaec5a41"></a> start_time: datetime.datetime</span>
<span id="cb3-21-9daaec5a41"><a href="#cb3-21-9daaec5a41"></a> courier: Optional[Courier] <span class="op">=</span> <span class="va">None</span></span>
<span id="cb3-22-9daaec5a41"><a href="#cb3-22-9daaec5a41"></a> end_time: Optional[datetime.datetime] <span class="op">=</span> <span class="va">None</span></span></code></pre></div>
<p>The line <code>courier: Optional[Courier] = None</code> is how we define an instance attribute <code>Courier</code> with a default value of <code>None</code>. The type annotation <code>Optional[Courier]</code> means that this attribute can either be <code>None</code> or a <code>Courier</code> instance. Similarly, the <code>end_time</code> attribute must be either <code>None</code> (its initial value) or a <code>datetime.datetime</code> value.</p>
<p>Here is how we could use this class (note that <code>Customer</code> is currently an empty data class, and so is instantiated simply as <code>Customer()</code>):</p>
<div class="sourceCode" id="cb4-9daaec5a41"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-9daaec5a41"><a href="#cb4-1-9daaec5a41"></a><span class="op">&gt;&gt;&gt;</span> david <span class="op">=</span> Customer()</span>
<span id="cb4-2-9daaec5a41"><a href="#cb4-2-9daaec5a41"></a><span class="op">&gt;&gt;&gt;</span> mcdonalds <span class="op">=</span> Restaurant(name<span class="op">=</span><span class="st">&#39;McDonalds&#39;</span>, address<span class="op">=</span><span class="st">&#39;160 Spadina Ave&#39;</span>,</span>
<span id="cb4-3-9daaec5a41"><a href="#cb4-3-9daaec5a41"></a>... menu<span class="op">=</span>{<span class="st">&#39;fries&#39;</span>: <span class="fl">4.5</span>}, location<span class="op">=</span>(<span class="fl">43.649</span>, <span class="op">-</span><span class="fl">79.397</span>))</span>
<span id="cb4-4-9daaec5a41"><a href="#cb4-4-9daaec5a41"></a><span class="op">&gt;&gt;&gt;</span> order <span class="op">=</span> Order(customer<span class="op">=</span>david, restaurant<span class="op">=</span>mcdonalds,</span>
<span id="cb4-5-9daaec5a41"><a href="#cb4-5-9daaec5a41"></a>... food_items<span class="op">=</span>{<span class="st">&#39;fries&#39;</span>: <span class="dv">10</span>},</span>
<span id="cb4-6-9daaec5a41"><a href="#cb4-6-9daaec5a41"></a>... start_time<span class="op">=</span>datetime.datetime(<span class="dv">2020</span>, <span class="dv">11</span>, <span class="dv">5</span>, <span class="dv">11</span>, <span class="dv">30</span>))</span>
<span id="cb4-7-9daaec5a41"><a href="#cb4-7-9daaec5a41"></a></span>
<span id="cb4-8-9daaec5a41"><a href="#cb4-8-9daaec5a41"></a><span class="op">&gt;&gt;&gt;</span> order.courier <span class="kw">is</span> <span class="va">None</span> <span class="co"># Illustrating default values</span></span>
<span id="cb4-9-9daaec5a41"><a href="#cb4-9-9daaec5a41"></a><span class="va">True</span></span>
<span id="cb4-10-9daaec5a41"><a href="#cb4-10-9daaec5a41"></a><span class="op">&gt;&gt;&gt;</span> order.end_time <span class="kw">is</span> <span class="va">None</span></span>
<span id="cb4-11-9daaec5a41"><a href="#cb4-11-9daaec5a41"></a><span class="va">True</span></span></code></pre></div>
<h2 id="class-composition-9daaec5a41">Class composition</h2>
<p>Just as we saw earlier in the course that built-in collection types like lists can be nested within each other, classes can also be “nested” within each other through their instance attributes. Our above <code>Order</code> data class has attributes which are instances of other classes we have defined (<code>Customer</code>, <code>Restaurant</code>, and <code>Courier</code>).</p>
<p>The relationship between <code>Order</code> and these other classes is called <strong>class composition</strong>, and is a fundamental to object-oriented design. When we create classes for a computational model, these classes dont exist in isolation. They can interact with each other in several ways, one of which is composition. We use class composition to represent a “has a” relationship between two classes (we say that “an <code>Order</code> has a <code>Customer</code>”).<label for="sn-0-9daaec5a41" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-9daaec5a41" class="margin-toggle"/><span class="sidenote"> This is in contrast to inheritance, which defines an “is a” relationships between two classes, e.g. “<code>Stack1</code> is a <code>Stack</code>”.</span></p>
</section>
<br/> <a id="anchor-10-03"></a>
<header id="title-block-header-41d4a35682">
<h1 class="title">10.3 A “Manager” Class</h1>
</header>
<section>
<p>In the previous section, we defined four different data classes—<code>Restaurant</code>, <code>Customer</code>, <code>Courier</code>, <code>Order</code>—to represent different entities in our food delivery system. We must now determine how to keep track of all of these entities, and how they can interact with each other. For example, as a user I would want to be able to look up a list of restaurants in my area to order food from. In code, how does a single <code>Customer</code> object “know” about all the different <code>Restaurant</code>s in the system? Should each <code>Customer</code> have an attribute containing list of <code>Restaurant</code>s?<label for="sn-0-41d4a35682" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-41d4a35682" class="margin-toggle"/><span class="sidenote"> The question of how objects “know” about other objects is similar to the notion of variable <em>scope</em>. A variables scope determines where it can be accessed in a program; the scope of an object dictates the objects lifetime and who the object belongs to. But now consider our current problem domain, with the hundreds of restaurants and potential thousands of customers. What should the scope of all those objects be?</span></p>
<p>There are many ways to approach this problem. A common object-oriented design approach is to create a new manager class whose role is to keep track of all of the entities in the system and to mediate the interactions between them (like a customer placing a new order). This class is more complex than the others we saw in the last section, and so we will not use a data class, and instead use a general class with a custom initializer and keep most of the instance attributes private.</p>
<p>Here is the manager class well create for our food delivery system. The <code>FoodDeliverySystem</code> class will store (and have access to) every customer, courier, and restaurant represented in our system.</p>
<div class="sourceCode" id="cb1-41d4a35682"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-41d4a35682"><a href="#cb1-1-41d4a35682"></a><span class="kw">class</span> FoodDeliverySystem:</span>
<span id="cb1-2-41d4a35682"><a href="#cb1-2-41d4a35682"></a> <span class="co">&quot;&quot;&quot;A system that maintains all entities (restaurants, customers, couriers, and orders).</span></span>
<span id="cb1-3-41d4a35682"><a href="#cb1-3-41d4a35682"></a></span>
<span id="cb1-4-41d4a35682"><a href="#cb1-4-41d4a35682"></a><span class="co"> Public Attributes:</span></span>
<span id="cb1-5-41d4a35682"><a href="#cb1-5-41d4a35682"></a><span class="co"> - name: the name of this food delivery system</span></span>
<span id="cb1-6-41d4a35682"><a href="#cb1-6-41d4a35682"></a></span>
<span id="cb1-7-41d4a35682"><a href="#cb1-7-41d4a35682"></a><span class="co"> Representation Invariants:</span></span>
<span id="cb1-8-41d4a35682"><a href="#cb1-8-41d4a35682"></a><span class="co"> - self.name != &#39;&#39;</span></span>
<span id="cb1-9-41d4a35682"><a href="#cb1-9-41d4a35682"></a><span class="co"> - all(r == self._restaurants[r].name for r in self._restaurants)</span></span>
<span id="cb1-10-41d4a35682"><a href="#cb1-10-41d4a35682"></a><span class="co"> - all(c == self._customers[c].name for c in self._customers)</span></span>
<span id="cb1-11-41d4a35682"><a href="#cb1-11-41d4a35682"></a><span class="co"> - all(c == self._couriers[c].name for c in self._couriers)</span></span>
<span id="cb1-12-41d4a35682"><a href="#cb1-12-41d4a35682"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-13-41d4a35682"><a href="#cb1-13-41d4a35682"></a> name: <span class="bu">str</span></span>
<span id="cb1-14-41d4a35682"><a href="#cb1-14-41d4a35682"></a></span>
<span id="cb1-15-41d4a35682"><a href="#cb1-15-41d4a35682"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb1-16-41d4a35682"><a href="#cb1-16-41d4a35682"></a> <span class="co"># - _restaurants: a mapping from restaurant name to Restaurant object.</span></span>
<span id="cb1-17-41d4a35682"><a href="#cb1-17-41d4a35682"></a> <span class="co"># This represents all the restaurants in the system.</span></span>
<span id="cb1-18-41d4a35682"><a href="#cb1-18-41d4a35682"></a> <span class="co"># - _customers: a mapping from customer name to Customer object.</span></span>
<span id="cb1-19-41d4a35682"><a href="#cb1-19-41d4a35682"></a> <span class="co"># This represents all the customers in the system.</span></span>
<span id="cb1-20-41d4a35682"><a href="#cb1-20-41d4a35682"></a> <span class="co"># - _couriers: a mapping from courier name to Courier object.</span></span>
<span id="cb1-21-41d4a35682"><a href="#cb1-21-41d4a35682"></a> <span class="co"># This represents all the couriers in the system.</span></span>
<span id="cb1-22-41d4a35682"><a href="#cb1-22-41d4a35682"></a> <span class="co"># - _orders: a list of all orders (both open and completed orders).</span></span>
<span id="cb1-23-41d4a35682"><a href="#cb1-23-41d4a35682"></a></span>
<span id="cb1-24-41d4a35682"><a href="#cb1-24-41d4a35682"></a> _restaurants: <span class="bu">dict</span>[<span class="bu">str</span>, Restaurant]</span>
<span id="cb1-25-41d4a35682"><a href="#cb1-25-41d4a35682"></a> _customers: <span class="bu">dict</span>[<span class="bu">str</span>, Customer]</span>
<span id="cb1-26-41d4a35682"><a href="#cb1-26-41d4a35682"></a> _couriers: <span class="bu">dict</span>[<span class="bu">str</span>, Courier]</span>
<span id="cb1-27-41d4a35682"><a href="#cb1-27-41d4a35682"></a> _orders: <span class="bu">list</span>[Order]</span>
<span id="cb1-28-41d4a35682"><a href="#cb1-28-41d4a35682"></a></span>
<span id="cb1-29-41d4a35682"><a href="#cb1-29-41d4a35682"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, name: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-30-41d4a35682"><a href="#cb1-30-41d4a35682"></a> <span class="co">&quot;&quot;&quot;Initialize a new food delivery system with the given company name.</span></span>
<span id="cb1-31-41d4a35682"><a href="#cb1-31-41d4a35682"></a></span>
<span id="cb1-32-41d4a35682"><a href="#cb1-32-41d4a35682"></a><span class="co"> The system starts with no entities.</span></span>
<span id="cb1-33-41d4a35682"><a href="#cb1-33-41d4a35682"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-34-41d4a35682"><a href="#cb1-34-41d4a35682"></a> <span class="va">self</span>.name <span class="op">=</span> name</span>
<span id="cb1-35-41d4a35682"><a href="#cb1-35-41d4a35682"></a></span>
<span id="cb1-36-41d4a35682"><a href="#cb1-36-41d4a35682"></a> <span class="va">self</span>._restaurants <span class="op">=</span> {}</span>
<span id="cb1-37-41d4a35682"><a href="#cb1-37-41d4a35682"></a> <span class="va">self</span>._customers <span class="op">=</span> {}</span>
<span id="cb1-38-41d4a35682"><a href="#cb1-38-41d4a35682"></a> <span class="va">self</span>._couriers <span class="op">=</span> {}</span>
<span id="cb1-39-41d4a35682"><a href="#cb1-39-41d4a35682"></a> <span class="va">self</span>._orders <span class="op">=</span> []</span></code></pre></div>
<h2 id="changing-state-41d4a35682">Changing state</h2>
<p>What we have done so far is model the <em>static</em> properties of our food delivery system, that is, the attributes that are necessary to capture a particular snapshot of the state of the system at a specific moment in time. Next, were going to look at how to model the <em>dynamic</em> properties of the system: how the entities interact with each other and cause the system state to change over time.</p>
<h3 id="adding-entities-41d4a35682">Adding entities</h3>
<p>Though a <code>FoodDeliverySystem</code> instance starts off empty, we can define simple methods to add entities to the system.<label for="sn-1-41d4a35682" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-41d4a35682" class="margin-toggle"/><span class="sidenote"> You can picture this happening when a new restaurant/customer/courier signs up for our app.</span> By making our collection attributes private and requiring client code call these methods, we can check for uniqueness of these entity names as well.</p>
<div class="sourceCode" id="cb2-41d4a35682"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-41d4a35682"><a href="#cb2-1-41d4a35682"></a><span class="kw">class</span> FoodDeliverySystem:</span>
<span id="cb2-2-41d4a35682"><a href="#cb2-2-41d4a35682"></a> ...</span>
<span id="cb2-3-41d4a35682"><a href="#cb2-3-41d4a35682"></a></span>
<span id="cb2-4-41d4a35682"><a href="#cb2-4-41d4a35682"></a> <span class="kw">def</span> add_restaurant(<span class="va">self</span>, restaurant: Restaurant) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-5-41d4a35682"><a href="#cb2-5-41d4a35682"></a> <span class="co">&quot;&quot;&quot;Add the given restaurant to this system.</span></span>
<span id="cb2-6-41d4a35682"><a href="#cb2-6-41d4a35682"></a></span>
<span id="cb2-7-41d4a35682"><a href="#cb2-7-41d4a35682"></a><span class="co"> Do NOT add the restaurant if one with the same name already exists.</span></span>
<span id="cb2-8-41d4a35682"><a href="#cb2-8-41d4a35682"></a></span>
<span id="cb2-9-41d4a35682"><a href="#cb2-9-41d4a35682"></a><span class="co"> Return whether the restaurant was successfully added to this system.</span></span>
<span id="cb2-10-41d4a35682"><a href="#cb2-10-41d4a35682"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-11-41d4a35682"><a href="#cb2-11-41d4a35682"></a> <span class="cf">if</span> restaurant.name <span class="kw">in</span> <span class="va">self</span>._restaurants:</span>
<span id="cb2-12-41d4a35682"><a href="#cb2-12-41d4a35682"></a> <span class="cf">return</span> <span class="va">False</span></span>
<span id="cb2-13-41d4a35682"><a href="#cb2-13-41d4a35682"></a> <span class="cf">else</span>:</span>
<span id="cb2-14-41d4a35682"><a href="#cb2-14-41d4a35682"></a> <span class="va">self</span>._restaurants[restaurant.name] <span class="op">=</span> restaurant</span>
<span id="cb2-15-41d4a35682"><a href="#cb2-15-41d4a35682"></a> <span class="cf">return</span> <span class="va">True</span></span>
<span id="cb2-16-41d4a35682"><a href="#cb2-16-41d4a35682"></a></span>
<span id="cb2-17-41d4a35682"><a href="#cb2-17-41d4a35682"></a> <span class="kw">def</span> add_customer(<span class="va">self</span>, customer: Customer) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-18-41d4a35682"><a href="#cb2-18-41d4a35682"></a> <span class="co">&quot;&quot;&quot;Add the given customer to this system.</span></span>
<span id="cb2-19-41d4a35682"><a href="#cb2-19-41d4a35682"></a></span>
<span id="cb2-20-41d4a35682"><a href="#cb2-20-41d4a35682"></a><span class="co"> Do NOT add the customer if one with the same name already exists.</span></span>
<span id="cb2-21-41d4a35682"><a href="#cb2-21-41d4a35682"></a></span>
<span id="cb2-22-41d4a35682"><a href="#cb2-22-41d4a35682"></a><span class="co"> Return whether the customer was successfully added to this system.</span></span>
<span id="cb2-23-41d4a35682"><a href="#cb2-23-41d4a35682"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-24-41d4a35682"><a href="#cb2-24-41d4a35682"></a> <span class="co"># Similar implementation to add_restaurant</span></span>
<span id="cb2-25-41d4a35682"><a href="#cb2-25-41d4a35682"></a></span>
<span id="cb2-26-41d4a35682"><a href="#cb2-26-41d4a35682"></a> <span class="kw">def</span> add_courier(<span class="va">self</span>, courier: Courier) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb2-27-41d4a35682"><a href="#cb2-27-41d4a35682"></a> <span class="co">&quot;&quot;&quot;Add the given courier to this system.</span></span>
<span id="cb2-28-41d4a35682"><a href="#cb2-28-41d4a35682"></a></span>
<span id="cb2-29-41d4a35682"><a href="#cb2-29-41d4a35682"></a><span class="co"> Do NOT add the courier if one with the same name already exists.</span></span>
<span id="cb2-30-41d4a35682"><a href="#cb2-30-41d4a35682"></a></span>
<span id="cb2-31-41d4a35682"><a href="#cb2-31-41d4a35682"></a><span class="co"> Return whether the courier was successfully added to this system.</span></span>
<span id="cb2-32-41d4a35682"><a href="#cb2-32-41d4a35682"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-33-41d4a35682"><a href="#cb2-33-41d4a35682"></a> <span class="co"># Similar implementation to add_restaurant</span></span></code></pre></div>
<h3 id="placing-orders-41d4a35682">Placing orders</h3>
<p>The main driving force in our simulation is customer orders. When a customer places an order, a chain of events is triggered:</p>
<ol type="1">
<li>The order is sent to the restaurant and to the assigned courier.</li>
<li>The courier travels to the restaurant and picks up the food, and then brings it to the customer.</li>
<li>Once the courier has reached their destination, they indicate that the delivery has been made.</li>
</ol>
<p>To represent these events in our program, we need to create functions that mutate the state of the system. Where should we create these functions? We could write them as top-level functions, or as methods of one of our existing entity classes (turning that class from a data class into a general class). We have previously said that one of the roles of the <code>FoodDeliverySystem</code> is to mediate interactions between the various entities in the system, and so this makes it a natural class to add these mutating methods.</p>
<div class="sourceCode" id="cb3-41d4a35682"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-41d4a35682"><a href="#cb3-1-41d4a35682"></a><span class="kw">class</span> FoodDeliverySystem:</span>
<span id="cb3-2-41d4a35682"><a href="#cb3-2-41d4a35682"></a> ...</span>
<span id="cb3-3-41d4a35682"><a href="#cb3-3-41d4a35682"></a></span>
<span id="cb3-4-41d4a35682"><a href="#cb3-4-41d4a35682"></a> <span class="kw">def</span> place_order(<span class="va">self</span>, order: Order) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-5-41d4a35682"><a href="#cb3-5-41d4a35682"></a> <span class="co">&quot;&quot;&quot;Record the new given order.</span></span>
<span id="cb3-6-41d4a35682"><a href="#cb3-6-41d4a35682"></a></span>
<span id="cb3-7-41d4a35682"><a href="#cb3-7-41d4a35682"></a><span class="co"> Assign a courier to this new order (if a courier is available).</span></span>
<span id="cb3-8-41d4a35682"><a href="#cb3-8-41d4a35682"></a></span>
<span id="cb3-9-41d4a35682"><a href="#cb3-9-41d4a35682"></a><span class="co"> Preconditions:</span></span>
<span id="cb3-10-41d4a35682"><a href="#cb3-10-41d4a35682"></a><span class="co"> - order not in self.orders</span></span>
<span id="cb3-11-41d4a35682"><a href="#cb3-11-41d4a35682"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-12-41d4a35682"><a href="#cb3-12-41d4a35682"></a></span>
<span id="cb3-13-41d4a35682"><a href="#cb3-13-41d4a35682"></a> <span class="kw">def</span> complete_order(<span class="va">self</span>, order: Order) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-14-41d4a35682"><a href="#cb3-14-41d4a35682"></a> <span class="co">&quot;&quot;&quot;Mark the given order as complete.</span></span>
<span id="cb3-15-41d4a35682"><a href="#cb3-15-41d4a35682"></a></span>
<span id="cb3-16-41d4a35682"><a href="#cb3-16-41d4a35682"></a><span class="co"> Make the courier who was assigned this order available to take a new order.</span></span>
<span id="cb3-17-41d4a35682"><a href="#cb3-17-41d4a35682"></a></span>
<span id="cb3-18-41d4a35682"><a href="#cb3-18-41d4a35682"></a><span class="co"> Preconditions:</span></span>
<span id="cb3-19-41d4a35682"><a href="#cb3-19-41d4a35682"></a><span class="co"> - order in self.orders</span></span>
<span id="cb3-20-41d4a35682"><a href="#cb3-20-41d4a35682"></a><span class="co"> &quot;&quot;&quot;</span></span></code></pre></div>
<p>We could then place an order from a customer using <code>FoodDeliverySystem.place_order</code>, which would be responsible for both recording the order and assigning a courier to that order. <code>FoodDeliverySystem.complete_order</code> does the opposite, marking the order as complete and un-assigning the courier so that they are free to take a new order. With both <code>FoodDeliverySystem.place_order</code> and <code>FoodDeliverySystem.complete_order</code>, we can begin to see how a simulation might take place where many customers are placing orders to different restaurants that are being delivered by available couriers.</p>
<p>Note that this discussion should make sense even though we havent implemented either of these methods. Questions like “How do we choose which courier to assign to a new order?” and “How do we mark an order as complete?” are about <em>implementation</em> rather than the public interface of these methods. Well discuss one potential implementation of these methods in lecture, but we welcome you to attempt your own implementations as an exercise.</p>
</section>
<br/> <a id="anchor-10-04"></a>
<header id="title-block-header-83894c018c">
<h1 class="title">10.4 Food Delivery Events</h1>
</header>
<section>
<p>In the previous two sections, we discussed the key classes we can use to represent a food delivery system: data classes <code>Restaurant</code>, <code>Customer</code>, <code>Courier</code>, and <code>Order</code> to represent individual entities, and a <code>FoodDeliverySystem</code> class to manage all of them. But even though the <code>FoodDeliverySystem</code> class has methods that allow us to <em>mutate</em> the state of the system, you might wonder: who is responsible for actually calling these methods?</p>
<p>If we were building a “real-world” app, we would need to write code that explicitly connects user actions (e.g., pressing a button on a mobile app) to these methods, and almost certainly rely on an existing software framework to do much of the “connecting” for us.</p>
<p>The approach were taking in this chapter is a bit different. Instead of writing the code necessary to respond to real-world actions, we are going to create a <em>simulation</em> that uses a combination of preset and random data to simulate these kinds of real-world actions. The driving force of our simulation will be <em>events</em> that cause our system to mutate. For example, a “new order” event for when a customer places an order, and a “complete order” event for when a courier has delivered an order to a customer.</p>
<h2 id="the-event-interface-83894c018c">The <code>Event</code> interface</h2>
<p>There are many other events we might add to the simulation, but they clearly have something in common: they are events that cause the state of the simulation to change. In <a href="../09-abstraction/08-common-interfaces.html">9.8 Defining a Shared Public Interface with Inheritance</a>, we learned how to define an abstract class to represent a shared public interface, and used inheritance to relate this abstract class to concrete subclasses that must adhere to this interface. In our case, well define abstract <code>Event</code> class with subclasses <code>NewOrderEvent</code> and <code>CompleteOrderEvent</code> to represent different kinds of events.</p>
<p>Here is an initial definition of this <code>Event</code> interface. The class has one abstract method, <code>handle_event</code>, which is how we connect each event to a change in the food delivery system.</p>
<div class="sourceCode" id="cb1-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-83894c018c"><a href="#cb1-1-83894c018c"></a><span class="kw">class</span> Event:</span>
<span id="cb1-2-83894c018c"><a href="#cb1-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;An abstract class representing an event in a food delivery simulation.</span></span>
<span id="cb1-3-83894c018c"><a href="#cb1-3-83894c018c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-4-83894c018c"><a href="#cb1-4-83894c018c"></a></span>
<span id="cb1-5-83894c018c"><a href="#cb1-5-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-6-83894c018c"><a href="#cb1-6-83894c018c"></a> <span class="co">&quot;&quot;&quot;Mutate the given food delivery system to process this event.&quot;&quot;&quot;</span></span>
<span id="cb1-7-83894c018c"><a href="#cb1-7-83894c018c"></a> <span class="cf">raise</span> <span class="pp">NotImplementedError</span></span></code></pre></div>
<p>Each <code>Event</code> subclass is responsible for implementing <code>handle_event</code> based on the type of change the subclass represents. For example, the <code>NewOrderEvent.handle_event</code> method should, well, add a new order to the system. In order to implement <code>handle_event</code>, each subclass will probably need its own set of instance attributes to represent the details of the event (e.g., what order to add in a <code>NewOrderEvent</code>).</p>
<p>But before we discuss these subclass-specific attributes, well take a brief detour well introduce another feature of inheritance: shared instance attributes. Specifically, our simulation will need to know exactly <em>when</em> every event should happen, which every event object needs to keep track of.</p>
<h2 id="common-instance-attributes-83894c018c">Common instance attributes</h2>
<p>We have seen that an abstract superclass declare methods that all its subclasses need to have in common, establishing a shared public interface. A superclass can also declare <em>public instance attributes</em> that its subclasses must have in common. For our <code>Event</code> class, we can establish that all event subclasses will have a timestamp indicating when the event took place. This <code>timestamp</code> attribute becomes part of the shared public interface of each subclass.</p>
<div class="sourceCode" id="cb2-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-83894c018c"><a href="#cb2-1-83894c018c"></a><span class="im">import</span> datetime</span>
<span id="cb2-2-83894c018c"><a href="#cb2-2-83894c018c"></a></span>
<span id="cb2-3-83894c018c"><a href="#cb2-3-83894c018c"></a></span>
<span id="cb2-4-83894c018c"><a href="#cb2-4-83894c018c"></a><span class="kw">class</span> Event:</span>
<span id="cb2-5-83894c018c"><a href="#cb2-5-83894c018c"></a> <span class="co">&quot;&quot;&quot;An abstract class representing an event in a food delivery simulation.</span></span>
<span id="cb2-6-83894c018c"><a href="#cb2-6-83894c018c"></a></span>
<span id="cb2-7-83894c018c"><a href="#cb2-7-83894c018c"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb2-8-83894c018c"><a href="#cb2-8-83894c018c"></a><span class="co"> - timestamp: the start time of the event</span></span>
<span id="cb2-9-83894c018c"><a href="#cb2-9-83894c018c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-10-83894c018c"><a href="#cb2-10-83894c018c"></a> timestamp: datetime.datetime</span></code></pre></div>
<p>Even though abstract classes should not be instantiated directly, we provide an initializer to initialize the common attributes (namely, <code>timestamp</code>):</p>
<div class="sourceCode" id="cb3-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-83894c018c"><a href="#cb3-1-83894c018c"></a><span class="im">import</span> datetime</span>
<span id="cb3-2-83894c018c"><a href="#cb3-2-83894c018c"></a></span>
<span id="cb3-3-83894c018c"><a href="#cb3-3-83894c018c"></a></span>
<span id="cb3-4-83894c018c"><a href="#cb3-4-83894c018c"></a><span class="kw">class</span> Event:</span>
<span id="cb3-5-83894c018c"><a href="#cb3-5-83894c018c"></a> <span class="co">&quot;&quot;&quot;An abstract class representing an event in a food delivery simulation.</span></span>
<span id="cb3-6-83894c018c"><a href="#cb3-6-83894c018c"></a></span>
<span id="cb3-7-83894c018c"><a href="#cb3-7-83894c018c"></a><span class="co"> Instance Attributes:</span></span>
<span id="cb3-8-83894c018c"><a href="#cb3-8-83894c018c"></a><span class="co"> - timestamp: the start time of the event</span></span>
<span id="cb3-9-83894c018c"><a href="#cb3-9-83894c018c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb3-10-83894c018c"><a href="#cb3-10-83894c018c"></a> timestamp: datetime.datetime</span>
<span id="cb3-11-83894c018c"><a href="#cb3-11-83894c018c"></a></span>
<span id="cb3-12-83894c018c"><a href="#cb3-12-83894c018c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, timestamp: datetime.datetime) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb3-13-83894c018c"><a href="#cb3-13-83894c018c"></a> <span class="co">&quot;&quot;&quot;Initialize this event with the given timestamp.&quot;&quot;&quot;</span></span>
<span id="cb3-14-83894c018c"><a href="#cb3-14-83894c018c"></a> <span class="va">self</span>.timestamp <span class="op">=</span> timestamp</span></code></pre></div>
<p>Now lets create a new class that inherits from <code>Event</code>:</p>
<div class="sourceCode" id="cb4-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-83894c018c"><a href="#cb4-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb4-2-83894c018c"><a href="#cb4-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;An event where a customer places an order for a restaurant.&quot;&quot;&quot;</span></span></code></pre></div>
<p>Remember that subclasses will inherit all the methods from their superclass. So when we attempt to initialize a <code>NewOrderEvent</code>, the Python interpreter will call <code>Event.__init__</code> (because <code>NewOrderEvent</code> did not override the parents <code>__init__</code> method). This means we <em>must</em> provide a <code>datetime.datetime</code> object as the first argument when creating a new <code>NewOrderEvent</code> object:</p>
<div class="sourceCode" id="cb5-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-83894c018c"><a href="#cb5-1-83894c018c"></a><span class="op">&gt;&gt;&gt;</span> e <span class="op">=</span> NewOrderEvent()</span>
<span id="cb5-2-83894c018c"><a href="#cb5-2-83894c018c"></a>Traceback (most recent call last):</span>
<span id="cb5-3-83894c018c"><a href="#cb5-3-83894c018c"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb5-4-83894c018c"><a href="#cb5-4-83894c018c"></a><span class="pp">TypeError</span>: <span class="fu">__init__</span>() missing <span class="dv">1</span> required positional argument: <span class="st">&#39;timestamp&#39;</span></span>
<span id="cb5-5-83894c018c"><a href="#cb5-5-83894c018c"></a><span class="op">&gt;&gt;&gt;</span> e <span class="op">=</span> NewOrderEvent(datetime.datetime(<span class="dv">2020</span>, <span class="dv">9</span>, <span class="dv">8</span>))</span>
<span id="cb5-6-83894c018c"><a href="#cb5-6-83894c018c"></a><span class="op">&gt;&gt;&gt;</span> e.timestamp</span>
<span id="cb5-7-83894c018c"><a href="#cb5-7-83894c018c"></a>datetime.datetime(<span class="dv">2020</span>, <span class="dv">7</span>, <span class="dv">20</span>, <span class="dv">0</span>, <span class="dv">0</span>)</span></code></pre></div>
<h2 id="subclass-specific-attributes-83894c018c">Subclass-specific attributes</h2>
<p>It is possible that subclasses need their own attributes in addition to the ones that are common through the base class. In these scenarios, we should document our new attributes in the subclass itself. We often make these attributes private, to avoid changing the public interface declared by the abstract superclass. We do <em>not</em> need to repeat the documentation for the <code>timestamp</code> attribute; our expectation is that users should read the documentation of both the <code>NewOrderEvent</code> and <code>Event</code> classes to get the full picture of how <code>NewOrderEvent</code> is used.</p>
<div class="sourceCode" id="cb6-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-83894c018c"><a href="#cb6-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb6-2-83894c018c"><a href="#cb6-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;An event representing a when a customer places an order at a restaurant.&quot;&quot;&quot;</span></span>
<span id="cb6-3-83894c018c"><a href="#cb6-3-83894c018c"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb6-4-83894c018c"><a href="#cb6-4-83894c018c"></a> <span class="co"># _order: the new order to be added to the FoodDeliverySystem</span></span>
<span id="cb6-5-83894c018c"><a href="#cb6-5-83894c018c"></a> _order: Order</span></code></pre></div>
<p>To initialize this new attribute, we must define a separate initializer for <code>NewOrderEvent</code>. Here is our first attempt:</p>
<div class="sourceCode" id="cb7-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-83894c018c"><a href="#cb7-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb7-2-83894c018c"><a href="#cb7-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;An event representing a when a customer places an order at a restaurant.&quot;&quot;&quot;</span></span>
<span id="cb7-3-83894c018c"><a href="#cb7-3-83894c018c"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb7-4-83894c018c"><a href="#cb7-4-83894c018c"></a> <span class="co"># _order: the new order to be added to the FoodDeliverySystem</span></span>
<span id="cb7-5-83894c018c"><a href="#cb7-5-83894c018c"></a> _order: Order</span>
<span id="cb7-6-83894c018c"><a href="#cb7-6-83894c018c"></a></span>
<span id="cb7-7-83894c018c"><a href="#cb7-7-83894c018c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, order: Order) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb7-8-83894c018c"><a href="#cb7-8-83894c018c"></a> <span class="co">&quot;&quot;&quot;Initialize a NewOrderEvent for the given order.&quot;&quot;&quot;</span></span>
<span id="cb7-9-83894c018c"><a href="#cb7-9-83894c018c"></a> <span class="va">self</span>._order <span class="op">=</span> order</span></code></pre></div>
<p>This code looks correct, but has a subtle bug. By defining our own initializer for <code>NewOrderEvent</code>, we have overridden the <code>Event.__init__</code> method. Python will no longer call <code>Event.__init__</code> when creating a new <code>NewOrderEvent</code> object. However, this is problematic because <strong>subclasses inherit methods, not attributes.</strong> This means that the public instance attribute <code>timestamp</code> is missing from our <code>NewOrderEvent</code> object:</p>
<div class="sourceCode" id="cb8-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-83894c018c"><a href="#cb8-1-83894c018c"></a><span class="op">&gt;&gt;&gt;</span> order <span class="op">=</span> ... <span class="co"># Assume we&#39;ve defined an Order object here</span></span>
<span id="cb8-2-83894c018c"><a href="#cb8-2-83894c018c"></a><span class="op">&gt;&gt;&gt;</span> event <span class="op">=</span> NewOrderEvent(order)</span>
<span id="cb8-3-83894c018c"><a href="#cb8-3-83894c018c"></a><span class="op">&gt;&gt;&gt;</span> event.timestamp</span>
<span id="cb8-4-83894c018c"><a href="#cb8-4-83894c018c"></a>Traceback (most recent call last):</span>
<span id="cb8-5-83894c018c"><a href="#cb8-5-83894c018c"></a> File <span class="st">&quot;&lt;input&gt;&quot;</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op">&lt;</span>module<span class="op">&gt;</span></span>
<span id="cb8-6-83894c018c"><a href="#cb8-6-83894c018c"></a><span class="pp">AttributeError</span>: <span class="st">&#39;NewOrderEvent&#39;</span> <span class="bu">object</span> has no attribute <span class="st">&#39;timestamp&#39;</span></span></code></pre></div>
<p>So how do we make <code>NewOrderEvent</code> have both an <code>_order</code> and <code>timestamp</code> attribute? We need to modify its initializer, since it is the responsibility of the initializer to give values to all instance attributes.</p>
<p>First, what <em>should</em> the value of the events <code>timestamp</code> be? A natural choice is that it should be the time that the order was placed—its <code>start_time</code> attribute. Here is our second attempt at the <code>NewOrderEvent.__init__</code> method:</p>
<div class="sourceCode" id="cb9-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-83894c018c"><a href="#cb9-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb9-2-83894c018c"><a href="#cb9-2-83894c018c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, order: Order) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb9-3-83894c018c"><a href="#cb9-3-83894c018c"></a> <span class="va">self</span>.timestamp <span class="op">=</span> order.start_time</span>
<span id="cb9-4-83894c018c"><a href="#cb9-4-83894c018c"></a> <span class="va">self</span>._order <span class="op">=</span> order</span></code></pre></div>
<p>However, initializing the <code>timestamp</code> attribute directly in the subclass is bad design; code has been duplicated and that makes <a href="https://en.wikipedia.org/wiki/Code_smell">our code smell bad</a>. Every time we modify the <code>Event</code> class to include new shared attributes, wed also need to modify <code>NewOrderEvent.__init__</code> (and the initializers of every other subclass) to initialize those attributes.</p>
<p>So instead, we modify <code>NewOrderEvent.__init__</code> so that it directly calls <code>Event.__init__</code>.<label for="sn-0-83894c018c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-83894c018c" class="margin-toggle"/><span class="sidenote"> Remember that when we call a method using the <code>&lt;Class&gt;.&lt;method&gt;</code> name, we need to pass in the <code>self</code> argument explicitly.</span> Here is our third and final version of this initializer:</p>
<div class="sourceCode" id="cb10-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-83894c018c"><a href="#cb10-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb10-2-83894c018c"><a href="#cb10-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;An event where a customer places an order for a restaurant.&quot;&quot;&quot;</span></span>
<span id="cb10-3-83894c018c"><a href="#cb10-3-83894c018c"></a> _order: Order</span>
<span id="cb10-4-83894c018c"><a href="#cb10-4-83894c018c"></a></span>
<span id="cb10-5-83894c018c"><a href="#cb10-5-83894c018c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, order: Order) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb10-6-83894c018c"><a href="#cb10-6-83894c018c"></a> Event.<span class="fu">__init__</span>(<span class="va">self</span>, order.start_time)</span>
<span id="cb10-7-83894c018c"><a href="#cb10-7-83894c018c"></a> <span class="va">self</span>._order <span class="op">=</span> order</span></code></pre></div>
<p>Now, whenever we call <code>NewOrderEvent.__init__</code>, Python also calls <code>Event.__init__</code>. This causes all shared instance attributes from <code>Event</code> to be “inherited” by the <code>NewOrderEvent</code> subclass.</p>
<p>To summarize, we must follow two rules when inheriting from a class that defines its own initializer:</p>
<ol type="1">
<li>The initializer of a subclass must call the initializer of its superclass to initialize all common attributes.</li>
<li>The initializer of a subclass is responsible for initializing any additional attributes that are specific to that subclass.</li>
</ol>
<h2 id="implementing-neworderevent.handle_event-83894c018c">Implementing <code>NewOrderEvent.handle_event</code></h2>
<p>Next, well show how to complete the implementation of <code>NewOrderEvent</code> by implementing its <code>handle_event</code> method. Our first attempt is quite simple, taking advantage of the methods we defined in <a href="03-manager-class.html">10.3 A “Manager” Class</a>.</p>
<div class="sourceCode" id="cb11-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-83894c018c"><a href="#cb11-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb11-2-83894c018c"><a href="#cb11-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;An event where a customer places an order for a restaurant.&quot;&quot;&quot;</span></span>
<span id="cb11-3-83894c018c"><a href="#cb11-3-83894c018c"></a> _order: Order</span>
<span id="cb11-4-83894c018c"><a href="#cb11-4-83894c018c"></a></span>
<span id="cb11-5-83894c018c"><a href="#cb11-5-83894c018c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, order: Order) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb11-6-83894c018c"><a href="#cb11-6-83894c018c"></a> Event.<span class="fu">__init__</span>(<span class="va">self</span>, timestamp)</span>
<span id="cb11-7-83894c018c"><a href="#cb11-7-83894c018c"></a> <span class="va">self</span>._order <span class="op">=</span> order</span>
<span id="cb11-8-83894c018c"><a href="#cb11-8-83894c018c"></a></span>
<span id="cb11-9-83894c018c"><a href="#cb11-9-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb11-10-83894c018c"><a href="#cb11-10-83894c018c"></a> <span class="co">&quot;&quot;&quot;Mutate system by placing an order.&quot;&quot;&quot;</span></span>
<span id="cb11-11-83894c018c"><a href="#cb11-11-83894c018c"></a> system.place_order(<span class="va">self</span>._order)</span></code></pre></div>
<p>Now, theres a subtle problem with this method that well return to at the end of this section. A good exercise is to pause here and try to think about what the problem might be.</p>
<h2 id="implementing-other-event-subclass-83894c018c">Implementing other <code>Event</code> subclass</h2>
<p>Below, weve shown the implementation of our <code>CompleteOrderEvent</code>, which is quite similar to <code>newOrderEvent</code>. The major difference is that its initializer takes an explicit <code>datetime.datetime</code> argument to represent when the given order is completed.<label for="sn-1-83894c018c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-83894c018c" class="margin-toggle"/><span class="sidenote"> By convention, the <code>timestamp</code> parameter is the first parameter, so that the subsequent parameters are seen as additional parameters needed by <code>NewOrderEvent</code> rather than <code>Event</code>. This example shows that initializers of subclasses can have different signatures than the initializer of their parent class.</span></p>
<div class="sourceCode" id="cb12-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-83894c018c"><a href="#cb12-1-83894c018c"></a><span class="kw">class</span> CompleteOrderEvent(Event):</span>
<span id="cb12-2-83894c018c"><a href="#cb12-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;When an order is delivered to a customer by a courier.&quot;&quot;&quot;</span></span>
<span id="cb12-3-83894c018c"><a href="#cb12-3-83894c018c"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb12-4-83894c018c"><a href="#cb12-4-83894c018c"></a> <span class="co"># _order: the order to be completed by this event</span></span>
<span id="cb12-5-83894c018c"><a href="#cb12-5-83894c018c"></a> _order: Order</span>
<span id="cb12-6-83894c018c"><a href="#cb12-6-83894c018c"></a></span>
<span id="cb12-7-83894c018c"><a href="#cb12-7-83894c018c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, timestamp: datetime.datetime, order: Order) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb12-8-83894c018c"><a href="#cb12-8-83894c018c"></a> Event.<span class="fu">__init__</span>(<span class="va">self</span>, timestamp)</span>
<span id="cb12-9-83894c018c"><a href="#cb12-9-83894c018c"></a> <span class="va">self</span>._order <span class="op">=</span> order</span>
<span id="cb12-10-83894c018c"><a href="#cb12-10-83894c018c"></a></span>
<span id="cb12-11-83894c018c"><a href="#cb12-11-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb12-12-83894c018c"><a href="#cb12-12-83894c018c"></a> <span class="co">&quot;&quot;&quot;Mutate the system by recording that the order has been delivered to the customer.&quot;&quot;&quot;</span></span>
<span id="cb12-13-83894c018c"><a href="#cb12-13-83894c018c"></a> system.complete_order(<span class="va">self</span>._order, <span class="va">self</span>.timestamp)</span></code></pre></div>
<h2 id="event-generation-83894c018c">Event generation</h2>
<p>We started off this section by asking, “when are the <code>FoodDeliverySystem</code> methods called”? We said that our simulation would have <code>Event</code> instances that would be responsible for calling these methods. But this really just changes the direction of our original question—it now becomes, “when are the <code>Event</code> instances created?”</p>
<p>One possible approach is to randomly create a whole set of events at the start of our simulation, and then process each of those events (in order of their <code>timestamp</code>). This approach works when the events are fairly simple and can be predictably generated all at once. However, one key feature of events in general is that <em>processing one event can cause other events to occur</em>. For example, when we process a <code>NewOrderEvent</code>, we expect that at some point in the future, a corresponding <code>CompleteOrderEvent</code> will occur.<label for="sn-2-83894c018c" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2-83894c018c" class="margin-toggle"/><span class="sidenote"> Once the delivery is started, it completes. This doesnt necessarily always happen in real life, but well assume it does for the purposes of this case study.</span></p>
<p>To model this behaviour, we change the return type of <code>handle_event</code> from <code>None</code> to <code>list[Event]</code>, where the return value is a list of the events <em>caused</em> by the current event.</p>
<div class="sourceCode" id="cb13-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-83894c018c"><a href="#cb13-1-83894c018c"></a><span class="kw">class</span> Event:</span>
<span id="cb13-2-83894c018c"><a href="#cb13-2-83894c018c"></a> ...</span>
<span id="cb13-3-83894c018c"><a href="#cb13-3-83894c018c"></a></span>
<span id="cb13-4-83894c018c"><a href="#cb13-4-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="bu">list</span>[Event]:</span>
<span id="cb13-5-83894c018c"><a href="#cb13-5-83894c018c"></a> <span class="co">&quot;&quot;&quot;Mutate the given food delivery system to process this event.</span></span>
<span id="cb13-6-83894c018c"><a href="#cb13-6-83894c018c"></a></span>
<span id="cb13-7-83894c018c"><a href="#cb13-7-83894c018c"></a><span class="co"> Return a new list of new events created by processing this event.</span></span>
<span id="cb13-8-83894c018c"><a href="#cb13-8-83894c018c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb13-9-83894c018c"><a href="#cb13-9-83894c018c"></a> <span class="cf">raise</span> <span class="pp">NotImplementedError</span></span></code></pre></div>
<p>Heres how we might change the <code>NewOrderEvent</code> to return a <code>CompleteOrderEvent</code> at some point in the future.</p>
<div class="sourceCode" id="cb14-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-83894c018c"><a href="#cb14-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb14-2-83894c018c"><a href="#cb14-2-83894c018c"></a> ...</span>
<span id="cb14-3-83894c018c"><a href="#cb14-3-83894c018c"></a></span>
<span id="cb14-4-83894c018c"><a href="#cb14-4-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="bu">list</span>[Event]:</span>
<span id="cb14-5-83894c018c"><a href="#cb14-5-83894c018c"></a> <span class="co">&quot;&quot;&quot;Mutate system by placing an order.&quot;&quot;&quot;</span></span>
<span id="cb14-6-83894c018c"><a href="#cb14-6-83894c018c"></a> system.place_order(<span class="va">self</span>._order)</span>
<span id="cb14-7-83894c018c"><a href="#cb14-7-83894c018c"></a></span>
<span id="cb14-8-83894c018c"><a href="#cb14-8-83894c018c"></a> <span class="co"># Create a new CompleteOrderEvent. Right now the completion time is</span></span>
<span id="cb14-9-83894c018c"><a href="#cb14-9-83894c018c"></a> <span class="co"># hard-coded as 10 minutes from the order creation.</span></span>
<span id="cb14-10-83894c018c"><a href="#cb14-10-83894c018c"></a> <span class="co"># How could be make this more realistic by taking into account the</span></span>
<span id="cb14-11-83894c018c"><a href="#cb14-11-83894c018c"></a> <span class="co"># positions of the courier, customer, and restaurant?</span></span>
<span id="cb14-12-83894c018c"><a href="#cb14-12-83894c018c"></a> completion_time <span class="op">=</span> <span class="va">self</span>.timestamp <span class="op">+</span> datetime.timedelta(minutes<span class="op">=</span><span class="dv">10</span>)</span>
<span id="cb14-13-83894c018c"><a href="#cb14-13-83894c018c"></a> <span class="cf">return</span> [CompleteOrderEvent(completion_time, <span class="va">self</span>._order)]</span></code></pre></div>
<p>So for every <code>NewOrderEvent</code> that is handled by our simulation, a subsequent <code>CompleteOrderEvent</code> will be handled at some point in the future.</p>
<p><em>Now heres where the problem we mentioned earlier comes in!</em> Remember our docstring for <code>FoodDeliverySystem.place_order</code>: we cannot place an order if there are no available couriers! So what should this event do if <code>system.place_order</code> returns <code>False</code>? At the very least, in this case no <code>CompleteOrderEvent</code> should be returned.</p>
<p>One approach we might take is a <em>polling technique</em>, where we return a duplicate of the event to try again a little bit later. Here is our second version of this method:</p>
<div class="sourceCode" id="cb15-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-83894c018c"><a href="#cb15-1-83894c018c"></a><span class="kw">class</span> NewOrderEvent(Event):</span>
<span id="cb15-2-83894c018c"><a href="#cb15-2-83894c018c"></a> ...</span>
<span id="cb15-3-83894c018c"><a href="#cb15-3-83894c018c"></a></span>
<span id="cb15-4-83894c018c"><a href="#cb15-4-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="bu">list</span>[Event]:</span>
<span id="cb15-5-83894c018c"><a href="#cb15-5-83894c018c"></a> <span class="co">&quot;&quot;&quot;Mutate system by placing an order.&quot;&quot;&quot;</span></span>
<span id="cb15-6-83894c018c"><a href="#cb15-6-83894c018c"></a> success <span class="op">=</span> system.place_order(<span class="va">self</span>._order)</span>
<span id="cb15-7-83894c018c"><a href="#cb15-7-83894c018c"></a></span>
<span id="cb15-8-83894c018c"><a href="#cb15-8-83894c018c"></a> <span class="cf">if</span> success:</span>
<span id="cb15-9-83894c018c"><a href="#cb15-9-83894c018c"></a> completion_time <span class="op">=</span> <span class="va">self</span>.timestamp <span class="op">+</span> datetime.timedelta(minutes<span class="op">=</span><span class="dv">10</span>)</span>
<span id="cb15-10-83894c018c"><a href="#cb15-10-83894c018c"></a> <span class="cf">return</span> [CompleteOrderEvent(completion_time, <span class="va">self</span>._order)]</span>
<span id="cb15-11-83894c018c"><a href="#cb15-11-83894c018c"></a> <span class="cf">else</span>:</span>
<span id="cb15-12-83894c018c"><a href="#cb15-12-83894c018c"></a> <span class="va">self</span>._order.start_time <span class="op">=</span> <span class="va">self</span>.timestamp <span class="op">+</span> datetime.timedelta(minutes<span class="op">=</span><span class="dv">5</span>)</span>
<span id="cb15-13-83894c018c"><a href="#cb15-13-83894c018c"></a> <span class="cf">return</span> [NewOrderEvent(<span class="va">self</span>._order)]</span></code></pre></div>
<h3 id="returning-no-events-83894c018c">Returning no events</h3>
<p>Our <code>CompleteOrderEvent</code> does not cause any new events to happen:</p>
<div class="sourceCode" id="cb16-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1-83894c018c"><a href="#cb16-1-83894c018c"></a><span class="kw">class</span> CompleteOrderEvent(Event):</span>
<span id="cb16-2-83894c018c"><a href="#cb16-2-83894c018c"></a> ...</span>
<span id="cb16-3-83894c018c"><a href="#cb16-3-83894c018c"></a></span>
<span id="cb16-4-83894c018c"><a href="#cb16-4-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="bu">list</span>[Event]:</span>
<span id="cb16-5-83894c018c"><a href="#cb16-5-83894c018c"></a> <span class="co">&quot;&quot;&quot;Mutate the system by recording that the order has been delivered to the customer.&quot;&quot;&quot;</span></span>
<span id="cb16-6-83894c018c"><a href="#cb16-6-83894c018c"></a> system.complete_order(<span class="va">self</span>._order, <span class="va">self</span>._timestamp)</span>
<span id="cb16-7-83894c018c"><a href="#cb16-7-83894c018c"></a> <span class="cf">return</span> []</span></code></pre></div>
<h3 id="a-new-event-type-83894c018c">A new event type</h3>
<p>Lastly, well sketch one new type of event which is more conceptual, but that illustrates the power of this <code>Event</code> interface. This event type will represent a <em>random generation of new orders over a given time period</em>, which well use to drive our simulation.</p>
<div class="sourceCode" id="cb17-83894c018c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1-83894c018c"><a href="#cb17-1-83894c018c"></a><span class="kw">class</span> GenerateOrdersEvent(Event):</span>
<span id="cb17-2-83894c018c"><a href="#cb17-2-83894c018c"></a> <span class="co">&quot;&quot;&quot;An event that causes a random generation of new orders.</span></span>
<span id="cb17-3-83894c018c"><a href="#cb17-3-83894c018c"></a></span>
<span id="cb17-4-83894c018c"><a href="#cb17-4-83894c018c"></a><span class="co"> Private Representation Invariants:</span></span>
<span id="cb17-5-83894c018c"><a href="#cb17-5-83894c018c"></a><span class="co"> - self._duration &gt; 0</span></span>
<span id="cb17-6-83894c018c"><a href="#cb17-6-83894c018c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb17-7-83894c018c"><a href="#cb17-7-83894c018c"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb17-8-83894c018c"><a href="#cb17-8-83894c018c"></a> <span class="co"># - _duration: the number of hours to generate orders for</span></span>
<span id="cb17-9-83894c018c"><a href="#cb17-9-83894c018c"></a> _duration: <span class="bu">int</span></span>
<span id="cb17-10-83894c018c"><a href="#cb17-10-83894c018c"></a></span>
<span id="cb17-11-83894c018c"><a href="#cb17-11-83894c018c"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, timestamp: datetime.datetime, duration: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb17-12-83894c018c"><a href="#cb17-12-83894c018c"></a> <span class="co">&quot;&quot;&quot;Initialize this event with timestamp and the duration in hours.</span></span>
<span id="cb17-13-83894c018c"><a href="#cb17-13-83894c018c"></a></span>
<span id="cb17-14-83894c018c"><a href="#cb17-14-83894c018c"></a><span class="co"> Preconditions:</span></span>
<span id="cb17-15-83894c018c"><a href="#cb17-15-83894c018c"></a><span class="co"> - duration &gt; 0</span></span>
<span id="cb17-16-83894c018c"><a href="#cb17-16-83894c018c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb17-17-83894c018c"><a href="#cb17-17-83894c018c"></a></span>
<span id="cb17-18-83894c018c"><a href="#cb17-18-83894c018c"></a> <span class="kw">def</span> handle_event(<span class="va">self</span>, system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="bu">list</span>[Event]:</span>
<span id="cb17-19-83894c018c"><a href="#cb17-19-83894c018c"></a> <span class="co">&quot;&quot;&quot;Generate new orders for this event&#39;s timestamp and duration.&quot;&quot;&quot;</span></span>
<span id="cb17-20-83894c018c"><a href="#cb17-20-83894c018c"></a> events <span class="op">=</span> []</span>
<span id="cb17-21-83894c018c"><a href="#cb17-21-83894c018c"></a></span>
<span id="cb17-22-83894c018c"><a href="#cb17-22-83894c018c"></a> <span class="cf">while</span> ...:</span>
<span id="cb17-23-83894c018c"><a href="#cb17-23-83894c018c"></a></span>
<span id="cb17-24-83894c018c"><a href="#cb17-24-83894c018c"></a> new_order_event <span class="op">=</span> ... <span class="co"># Create a randomly-generated NewOrderEvent</span></span>
<span id="cb17-25-83894c018c"><a href="#cb17-25-83894c018c"></a> events.append(new_order_event)</span>
<span id="cb17-26-83894c018c"><a href="#cb17-26-83894c018c"></a></span>
<span id="cb17-27-83894c018c"><a href="#cb17-27-83894c018c"></a> <span class="cf">return</span> events</span></code></pre></div>
<p>Well discuss how we might implement this class in lecture, but its a good exercise to try to implement it yourself. Theres many ways to randomly generate new events, so dont be afraid to experiment!</p>
<h2 id="from-events-to-a-simulation-83894c018c">From events to a simulation</h2>
<p>In this section, we focused only on defining individual <code>Event</code> classes to represent different events in our simulation. In the next section, well put together everything weve covered up to this point to finally get a full simulation up and running, so keep reading!</p>
</section>
<br/> <a id="anchor-10-05"></a>
<header id="title-block-header-e817852503">
<h1 class="title">10.5 Creating a Discrete-Event Simulation</h1>
</header>
<section>
<p>Lets put together all of the classes weve designed over the course of this chapter to create a full simulation our of food delivery system. In this section, well first learn about how the main simulation loop works. Then, well turn our attention to the possible ways a simulation can be configured, and how to incorporate these configuration options as part of the public interface of a class.</p>
<h2 id="the-main-simulation-loop-e817852503">The main simulation loop</h2>
<p>Before we get to creating a full simulation class, well discuss how our simulation works. The type of simulation were learning about is called a <strong>discrete-event simulation</strong>, because it is driven by individual events occurring at specified periods of time.</p>
<p>A discrete-event simulation runs as follows:</p>
<ol type="1">
<li>It keeps track of a collection of events, which begins with some initial events. The collection is a <em>priority queue</em>, where an events priority is its timestamp (earlier timestamps mean higher priority).</li>
<li>The highest-priority event (i.e., the one with the earliest timestamp) is removed and processed. Any new events it generates are added to the priority queue.</li>
<li>Step 2 repeats until there are no events left.</li>
</ol>
<p>The algorithm is remarkably simple, though it does rely on a slightly modified version of our <em>priority queue</em> implementation from <a href="" title="../09-abstraction/07-priority-queues.html">Section 9.7</a>.<label for="sn-0-e817852503" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-e817852503" class="margin-toggle"/><span class="sidenote">In that section, we used <code>int</code>s to represent priority, while here were using <code>datetime.datetime</code> values.</span> Assuming we have such an implementation called <code>EventQueueList</code>, here is how we could write a simple function that runs this simulation loop:</p>
<div class="sourceCode" id="cb1-e817852503"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-e817852503"><a href="#cb1-1-e817852503"></a><span class="kw">def</span> run_simulation(initial_events: <span class="bu">list</span>[Event], system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-2-e817852503"><a href="#cb1-2-e817852503"></a> events <span class="op">=</span> EventQueueList() <span class="co"># Initialize an empty priority queue of events</span></span>
<span id="cb1-3-e817852503"><a href="#cb1-3-e817852503"></a> <span class="cf">for</span> event <span class="kw">in</span> initial_events:</span>
<span id="cb1-4-e817852503"><a href="#cb1-4-e817852503"></a> events.enqueue(event)</span>
<span id="cb1-5-e817852503"><a href="#cb1-5-e817852503"></a></span>
<span id="cb1-6-e817852503"><a href="#cb1-6-e817852503"></a> <span class="co"># Repeatedly remove and process the next event</span></span>
<span id="cb1-7-e817852503"><a href="#cb1-7-e817852503"></a> <span class="cf">while</span> <span class="kw">not</span> events.is_empty():</span>
<span id="cb1-8-e817852503"><a href="#cb1-8-e817852503"></a> event <span class="op">=</span> events.dequeue()</span>
<span id="cb1-9-e817852503"><a href="#cb1-9-e817852503"></a></span>
<span id="cb1-10-e817852503"><a href="#cb1-10-e817852503"></a> new_events <span class="op">=</span> event.handle_event(system)</span>
<span id="cb1-11-e817852503"><a href="#cb1-11-e817852503"></a> <span class="cf">for</span> new_event <span class="kw">in</span> new_events:</span>
<span id="cb1-12-e817852503"><a href="#cb1-12-e817852503"></a> events.enqueue(new_event)</span></code></pre></div>
<p>The main reason for this implementations simplicity is abstraction. Remember that <code>Event</code> is an abstract class; the complex behaviour of how different events are handled is deferred to its concrete subclasses via our calls to <code>event.handle_event</code>. Our <code>run_simulation</code> function is <em>polymorphic</em>: it works regardless of what <code>Event</code> instances its given in its <code>initial_events</code> parameter, or what new events are generated and stored in <code>new_events</code>. The only thing our function needs to be able to do is call the <code>handle_event</code> method on each event object, which we can assume is present because it is defined in the <code>Event</code> public interface.</p>
<h2 id="a-simulation-class-e817852503">A simulation class</h2>
<p>Next, we will take our <code>run_simulation</code> in the previous section and “wrap” it inside a new class. This isnt necessary to the running of the simulation, but is a standard practice in an object-oriented design, and makes it easier to both configure the simulation parameters and report results after the simulation is complete.</p>
<p>Were going to begin with a sketch of a class to represent our simulation:</p>
<div class="sourceCode" id="cb2-e817852503"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-e817852503"><a href="#cb2-1-e817852503"></a><span class="kw">class</span> FoodDeliverySimulation:</span>
<span id="cb2-2-e817852503"><a href="#cb2-2-e817852503"></a> <span class="co">&quot;&quot;&quot;A simulation of the food delivery system.</span></span>
<span id="cb2-3-e817852503"><a href="#cb2-3-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-4-e817852503"><a href="#cb2-4-e817852503"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb2-5-e817852503"><a href="#cb2-5-e817852503"></a> <span class="co"># - _system: The FoodDeliverySystem instance that this simulation uses.</span></span>
<span id="cb2-6-e817852503"><a href="#cb2-6-e817852503"></a> <span class="co"># - _events: A collection of the events to process during the simulation.</span></span>
<span id="cb2-7-e817852503"><a href="#cb2-7-e817852503"></a> _system: FoodDeliverySystem</span>
<span id="cb2-8-e817852503"><a href="#cb2-8-e817852503"></a> _events: EventQueue</span>
<span id="cb2-9-e817852503"><a href="#cb2-9-e817852503"></a></span>
<span id="cb2-10-e817852503"><a href="#cb2-10-e817852503"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, start_time: datetime.datetime, num_days: <span class="bu">int</span>,</span>
<span id="cb2-11-e817852503"><a href="#cb2-11-e817852503"></a> num_couriers: <span class="bu">int</span>, num_customers: <span class="bu">int</span>,</span>
<span id="cb2-12-e817852503"><a href="#cb2-12-e817852503"></a> num_restaurants: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-13-e817852503"><a href="#cb2-13-e817852503"></a> <span class="co">&quot;&quot;&quot;Initialize a new simulation with the given simulation parameters.</span></span>
<span id="cb2-14-e817852503"><a href="#cb2-14-e817852503"></a></span>
<span id="cb2-15-e817852503"><a href="#cb2-15-e817852503"></a><span class="co"> start_time: the starting time of the simulation</span></span>
<span id="cb2-16-e817852503"><a href="#cb2-16-e817852503"></a><span class="co"> num_days: the number of days that the simulation runs</span></span>
<span id="cb2-17-e817852503"><a href="#cb2-17-e817852503"></a><span class="co"> num_couriers: the number of couriers in the system</span></span>
<span id="cb2-18-e817852503"><a href="#cb2-18-e817852503"></a><span class="co"> num_customers: the number of customers in the system</span></span>
<span id="cb2-19-e817852503"><a href="#cb2-19-e817852503"></a><span class="co"> num_restaurants: the number of restaurants in the system</span></span>
<span id="cb2-20-e817852503"><a href="#cb2-20-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-21-e817852503"><a href="#cb2-21-e817852503"></a> <span class="va">self</span>._events <span class="op">=</span> EventQueueList()</span>
<span id="cb2-22-e817852503"><a href="#cb2-22-e817852503"></a> <span class="va">self</span>._system <span class="op">=</span> FoodDeliverySystem()</span>
<span id="cb2-23-e817852503"><a href="#cb2-23-e817852503"></a></span>
<span id="cb2-24-e817852503"><a href="#cb2-24-e817852503"></a> <span class="va">self</span>._populate_initial_events(start_time, num_days)</span>
<span id="cb2-25-e817852503"><a href="#cb2-25-e817852503"></a> <span class="va">self</span>._generate_system(num_couriers, num_customers, num_restaurants)</span>
<span id="cb2-26-e817852503"><a href="#cb2-26-e817852503"></a></span>
<span id="cb2-27-e817852503"><a href="#cb2-27-e817852503"></a> <span class="kw">def</span> _populate_initial_events(<span class="va">self</span>, start_time: datetime.datetime, num_days: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-28-e817852503"><a href="#cb2-28-e817852503"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s Event priority queue with GenerateOrdersEvents.</span></span>
<span id="cb2-29-e817852503"><a href="#cb2-29-e817852503"></a></span>
<span id="cb2-30-e817852503"><a href="#cb2-30-e817852503"></a><span class="co"> One new GenerateOrderEvent is generated per day, starting with start_time and</span></span>
<span id="cb2-31-e817852503"><a href="#cb2-31-e817852503"></a><span class="co"> repeating num_days times.</span></span>
<span id="cb2-32-e817852503"><a href="#cb2-32-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-33-e817852503"><a href="#cb2-33-e817852503"></a></span>
<span id="cb2-34-e817852503"><a href="#cb2-34-e817852503"></a> <span class="kw">def</span> _generate_system(<span class="va">self</span>, num_couriers: <span class="bu">int</span>, num_customers: <span class="bu">int</span>, num_restaurants: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-35-e817852503"><a href="#cb2-35-e817852503"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s FoodDeliverySystem with the specified number of entities.</span></span>
<span id="cb2-36-e817852503"><a href="#cb2-36-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-37-e817852503"><a href="#cb2-37-e817852503"></a></span>
<span id="cb2-38-e817852503"><a href="#cb2-38-e817852503"></a> <span class="kw">def</span> run(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-39-e817852503"><a href="#cb2-39-e817852503"></a> <span class="co">&quot;&quot;&quot;Run this simulation.</span></span>
<span id="cb2-40-e817852503"><a href="#cb2-40-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-41-e817852503"><a href="#cb2-41-e817852503"></a> <span class="cf">while</span> <span class="kw">not</span> <span class="va">self</span>._events.is_empty():</span>
<span id="cb2-42-e817852503"><a href="#cb2-42-e817852503"></a> event <span class="op">=</span> <span class="va">self</span>._events.dequeue()</span>
<span id="cb2-43-e817852503"><a href="#cb2-43-e817852503"></a></span>
<span id="cb2-44-e817852503"><a href="#cb2-44-e817852503"></a> new_events <span class="op">=</span> event.handle_event(<span class="va">self</span>._system)</span>
<span id="cb2-45-e817852503"><a href="#cb2-45-e817852503"></a> <span class="cf">for</span> new_event <span class="kw">in</span> new_events:</span>
<span id="cb2-46-e817852503"><a href="#cb2-46-e817852503"></a> <span class="va">self</span>._events.enqueue(new_event)</span></code></pre></div>
<p>There are a few key items to note in this (incomplete) implementation:</p>
<ol type="1">
<li><p>The <code>run_simulation</code> method has been renamed to simply <code>run</code>, since its a method in the <code>FoodDeliverySimulation</code> class.</p></li>
<li><p>The local variable <code>events</code> and parameter <code>system</code> from the function are now instance attributes for the <code>FoodDeliverySimulation</code> class, and have been moved out of the <code>run</code> method entirely. Its the job of <code>FoodDeliverySimulation.__init__</code> to initialize these objects.</p></li>
<li><p>The initializer takes in several parameters representing <em>configuration values</em> for the simulation. It then uses these values in two helper methods to initialize the <code>_system</code> and <code>_events</code> objects. These methods are marked private (named with a leading underscore) because theyre only meant to be called by the initializer, and not code outside of the class.</p>
<p>Here is how we could use the <code>FoodDeliverySimulation</code> class:</p>
<div class="sourceCode" id="cb3-e817852503"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-e817852503"><a href="#cb3-1-e817852503"></a><span class="op">&gt;&gt;&gt;</span> simulation <span class="op">=</span> FoodDeliverySimulation(datetime.datetime(<span class="dv">2020</span>, <span class="dv">11</span>, <span class="dv">30</span>), <span class="dv">7</span>, <span class="dv">4</span>, <span class="dv">100</span>, <span class="dv">50</span>)</span>
<span id="cb3-2-e817852503"><a href="#cb3-2-e817852503"></a><span class="op">&gt;&gt;&gt;</span> simulation.run()</span></code></pre></div></li>
</ol>
<p>Next, well briefly discuss one way to implement each of the two key helper methods for the initializer, <code>_populate_initial_events</code> and <code>_generate_system</code>.</p>
<h3 id="populating-initial-events-e817852503">Populating initial events</h3>
<p>The key idea for our first helper method is that given a start time and a number of days, our initial events will be a series of <code>GenerateOrderEvents</code> that will generate <code>NewOrderEvents</code> when they are processed. Here is the basic skeleton, which will be leave as an exercise for you to complete:</p>
<div class="sourceCode" id="cb4-e817852503"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-e817852503"><a href="#cb4-1-e817852503"></a> <span class="kw">def</span> _populate_initial_events(<span class="va">self</span>, start_time: datetime.datetime, num_days: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb4-2-e817852503"><a href="#cb4-2-e817852503"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s Event priority queue with GenerateOrdersEvents.</span></span>
<span id="cb4-3-e817852503"><a href="#cb4-3-e817852503"></a></span>
<span id="cb4-4-e817852503"><a href="#cb4-4-e817852503"></a><span class="co"> One new GenerateOrderEvent is generated per day, starting with start_time and</span></span>
<span id="cb4-5-e817852503"><a href="#cb4-5-e817852503"></a><span class="co"> repeating num_days times.</span></span>
<span id="cb4-6-e817852503"><a href="#cb4-6-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-7-e817852503"><a href="#cb4-7-e817852503"></a> <span class="cf">for</span> day <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, num_days):</span>
<span id="cb4-8-e817852503"><a href="#cb4-8-e817852503"></a> <span class="co"># 1. Create a GenerateOrderEvent for the given day after the start time.</span></span>
<span id="cb4-9-e817852503"><a href="#cb4-9-e817852503"></a></span>
<span id="cb4-10-e817852503"><a href="#cb4-10-e817852503"></a> <span class="co"># 2. Enqueue the new event.</span></span></code></pre></div>
<h3 id="populating-the-system-entities-e817852503">Populating the system entities</h3>
<p>The way that our simulation is currently set up, our <code>FoodDeliverySystem</code> instance will contain all restaurants, customers, and couriers before the events start being processed. That is, we assume that only <em>orders</em> are dynamic in our system; the restaurants, customers, and couriers do not change over time.</p>
<p>The easiest way to populate these three entity types is to randomly generate new instances of each of these classes. Weve shown an example with <code>Customer</code>s below.</p>
<div class="sourceCode" id="cb5-e817852503"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-e817852503"><a href="#cb5-1-e817852503"></a> <span class="kw">def</span> _generate_system(<span class="va">self</span>, num_couriers: <span class="bu">int</span>, num_customers: <span class="bu">int</span>, num_restaurants: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb5-2-e817852503"><a href="#cb5-2-e817852503"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s FoodDeliverySystem with the specified number of entities.</span></span>
<span id="cb5-3-e817852503"><a href="#cb5-3-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-4-e817852503"><a href="#cb5-4-e817852503"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, num_customers):</span>
<span id="cb5-5-e817852503"><a href="#cb5-5-e817852503"></a> location <span class="op">=</span> _generate_location()</span>
<span id="cb5-6-e817852503"><a href="#cb5-6-e817852503"></a> customer <span class="op">=</span> Customer(<span class="ss">f&#39;Customer </span><span class="sc">{i}</span><span class="ss">&#39;</span>, location)</span>
<span id="cb5-7-e817852503"><a href="#cb5-7-e817852503"></a> <span class="va">self</span>._system.add_customer(customer)</span>
<span id="cb5-8-e817852503"><a href="#cb5-8-e817852503"></a></span>
<span id="cb5-9-e817852503"><a href="#cb5-9-e817852503"></a> <span class="co"># Couriers and Restaurants are similar</span></span>
<span id="cb5-10-e817852503"><a href="#cb5-10-e817852503"></a> ...</span>
<span id="cb5-11-e817852503"><a href="#cb5-11-e817852503"></a></span>
<span id="cb5-12-e817852503"><a href="#cb5-12-e817852503"></a></span>
<span id="cb5-13-e817852503"><a href="#cb5-13-e817852503"></a><span class="co"># Outside the class: helper for generating random locations in Toronto</span></span>
<span id="cb5-14-e817852503"><a href="#cb5-14-e817852503"></a>TORONTO_COORDS <span class="op">=</span> (<span class="fl">43.747743</span>, <span class="fl">43.691170</span>, <span class="op">-</span><span class="fl">79.633951</span>, <span class="op">-</span><span class="fl">79.176646</span>)</span>
<span id="cb5-15-e817852503"><a href="#cb5-15-e817852503"></a></span>
<span id="cb5-16-e817852503"><a href="#cb5-16-e817852503"></a></span>
<span id="cb5-17-e817852503"><a href="#cb5-17-e817852503"></a><span class="kw">def</span> _generate_location() <span class="op">-&gt;</span> <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">float</span>]:</span>
<span id="cb5-18-e817852503"><a href="#cb5-18-e817852503"></a> <span class="co">&quot;&quot;&quot;Return a randomly-generated location (latitude, longitude) within the Toronto bounds.</span></span>
<span id="cb5-19-e817852503"><a href="#cb5-19-e817852503"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-20-e817852503"><a href="#cb5-20-e817852503"></a> <span class="cf">return</span> (random.uniform(TORONTO_COORDS[<span class="dv">0</span>], TORONTO_COORDS[<span class="dv">1</span>]),</span>
<span id="cb5-21-e817852503"><a href="#cb5-21-e817852503"></a> random.uniform(TORONTO_COORDS[<span class="dv">2</span>], TORONTO_COORDS[<span class="dv">3</span>]))</span></code></pre></div>
<h2 id="putting-it-all-together-e817852503">Putting it all together</h2>
<p>After completing the implementation of these two helper methods, you are ready to run the simulation! Try doing the following in the Python console:</p>
<div class="sourceCode" id="cb6-e817852503"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-e817852503"><a href="#cb6-1-e817852503"></a><span class="op">&gt;&gt;&gt;</span> simulation <span class="op">=</span> FoodDeliverySimulation(datetime.datetime(<span class="dv">2020</span>, <span class="dv">11</span>, <span class="dv">30</span>), <span class="dv">7</span>, <span class="dv">4</span>, <span class="dv">100</span>, <span class="dv">50</span>)</span>
<span id="cb6-2-e817852503"><a href="#cb6-2-e817852503"></a><span class="op">&gt;&gt;&gt;</span> simulation.run()</span></code></pre></div>
<p>Of course, we arent printing anything out, and the <code>FoodDeliverySimualtion.run</code> method doesnt actually return anything. You are free to insert some <code>print</code> calls to see whether events are actually being processed, but thats not the only way to see the results of the simulation.</p>
<p>Once the simulation is complete, <code>self._system</code> will have accumulated several completed orders, as a <code>list[Order]</code>. We can access these values and perform any kind of computation on them we want, just like we did all the way back in Chapter 4!</p>
<p>For example, we might ask:</p>
<ul>
<li>How many orders were delivered in total?</li>
<li>What was the average number of orders delivered per courier?</li>
<li>For a given restaurant, which menu items were most popular?</li>
<li><em>What else can you come up with?</em></li>
</ul>
</section>
<br/>
<h2 id="appendix-a.-python-reference">Appendix A. Python Reference</h2>
<a id="anchor-A--01"></a>
<header id="title-block-header-ceff4325fd">
<h1 class="title">A.1 Python Built-In Function Reference</h1>
</header>
<section>
<p><em>Adapted from <a href="https://docs.python.org/3/library/functions.html" class="uri">https://docs.python.org/3/library/functions.html</a>.</em> Note that not all built-in functions are shown.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 15%" />
<col style="width: 84%" />
</colgroup>
<thead>
<tr class="header">
<th>Built-in Function</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>abs(x)</code></td>
<td>Return the absolute value of a number. The argument may be an integer or a floating point number.</td>
</tr>
<tr class="even">
<td><code>all(iterable)</code></td>
<td>Return <code>True</code> if all elements of the <code>iterable</code> are true (or if the <code>iterable</code> is empty).</td>
</tr>
<tr class="odd">
<td><code>any(iterable)</code></td>
<td>Return <code>True</code> if any element of the <code>iterable</code> is true. If the <code>iterable</code> is empty, return <code>False</code>.</td>
</tr>
<tr class="even">
<td><code>chr(i)</code></td>
<td><p>Return the string representing a character whose Unicode code point is the integer <em>i</em>. For example, <code>chr(97)</code> returns the string <code>'a'</code>, while <code>chr(8364)</code> returns the string <code>'€'</code>. This is the inverse of <code>ord()</code>.</p>
<p>The valid range for the argument is from 0 through 1,114,111. <code>ValueError</code> will be raised if <em>i</em> is outside that range.</p></td>
</tr>
<tr class="odd">
<td><code>divmod(a, b)</code></td>
<td>Take two (non complex) numbers as arguments and return a pair of numbers consisting of their quotient and remainder when using integer division. For integers, the result is the same as <code>(a // b, a % b)</code>.</td>
</tr>
<tr class="even">
<td><pre><code>filter(
function,
iterable
)</code></pre></td>
<td>Construct an iterator from those elements of <code>iterable</code> for which <code>function</code> returns <code>True</code>. <code>iterable</code> may be either a sequence, a container which supports iteration, or an iterator.</td>
</tr>
<tr class="odd">
<td><code>id(object)</code></td>
<td>Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime.</td>
</tr>
<tr class="even">
<td><code>input([prompt])</code></td>
<td><p>If the <code>prompt</code> argument is present, it is written to standard output without a trailing newline. The function then reads a line from input, converts it to a string (stripping a trailing newline), and returns that. Example:</p>
<div class="sourceCode" id="cb2-ceff4325fd"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-ceff4325fd"><a href="#cb2-1-ceff4325fd"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="bu">input</span>(<span class="st">&#39;Type in a word: &#39;</span>)</span>
<span id="cb2-2-ceff4325fd"><a href="#cb2-2-ceff4325fd"></a>Type <span class="kw">in</span> a word: Python <span class="co"># &quot;Python&quot; is user input</span></span>
<span id="cb2-3-ceff4325fd"><a href="#cb2-3-ceff4325fd"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb2-4-ceff4325fd"><a href="#cb2-4-ceff4325fd"></a><span class="co">&#39;Python&#39;</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><pre><code>isinstance(
object,
classinfo
)</code></pre></td>
<td>Return <code>True</code> if the <code>object</code> argument is an instance of the <code>classinfo</code> argument, or of a subclass thereof. If <code>object</code> is not an object of the given type, the function always returns <code>False</code>.</td>
</tr>
<tr class="even">
<td><code>len(s)</code></td>
<td>Return the length (the number of items) of an object.</td>
</tr>
<tr class="odd">
<td><pre><code># Form 1
max(
iterable,
*
[, key,
default]
)
# Form 2
max(
arg1,
arg2,
*args,
[key]
)</code></pre></td>
<td><p>Return the largest item in an <code>iterable</code> or the largest of two or more arguments.</p>
<p>If one positional argument is provided, it should be an iterable. The largest item in the iterable is returned. If two or more positional arguments are provided, the largest of the positional arguments is returned.</p>
<p>There are two optional keyword-only arguments. The <code>key</code> argument specifies a one-argument ordering function like that used for <code>list.sort()</code>.</p>
<p>The <code>default</code> argument specifies an object to return if the provided iterable is empty. If the iterable is empty and <code>default</code> is not provided, a <code>ValueError</code> is raised. If multiple items are maximal, the function returns the first one encountered.</p></td>
</tr>
<tr class="even">
<td><pre><code># Form 1
min(
iterable, *
[, key,
default]
)
# Form 2
min(
arg1,
arg2,
*args,
[key]
)</code></pre></td>
<td><p>Return the smallest item in an <code>iterable</code> or the smallest of two or more arguments.</p>
<p>If one positional argument is provided, it should be an iterable. The smallest item in the iterable is returned. If two or more positional arguments are provided, the smallest of the positional arguments is returned.</p>
<p>There are two optional keyword-only arguments. The <code>key</code> argument specifies a one-argument ordering function like that used for <code>list.sort()</code>.</p>
<p>The <code>default</code> argument specifies an object to return if the provided iterable is empty. If the iterable is empty and <code>default</code> is not provided, a <code>ValueError</code> is raised. If multiple items are minimal, the function returns the first one encountered.</p></td>
</tr>
<tr class="odd">
<td><pre><code>open(
file,
mode=&#39;r&#39;
)</code></pre></td>
<td><p>Open <code>file</code> and return a corresponding file object. If the file cannot be opened, an <code>OSError</code> is raised.</p>
<p><code>file</code> is a path-like object giving the pathname (absolute or relative to the current working directory) of the file to be opened.</p>
<p><code>mode</code> is an optional string that specifies the mode in which the file is opened. It defaults to r which means open for reading in text mode. Other common values are w for writing (truncating the file if it already exists), x for exclusive creation and a for appending.</p></td>
</tr>
<tr class="even">
<td><code>ord(c)</code></td>
<td>Given a string representing one Unicode character, return an integer representing the Unicode code point of that character. For example, <code>ord('a')</code> returns the integer <code>97</code> and <code>ord('€')</code> (Euro sign) returns <code>8364</code>. This is the inverse of <code>chr()</code>.</td>
</tr>
<tr class="odd">
<td><pre><code>pow(
base, exp
[, mod]
)</code></pre></td>
<td>Return <code>base</code> to the power <code>exp</code>; if <code>mod</code> is present, return <code>base</code> to the power <code>exp</code>, modulo <code>mod</code> (computed more efficiently than <code>pow(base, exp) % mod</code>). The two-argument form <code>pow(base, exp)</code> is equivalent to using the power operator: <code>base ** exp</code>.</td>
</tr>
<tr class="even">
<td><pre><code>print(
*objects,
sep=&#39; &#39;,
end=&#39;\&#39;
)</code></pre></td>
<td><p>Print <code>objects</code> to standard output, separated by <code>sep</code> and followed by <code>end</code>. <code>sep</code> and <code>end</code>, if present, must be given as keyword arguments.</p>
<p>Both <code>sep</code> and <code>end</code> must be strings; they can also be <code>None</code>, which means to use the default values.</p></td>
</tr>
<tr class="odd">
<td><code>reversed(seq)</code></td>
<td>Return a reverse iterator.</td>
</tr>
<tr class="even">
<td><pre><code>round(
number
[, ndigits]
)</code></pre></td>
<td><p>Return <code>number</code> rounded to <code>ndigits</code> precision after the decimal point. If <code>ndigits</code> is omitted or is <code>None</code>, it returns the nearest integer to its input.</p>
<p>For the built-in types supporting <code>round()</code>, values are rounded to the closest multiple of 10 to the power minus <em>ndigits</em>; if two multiples are equally close, rounding is done toward the even choice (so, for example, both <code>round(0.5)</code> and <code>round(-0.5)</code> are <code>0</code>, and <code>round(1.5)</code> is 2).</p>
<p>Any integer value is valid for <em>ndigits</em> (positive, zero, or negative). The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as number. <em>Note</em>: The behavior of <code>round()</code> for floats can be surprising: for example, <code>round(2.675, 2)</code> gives <code>2.67</code> instead of the expected <code>2.68</code>. This is not a bug: its a result of the fact that most decimal fractions cant be represented exactly as a float. See <a href="https://docs.python.org/3/tutorial/floatingpoint.html#tut-fp-issues">Floating Point Arithmetic: Issues and Limitations</a> for more information.</p></td>
</tr>
<tr class="odd">
<td><pre><code>sorted(
iterable, *,
key=None,
reverse=False
)</code></pre></td>
<td><p>Return a new sorted list from the items in <code>iterable</code>.</p>
<p>Has two optional arguments which must be specified as keyword arguments.</p>
<p><code>key</code> specifies a function of one argument that is used to extract a comparison key from each element in iterable<code>(for example,</code>key=str.lower<code>). The default value is</code>None<code>(compare the elements directly).</code>reverse<code>is a boolean value. If set to</code>True`, then the list elements are sorted as if each comparison were reversed.</p></td>
</tr>
<tr class="even">
<td><pre><code>sum(
iterable,
/,
start=0
)</code></pre></td>
<td>Sums <code>start</code> and the items of an <code>iterable</code> from left to right and returns the total.</td>
</tr>
<tr class="odd">
<td><code>type(object)</code></td>
<td><p>Return the type of an <code>object</code>.</p>
<p>The <code>isinstance()</code> built-in function is recommended for testing the type of an object, because it takes subclasses into account.</p></td>
</tr>
</tbody>
</table>
</div>
</section>
<br/> <a id="anchor-A--02"></a>
<header id="title-block-header-6465548919">
<h1 class="title">A.2 Python Built-In Data Types Reference</h1>
</header>
<section>
<p><em>Adapted from <a href="https://docs.python.org/3/library/stdtypes.html" class="uri">https://docs.python.org/3/library/stdtypes.html</a>.</em></p>
<h2 id="boolean-typebool-6465548919">Boolean type—<code>bool</code></h2>
<p>Boolean values are the two constant objects <code>False</code> and <code>True</code>. They are used to represent truth values.</p>
<h2 id="numeric-typesint-float-6465548919">Numeric types—<code>int</code>, <code>float</code></h2>
<p>There are two distinct numeric types: integers and floating point numbers. Numbers are created by numeric literals or as the result of built-in functions and operators. Unadorned integer literals yield integers. Numeric literals containing a decimal point or an exponent sign yield floating point numbers.</p>
<p>Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the “narrower” type is widened to that of the other, where integer is narrower than floating point. Comparisons between numbers of mixed type use the same rule.</p>
<p>All numeric types support the following operations (for priorities of the operations, see Operator precedence):</p>
<div class="fullwidth reference-table">
<table style="width:97%;">
<colgroup>
<col style="width: 25%" />
<col style="width: 72%" />
</colgroup>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x + y</code></td>
<td><p>Returns the sum of <code>x</code> and <code>y</code>.</p>
<div class="sourceCode" id="cb1-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-6465548919"><a href="#cb1-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb1-2-6465548919"><a href="#cb1-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb1-3-6465548919"><a href="#cb1-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">+</span> y</span>
<span id="cb1-4-6465548919"><a href="#cb1-4-6465548919"></a><span class="dv">8</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>x - y</code></td>
<td><p>Returns the difference of <code>x</code> and <code>y</code>.</p>
<div class="sourceCode" id="cb2-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-6465548919"><a href="#cb2-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb2-2-6465548919"><a href="#cb2-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb2-3-6465548919"><a href="#cb2-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">-</span> y</span>
<span id="cb2-4-6465548919"><a href="#cb2-4-6465548919"></a><span class="dv">2</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>x * y</code></td>
<td><p>Returns the product of <code>x</code> and <code>y</code>.</p>
<div class="sourceCode" id="cb3-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-6465548919"><a href="#cb3-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb3-2-6465548919"><a href="#cb3-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb3-3-6465548919"><a href="#cb3-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">*</span> y</span>
<span id="cb3-4-6465548919"><a href="#cb3-4-6465548919"></a><span class="dv">15</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>x / y</code></td>
<td><p>Returns the quotient of <code>x</code> and <code>y</code>.</p>
<div class="sourceCode" id="cb4-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-6465548919"><a href="#cb4-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb4-2-6465548919"><a href="#cb4-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb4-3-6465548919"><a href="#cb4-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">/</span> y</span>
<span id="cb4-4-6465548919"><a href="#cb4-4-6465548919"></a><span class="fl">1.6666666666666667</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>x // y</code></td>
<td><p>Returns the floored quotient of <code>x</code> and <code>y</code>. Also referred to as <em>integer division</em>.</p>
<div class="sourceCode" id="cb5-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-6465548919"><a href="#cb5-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb5-2-6465548919"><a href="#cb5-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb5-3-6465548919"><a href="#cb5-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">//</span> y</span>
<span id="cb5-4-6465548919"><a href="#cb5-4-6465548919"></a><span class="dv">1</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>x % y</code></td>
<td><p>Returns the remainder of <code>x / y</code>.</p>
<div class="sourceCode" id="cb6-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-6465548919"><a href="#cb6-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb6-2-6465548919"><a href="#cb6-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> y <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb6-3-6465548919"><a href="#cb6-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">%</span> y</span>
<span id="cb6-4-6465548919"><a href="#cb6-4-6465548919"></a><span class="dv">2</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>x ** y</code></td>
<td><p>Returns <code>x</code> to raised to the power of <code>y</code>.</p>
<div class="sourceCode" id="cb7-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-6465548919"><a href="#cb7-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="dv">3</span> <span class="op">**</span> <span class="dv">2</span></span>
<span id="cb7-2-6465548919"><a href="#cb7-2-6465548919"></a><span class="dv">9</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>-x</code></td>
<td><p>Returns <code>x</code> negated.</p>
<div class="sourceCode" id="cb8-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-6465548919"><a href="#cb8-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb8-2-6465548919"><a href="#cb8-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="op">-</span>x</span>
<span id="cb8-3-6465548919"><a href="#cb8-3-6465548919"></a><span class="op">-</span><span class="dv">5</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>int(x)</code></td>
<td><p>Returns <code>x</code> converted to integer. For floating-point numbers, this truncates towards 0.</p>
<div class="sourceCode" id="cb9-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-6465548919"><a href="#cb9-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="st">&#39;3&#39;</span></span>
<span id="cb9-2-6465548919"><a href="#cb9-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">int</span>(x)</span>
<span id="cb9-3-6465548919"><a href="#cb9-3-6465548919"></a><span class="dv">3</span></span>
<span id="cb9-4-6465548919"><a href="#cb9-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="op">-</span><span class="fl">1.5</span></span>
<span id="cb9-5-6465548919"><a href="#cb9-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">int</span>(x)</span>
<span id="cb9-6-6465548919"><a href="#cb9-6-6465548919"></a><span class="op">-</span><span class="dv">1</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>float(x)</code></td>
<td><p>Returns <code>x</code> converted to a floating point number.</p>
<div class="sourceCode" id="cb10-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-6465548919"><a href="#cb10-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="st">&#39;3.5&#39;</span></span>
<span id="cb10-2-6465548919"><a href="#cb10-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">float</span>(x)</span>
<span id="cb10-3-6465548919"><a href="#cb10-3-6465548919"></a><span class="fl">3.5</span></span>
<span id="cb10-4-6465548919"><a href="#cb10-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="op">-</span><span class="dv">1</span></span>
<span id="cb10-5-6465548919"><a href="#cb10-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">float</span>(x)</span>
<span id="cb10-6-6465548919"><a href="#cb10-6-6465548919"></a><span class="op">-</span><span class="fl">1.0</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>math.floor(x)</code></td>
<td><p>Returns the greatest integer <code>&lt;= x</code>.</p>
<div class="sourceCode" id="cb11-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-6465548919"><a href="#cb11-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> math</span>
<span id="cb11-2-6465548919"><a href="#cb11-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> math.floor(<span class="fl">2.45</span>)</span>
<span id="cb11-3-6465548919"><a href="#cb11-3-6465548919"></a><span class="dv">2</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>math.ceil(x)</code></td>
<td><p>Returns the least integer <code>&gt;= x</code>.</p>
<div class="sourceCode" id="cb12-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-6465548919"><a href="#cb12-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="im">import</span> math</span>
<span id="cb12-2-6465548919"><a href="#cb12-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> math.ceil(<span class="fl">2.45</span>)</span>
<span id="cb12-3-6465548919"><a href="#cb12-3-6465548919"></a><span class="dv">3</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>See also the <a href="../01-builtins.html">built-in functions</a> <code>abs</code>, <code>divmod</code>, <code>pow</code>, and <code>round</code>.</p>
</div>
<h2 id="sequence-typesstr-list-tuple-6465548919">Sequence types—<code>str</code>, <code>list</code>, <code>tuple</code></h2>
<p>The operations in the following table are supported by most sequence types, both mutable and immutable.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 24%" />
<col style="width: 75%" />
</colgroup>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>x in s</code></td>
<td><p>Returns <code>True</code> if an item of <code>s</code> is equal to <code>x</code>, else <code>False</code>.</p>
<div class="sourceCode" id="cb13-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-6465548919"><a href="#cb13-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="st">&#39;Mon&#39;</span>, <span class="st">&#39;Wed&#39;</span>, <span class="st">&#39;Fri&#39;</span>]</span>
<span id="cb13-2-6465548919"><a href="#cb13-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="st">&#39;Tue&#39;</span></span>
<span id="cb13-3-6465548919"><a href="#cb13-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="kw">in</span> s</span>
<span id="cb13-4-6465548919"><a href="#cb13-4-6465548919"></a><span class="va">False</span></span>
<span id="cb13-5-6465548919"><a href="#cb13-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="st">&#39;Wed&#39;</span></span>
<span id="cb13-6-6465548919"><a href="#cb13-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="kw">in</span> s</span>
<span id="cb13-7-6465548919"><a href="#cb13-7-6465548919"></a><span class="va">True</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>x not in s</code></td>
<td><p>Returns <code>False</code> if an item of <code>s</code> is equal to <code>x</code>, else <code>True</code>.</p>
<div class="sourceCode" id="cb14-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1-6465548919"><a href="#cb14-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="st">&#39;Mon&#39;</span>, <span class="st">&#39;Wed&#39;</span>, <span class="st">&#39;Fri&#39;</span>]</span>
<span id="cb14-2-6465548919"><a href="#cb14-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="st">&#39;Tue&#39;</span></span>
<span id="cb14-3-6465548919"><a href="#cb14-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="kw">not</span> <span class="kw">in</span> s</span>
<span id="cb14-4-6465548919"><a href="#cb14-4-6465548919"></a><span class="va">True</span></span>
<span id="cb14-5-6465548919"><a href="#cb14-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="st">&#39;Wed&#39;</span></span>
<span id="cb14-6-6465548919"><a href="#cb14-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="kw">not</span> <span class="kw">in</span> s</span>
<span id="cb14-7-6465548919"><a href="#cb14-7-6465548919"></a><span class="va">False</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>s + t</code></td>
<td><p>Returns the concatenation of <code>s</code> and <code>t</code>.</p>
<div class="sourceCode" id="cb15-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1-6465548919"><a href="#cb15-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Mon&#39;</span></span>
<span id="cb15-2-6465548919"><a href="#cb15-2-6465548919"></a></span>
<span id="cb15-3-6465548919"><a href="#cb15-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="st">&#39;day&#39;</span></span>
<span id="cb15-4-6465548919"><a href="#cb15-4-6465548919"></a></span>
<span id="cb15-5-6465548919"><a href="#cb15-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">+</span> s</span>
<span id="cb15-6-6465548919"><a href="#cb15-6-6465548919"></a><span class="co">&#39;Monday&#39;</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>s * n</code> or <code>n * s</code></td>
<td><p>Returns the equivalent to adding <code>s</code> to itself <code>n</code> times.</p>
<div class="sourceCode" id="cb16-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1-6465548919"><a href="#cb16-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;ha&#39;</span></span>
<span id="cb16-2-6465548919"><a href="#cb16-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">5</span></span>
<span id="cb16-3-6465548919"><a href="#cb16-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">*</span> s</span>
<span id="cb16-4-6465548919"><a href="#cb16-4-6465548919"></a><span class="co">&#39;hahahahaha&#39;</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>s[i]</code></td>
<td><p>Returns the <code>i</code>th item of <code>s</code>, with starting index <code>0</code>.</p>
<div class="sourceCode" id="cb17-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1-6465548919"><a href="#cb17-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Hugo&#39;</span></span>
<span id="cb17-2-6465548919"><a href="#cb17-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="dv">0</span>]</span>
<span id="cb17-3-6465548919"><a href="#cb17-3-6465548919"></a><span class="co">&#39;H&#39;</span></span>
<span id="cb17-4-6465548919"><a href="#cb17-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="op">-</span><span class="dv">1</span>]</span>
<span id="cb17-5-6465548919"><a href="#cb17-5-6465548919"></a><span class="co">&#39;o&#39;</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>s[i:j]</code></td>
<td><p>Returns the slice of <code>s</code> from <code>i</code> to <code>j</code>.</p>
<div class="sourceCode" id="cb18-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb18-1-6465548919"><a href="#cb18-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Hugo&#39;</span></span>
<span id="cb18-2-6465548919"><a href="#cb18-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="dv">0</span>:<span class="dv">3</span>]</span>
<span id="cb18-3-6465548919"><a href="#cb18-3-6465548919"></a><span class="co">&#39;Hug&#39;</span></span>
<span id="cb18-4-6465548919"><a href="#cb18-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="op">-</span><span class="dv">2</span>:]</span>
<span id="cb18-5-6465548919"><a href="#cb18-5-6465548919"></a><span class="co">&#39;go&#39;</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>s[i:j:k]</code></td>
<td><p>Returns the slice of <code>s</code> from <code>i</code> to <code>j</code> with step <code>k</code>.</p>
<div class="sourceCode" id="cb19-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb19-1-6465548919"><a href="#cb19-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Hugo&#39;</span></span>
<span id="cb19-2-6465548919"><a href="#cb19-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="dv">0</span>:<span class="dv">3</span>:<span class="dv">2</span>]</span>
<span id="cb19-3-6465548919"><a href="#cb19-3-6465548919"></a><span class="co">&#39;Hg&#39;</span></span>
<span id="cb19-4-6465548919"><a href="#cb19-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="op">-</span><span class="dv">1</span>:<span class="op">-</span><span class="dv">4</span>:<span class="op">-</span><span class="dv">2</span>]</span>
<span id="cb19-5-6465548919"><a href="#cb19-5-6465548919"></a><span class="co">&#39;ou&#39;</span></span>
<span id="cb19-6-6465548919"><a href="#cb19-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[::<span class="op">-</span><span class="dv">1</span>]</span>
<span id="cb19-7-6465548919"><a href="#cb19-7-6465548919"></a><span class="co">&#39;oguH&#39;</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>s.index(x[, i[, j]])</code></td>
<td><p>Returns the <code>index</code> of the first occurrence of <code>x</code> in <code>s</code> (at or after index <code>i</code> and before index <code>j</code>, if those parameters are given).</p>
<div class="sourceCode" id="cb20-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb20-1-6465548919"><a href="#cb20-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Bipbopboopbap&#39;</span></span>
<span id="cb20-2-6465548919"><a href="#cb20-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.index(<span class="st">&#39;b&#39;</span>)</span>
<span id="cb20-3-6465548919"><a href="#cb20-3-6465548919"></a><span class="dv">3</span></span>
<span id="cb20-4-6465548919"><a href="#cb20-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.index(<span class="st">&#39;b&#39;</span>, <span class="dv">3</span>)</span>
<span id="cb20-5-6465548919"><a href="#cb20-5-6465548919"></a><span class="dv">3</span></span>
<span id="cb20-6-6465548919"><a href="#cb20-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.index(<span class="st">&#39;b&#39;</span>, <span class="dv">4</span>)</span>
<span id="cb20-7-6465548919"><a href="#cb20-7-6465548919"></a><span class="dv">6</span></span>
<span id="cb20-8-6465548919"><a href="#cb20-8-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.index(<span class="st">&#39;b&#39;</span>, <span class="dv">0</span>, <span class="dv">5</span>)</span>
<span id="cb20-9-6465548919"><a href="#cb20-9-6465548919"></a><span class="dv">3</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>s.count(x)</code></td>
<td><p>Returns the total number of occurrences of <code>x</code> in <code>s</code>.</p>
<div class="sourceCode" id="cb21-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb21-1-6465548919"><a href="#cb21-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Bipbopboop&#39;</span></span>
<span id="cb21-2-6465548919"><a href="#cb21-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.count(<span class="st">&#39;o&#39;</span>)</span>
<span id="cb21-3-6465548919"><a href="#cb21-3-6465548919"></a><span class="dv">3</span></span>
<span id="cb21-4-6465548919"><a href="#cb21-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="st">&#39;ho&#39;</span>, <span class="st">&#39;hey&#39;</span>, <span class="st">&#39;ho&#39;</span>]</span>
<span id="cb21-5-6465548919"><a href="#cb21-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.count(<span class="st">&#39;ho&#39;</span>)</span>
<span id="cb21-6-6465548919"><a href="#cb21-6-6465548919"></a><span class="dv">2</span></span>
<span id="cb21-7-6465548919"><a href="#cb21-7-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.count(<span class="st">&#39;h&#39;</span>)</span>
<span id="cb21-8-6465548919"><a href="#cb21-8-6465548919"></a><span class="dv">0</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>See also the <a href="../01-builtins.html">built-in functions</a> <code>len</code>, <code>max</code>, and <code>min</code>.</p>
</div>
<p>Sequences of the same type also support comparisons. In particular, tuples and lists are compared lexicographically by comparing corresponding elements. This means that to compare equal, every element must compare equal and the two sequences must be of the same type and have the same length.</p>
<h2 id="mutable-sequence-typelist-6465548919">Mutable sequence type—<code>list</code></h2>
<p>The <code>list</code> data type supports all of the immutable sequence operations from the previous section, as well as the following operations.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 27%" />
<col style="width: 72%" />
</colgroup>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>s[i] = x</code></td>
<td><p>Set the item at index <code>i</code> of <code>s</code> to be <code>x</code>.</p>
<div class="sourceCode" id="cb22-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb22-1-6465548919"><a href="#cb22-1-6465548919"></a></span>
<span id="cb22-2-6465548919"><a href="#cb22-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span>
<span id="cb22-3-6465548919"><a href="#cb22-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s[<span class="dv">3</span>] <span class="op">=</span> <span class="dv">100</span></span>
<span id="cb22-4-6465548919"><a href="#cb22-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb22-5-6465548919"><a href="#cb22-5-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">100</span>, <span class="dv">5</span>]</span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>list.append(self, x)</code></td>
<td><p>Appends <code>x</code> to the end of the sequence <code>self</code>.</p>
<div class="sourceCode" id="cb23-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb23-1-6465548919"><a href="#cb23-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span>
<span id="cb23-2-6465548919"><a href="#cb23-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.append(s, <span class="dv">100</span>) <span class="co"># or, s.append(100)</span></span>
<span id="cb23-3-6465548919"><a href="#cb23-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb23-4-6465548919"><a href="#cb23-4-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">100</span>]</span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>list.extend(self, t)</code> or <code>self += t</code></td>
<td><p>Extends <code>self</code> with the contents of an iterable <code>t</code>.</p>
<div class="sourceCode" id="cb24-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb24-1-6465548919"><a href="#cb24-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span>
<span id="cb24-2-6465548919"><a href="#cb24-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.extend(s, [<span class="dv">100</span>, <span class="dv">200</span>]) <span class="co"># or, s.extend([100, 200])</span></span>
<span id="cb24-3-6465548919"><a href="#cb24-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb24-4-6465548919"><a href="#cb24-4-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">100</span>, <span class="dv">200</span>]</span>
<span id="cb24-5-6465548919"><a href="#cb24-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">+=</span> [<span class="dv">300</span>]</span>
<span id="cb24-6-6465548919"><a href="#cb24-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb24-7-6465548919"><a href="#cb24-7-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">100</span>, <span class="dv">200</span>, <span class="dv">300</span>]</span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>list.insert(self, i, x)</code></td>
<td><p>Inserts <code>x</code> into <code>self</code> at the index given by <code>i</code>.</p>
<div class="sourceCode" id="cb25-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb25-1-6465548919"><a href="#cb25-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span>
<span id="cb25-2-6465548919"><a href="#cb25-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.insert(s, <span class="dv">1</span>, <span class="dv">100</span>) <span class="co"># or, s.insert(1, 100)</span></span>
<span id="cb25-3-6465548919"><a href="#cb25-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb25-4-6465548919"><a href="#cb25-4-6465548919"></a>[<span class="dv">1</span>, <span class="dv">100</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>list.pop(self[, i])</code></td>
<td><p>Returns the item at <code>i</code> and also removes it from <code>self</code>. If <code>i</code> is omitted, the last item is removed and returned.</p>
<div class="sourceCode" id="cb26-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb26-1-6465548919"><a href="#cb26-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span>
<span id="cb26-2-6465548919"><a href="#cb26-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.pop() <span class="co"># or, list.pop(s)</span></span>
<span id="cb26-3-6465548919"><a href="#cb26-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb26-4-6465548919"><a href="#cb26-4-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>]</span>
<span id="cb26-5-6465548919"><a href="#cb26-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.pop(<span class="dv">1</span>) <span class="co"># or, list.pop(s, 1)</span></span>
<span id="cb26-6-6465548919"><a href="#cb26-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb26-7-6465548919"><a href="#cb26-7-6465548919"></a>[<span class="dv">1</span>, <span class="dv">3</span>, <span class="dv">4</span>]</span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>list.remove(self, x)</code></td>
<td><p>Removes the first occurrence of <code>x</code> from <code>self</code>.</p>
<div class="sourceCode" id="cb27-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb27-1-6465548919"><a href="#cb27-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span>
<span id="cb27-2-6465548919"><a href="#cb27-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.remove(s, <span class="dv">3</span>) <span class="co"># or, s.remove(3)</span></span>
<span id="cb27-3-6465548919"><a href="#cb27-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb27-4-6465548919"><a href="#cb27-4-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">4</span>, <span class="dv">5</span>]</span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>list.reverse(self)</code></td>
<td>Reverses the items of <code>self</code> in place (mutates <code>self</code>).</td>
</tr>
<tr class="even">
<td><pre><code>list.sort(
self, *,
key=None,
reverse=False
)</code></pre></td>
<td><p>Sorts <code>self</code> in place, using only <code>&lt;</code> comparisons between items.</p>
<p><code>key</code> specifies a function of one argument that is used to extract a comparison key from each list element (for example, <code>key=str.lower</code>). The key corresponding to each item in the list is calculated once and then used for the entire sorting process. The default value of <code>None</code> means that list items are sorted directly without calculating a separate key value.</p>
<p><code>reverse</code> is a boolean value. If set to <code>True</code>, then the list elements are sorted as if each comparison were reversed.</p>
<p>The <code>list.sort</code> method is guaranteed to be stable. A sort is stable if it guarantees not to change the relative order of elements that compare equal—this is helpful for sorting in multiple passes (for example, sort by department, then by salary grade).</p>
<p>Example:</p>
<div class="sourceCode" id="cb29-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb29-1-6465548919"><a href="#cb29-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> [<span class="dv">1</span>, <span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb29-2-6465548919"><a href="#cb29-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.sort(s) <span class="co"># or, s.sort()</span></span>
<span id="cb29-3-6465548919"><a href="#cb29-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb29-4-6465548919"><a href="#cb29-4-6465548919"></a>[<span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb29-5-6465548919"><a href="#cb29-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>.sort(s, reverse<span class="op">=</span><span class="va">True</span>) <span class="co"># or, s.sort(reverse=True)</span></span>
<span id="cb29-6-6465548919"><a href="#cb29-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s</span>
<span id="cb29-7-6465548919"><a href="#cb29-7-6465548919"></a>[<span class="dv">3</span>, <span class="dv">2</span>, <span class="dv">1</span>, <span class="dv">0</span>, <span class="op">-</span><span class="dv">1</span>]</span></code></pre></div></td>
</tr>
</tbody>
</table>
</div>
<h2 id="text-sequence-typestr-6465548919">Text sequence type—<code>str</code></h2>
<p>Textual data in Python is handled with <code>str</code> objects, or <strong>strings</strong>. Strings are immutable sequences.</p>
<p>Triple quoted strings may span multiple lines—all associated whitespace will be included in the string literal.</p>
<p>Strings may also be created from other objects using the <code>str</code> constructor.</p>
<p>Since there is no separate “character” type, indexing a string produces strings of length 1. That is, for a non-empty string <code>s</code>, <code>s[0] == s[0:1]</code>. Strings implement all of the common sequence operations, along with the additional methods described below.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 31%" />
<col style="width: 68%" />
</colgroup>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>str.capitalize(self)</code></td>
<td><p>Return a copy of the string with its first character capitalized and the rest lowercased. Example:</p>
<div class="sourceCode" id="cb30-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb30-1-6465548919"><a href="#cb30-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> ABC<span class="st">&#39;</span></span>
<span id="cb30-2-6465548919"><a href="#cb30-2-6465548919"></a><span class="st">&gt;&gt;&gt; str.capitalize(s) # or, s.capitalize()</span></span>
<span id="cb30-3-6465548919"><a href="#cb30-3-6465548919"></a><span class="st">&#39;</span>Abc<span class="st">&#39;</span></span>
<span id="cb30-4-6465548919"><a href="#cb30-4-6465548919"></a><span class="st">&gt;&gt;&gt; s = &#39;</span>aBC<span class="st">&#39;</span></span>
<span id="cb30-5-6465548919"><a href="#cb30-5-6465548919"></a><span class="st">&gt;&gt;&gt; str.capitalize(s)</span></span>
<span id="cb30-6-6465548919"><a href="#cb30-6-6465548919"></a><span class="st">&#39;</span>Abc<span class="st">&#39;</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><pre><code>str.count(
self, sub
[, start
[, end]]
)</code></pre></td>
<td><p>Return the number of non-overlapping occurrences of substring <code>sub</code> in the range <code>[start, end]</code>.</p>
<p>Optional arguments <code>start</code> and <code>end</code> are interpreted as in slice notation.</p>
<p>Example:</p>
<div class="sourceCode" id="cb32-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb32-1-6465548919"><a href="#cb32-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Beepbopboopbop&#39;</span></span>
<span id="cb32-2-6465548919"><a href="#cb32-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.count(s, <span class="st">&#39;o&#39;</span>) <span class="co"># or, s.count(&#39;o&#39;)</span></span>
<span id="cb32-3-6465548919"><a href="#cb32-3-6465548919"></a><span class="dv">4</span></span>
<span id="cb32-4-6465548919"><a href="#cb32-4-6465548919"></a><span class="op">&gt;&gt;</span> <span class="bu">str</span>.count(s, <span class="st">&#39;bo&#39;</span>)</span>
<span id="cb32-5-6465548919"><a href="#cb32-5-6465548919"></a><span class="dv">3</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><pre><code>str.endswith(
self, suffix
[, start
[, end]]
)</code></pre></td>
<td><p>Return <code>True</code> if the string ends with the specified suffix, otherwise return <code>False</code> <code>suffix</code> can also be a tuple of suffixes to look for.</p>
<p>With optional <code>start</code>, test beginning at that position. With optional <code>end</code>, stop comparing at that position.</p>
<p>Example:</p>
<div class="sourceCode" id="cb34-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb34-1-6465548919"><a href="#cb34-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;www.google.com&#39;</span></span>
<span id="cb34-2-6465548919"><a href="#cb34-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.endswith(s, <span class="st">&#39;.com&#39;</span>) <span class="co"># or, s.endswith(&#39;.com&#39;)</span></span>
<span id="cb34-3-6465548919"><a href="#cb34-3-6465548919"></a><span class="va">True</span></span>
<span id="cb34-4-6465548919"><a href="#cb34-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.endswith(<span class="st">&#39;.com&#39;</span>, <span class="dv">12</span>)</span>
<span id="cb34-5-6465548919"><a href="#cb34-5-6465548919"></a><span class="va">False</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>str.find(self, sub[, start[, end]])</code></td>
<td><p>Return the lowest index in the string where substring <code>sub</code> is found within the slice <code>s[start:end]</code>.</p>
<p>Optional arguments <code>start</code> and <code>end</code> are interpreted as in slice notation.</p>
<p>Example:</p>
<div class="sourceCode" id="cb35-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb35-1-6465548919"><a href="#cb35-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;www.google.com&#39;</span></span>
<span id="cb35-2-6465548919"><a href="#cb35-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.find(s, <span class="st">&#39;o&#39;</span>) <span class="co"># or, s.find(&#39;o&#39;)</span></span>
<span id="cb35-3-6465548919"><a href="#cb35-3-6465548919"></a><span class="dv">5</span></span>
<span id="cb35-4-6465548919"><a href="#cb35-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.find(<span class="st">&#39;.com&#39;</span>)</span>
<span id="cb35-5-6465548919"><a href="#cb35-5-6465548919"></a><span class="dv">10</span></span>
<span id="cb35-6-6465548919"><a href="#cb35-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.find(bop<span class="st">&#39;)</span></span>
<span id="cb35-7-6465548919"><a href="#cb35-7-6465548919"></a><span class="st">-1</span></span></code></pre></div>
<p>Return -1 if <code>sub</code> is not found.</p>
<p>Note: The <code>find()</code> method should be used only if you need to know the position of <code>sub</code>. To check if <code>sub</code> is a substring or not, use the <code>in</code> operator:</p>
<div class="sourceCode" id="cb36-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb36-1-6465548919"><a href="#cb36-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;Py&#39;</span> <span class="kw">in</span> <span class="st">&#39;Python&#39;</span></span>
<span id="cb36-2-6465548919"><a href="#cb36-2-6465548919"></a><span class="va">True</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><pre><code>str.index(
self, sub
[, start
[, end]]
)</code></pre></td>
<td><p>Like <code>find()</code>, but raise <code>ValueError</code> when the substring is not found.</p>
<p>Example:</p>
<div class="sourceCode" id="cb38-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb38-1-6465548919"><a href="#cb38-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;www.google.com&#39;</span></span>
<span id="cb38-2-6465548919"><a href="#cb38-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.index(x, <span class="st">&#39;o&#39;</span>) <span class="co"># or, s.index(&#39;o&#39;)</span></span>
<span id="cb38-3-6465548919"><a href="#cb38-3-6465548919"></a><span class="dv">5</span></span>
<span id="cb38-4-6465548919"><a href="#cb38-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.index(<span class="st">&#39;.com&#39;</span>)</span>
<span id="cb38-5-6465548919"><a href="#cb38-5-6465548919"></a><span class="dv">10</span></span>
<span id="cb38-6-6465548919"><a href="#cb38-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.index(<span class="st">&#39;bop&#39;</span>)</span>
<span id="cb38-7-6465548919"><a href="#cb38-7-6465548919"></a><span class="pp">ValueError</span>: substring <span class="kw">not</span> found</span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>str.isalnum(self)</code></td>
<td><p>Return <code>True</code> if all characters in the string are alphanumeric and there is at least one character, <code>False</code> otherwise. A character <code>c</code> is alphanumeric if one of the following returns <code>True</code>: <code>c.isalpha()</code>, <code>c.isdecimal()</code>, <code>c.isdigit()</code>, or <code>c.isnumeric()</code>.</p>
<p>Example:</p>
<div class="sourceCode" id="cb39-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb39-1-6465548919"><a href="#cb39-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;www.google.com&#39;</span></span>
<span id="cb39-2-6465548919"><a href="#cb39-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.isalnum(s) <span class="co"># or, s.isalnum()</span></span>
<span id="cb39-3-6465548919"><a href="#cb39-3-6465548919"></a><span class="va">False</span></span>
<span id="cb39-4-6465548919"><a href="#cb39-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;passw0rd&#39;</span></span>
<span id="cb39-5-6465548919"><a href="#cb39-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isalnum()</span>
<span id="cb39-6-6465548919"><a href="#cb39-6-6465548919"></a><span class="va">True</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>str.isalpha(self)</code></td>
<td><p>Return <code>True</code> if all characters in the string are alphabetic and there is at least one character, <code>False</code> otherwise. Alphabetic characters are those characters defined in the Unicode character database as “Letter”, i.e., those with general category property being one of “Lm”, “Lt”, “Lu”, “Ll”, or “Lo”. Note that this is different from the “Alphabetic” property defined in the Unicode Standard.</p>
<p>Example:</p>
<div class="sourceCode" id="cb40-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb40-1-6465548919"><a href="#cb40-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb40-2-6465548919"><a href="#cb40-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.isalpha(s) <span class="co"># or, s.isalpha()</span></span>
<span id="cb40-3-6465548919"><a href="#cb40-3-6465548919"></a><span class="va">False</span></span>
<span id="cb40-4-6465548919"><a href="#cb40-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;passw0rd&#39;</span></span>
<span id="cb40-5-6465548919"><a href="#cb40-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isalpha()</span>
<span id="cb40-6-6465548919"><a href="#cb40-6-6465548919"></a><span class="va">False</span></span>
<span id="cb40-7-6465548919"><a href="#cb40-7-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;word&#39;</span></span>
<span id="cb40-8-6465548919"><a href="#cb40-8-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isalpha()</span>
<span id="cb40-9-6465548919"><a href="#cb40-9-6465548919"></a><span class="va">True</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>str.isdigit(self)</code></td>
<td><p>Return <code>True</code> if all characters in the string are digits and there is at least one character, <code>False</code> otherwise. Example:</p>
<div class="sourceCode" id="cb41-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb41-1-6465548919"><a href="#cb41-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;10&#39;</span></span>
<span id="cb41-2-6465548919"><a href="#cb41-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.isdigit(s) <span class="co"># or, s.isdigit()</span></span>
<span id="cb41-3-6465548919"><a href="#cb41-3-6465548919"></a><span class="va">True</span></span>
<span id="cb41-4-6465548919"><a href="#cb41-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;-10&#39;</span></span>
<span id="cb41-5-6465548919"><a href="#cb41-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isdigit()</span>
<span id="cb41-6-6465548919"><a href="#cb41-6-6465548919"></a><span class="va">False</span></span>
<span id="cb41-7-6465548919"><a href="#cb41-7-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;10 kittens&#39;</span></span>
<span id="cb41-8-6465548919"><a href="#cb41-8-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isdigit()</span>
<span id="cb41-9-6465548919"><a href="#cb41-9-6465548919"></a><span class="va">False</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>str.islower(self)</code></td>
<td><p>Return <code>True</code> if all cased characters in the string are lowercase and there is at least one cased character, <code>False</code> otherwise.</p>
<p>Example:</p>
<div class="sourceCode" id="cb42-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb42-1-6465548919"><a href="#cb42-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;www.google.com&#39;</span></span>
<span id="cb42-2-6465548919"><a href="#cb42-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.islower(s) <span class="co"># or, s.islower()</span></span>
<span id="cb42-3-6465548919"><a href="#cb42-3-6465548919"></a><span class="va">True</span></span>
<span id="cb42-4-6465548919"><a href="#cb42-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Capitalized&#39;</span></span>
<span id="cb42-5-6465548919"><a href="#cb42-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.islower()</span>
<span id="cb42-6-6465548919"><a href="#cb42-6-6465548919"></a><span class="va">False</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>str.isnumeric(self)</code></td>
<td><p>Return <code>True</code> if all characters in the string are numeric characters, and there is at least one character, <code>False</code> otherwise. Numeric characters include digit characters, and all characters that have the Unicode numeric value property.</p>
<p>Example:</p>
<div class="sourceCode" id="cb43-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb43-1-6465548919"><a href="#cb43-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;abc123&#39;</span></span>
<span id="cb43-2-6465548919"><a href="#cb43-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.isnumeric(s) <span class="co"># or, s.isnumeric()</span></span>
<span id="cb43-3-6465548919"><a href="#cb43-3-6465548919"></a><span class="va">False</span></span>
<span id="cb43-4-6465548919"><a href="#cb43-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;1647123123&#39;</span></span>
<span id="cb43-5-6465548919"><a href="#cb43-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isnumeric()</span>
<span id="cb43-6-6465548919"><a href="#cb43-6-6465548919"></a><span class="va">True</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>str.isupper(self)</code></td>
<td><p>Return <code>True</code> if all cased characters in the string are uppercase and there is at least one cased character, <code>False</code> otherwise.</p>
<p>Example:</p>
<div class="sourceCode" id="cb44-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb44-1-6465548919"><a href="#cb44-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;www.google.com&#39;</span></span>
<span id="cb44-2-6465548919"><a href="#cb44-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.isupper(s) <span class="co"># or, s.isupper()</span></span>
<span id="cb44-3-6465548919"><a href="#cb44-3-6465548919"></a><span class="va">False</span></span>
<span id="cb44-4-6465548919"><a href="#cb44-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Capitalized&#39;</span></span>
<span id="cb44-5-6465548919"><a href="#cb44-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isupper()</span>
<span id="cb44-6-6465548919"><a href="#cb44-6-6465548919"></a><span class="va">False</span></span>
<span id="cb44-7-6465548919"><a href="#cb44-7-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;SHOUTING&#39;</span></span>
<span id="cb44-8-6465548919"><a href="#cb44-8-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.isupper()</span>
<span id="cb44-9-6465548919"><a href="#cb44-9-6465548919"></a><span class="va">True</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><code>str.join(self, iterable)</code></td>
<td><p>Return a string which is the concatenation of the strings in <code>iterable</code>. A <code>TypeError</code> will be raised if there are any non-string values in <code>iterable</code>, including bytes objects. The separator between elements is the string providing this method.</p>
<p>Example:</p>
<div class="sourceCode" id="cb45-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb45-1-6465548919"><a href="#cb45-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> lst <span class="op">=</span> [<span class="st">&#39;John&#39;</span>, <span class="st">&#39;David&#39;</span>, <span class="st">&#39;Jen&#39;</span>]</span>
<span id="cb45-2-6465548919"><a href="#cb45-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> separator <span class="op">=</span> <span class="st">&#39;, and &#39;</span></span>
<span id="cb45-3-6465548919"><a href="#cb45-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.join(separator, lst) <span class="co"># or, separator.join(lst)</span></span>
<span id="cb45-4-6465548919"><a href="#cb45-4-6465548919"></a><span class="co">&#39;John, and David, and Jen&#39;</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><code>str.lower(self)</code></td>
<td><p>Return a copy of the string with all the cased characters converted to lowercase. Example:</p>
<div class="sourceCode" id="cb46-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb46-1-6465548919"><a href="#cb46-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;lower&#39;</span></span>
<span id="cb46-2-6465548919"><a href="#cb46-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.lower(s) <span class="co"># or, s.lower()</span></span>
<span id="cb46-3-6465548919"><a href="#cb46-3-6465548919"></a><span class="co">&#39;www.google.com&#39;</span></span>
<span id="cb46-4-6465548919"><a href="#cb46-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Capitalized&#39;</span></span>
<span id="cb46-5-6465548919"><a href="#cb46-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.lower()</span>
<span id="cb46-6-6465548919"><a href="#cb46-6-6465548919"></a><span class="co">&#39;capitalized&#39;</span></span>
<span id="cb46-7-6465548919"><a href="#cb46-7-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;SHOUTING&#39;</span></span>
<span id="cb46-8-6465548919"><a href="#cb46-8-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.lower()</span>
<span id="cb46-9-6465548919"><a href="#cb46-9-6465548919"></a><span class="co">&#39;shouting&#39;</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><pre><code>str.replace(
self, old, new
[, count]
)</code></pre></td>
<td><p>Return a copy of the string with all occurrences of substring <code>old</code> replaced by <code>new</code>. If the optional argument <code>count</code> is given, only the first <code>count</code> occurrences are replaced.</p>
<p>Example:</p>
<div class="sourceCode" id="cb48-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb48-1-6465548919"><a href="#cb48-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;www.google.com&#39;</span></span>
<span id="cb48-2-6465548919"><a href="#cb48-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.replace(s, <span class="st">&#39;www.&#39;</span>, <span class="st">&#39;https://&#39;</span>) <span class="co"># or, s.replace(&#39;www.&#39;, &#39;https://&#39;)</span></span>
<span id="cb48-3-6465548919"><a href="#cb48-3-6465548919"></a><span class="co">&#39;https://google.com&#39;</span></span>
<span id="cb48-4-6465548919"><a href="#cb48-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s <span class="op">=</span> <span class="st">&#39;Far Farquad on a Far Quad&#39;</span></span>
<span id="cb48-5-6465548919"><a href="#cb48-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> s.replace(<span class="st">&#39;Far&#39;</span>, <span class="st">&#39;Close&#39;</span>)</span>
<span id="cb48-6-6465548919"><a href="#cb48-6-6465548919"></a><span class="co">&#39;Close Closequad on a Close Quad&#39;</span></span></code></pre></div></td>
</tr>
<tr class="odd">
<td><pre><code>str.split(
self,
sep=None,
maxsplit=-1
)</code></pre></td>
<td><p>Return a list of the words in the string, using <code>sep</code> as the delimiter string. If <code>maxsplit</code> is given, at most <code>maxsplit</code> splits are done (thus, the list will have at most <code>maxsplit+1</code> elements). If <code>maxsplit</code> is not specified or -1, then there is no limit on the number of splits (all possible splits are made).</p>
<p>If <code>sep</code> is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, <code>'1,,2'.split(',')</code> returns <code>['1', '', '2']</code>). The <code>sep</code> argument may consist of multiple characters (for example, <code>'1&lt;&gt;2&lt;&gt;3'.split('&lt;&gt;')</code> returns <code>['1', '2', '3']</code>).</p>
<p>Splitting an empty string with a specified separator returns [’’].</p>
<p>Example:</p>
<div class="sourceCode" id="cb50-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb50-1-6465548919"><a href="#cb50-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.split(<span class="st">&#39;1,2,3&#39;</span>, <span class="st">&#39;,&#39;</span>) <span class="co"># or, &#39;1,2,3&#39;.split(&#39;,&#39;)</span></span>
<span id="cb50-2-6465548919"><a href="#cb50-2-6465548919"></a>[<span class="st">&#39;1&#39;</span>, <span class="st">&#39;2&#39;</span>, <span class="st">&#39;3&#39;</span>]</span>
<span id="cb50-3-6465548919"><a href="#cb50-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;1,2,3&#39;</span>.split(<span class="st">&#39;,&#39;</span>, maxsplit<span class="op">=</span><span class="dv">1</span>)</span>
<span id="cb50-4-6465548919"><a href="#cb50-4-6465548919"></a>[<span class="st">&#39;1&#39;</span>, <span class="st">&#39;2,3&#39;</span>]</span>
<span id="cb50-5-6465548919"><a href="#cb50-5-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;1,2,,3,&#39;</span>.split(<span class="st">&#39;,&#39;</span>)</span>
<span id="cb50-6-6465548919"><a href="#cb50-6-6465548919"></a>[<span class="st">&#39;1&#39;</span>, <span class="st">&#39;2&#39;</span>, <span class="st">&#39;&#39;</span>, <span class="st">&#39;3&#39;</span>, <span class="st">&#39;&#39;</span>]</span></code></pre></div>
<p>If <code>sep</code> is not specified or is <code>None</code>, a different splitting algorithm is applied: runs of consecutive whitespace are regarded as a single separator, and the result will contain no empty strings at the start or end if the string has leading or trailing whitespace. Consequently, splitting an empty string or a string consisting of just whitespace with a <code>None</code> separator returns <code>[]</code>.</p></td>
</tr>
<tr class="even">
<td><pre><code>str.startswith(
self, prefix,
[, start
[, end]]
)</code></pre></td>
<td>Return <code>True</code> if string starts with the <code>prefix</code>, otherwise return <code>False</code>. With optional <code>start</code>, test string begins at that position. With optional <code>end</code>, stop comparing string at that position.</td>
</tr>
<tr class="odd">
<td><code>str.strip(self, [chars])</code></td>
<td><p>Return a copy of the string with the leading and trailing characters removed. The <code>chars</code> argument is a string specifying the set of characters to be removed. If omitted or <code>None</code>, the chars argument defaults to removing whitespace.</p>
<p>The <code>chars</code> argument is not a prefix or suffix; rather, all combinations of its values are stripped.</p>
<p>Example:</p>
<div class="sourceCode" id="cb52-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb52-1-6465548919"><a href="#cb52-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">str</span>.strip(<span class="st">&#39; spacious &#39;</span>) <span class="co"># or, &#39; spacious &#39;.strip()</span></span>
<span id="cb52-2-6465548919"><a href="#cb52-2-6465548919"></a><span class="co">&#39;spacious&#39;</span></span>
<span id="cb52-3-6465548919"><a href="#cb52-3-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="st">&#39;www.example.com&#39;</span>.strip(<span class="st">&#39;cmowz.&#39;</span>)</span>
<span id="cb52-4-6465548919"><a href="#cb52-4-6465548919"></a><span class="co">&#39;example&#39;</span></span></code></pre></div>
<p>The outermost leading and trailing chars argument values are stripped from the string. Characters are removed from the leading end until reaching a string character that is not contained in the set of characters in chars. A similar action takes place on the trailing end.</p>
<p>Example:</p>
<div class="sourceCode" id="cb53-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb53-1-6465548919"><a href="#cb53-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> comment_string <span class="op">=</span> <span class="st">&#39;#....... Section 3.2.1 Issue #32 .......&#39;</span></span>
<span id="cb53-2-6465548919"><a href="#cb53-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> comment_string.strip(<span class="st">&#39;.#! &#39;</span>)</span>
<span id="cb53-3-6465548919"><a href="#cb53-3-6465548919"></a><span class="co">&#39;Section 3.2.1 Issue #32&#39;</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
</div>
<h2 id="set-typeset-6465548919">Set type—<code>set</code></h2>
<p>A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference.</p>
<p>Like other collections, sets support x in set, <code>len(set)</code>, and <code>for x in set</code>. Being an unordered collection, sets do not record element position or order of insertion. Accordingly, sets do not support indexing, slicing, or other sequence-like behavior.</p>
<p>The set type is mutable—the contents can be changed using methods like <code>add()</code> and <code>remove()</code>. Since it is mutable, it has no hash value and cannot be used as either a dictionary key or as an element of another set.</p>
<p>Non-empty sets can be created by placing a comma-separated list of elements within braces, for example: <code>{'jack', 'sjoerd'}</code>, in addition to the <code>set</code> constructor.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 38%" />
<col style="width: 61%" />
</colgroup>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>len(self)</code></td>
<td>Return the size (number of elements) of <code>self</code>.</td>
</tr>
<tr class="even">
<td><code>x in self</code></td>
<td>Return whether <code>x</code> is in <code>self</code>.</td>
</tr>
<tr class="odd">
<td><code>x not in self</code></td>
<td>Return whether <code>x</code> is <em>not</em> in <code>self</code>.</td>
</tr>
<tr class="even">
<td><code>set.isdisjoint(self, other)</code></td>
<td>Return whether the set <code>self</code> has no elements in common with <code>other</code>. Sets are disjoint if and only if their intersection is the empty set.</td>
</tr>
<tr class="odd">
<td><code>set.issubset(self, other)</code></td>
<td>Return whether every element in the set <code>self</code> is in <code>other</code>. Can also use <code>self &lt;= other</code>.</td>
</tr>
<tr class="even">
<td><code>self &lt; other</code></td>
<td>Return whether the set <code>self</code> is a proper subset of <code>other</code>, that is, <code>self &lt;= other and self != other</code>.</td>
</tr>
<tr class="odd">
<td><code>set.issuperset(self, other)</code></td>
<td>Return whether every element in <code>other</code> is in the set <code>self</code>. Can also use <code>self &gt;= other</code>.</td>
</tr>
<tr class="even">
<td><code>self &gt; other</code></td>
<td>Return whether the set <code>self</code> is a proper superset of <code>other</code>, that is, <code>self &gt;= other and self != other</code>.</td>
</tr>
<tr class="odd">
<td><code>set.union(self, *others)</code></td>
<td>Return a new set with elements from the set and all others.</td>
</tr>
<tr class="even">
<td><code>set.intersection(self, *others)</code></td>
<td>Return a new set with elements common to the set and all others.</td>
</tr>
<tr class="odd">
<td><code>set.difference(self, *others)</code></td>
<td>Return a new set with elements in the set that are not in the others.</td>
</tr>
<tr class="even">
<td><code>set.symmetric_difference(self, other)</code></td>
<td>Return a new set with elements in either the set or <code>other</code> but not both.</td>
</tr>
<tr class="odd">
<td><code>set.update(self, *others)</code></td>
<td>Update the set, adding elements from all others.</td>
</tr>
<tr class="even">
<td><code>set.intersection_update(self, *others)</code></td>
<td>Update the set, keeping only elements found in it and all others.</td>
</tr>
<tr class="odd">
<td><code>set.difference_update(self, *others)</code></td>
<td>Update the set, removing elements found in others.</td>
</tr>
<tr class="even">
<td><code>set.symmetric_difference_update(self, other)</code></td>
<td>Update the set, keeping only elements found in either set, but not in both.</td>
</tr>
<tr class="odd">
<td><code>set.add(self, elem)</code></td>
<td>Add element <code>elem</code> to the <code>set</code>.</td>
</tr>
<tr class="even">
<td><code>set.remove(self, elem)</code></td>
<td>Remove element <code>elem</code> from the set. Raises <code>KeyError</code> if <code>elem</code> is not contained in the set.</td>
</tr>
<tr class="odd">
<td><code>set.discard(self, elem)</code></td>
<td>Remove element <code>elem</code> from the set if it is present.</td>
</tr>
<tr class="even">
<td><code>set.pop(self)</code></td>
<td>Remove and return an arbitrary element from the set. Raises <code>KeyError</code> if the set is empty.</td>
</tr>
</tbody>
</table>
</div>
<p><code>set</code> supports set to set comparisons. Two sets are equal if and only if every element of each set is contained in the other (each is a subset of the other). A set is less than another set if and only if the first set is a proper subset of the second set (is a subset, but is not equal). A set is greater than another set if and only if the first set is a proper superset of the second set (is a superset, but is not equal).</p>
<h2 id="mapping-typedict-6465548919">Mapping type<code>dict</code></h2>
<p>A mapping object maps hashable values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the dictionary.</p>
<p>Dictionaries can be created by placing a comma-separated list of key: value pairs within braces, for example: <code>{'jack': 4098, 'sjoerd': 4127}</code> or <code>{4098: 'jack', 4127: 'sjoerd'}</code>, or by the <code>dic</code>t constructor.</p>
<p>These are the operations that dictionaries support (and therefore, custom mapping types should support too):</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 21%" />
<col style="width: 78%" />
</colgroup>
<thead>
<tr class="header">
<th>Operation</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>list(d)</code></td>
<td>Return a list of all the keys used in the dictionary <code>d</code>.</td>
</tr>
<tr class="even">
<td><code>len(d)</code></td>
<td>Return the number of items in the dictionary <code>d</code>.</td>
</tr>
<tr class="odd">
<td><code>d[key]</code></td>
<td>Return the item of <code>d</code> with key <code>key</code>. Raises a <code>KeyError</code> if <code>key</code> is not in the map.</td>
</tr>
<tr class="even">
<td><code>d[key] = value</code></td>
<td>Set <code>d[key]</code> to <code>value</code>.</td>
</tr>
<tr class="odd">
<td><code>key in d</code></td>
<td>Return <code>True</code> if <code>d</code> has a key <code>key</code>, else <code>False</code>.</td>
</tr>
<tr class="even">
<td><code>key not in d</code></td>
<td>Equivalent to <code>not key in d</code>.</td>
</tr>
<tr class="odd">
<td><pre><code>dict.get(self, key
[, default]
)</code></pre></td>
<td>Return the value for <code>key</code> if <code>key</code> is in the dictionary, else <code>default</code>. If <code>default</code> is not given, it defaults to <code>None</code>, so that this method never raises a <code>KeyError</code>.</td>
</tr>
<tr class="even">
<td><code>dict.items(self)</code></td>
<td>Return a new view of the dictionarys items ((key, value) pairs).</td>
</tr>
<tr class="odd">
<td><pre><code>dict.pop(self, key
[, default]
)</code></pre></td>
<td>If <code>key</code> is in the dictionary, remove it and return its value, else return <code>default</code> If <code>default</code> is not given and <code>key</code> is not in the dictionary, a <code>KeyError</code> is raised.</td>
</tr>
<tr class="even">
<td><code>dict.popitem(self)</code></td>
<td>Remove and return a (key, value) pair from the dictionary. Pairs are returned in last-in-first-out (LIFO) order. <code>popitem()</code> is useful to destructively iterate over a dictionary, as often used in set algorithms. If the dictionary is empty, calling <code>popitem()</code> raises a <code>KeyError</code>.</td>
</tr>
<tr class="odd">
<td><pre><code>dict.setdefault(self, key
[, default]
)</code></pre></td>
<td>If <code>key</code> is in the dictionary, return its value. If not, insert <code>key</code> with a value of <code>default</code> and return <code>default</code>. <code>default</code> defaults to <code>None</code>.</td>
</tr>
</tbody>
</table>
</div>
<p>Dictionaries compare equal if and only if they have the same (key, value) pairs (regardless of ordering). Order comparisons (<code>&lt;</code>, <code>&lt;=</code>, <code>&gt;=</code> <code>&gt;</code>) raise <code>TypeError</code>.</p>
<p>Dictionaries preserve insertion order. Note that updating a key does not affect the order. Keys added after deletion are inserted at the end.</p>
<div class="sourceCode" id="cb57-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb57-1-6465548919"><a href="#cb57-1-6465548919"></a><span class="op">&gt;&gt;&gt;</span> d <span class="op">=</span> {<span class="st">&quot;one&quot;</span>: <span class="dv">1</span>, <span class="st">&quot;two&quot;</span>: <span class="dv">2</span>, <span class="st">&quot;three&quot;</span>: <span class="dv">3</span>, <span class="st">&quot;four&quot;</span>: <span class="dv">4</span>}</span>
<span id="cb57-2-6465548919"><a href="#cb57-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> d</span>
<span id="cb57-3-6465548919"><a href="#cb57-3-6465548919"></a>{<span class="st">&#39;one&#39;</span>: <span class="dv">1</span>, <span class="st">&#39;two&#39;</span>: <span class="dv">2</span>, <span class="st">&#39;three&#39;</span>: <span class="dv">3</span>, <span class="st">&#39;four&#39;</span>: <span class="dv">4</span>}</span>
<span id="cb57-4-6465548919"><a href="#cb57-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(d)</span>
<span id="cb57-5-6465548919"><a href="#cb57-5-6465548919"></a>[<span class="st">&#39;one&#39;</span>, <span class="st">&#39;two&#39;</span>, <span class="st">&#39;three&#39;</span>, <span class="st">&#39;four&#39;</span>]</span>
<span id="cb57-6-6465548919"><a href="#cb57-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(d.values())</span>
<span id="cb57-7-6465548919"><a href="#cb57-7-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>]</span>
<span id="cb57-8-6465548919"><a href="#cb57-8-6465548919"></a><span class="op">&gt;&gt;&gt;</span> d[<span class="st">&quot;one&quot;</span>] <span class="op">=</span> <span class="dv">42</span></span>
<span id="cb57-9-6465548919"><a href="#cb57-9-6465548919"></a><span class="op">&gt;&gt;&gt;</span> d</span>
<span id="cb57-10-6465548919"><a href="#cb57-10-6465548919"></a>{<span class="st">&#39;one&#39;</span>: <span class="dv">42</span>, <span class="st">&#39;two&#39;</span>: <span class="dv">2</span>, <span class="st">&#39;three&#39;</span>: <span class="dv">3</span>, <span class="st">&#39;four&#39;</span>: <span class="dv">4</span>}</span>
<span id="cb57-11-6465548919"><a href="#cb57-11-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="kw">del</span> d[<span class="st">&quot;two&quot;</span>]</span>
<span id="cb57-12-6465548919"><a href="#cb57-12-6465548919"></a><span class="op">&gt;&gt;&gt;</span> d[<span class="st">&quot;two&quot;</span>] <span class="op">=</span> <span class="va">None</span></span>
<span id="cb57-13-6465548919"><a href="#cb57-13-6465548919"></a><span class="op">&gt;&gt;&gt;</span> d</span>
<span id="cb57-14-6465548919"><a href="#cb57-14-6465548919"></a>{<span class="st">&#39;one&#39;</span>: <span class="dv">42</span>, <span class="st">&#39;three&#39;</span>: <span class="dv">3</span>, <span class="st">&#39;four&#39;</span>: <span class="dv">4</span>, <span class="st">&#39;two&#39;</span>: <span class="va">None</span>}</span></code></pre></div>
<h2 id="numeric-sequence-data-typerange-6465548919">Numeric sequence data type—<code>range</code></h2>
<p>The <code>range</code> type represents an immutable sequence of numbers and is commonly used for looping a specific number of times in for loops.</p>
<p>Constructor: <code>range(stop)</code> or <code>range(start, stop[, step])</code>.</p>
<p>The arguments to the range constructor must be integers. If the <code>step</code> argument is omitted, it defaults to 1. If the <code>start</code> argument is omitted, it defaults to 0. If <code>step</code> is zero, <code>ValueError</code> is raised.</p>
<p>For a positive step, the contents of a range <code>r</code> are determined by the formula <code>r[i] = start + step*i</code> where <code>i &gt;= 0</code> and <code>r[i] &lt; stop</code>.</p>
<p>For a negative step, the contents of the range are still determined by the formula <code>r[i] = start + step*i</code>, but the constraints are <code>i &gt;= 0</code> and <code>r[i] &gt; stop</code>.</p>
<p>Range examples:</p>
<div class="sourceCode" id="cb58-6465548919"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb58-1-6465548919"><a href="#cb58-1-6465548919"></a></span>
<span id="cb58-2-6465548919"><a href="#cb58-2-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">10</span>))</span>
<span id="cb58-3-6465548919"><a href="#cb58-3-6465548919"></a>[<span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>, <span class="dv">9</span>]</span>
<span id="cb58-4-6465548919"><a href="#cb58-4-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">1</span>, <span class="dv">11</span>))</span>
<span id="cb58-5-6465548919"><a href="#cb58-5-6465548919"></a>[<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>, <span class="dv">9</span>, <span class="dv">10</span>]</span>
<span id="cb58-6-6465548919"><a href="#cb58-6-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">30</span>, <span class="dv">5</span>))</span>
<span id="cb58-7-6465548919"><a href="#cb58-7-6465548919"></a>[<span class="dv">0</span>, <span class="dv">5</span>, <span class="dv">10</span>, <span class="dv">15</span>, <span class="dv">20</span>, <span class="dv">25</span>]</span>
<span id="cb58-8-6465548919"><a href="#cb58-8-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">10</span>, <span class="dv">3</span>))</span>
<span id="cb58-9-6465548919"><a href="#cb58-9-6465548919"></a>[<span class="dv">0</span>, <span class="dv">3</span>, <span class="dv">6</span>, <span class="dv">9</span>]</span>
<span id="cb58-10-6465548919"><a href="#cb58-10-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">0</span>, <span class="op">-</span><span class="dv">10</span>, <span class="op">-</span><span class="dv">1</span>))</span>
<span id="cb58-11-6465548919"><a href="#cb58-11-6465548919"></a>[<span class="dv">0</span>, <span class="op">-</span><span class="dv">1</span>, <span class="op">-</span><span class="dv">2</span>, <span class="op">-</span><span class="dv">3</span>, <span class="op">-</span><span class="dv">4</span>, <span class="op">-</span><span class="dv">5</span>, <span class="op">-</span><span class="dv">6</span>, <span class="op">-</span><span class="dv">7</span>, <span class="op">-</span><span class="dv">8</span>, <span class="op">-</span><span class="dv">9</span>]</span>
<span id="cb58-12-6465548919"><a href="#cb58-12-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">0</span>))</span>
<span id="cb58-13-6465548919"><a href="#cb58-13-6465548919"></a>[]</span>
<span id="cb58-14-6465548919"><a href="#cb58-14-6465548919"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(<span class="bu">range</span>(<span class="dv">1</span>, <span class="dv">0</span>))</span>
<span id="cb58-15-6465548919"><a href="#cb58-15-6465548919"></a>[]</span></code></pre></div>
<h2 id="the-null-typenone-6465548919">The “Null” type—<code>None</code></h2>
<p>This object is returned by functions that dont explicitly return a value. It supports no special operations. There is exactly one null object, named <code>None</code> (a built-in name).</p>
</section>
<br/> <a id="anchor-A--03"></a>
<header id="title-block-header-b72cc12183">
<h1 class="title">A.3 Python Special Method Reference</h1>
</header>
<section>
<p><em>Adapted from <a href="https://docs.python.org/3/reference/datamodel.html#special-method-names" class="uri">https://docs.python.org/3/reference/datamodel.html#special-method-names</a>.</em> Note that not all special methods are shown.</p>
<p>A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Pythons approach to operator overloading, allowing classes to define their own behavior with respect to language operators. For instance, if a class defines a method named <code>__getitem__()</code>, and <code>x</code> is an instance of this class, then <code>x[i]</code> is roughly equivalent to <code>type(x).__getitem__(x, i)</code>.</p>
<h2 id="basic-customization-b72cc12183">Basic customization</h2>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 24%" />
<col style="width: 75%" />
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>object.__init__(self[, ...])</code></td>
<td><p>Called after the instance has been created, but before it is returned to the caller.</p>
<p>The arguments are those passed to the class constructor expression.</p>
<p>If a base class has an <code>__init__()</code> method, the derived classs <code>__init__()</code> method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance.</p></td>
</tr>
<tr class="even">
<td><code>object.__str__(self)</code></td>
<td>Called by <code>str(object)</code> and the built-in functions <code>format()</code> and <code>print()</code> to compute the “informal” or nicely printable string representation of an object. The return value must be a string object.</td>
</tr>
<tr class="odd">
<td><code>object.__lt__(self, other)</code> <code>object.__le__(self, other)</code> <code>object.__eq__(self, other)</code> <code>object.__ne__(self, other)</code> <code>object.__gt__(self, other)</code> <code>object.__ge__(self, other)</code></td>
<td><p>These are the so-called “rich comparison” methods.</p>
<p>The correspondence between operator symbols and method names is as follows:</p>
<ul>
<li><code>x &lt; y</code> calls <code>x.__lt__(y)</code></li>
<li><code>x &lt;= y</code> calls <code>x.__le__(y)</code></li>
<li><code>x == y</code> calls <code>x.__eq__(y)</code></li>
<li><code>x != y</code> calls <code>x.__ne__(y)</code></li>
<li><code>x &gt; y</code> calls <code>x.__gt__(y)</code></li>
<li><code>x &gt;= y</code> calls <code>x.__ge__(y)</code></li>
</ul></td>
</tr>
</tbody>
</table>
</div>
<h2 id="emulating-container-types-b72cc12183">Emulating container types</h2>
<p>The following methods can be defined to implement container objects. Containers usually are sequences (such as lists or tuples) or mappings (like dictionaries), but can represent other containers as well.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 30%" />
<col style="width: 69%" />
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>object.__len__(self)</code></td>
<td>Called to implement the built-in function <code>len()</code>. Should return the length of the object, an integer <code>&gt;=</code> 0.</td>
</tr>
<tr class="even">
<td><code>object.__getitem__(self, key)</code></td>
<td><p>Called to implement evaluation of <code>self[key]</code>.</p>
<p>For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the <code>__getitem__()</code> method.</p>
<p>If key is of an inappropriate type, <code>TypeError</code> may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), <code>IndexError</code> should be raised. For mapping types, if key is missing (not in the container), <code>KeyError</code> should be raised.</p></td>
</tr>
<tr class="odd">
<td><code>object.__setitem__(self, key, value)</code></td>
<td><p>Called to implement assignment to <code>self[key]</code>.</p>
<p>Same note as for <code>__getitem__()</code>.</p>
<p>This should only be implemented for mappings if the objects support changes to the values for keys, or if new keys can be added, or for sequences if elements can be replaced.</p>
<p>The same exceptions should be raised for improper key values as for the <code>__getitem__()</code> method.</p></td>
</tr>
<tr class="even">
<td><code>object.__contains__(self, item)</code></td>
<td><p>Called to implement membership test operators (<code>in</code> and <code>not in</code>). Should return <code>True</code> if <code>item</code> is in <code>self</code>, <code>False</code> otherwise.</p>
<p>For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs.</p></td>
</tr>
<tr class="odd">
<td><code>object.__iter__(self)</code></td>
<td><p>This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container.</p>
<p>For mappings, it should iterate over the keys of the container.</p></td>
</tr>
</tbody>
</table>
</div>
</section>
<br/> <a id="anchor-A--04"></a>
<header id="title-block-header-385ffb0170">
<h1 class="title">A.4 Python Exceptions Reference</h1>
</header>
<section>
<p><em>Adapted from <a href="https://docs.python.org/3/library/exceptions.html" class="uri">https://docs.python.org/3/library/exceptions.html</a>.</em> Note: Not all built-in Python exceptions are shown.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 19%" />
<col style="width: 80%" />
</colgroup>
<thead>
<tr class="header">
<th>Exception</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>AssertionError</code></td>
<td>Raised when an <code>assert</code> statement fails.</td>
</tr>
<tr class="even">
<td><code>AttributeError</code></td>
<td><p>Raised when an attribute reference or assignment fails.</p>
<p>(When an object does not support attribute references or attribute assignments at all, <code>TypeError</code> is raised.)</p></td>
</tr>
<tr class="odd">
<td><code>FileNotFoundError</code></td>
<td>Raised when a file or directory is requested but doesnt exist.</td>
</tr>
<tr class="even">
<td><code>ImportError</code></td>
<td>Raised when the import statement has troubles trying to load a module. Also raised when the “from list” in <code>from ... import</code> has a name that cannot be found.</td>
</tr>
<tr class="odd">
<td><code>ModuleNotFoundError</code></td>
<td>A subclass of <code>ImportError</code> which is raised by <code>import</code> when a module could not be located.</td>
</tr>
<tr class="even">
<td><code>IndexError</code></td>
<td>Raised when a sequence subscript is out of range. (Slice indices are silently truncated to fall in the allowed range; if an index is not an integer, <code>TypeError</code> is raised.)</td>
</tr>
<tr class="odd">
<td><code>KeyError</code></td>
<td>Raised when a mapping (dictionary) key is not found in the set of existing keys.</td>
</tr>
<tr class="even">
<td><code>NameError</code></td>
<td>Raised when a local or global name is not found.</td>
</tr>
<tr class="odd">
<td><code>NotImplementedError</code></td>
<td>In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added.</td>
</tr>
<tr class="even">
<td><code>RecursionError</code></td>
<td>It is raised when the interpreter detects that the maximum recursion depth (see <code>sys.getrecursionlimit()</code>) is exceeded.</td>
</tr>
<tr class="odd">
<td><code>SyntaxError</code></td>
<td>Raised when the parser encounters a syntax error. This may occur in an import statement, in a call to the built-in functions <code>exec()</code> or <code>eval()</code>, or when reading the initial script or standard input (also interactively).</td>
</tr>
<tr class="even">
<td><code>IndentationError</code></td>
<td>Base class for syntax errors related to incorrect indentation.</td>
</tr>
<tr class="odd">
<td><code>TabError</code></td>
<td>Raised when indentation contains an inconsistent use of tabs and spaces.</td>
</tr>
<tr class="even">
<td><code>TypeError</code></td>
<td><p>Raised when an operation or function is applied to an object of inappropriate type. The associated value is a string giving details about the type mismatch.</p>
<p>This exception may be raised by user code to indicate that an attempted operation on an object is not supported, and is not meant to be. If an object is meant to support a given operation but has not yet provided an implementation, <code>NotImplementedError</code> is the proper exception to raise.</p>
<p>Passing arguments of the wrong type (e.g. passing a list when an int is expected) should result in a <code>TypeError</code>, but passing arguments with the wrong value (e.g. a number outside expected boundaries) should result in a <code>ValueError</code>.</p></td>
</tr>
<tr class="odd">
<td><code>ValueError</code></td>
<td>Raised when an operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception such as <code>IndexError</code>.</td>
</tr>
<tr class="even">
<td><code>ZeroDivisionError</code></td>
<td>Raised when the second argument of a division or modulo operation is zero. The associated value is a string indicating the type of the operands and the operation.</td>
</tr>
</tbody>
</table>
</div>
</section> <br/> <a id="anchor-A--05"></a>
<header id="title-block-header-b8c3143477">
<h1 class="title">A.5 Python Syntax Diagrams</h1>
</header>
<section>
<h2 id="literals-b8c3143477">Literals</h2>
<p><img src="images/literals_diagram.png" alt="Literals diagram" /><br />
</p>
<h2 id="comprehensions-b8c3143477">Comprehensions</h2>
<p><img src="images/comprehensions_diagram.png" alt="Comprehensions diagram" /><br />
</p>
<h2 id="assignment-statements-b8c3143477">Assignment statements</h2>
<p><img src="images/assignment_statement_diagram.png" alt="Assignment statement diagram" /><br />
</p>
<h2 id="function-definitions-b8c3143477">Function definitions</h2>
<p><img src="images/function_definition_diagram.png" alt="Function definition diagram" /><br />
</p>
<h2 id="data-class-definitions-b8c3143477">Data class definitions</h2>
<p><img src="images/data_class_diagram.png" alt="Data class definition diagram" /><br />
</p>
<h2 id="if-statements-b8c3143477">If statements</h2>
<p><img src="images/if_statement_diagram.png" alt="If statement diagram" /><br />
</p>
<h2 id="for-loop-statements-b8c3143477">For loop statements</h2>
<p><img src="images/for_loop_diagram.png" alt="For loop statement diagram" /><br />
</p>
<h2 id="while-loop-statements-b8c3143477">While loop statements</h2>
<p><img src="images/while_loop_diagram.png" alt="While loop statement diagram" /><br />
</p>
<h2 id="import-statements-b8c3143477">Import statements</h2>
<p><img src="images/import_statement_diagram.png" alt="Import statement diagram" /><br />
</p>
<h2 id="raise-statements-b8c3143477">Raise statements</h2>
<p><img src="images/raise_diagram.png" alt="Raise statement diagram" /><br />
</p>
<h2 id="try-except-statements-b8c3143477">Try-except statements</h2>
<p><img src="images/try_except_diagram.png" alt="Try-except statement diagram" /><br />
</p>
</section>
<br/>
<h2 id="appendix-b.-python-libraries">Appendix B. Python Libraries</h2>
<a id="anchor-B--01"></a>
<header id="title-block-header-4143a8596c">
<h1 class="title">B.1 <code>doctest</code></h1>
</header>
<section>
<p><em>Adapted from <a href="https://docs.python.org/3.8/library/doctest.html" class="uri">https://docs.python.org/3.8/library/doctest.html</a>.</em></p>
<p>The <code>doctest</code> module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown.</p>
<p>Heres a simple standalone example:</p>
<div class="sourceCode" id="cb1-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-4143a8596c"><a href="#cb1-1-4143a8596c"></a><span class="kw">def</span> is_even(value: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-4143a8596c"><a href="#cb1-2-4143a8596c"></a> <span class="co">&quot;&quot;&quot; Return whether value is divisible by 2.</span></span>
<span id="cb1-3-4143a8596c"><a href="#cb1-3-4143a8596c"></a></span>
<span id="cb1-4-4143a8596c"><a href="#cb1-4-4143a8596c"></a><span class="co"> &gt;&gt;&gt; is_even(2)</span></span>
<span id="cb1-5-4143a8596c"><a href="#cb1-5-4143a8596c"></a><span class="co"> True</span></span>
<span id="cb1-6-4143a8596c"><a href="#cb1-6-4143a8596c"></a><span class="co"> &gt;&gt;&gt; is_even(17)</span></span>
<span id="cb1-7-4143a8596c"><a href="#cb1-7-4143a8596c"></a><span class="co"> False</span></span>
<span id="cb1-8-4143a8596c"><a href="#cb1-8-4143a8596c"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-9-4143a8596c"><a href="#cb1-9-4143a8596c"></a> <span class="cf">return</span> value <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span></span></code></pre></div>
<p>The simplest way to start using <code>doctest</code> is to end each module with:</p>
<div class="sourceCode" id="cb2-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-4143a8596c"><a href="#cb2-1-4143a8596c"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb2-2-4143a8596c"><a href="#cb2-2-4143a8596c"></a> <span class="im">import</span> doctest</span>
<span id="cb2-3-4143a8596c"><a href="#cb2-3-4143a8596c"></a> doctest.testmod()</span></code></pre></div>
<p><code>doctest</code> then examines docstrings in the module.</p>
<p>Running the module as a script causes the examples in the docstrings to get executed and verified.</p>
<p>This wont display anything unless an example fails, in which case the failing example(s) and the cause(s) of the failure(s) are printed, and the final line of output is <code>***Test Failed*** N failures.</code>, where <code>N</code> is the number of examples that failed.</p>
<p>You can force verbose mode by passing <code>verbose=True</code> to <code>testmod()</code>. In this case, a detailed report of all examples tried is printed to standard output, along with assorted summaries at the end.</p>
<h2 id="how-it-works-4143a8596c">How it works</h2>
<p>This section examines in detail how doctest works: which docstrings it looks at, how it finds interactive examples, and how it handles exceptions. This is the information that you need to know to write doctest examples; for information about actually running doctest on these examples, see the following sections.</p>
<h2 id="which-docstrings-are-examined-4143a8596c">Which docstrings are examined?</h2>
<p>The module docstring, and all function, class and method docstrings are searched. Objects imported into the module are not searched.</p>
<h2 id="how-are-docstring-examples-recognized-4143a8596c">How are docstring examples recognized?</h2>
<p>The module docstring, and all function, class and method docstrings are searched. Objects imported into the module are not searched.</p>
<p>In most cases a copy-and-paste of an interactive console session works fine, but doctest isnt trying to do an exact emulation of any specific Python shell.</p>
<div class="sourceCode" id="cb3-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-4143a8596c"><a href="#cb3-1-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> <span class="co"># comments are ignored</span></span>
<span id="cb3-2-4143a8596c"><a href="#cb3-2-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> x <span class="op">=</span> <span class="dv">12</span></span>
<span id="cb3-3-4143a8596c"><a href="#cb3-3-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> x</span>
<span id="cb3-4-4143a8596c"><a href="#cb3-4-4143a8596c"></a><span class="dv">12</span></span>
<span id="cb3-5-4143a8596c"><a href="#cb3-5-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> <span class="cf">if</span> x <span class="op">==</span> <span class="dv">13</span>:</span>
<span id="cb3-6-4143a8596c"><a href="#cb3-6-4143a8596c"></a>... <span class="bu">print</span>(<span class="st">&quot;yes&quot;</span>)</span>
<span id="cb3-7-4143a8596c"><a href="#cb3-7-4143a8596c"></a>... <span class="cf">else</span>:</span>
<span id="cb3-8-4143a8596c"><a href="#cb3-8-4143a8596c"></a>... <span class="bu">print</span>(<span class="st">&quot;no&quot;</span>)</span>
<span id="cb3-9-4143a8596c"><a href="#cb3-9-4143a8596c"></a>... <span class="bu">print</span>(<span class="st">&quot;NO&quot;</span>)</span>
<span id="cb3-10-4143a8596c"><a href="#cb3-10-4143a8596c"></a>... <span class="bu">print</span>(<span class="st">&quot;NO!!!&quot;</span>)</span>
<span id="cb3-11-4143a8596c"><a href="#cb3-11-4143a8596c"></a>...</span>
<span id="cb3-12-4143a8596c"><a href="#cb3-12-4143a8596c"></a>no</span>
<span id="cb3-13-4143a8596c"><a href="#cb3-13-4143a8596c"></a>NO</span>
<span id="cb3-14-4143a8596c"><a href="#cb3-14-4143a8596c"></a>NO<span class="op">!!!</span></span>
<span id="cb3-15-4143a8596c"><a href="#cb3-15-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span></span></code></pre></div>
<p>Any expected output must immediately follow the final <code>'&gt;&gt;&gt; '</code> or <code>'... '</code> line containing the code, and the expected output (if any) extends to the next <code>'&gt;&gt;&gt; '</code> or all-whitespace line.</p>
<p>Notes:</p>
<ul>
<li><p>Expected output cannot contain an all-whitespace line, since such a line is taken to signal the end of expected output. If expected output does contain a blank line, put <code>&lt;BLANKLINE&gt;</code> in your doctest example each place a blank line is expected.</p></li>
<li><p>This is an incorrect example because the prompt characters (i.e., <code>&gt;&gt;&gt;</code>) are missing:</p>
<div class="sourceCode" id="cb4-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-4143a8596c"><a href="#cb4-1-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span>
<span id="cb4-2-4143a8596c"><a href="#cb4-2-4143a8596c"></a><span class="co">is_even(2)</span></span>
<span id="cb4-3-4143a8596c"><a href="#cb4-3-4143a8596c"></a><span class="co">True</span></span>
<span id="cb4-4-4143a8596c"><a href="#cb4-4-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span></code></pre></div></li>
<li><p>This is an incorrect example because there is no space between the <code>&gt;&gt;&gt;</code> and the function call:</p>
<div class="sourceCode" id="cb5-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1-4143a8596c"><a href="#cb5-1-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span>
<span id="cb5-2-4143a8596c"><a href="#cb5-2-4143a8596c"></a><span class="co">&gt;&gt;&gt;is_even(2)</span></span>
<span id="cb5-3-4143a8596c"><a href="#cb5-3-4143a8596c"></a><span class="co">True</span></span>
<span id="cb5-4-4143a8596c"><a href="#cb5-4-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span></code></pre></div></li>
<li><p>This is an incorrect example because the result of the function call (<code>True</code>) is not included:</p>
<div class="sourceCode" id="cb6-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1-4143a8596c"><a href="#cb6-1-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span>
<span id="cb6-2-4143a8596c"><a href="#cb6-2-4143a8596c"></a><span class="co">&gt;&gt;&gt; is_even(2)</span></span>
<span id="cb6-3-4143a8596c"><a href="#cb6-3-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span></code></pre></div></li>
<li><p>This is an incorrect example because the result of the function call (<code>True</code>) is indented:</p>
<div class="sourceCode" id="cb7-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1-4143a8596c"><a href="#cb7-1-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span>
<span id="cb7-2-4143a8596c"><a href="#cb7-2-4143a8596c"></a><span class="co">&gt;&gt;&gt; is_even(2)</span></span>
<span id="cb7-3-4143a8596c"><a href="#cb7-3-4143a8596c"></a><span class="co"> True</span></span>
<span id="cb7-4-4143a8596c"><a href="#cb7-4-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span></code></pre></div></li>
</ul>
<h3 id="what-about-exceptions-4143a8596c">What about exceptions?</h3>
<p>The expected output for an exception must start with a traceback header, which may be either of the following two lines, indented the same as the first line of the example:</p>
<div class="sourceCode" id="cb8-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1-4143a8596c"><a href="#cb8-1-4143a8596c"></a>Traceback (most recent call last):</span>
<span id="cb8-2-4143a8596c"><a href="#cb8-2-4143a8596c"></a>Traceback (innermost last):</span></code></pre></div>
<p>The traceback header is followed by an optional traceback stack, whose contents are ignored by doctest. The traceback stack is typically omitted, or copied verbatim from an interactive session.</p>
<p>The traceback stack is followed by the most interesting part: the line(s) containing the exception type and detail. This is usually the last line of a traceback, but can extend across multiple lines if the exception has a multi-line detail:</p>
<div class="sourceCode" id="cb9-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1-4143a8596c"><a href="#cb9-1-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span>
<span id="cb9-2-4143a8596c"><a href="#cb9-2-4143a8596c"></a><span class="co">&gt;&gt;&gt; 1 + &#39;hi&#39;</span></span>
<span id="cb9-3-4143a8596c"><a href="#cb9-3-4143a8596c"></a><span class="co">Traceback (most recent call last):</span></span>
<span id="cb9-4-4143a8596c"><a href="#cb9-4-4143a8596c"></a><span class="co"> File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;</span></span>
<span id="cb9-5-4143a8596c"><a href="#cb9-5-4143a8596c"></a><span class="co">TypeError: unsupported operand type(s) for +: &#39;int&#39; and &#39;str&#39;</span></span>
<span id="cb9-6-4143a8596c"><a href="#cb9-6-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span></code></pre></div>
<p>Best practice is to omit the traceback stack, unless it adds significant documentation value to the example. So the last example is probably better as:</p>
<div class="sourceCode" id="cb10-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1-4143a8596c"><a href="#cb10-1-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span>
<span id="cb10-2-4143a8596c"><a href="#cb10-2-4143a8596c"></a><span class="co">&gt;&gt;&gt; 1 + &#39;hi&#39;</span></span>
<span id="cb10-3-4143a8596c"><a href="#cb10-3-4143a8596c"></a><span class="co">Traceback (most recent call last):</span></span>
<span id="cb10-4-4143a8596c"><a href="#cb10-4-4143a8596c"></a><span class="co">TypeError: unsupported operand type(s) for +: &#39;int&#39; and &#39;str&#39;</span></span>
<span id="cb10-5-4143a8596c"><a href="#cb10-5-4143a8596c"></a><span class="co">&quot;&quot;&quot;</span></span></code></pre></div>
<h2 id="warnings-4143a8596c">Warnings</h2>
<p><code>doctest</code> is serious about requiring exact matches in expected output. If even a single character doesnt match, the test fails. This will probably surprise you a few times, as you learn exactly what Python does and doesnt guarantee about output. For example, when printing a set, Python doesnt guarantee that the element is printed in any particular order, so a test like</p>
<div class="sourceCode" id="cb11-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1-4143a8596c"><a href="#cb11-1-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> foo()</span>
<span id="cb11-2-4143a8596c"><a href="#cb11-2-4143a8596c"></a>{<span class="st">&#39;Hermione&#39;</span>, <span class="st">&#39;Harry&#39;</span>}</span></code></pre></div>
<p>is vulnerable! One workaround is to do</p>
<div class="sourceCode" id="cb12-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1-4143a8596c"><a href="#cb12-1-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> foo() <span class="op">==</span> {<span class="st">&#39;Hermione&#39;</span>, <span class="st">&#39;Harry&#39;</span>}</span>
<span id="cb12-2-4143a8596c"><a href="#cb12-2-4143a8596c"></a><span class="va">True</span></span></code></pre></div>
<p>instead. Another is to do</p>
<div class="sourceCode" id="cb13-4143a8596c"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1-4143a8596c"><a href="#cb13-1-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> d <span class="op">=</span> <span class="bu">sorted</span>(foo())</span>
<span id="cb13-2-4143a8596c"><a href="#cb13-2-4143a8596c"></a><span class="op">&gt;&gt;&gt;</span> d</span>
<span id="cb13-3-4143a8596c"><a href="#cb13-3-4143a8596c"></a>[<span class="st">&#39;Harry&#39;</span>, <span class="st">&#39;Hermione&#39;</span>]</span></code></pre></div>
<h2 id="soapbox-4143a8596c">Soapbox</h2>
<p>As mentioned in the introduction, <code>doctest</code> has grown to have three primary uses:</p>
<ol type="1">
<li>Checking examples in docstrings.</li>
<li>Regression testing.</li>
<li>Executable documentation / literate testing.</li>
</ol>
<p>These uses have different requirements, and it is important to distinguish them. In particular, filling your docstrings with obscure test cases makes for bad documentation.</p>
<p>When writing a docstring, choose docstring examples with care. Theres an art to this that needs to be learned—it may not be natural at first. Examples should add genuine value to the documentation. A good example can often be worth many words. If done with care, the examples will be invaluable for your users, and will pay back the time it takes to collect them many times over as the years go by and things change. Were still amazed at how often one of our <code>doctest</code> examples stops working after a “harmless” change.</p>
</section>
<br/> <a id="anchor-B--02"></a>
<header id="title-block-header-d6ba117be7">
<h1 class="title">B.2 <code>pytest</code></h1>
</header>
<section>
<p><code>pytest</code> is a Python library used to run tests for your code. In this section, well describe how to write tests that are automatically discovered and run by <code>pytest</code>, how to actually run <code>pytest</code> in your code, and some tips and tricks for making the most of <code>pytest</code>.</p>
<h2 id="how-do-you-write-a-pytest-test-d6ba117be7">How do you write a <code>pytest</code> test?</h2>
<p>A <strong>test</strong> in <code>pytest</code> is a Python function whose name starts with <code>test_</code>. Inside a test function, we use <code>assert</code> statements to verify expected values or behaviours of a function.</p>
<p>For example:</p>
<div class="sourceCode" id="cb1-d6ba117be7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-d6ba117be7"><a href="#cb1-1-d6ba117be7"></a><span class="co"># This is the function to test</span></span>
<span id="cb1-2-d6ba117be7"><a href="#cb1-2-d6ba117be7"></a><span class="kw">def</span> has_more_trues(booleans: <span class="bu">list</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-3-d6ba117be7"><a href="#cb1-3-d6ba117be7"></a> <span class="co">&quot;&quot;&quot;Return whether booleans contains more True values than False values.</span></span>
<span id="cb1-4-d6ba117be7"><a href="#cb1-4-d6ba117be7"></a></span>
<span id="cb1-5-d6ba117be7"><a href="#cb1-5-d6ba117be7"></a><span class="co"> &gt;&gt;&gt; has_more_trues([True, False, True])</span></span>
<span id="cb1-6-d6ba117be7"><a href="#cb1-6-d6ba117be7"></a><span class="co"> True</span></span>
<span id="cb1-7-d6ba117be7"><a href="#cb1-7-d6ba117be7"></a><span class="co"> &gt;&gt;&gt; has_more_trues([True, False, False])</span></span>
<span id="cb1-8-d6ba117be7"><a href="#cb1-8-d6ba117be7"></a><span class="co"> False</span></span>
<span id="cb1-9-d6ba117be7"><a href="#cb1-9-d6ba117be7"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-10-d6ba117be7"><a href="#cb1-10-d6ba117be7"></a> <span class="co"># Function body omitted</span></span>
<span id="cb1-11-d6ba117be7"><a href="#cb1-11-d6ba117be7"></a></span>
<span id="cb1-12-d6ba117be7"><a href="#cb1-12-d6ba117be7"></a></span>
<span id="cb1-13-d6ba117be7"><a href="#cb1-13-d6ba117be7"></a><span class="co"># This the test</span></span>
<span id="cb1-14-d6ba117be7"><a href="#cb1-14-d6ba117be7"></a><span class="kw">def</span> test_mixture_one_more_true() <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-15-d6ba117be7"><a href="#cb1-15-d6ba117be7"></a> <span class="co">&quot;&quot;&quot;Test has_more_trues on a list with a mixture of True and False,</span></span>
<span id="cb1-16-d6ba117be7"><a href="#cb1-16-d6ba117be7"></a><span class="co"> with one more True than False.</span></span>
<span id="cb1-17-d6ba117be7"><a href="#cb1-17-d6ba117be7"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb1-18-d6ba117be7"><a href="#cb1-18-d6ba117be7"></a> <span class="cf">assert</span> has_more_trues([<span class="va">True</span>, <span class="va">False</span>, <span class="va">True</span>])</span></code></pre></div>
<p>A single test can have multiple <code>assert</code> statements, although it is generally recommended to separate each <code>assert</code> statement into a separate test. A single Python file can have multiple tests; when <code>pytest</code> is run on a file, it (by default) runs all the tests in that file.</p>
<h2 id="running-pytest-d6ba117be7">Running <code>pytest</code></h2>
<p>The simplest way of running <code>pytest</code> is to add the following <code>if __name__ == '__main__'</code> block to the bottom of a test file:</p>
<div class="sourceCode" id="cb2-d6ba117be7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1-d6ba117be7"><a href="#cb2-1-d6ba117be7"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb2-2-d6ba117be7"><a href="#cb2-2-d6ba117be7"></a> <span class="im">import</span> pytest</span>
<span id="cb2-3-d6ba117be7"><a href="#cb2-3-d6ba117be7"></a> pytest.main()</span></code></pre></div>
<p>When you run this file, <code>pytest.main</code> will run all test functions in the file. <em>Note</em>: by default, <code>pytest.main</code> actually searches through <em>all</em> Python files in the current directory whose name starts with <code>test_</code> or ends with <code>_test</code>, which can be a bit surprising. So our practice will be to explicitly pass in the name of the current test file to <code>pytest.main</code>, wrapped in a list:</p>
<div class="sourceCode" id="cb3-d6ba117be7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1-d6ba117be7"><a href="#cb3-1-d6ba117be7"></a><span class="co"># If we&#39;re in a file test_my_file.py</span></span>
<span id="cb3-2-d6ba117be7"><a href="#cb3-2-d6ba117be7"></a></span>
<span id="cb3-3-d6ba117be7"><a href="#cb3-3-d6ba117be7"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb3-4-d6ba117be7"><a href="#cb3-4-d6ba117be7"></a> <span class="im">import</span> pytest</span>
<span id="cb3-5-d6ba117be7"><a href="#cb3-5-d6ba117be7"></a> pytest.main([<span class="st">&#39;test_my_file.py&#39;</span>])</span></code></pre></div>
<h2 id="testing-for-an-exceptions-d6ba117be7">Testing for an exceptions</h2>
<p>It is possible to write a <code>pytest</code> test that checks whether a function raises a specific error. To do so, use <code>pytest.raises</code>, which takes an error type as an argument, inside a <code>with</code> statement. Here is an example</p>
<div class="sourceCode" id="cb4-d6ba117be7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1-d6ba117be7"><a href="#cb4-1-d6ba117be7"></a><span class="im">import</span> pytest</span>
<span id="cb4-2-d6ba117be7"><a href="#cb4-2-d6ba117be7"></a></span>
<span id="cb4-3-d6ba117be7"><a href="#cb4-3-d6ba117be7"></a></span>
<span id="cb4-4-d6ba117be7"><a href="#cb4-4-d6ba117be7"></a><span class="kw">def</span> add_one(n):</span>
<span id="cb4-5-d6ba117be7"><a href="#cb4-5-d6ba117be7"></a> <span class="cf">return</span> n <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb4-6-d6ba117be7"><a href="#cb4-6-d6ba117be7"></a></span>
<span id="cb4-7-d6ba117be7"><a href="#cb4-7-d6ba117be7"></a></span>
<span id="cb4-8-d6ba117be7"><a href="#cb4-8-d6ba117be7"></a><span class="kw">def</span> test_add_one_type_error():</span>
<span id="cb4-9-d6ba117be7"><a href="#cb4-9-d6ba117be7"></a> <span class="co">&quot;&quot;&quot;Test add_one when given a non-numeric argument.&quot;&quot;&quot;</span></span>
<span id="cb4-10-d6ba117be7"><a href="#cb4-10-d6ba117be7"></a> <span class="cf">with</span> pytest.raises(<span class="pp">TypeError</span>):</span>
<span id="cb4-11-d6ba117be7"><a href="#cb4-11-d6ba117be7"></a> add_one(<span class="st">&#39;hello&#39;</span>)</span></code></pre></div>
<h2 id="options-for-pytest.main-d6ba117be7">Options for <code>pytest.main</code></h2>
<p><code>pytest.main</code> takes a list of strings as an argument because users can add options (as strings) to modify <code>pytest</code>s default behaviour when running tests. The format for this is <code>pytest.main([&lt;option1&gt;, &lt;option2&gt;, ...])</code>.</p>
<p>Here are some useful options:</p>
<ul>
<li><code>'&lt;filename&gt;'</code>: as we saw above, adding a filename restricts <code>pytest</code> to only running the tests in that Python file.</li>
<li><code>'&lt;filename&gt;::&lt;test_name&gt;'</code>: restrict <code>pytest</code> to run a specific test in the given file (e.g., <code>'test_my_file.py::test_1'</code>)</li>
<li><code>'-x'</code>: stop running tests after the first failure (by default, <code>pytest</code> runs all tests, regardless of the number of failures)</li>
<li><code>'--pdb'</code>: start the Python debugger when a test fails</li>
</ul>
<h2 id="references-d6ba117be7">References</h2>
<p>For the full documentation for the <code>pytest</code> library, check out <a href="https://docs.pytest.org/en/latest/" class="uri">https://docs.pytest.org/en/latest/</a>.</p>
</section>
<br/> <a id="anchor-B--03"></a>
<header id="title-block-header-9991a60864">
<h1 class="title">B.3 <code>python_ta</code></h1>
</header>
<section>
<p>PythonTA is a Python program that analyses Python code to help students find and fix common coding and style errors. Unlike testing libraries like <code>doctest</code> or <code>pytest</code>, PythonTA does not actually run your code. Instead, it analyzes the program text directly, looking for common patterns of code that oftne lead to errors.<label for="sn-0-9991a60864" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-9991a60864" class="margin-toggle"/><span class="sidenote">PyCharm does something very similar, which is why youll see red or yellow highlighted text in your Python files as youre working, before running the file.</span></p>
<h2 id="running-pythonta-9991a60864">Running PythonTA</h2>
<p>To run PythonTA on a Python file, put the following code at the bottom of the file you want to check:</p>
<div class="sourceCode" id="cb1-9991a60864"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-9991a60864"><a href="#cb1-1-9991a60864"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb1-2-9991a60864"><a href="#cb1-2-9991a60864"></a> <span class="im">import</span> python_ta</span>
<span id="cb1-3-9991a60864"><a href="#cb1-3-9991a60864"></a> python_ta.check_all()</span></code></pre></div>
<p>When you run this file, youll see a report open up in your web browser that shows any errors that PythonTA detected. These errors are divided into two broad categories:</p>
<ul>
<li>Code Errors or Forbidden Usage: you should fix these immediately, as they point out logical errors in your code, or a part of your code that is using some feature that is not allowed for your current assignment.</li>
<li>Style or Convention Errors: these identify ways to improve the formatting and design of your Python code. Fixing these is a lower priority, but you should still fix them before your final submission.<label for="sn-1-9991a60864" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-9991a60864" class="margin-toggle"/><span class="sidenote"> Tip: In PyCharm, you can go to the menu Code -&gt; Reformat File… to automatically fix common style errors in your current file.</span></li>
</ul>
<p>We recommend running PythonTA regularly as youre working on an assignment, as it can be a useful way to check your work and improve the quality of your code. If youre ever stuck, try taking a break and running PythonTA and fixing any errors it finds for you! This is a way to develop good programming habits and style, which will come in handy in this course (and all future courses).</p>
<h3 id="cleaning-up-9991a60864">Cleaning up</h3>
<p>When you run PythonTA, it generates a new report file called <code>pyta_report.html</code> in the same folder as the file youre checking. After youre done running PythonTA, you can safely delete this report file.</p>
<h2 id="checking-contracts-using-pythonta-9991a60864">Checking contracts using PythonTA</h2>
</section>
<br/> <a id="anchor-B--04"></a>
<header id="title-block-header-c4f9dd6ee5">
<h1 class="title">B.4 <code>typing</code></h1>
</header>
<section>
<p><em>Reference: <a href="https://docs.python.org/3.9/library/typing.html" class="uri">https://docs.python.org/3.9/library/typing.html</a>.</em></p>
<div class="fullwidth">
<table>
<colgroup>
<col style="width: 26%" />
<col style="width: 73%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>Any</code></td>
<td>A value that could be of any type. (Used as a placeholder when a variable’s type could be anything, or is unknown.)</td>
</tr>
<tr class="even">
<td><code>Callable[[T1, T2, ...], Tr]</code></td>
<td><p>A function whose parameters have type <code>T1</code>, <code>T2</code>, etc., and whose return type is <code>Tr</code>.</p>
<p>Example: the function</p>
<div class="sourceCode" id="cb1-c4f9dd6ee5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-c4f9dd6ee5"><a href="#cb1-1-c4f9dd6ee5"></a><span class="kw">def</span> f(x: <span class="bu">int</span>, y: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="bu">bool</span>:</span>
<span id="cb1-2-c4f9dd6ee5"><a href="#cb1-2-c4f9dd6ee5"></a> <span class="co"># Body omitted</span></span></code></pre></div>
<p>has type <code>Callable[[int, str], bool]</code>.</p></td>
</tr>
<tr class="odd">
<td><code>dict[T1, T2]</code></td>
<td><p>A dictionary whose keys have type <code>T1</code> and whose values have type <code>T2</code>.</p>
<p>Example: <code>{'a': 1, 'b': 2}</code> has type <code>dict[str, int]</code>.</p></td>
</tr>
<tr class="even">
<td><code>list[T]</code></td>
<td><p>A list whose elements all have type <code>T</code>.</p>
<p>Example: <code>[1, 2, 3]</code> has type <code>list[int]</code>.</p></td>
</tr>
<tr class="odd">
<td><code>Optional[T]</code></td>
<td>Synonym of <code>Union[T, None]</code>.</td>
</tr>
<tr class="even">
<td><code>set[T]</code></td>
<td><p>A set whose elements all have type <code>T</code>.</p>
<p>Example: <code>{'hi', 'bye'}</code> has type <code>set[str]</code>.</p></td>
</tr>
<tr class="odd">
<td><code>tuple[T1, T2, ...]</code></td>
<td><p>A tuple whose first element has type <code>T1</code>, second element has type <code>T2</code>, etc.</p>
<p>Example: <code>('hello', True, 3.4)</code> has type <code>tuple[str, bool, float]</code>.</p></td>
</tr>
<tr class="even">
<td><code>Union[T1, T2, ...]</code></td>
<td><p>A value whose type is one of <code>T1</code>, <code>T2</code>, etc.</p>
<p>Example: both <code>1</code> and <code>'hello'</code> are instance of type <code>Union[int, str]</code>.</p></td>
</tr>
</tbody>
</table>
</div>
</section>
<br/> <a id="anchor-B--05"></a>
<header id="title-block-header-bf08655483">
<h1 class="title">B.5 <code>pdb</code> (Python Debugger)</h1>
</header>
<section>
<p><em>Adapted from <a href="https://docs.python.org/3/library/pdb.html" class="uri">https://docs.python.org/3/library/pdb.html</a>.</em></p>
<p>The module <code>pdb</code> defines an interactive source code debugger for Python programs.</p>
<p>The typical usage to break into the debugger from a running program is to insert</p>
<div class="sourceCode" id="cb1-bf08655483"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1-bf08655483"><a href="#cb1-1-bf08655483"></a><span class="bu">breakpoint</span>()</span></code></pre></div>
<p>at the location you want to break into the debugger. You can then step through the code following this statement, and continue running without the debugger using the continue command.</p>
<h2 id="debugger-commands-bf08655483">Debugger commands</h2>
<p>The commands recognized by the debugger are listed below. Most commands can be abbreviated to one or two letters as indicated; e.g. <code>h(elp)</code> means that either <code>h</code> or <code>help</code> can be used to enter the help command (but not <code>he</code> or <code>hel</code>, nor <code>H</code> or <code>Help</code> or <code>HELP</code>). Arguments to commands must be separated by whitespace (spaces or tabs).</p>
<p>Entering a blank line repeats the last command entered. Exception: if the last command was a list command, the next 11 lines are listed.</p>
<p>Commands that the debugger doesnt recognize are assumed to be Python statements and are executed in the context of the program being debugged. This is a powerful way to inspect the program being debugged; it is even possible to change a variable or call a function. When an exception occurs in such a statement, the exception name is printed but the debuggers state is not changed.</p>
<div class="fullwidth reference-table">
<table>
<colgroup>
<col style="width: 16%" />
<col style="width: 83%" />
</colgroup>
<thead>
<tr class="header">
<th>Command</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>a(rgs)</td>
<td>Print the argument list of the current function.</td>
</tr>
<tr class="even">
<td>c(ont(inue))</td>
<td>Continue execution, only stop when a breakpoint is encountered.</td>
</tr>
<tr class="odd">
<td>h(elp)</td>
<td>Without argument, print the list of available commands. With a <em>command</em> as an argument, print help about that command.</td>
</tr>
<tr class="even">
<td>l(ist)</td>
<td><p>List source code for the current file. Without arguments, list 11 lines around the current line or continue the previous listing.</p>
<p>The current line in the current frame is indicated by <code>-&gt;</code>.</p></td>
</tr>
<tr class="odd">
<td>ll</td>
<td>List all source code for the current function or frame. (Short for “long list”.)</td>
</tr>
<tr class="even">
<td>n(ext)</td>
<td>Continue execution until the next line in the current function is reached or it returns. (The difference between <code>next</code> and <code>step</code> is that <code>step</code> stops inside a called function, while <code>next</code> executes called functions at (nearly) full speed, only stopping at the next line in the current function.)</td>
</tr>
<tr class="odd">
<td>r(eturn)</td>
<td>Continue execution until the current function returns.</td>
</tr>
<tr class="even">
<td>s(tep)</td>
<td>Execute the current line, stop at the first possible occasion (either in a function that is called or on the next line in the current function.)</td>
</tr>
</tbody>
</table>
</div>
</section>
<br/>
<!-- [B.3 `hypothesis`](B-python-libraries/03-hypothesis.html) <br/> -->
<h2 id="appendix-c.-math-reference">Appendix C. Math Reference</h2>
<a id="anchor-C--01"></a>
<header id="title-block-header-8266bd52bd">
<h1 class="title">C.1 Summations and Products</h1>
</header>
<section>
<p>When performing calculations, well often end up writing sums of terms, where each term follows a pattern. For example: <span class="math display">\[\frac{1 + 1^2}{3 + 1} +
\frac{2 + 2^2}{3 + 2} +
\frac{3 + 3^2}{3 + 3} +
\cdots +
\frac{100 + 100^2}{3 + 100}\]</span></p>
<p>We will often use <em>summation notation</em> to express such sums concisely. We could rewrite the previous example simply as: <span class="math display">\[\sum_{i=1}^{100} \frac{i + i^2}{3 + i}.\]</span></p>
<p>In this example, <span class="math inline">\(i\)</span> is called the <em>index of summation</em>, and <span class="math inline">\(1\)</span> and <span class="math inline">\(100\)</span> are the <em>lower</em> and <em>upper bounds</em> of the summation, respectively. A bit more generally, for any pair of integers <span class="math inline">\(j\)</span> and <span class="math inline">\(k\)</span>, and any function <span class="math inline">\(f : \Z \to \R\)</span>, we can use summation notation in the following way: <span class="math display">\[\sum_{i=j}^k f(i) = f(j) + f(j+1) + f(j+2) + \dots + f(k).\]</span></p>
<p>We can similarly use <em>product notation</em> to abbreviate multiplication:<label for="sn-0-8266bd52bd" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-8266bd52bd" class="margin-toggle"/><span class="sidenote">Fun fact: the Greek letter <span class="math inline">\(\Sigma\)</span> (sigma) corresponds to the first letter of “sum,” and the Greek letter <span class="math inline">\(\Pi\)</span> (pi) corresponds to the first letter of “product.”</span> <span class="math display">\[\prod_{i=j}^k f(i) = f(j) \times f(j+1) \times f(j+2) \times \dots \times f(k).\]</span></p>
<p>It is sometimes useful (e.g., in certain formulas) to allow a summation or products lower bound to be greater than its upper bound. In this case, we say the summation or product is <em>empty</em>, and define their values as follows:<label for="sn-1-8266bd52bd" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-8266bd52bd" class="margin-toggle"/><span class="sidenote">These particular values are chosen so that adding an empty summation and multiplying by an empty product do not change the value of an expression.</span></p>
<ul>
<li>When <span class="math inline">\(j &gt; k\)</span>, <span class="math inline">\(\sum_{i=j}^k f(i) = 0\)</span>.</li>
<li>When <span class="math inline">\(j &gt; k\)</span>, <span class="math inline">\(\prod_{i=j}^k f(i) = 1\)</span>.</li>
</ul>
<p>Finally, well end off this section with a few formulas for common summation formulas, and a few laws governing how expressions using summation and product notation can be simplified.</p>
<div id="theorem:summation_formulas-8266bd52bd" class="theorem">
<p>For all <span class="math inline">\(n \in \N\)</span>, the following formulas hold:</p>
<ol type="1">
<li>For all <span class="math inline">\(c \in \R\)</span>, <span class="math inline">\(\sum_{i=1}^{n} c = c \cdot n\)</span> (sum with constant terms).</li>
<li><span class="math inline">\(\sum_{i=0}^{n} i = \frac{n(n+1)}{2}\)</span> (sum of consecutive numbers).</li>
<li><span class="math inline">\(\sum_{i=0}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}\)</span> (sum of consecutive squares).</li>
<li>For all <span class="math inline">\(r \in \R\)</span>, if <span class="math inline">\(r \neq 1\)</span> then <span class="math inline">\(\sum_{i=0}^{n-1} r^i = \frac{r^n - 1}{r - 1}\)</span> (sum of powers).</li>
<li>For all <span class="math inline">\(r \in \R\)</span>, if <span class="math inline">\(r \neq 1\)</span> then <span class="math inline">\(\sum_{i=0}^{n-1} i \cdot r^i = \frac{n \cdot r^n}{r - 1} - \frac{r(r^n - 1)}{(r - 1)^2}\)</span> (arithmetico-geometric series).</li>
</ol>
</div>
<div id="theorem:summation_product_laws-8266bd52bd" class="theorem">
<p>For all <span class="math inline">\(m, n \in \Z\)</span>, the following formulas hold:</p>
<ol type="1">
<li><p><span class="math inline">\(\sum_{i=m}^{n} (a_i + b_i) = \left( \sum_{i=m}^{n} a_i \right) + \left(\sum_{i=m}^{n} b_i \right)\)</span> (separating sums)</p></li>
<li><p><span class="math inline">\(\prod_{i=m}^{n} (a_i \cdot b_i) = \left( \prod_{i=m}^{n} a_i \right) \cdot \left (\prod_{i=m}^{n} b_i \right)\)</span> (separating products)</p></li>
<li><p><span class="math inline">\(\sum_{i=m}^{n} c \cdot a_i = c \cdot \left( \sum_{i=m}^{n} a_i \right)\)</span> (factoring out constants, sums)</p></li>
<li><p><span class="math inline">\(\prod_{i=m}^{n} c \cdot a_i = c^{n - m + 1} \cdot \left( \prod_{i=m}^{n} a_i \right)\)</span> (factoring out constants, products)</p></li>
<li><p><span class="math inline">\(\sum_{i=m}^{n} a_i = \sum_{i&#39;=0}^{n-m} a_{i&#39;+m}\)</span> (change of index <span class="math inline">\(i&#39; = i - m\)</span>)</p></li>
<li><p><span class="math inline">\(\prod_{i=m}^{n} a_i = \prod_{i&#39;=0}^{n-m} a_{i&#39;+m}\)</span> (change of index <span class="math inline">\(i&#39; = i - m\)</span>)</p></li>
</ol>
</div>
</section>
<br/> <a id="anchor-C--02"></a>
<header id="title-block-header-d9b7447fef">
<h1 class="title">C.2 Inequalities</h1>
</header>
<section>
<p>In this course we will deal heavily with the manipulation of <em>inequalities</em>. While many of these operations are very similar to manipulating equalities, there are enough differences to warrant a comprehensive list.</p>
<div id="theorem:inequalities_basics-d9b7447fef" class="theorem">
<p>(<em>Arithmetic manipulations</em>) For all real numbers <span class="math inline">\(a\)</span>, <span class="math inline">\(b\)</span>, and <span class="math inline">\(c\)</span>, the following are true:</p>
<ol type="a">
<li>If <span class="math inline">\(a \leq b\)</span> and <span class="math inline">\(b \leq c\)</span>, then <span class="math inline">\(a \leq c\)</span>.</li>
<li>If <span class="math inline">\(a \leq b\)</span>, then <span class="math inline">\(a + c \leq b + c\)</span>.</li>
<li>If <span class="math inline">\(a \leq b\)</span> and <span class="math inline">\(c &gt; 0\)</span>, then <span class="math inline">\(ac \leq bc\)</span>.</li>
<li>If <span class="math inline">\(a \leq b\)</span> and <span class="math inline">\(c &lt; 0\)</span>, then <span class="math inline">\(ac \geq bc\)</span>.</li>
<li>If <span class="math inline">\(0 &lt; a \leq b\)</span>, then <span class="math inline">\(\frac{1}{a} \geq \frac{1}{b}\)</span>.</li>
<li>If <span class="math inline">\(a \leq b &lt; 0\)</span>, then <span class="math inline">\(\frac{1}{a} \geq \frac{1}{b}\)</span>.</li>
</ol>
<p>Moreover, if we replace any of the “if” inequalities with a strict inequality (i.e., change <span class="math inline">\(\leq\)</span> to <span class="math inline">\(&lt;\)</span>), then the corresponding “then” inequality is also strict.<label for="sn-0-d9b7447fef" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0-d9b7447fef" class="margin-toggle"/><span class="sidenote">For example, the following is true: “If <span class="math inline">\(a &lt; b\)</span>, then <span class="math inline">\(a + c &lt; b + c\)</span>.”</span></p>
</div>
<p>The previous theorem tells us that basic operations like adding a number or multiplying by a positive number preserves inequalities. However, other operations like multiplying by a negative number or taking reciprocals <em>reverses</em> the direction of the inequality, which is something we didnt have to worry about when dealing with equalities. But it turns out that, at least for non-negative numbers, most of our familiar functions preserve inequalities.</p>
<div class="definition" data-terms="increasing">
<p>Let <span class="math inline">\(f : \R^{\geq 0} \to \R^{\geq 0}\)</span>. We say that <span class="math inline">\(f\)</span> is when for all <span class="math inline">\(x, y \in \R^{\geq 0}\)</span>, if <span class="math inline">\(x &lt; y\)</span> then <span class="math inline">\(f(x) &lt; f(y)\)</span>.</p>
<p>Most common functions are strictly increasing:</p>
<ul>
<li>Raising to a positive power, e.g., <span class="math inline">\(f(x) = x^2\)</span> or <span class="math inline">\(f(x) = x^{3.14}\)</span>.<label for="sn-1-d9b7447fef" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1-d9b7447fef" class="margin-toggle"/><span class="sidenote"> Remember that were restricting ourselves to the <span class="math inline">\(\R^{\geq 0}\)</span> for the domain of these functions! <span class="math inline">\(f(x) = x^2\)</span> is not increasing on the domain <span class="math inline">\(\R\)</span>, for example.</span></li>
<li>Logarithms with a base greater than one, e.g., <span class="math inline">\(f(x) = \log_3(x + 1)\)</span>.</li>
<li>Exponential functions with a base greater than one, e.g., <span class="math inline">\(f(x) = 2^x\)</span>.</li>
</ul>
<p>Moreover, adding two strictly increasing functions, or multiplying a strictly increasing function by a positive constant or another always-positive strictly increasing function, results in another strictly increasing function. So for example, we know that <span class="math inline">\(f(x) = 300x^2 + x \log_3 x + 2^{x+100}\)</span> is also strictly increasing.</p>
</div>
<p>It should be clear from this definition that the following property holds, which enables us to manipulate inequalities using a host of common functions.</p>
<div id="theorem:inequalities_functions-d9b7447fef" class="theorem">
<p>For all non-negative real numbers <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span>, and all strictly increasing functions <span class="math inline">\(f: \R^{\geq 0} \TO \R^{\geq 0}\)</span>, if <span class="math inline">\(a \leq b\)</span>, then <span class="math inline">\(f(a) \leq f(b)\)</span>.</p>
<p>Moreover, if <span class="math inline">\(a &lt; b\)</span>, then <span class="math inline">\(f(a) &lt; f(b)\)</span>.</p>
</div>
<p>It is this theorem that allows us to perform several common operations on inequalities as a “step” in a computation. For example, if we know <span class="math inline">\(0 &lt; a \leq b\)</span>, then we can conclude that <span class="math inline">\(a^2 \leq b^2\)</span>, or <span class="math inline">\(\log_2(a) \leq \log_2(b)\)</span>, because both of the functions <span class="math inline">\(x^2\)</span> and <span class="math inline">\(\log_2(x)\)</span> are strictly increasing functions.</p>
</section>
<br/>
<h2 id="acknowledgments">Acknowledgments</h2>
<span class="marginnote"> <img src="images/logo.png" width="200" alt="CSC110 logo artwork" /><br />
</span>
These notes draw heavily from existing videos from <em>CSC108 Introduction to Computer Programming</em> (made by Jen Campbell and Paul Gries), course notes from <em>CSC148 Introduction to Computer Science</em> (co-authored by Diane Horton and David Liu) and <em>CSC165 Mathematical Expression and Reasoning for Computer Science</em> (co-authored by Toniann Pitassi and David Liu). We have linked to related CSC108 videos throughout the sections in these notes.
We were also assisted by a team of undergraduate students: Shannon Komguem, Oleksandr Kozin, Callum Cassidy-Nolan, Amy Peng, and Evan Kanter.
Cover artwork by Clémence Koh.
<h2 id="errata">Errata</h2>
If you encounter any typos or errors in these notes, please let us know by email at csc110-2020-09@cs.toronto.edu.
<footer>
<div class="anchor-links">
<h1 id="anchor-links">Anchor Links</h1>
<h3>1. Working with Data</h3>
<a href="#anchor-01-01">1.1 The Different Types of Data</a>
<a href="#anchor-01-02">1.2 Introducing the Python Programming Language</a>
<a href="#anchor-01-03">1.3 Representing Data in Python</a>
<a href="#anchor-01-04">1.4 Storing Data in Variables</a>
<a href="#anchor-01-05">1.5 Building Up Data with Comprehensions</a>
<a href="#anchor-01-06">1.6 Application: Representing Colour</a>
<h3>2. Functions</h3>
<a href="#anchor-02-01">2.1 Pythons Built-In Functions</a>
<a href="#anchor-02-02">2.2 Defining Our Own Functions</a>
<a href="#anchor-02-03">2.3 Local Variables and Function Scope</a>
<a href="#anchor-02-04">2.4 Importing Modules</a>
<a href="#anchor-02-05">2.5 The Function Design Recipe</a>
<a href="#anchor-02-06">2.6 Testing Functions I: <code>doctest</code> and <code>pytest</code></a>
<a href="#anchor-02-07">2.7 Type Conversion Functions</a>
<a href="#anchor-02-08">2.8 Application: Representing Text</a>
<h3>3. Formal Logic</h3>
<a href="#anchor-03-01">3.1 Propositional Logic</a>
<a href="#anchor-03-02">3.2 Predicate Logic</a>
<a href="#anchor-03-03">3.3 Filtering Collections</a>
<a href="#anchor-03-04">3.4 Conditional Execution</a>
<a href="#anchor-03-05">3.5 Simplifying If Statements</a>
<a href="#anchor-03-06">3.6 <code>if __name__ == '__main__'</code></a>
<a href="#anchor-03-07">3.7 Function Specification</a>
<a href="#anchor-03-08">3.8 Richer Type Annotations</a>
<a href="#anchor-03-09">3.9 Working With Definitions</a>
<a href="#anchor-03-10">3.10 Testing Functions II: <code>hypothesis</code></a>
<a href="#anchor-03-11">3.11 Working with Multiple Quantifiers</a>
<h3>4. Working with Complex Data</h3>
<a href="#anchor-04-01">4.1 Tabular Data</a>
<a href="#anchor-04-02">4.2 Defining Our Own Data Types, Part 1</a>
<a href="#anchor-04-03">4.3 Defining Our Own Data Types, Part 2</a>
<a href="#anchor-04-04">4.4 Repeated Execution: Loops</a>
<a href="#anchor-04-05">4.5 For Loop Variations</a>
<a href="#anchor-04-06">4.6 Index-Based For loops</a>
<a href="#anchor-04-07">4.7 Nested For Loops</a>
<h3>5. Modifying Values and Variables</h3>
<a href="#anchor-05-01">5.1 Variable Reassignment and Object Mutation</a>
<a href="#anchor-05-02">5.2 Operations on Mutable Data Types</a>
<a href="#anchor-05-03">5.3 The Full Python Memory Model: Introduction</a>
<a href="#anchor-05-04">5.4 Aliasing and “Mutation at a Distance”</a>
<a href="#anchor-05-05">5.5 The Full Python Memory Model: Function Calls</a>
<a href="#anchor-05-06">5.6 Testing Functions III: Testing Mutation</a>
<h3>6. Formal Proofs</h3>
<a href="#anchor-06-01">6.1 An Introduction to Number Theory</a>
<a href="#anchor-06-02">6.2 Proofs with Number Theory</a>
<a href="#anchor-06-03">6.3 Proofs and Algorithms I: Primality Testing</a>
<a href="#anchor-06-04">6.4 Proof by Cases and Disproofs</a>
<a href="#anchor-06-05">6.5 Greatest Common Divisor</a>
<a href="#anchor-06-06">6.6 Proofs and Algorithms II: Computing the Greatest Common Divisor</a>
<a href="#anchor-06-07">6.7 Modular Arithmetic</a>
<h3>7. Cryptography</h3>
<a href="#anchor-07-01">7.1 Introduction to Cryptography</a>
<a href="#anchor-07-02">7.2 The One-Time Pad and Perfect Secrecy</a>
<a href="#anchor-07-03">7.3 Computing Shared Secret Keys</a>
<a href="#anchor-07-04">7.4 The RSA Cryptosystem</a>
<a href="#anchor-07-05">7.5 Implementing RSA in Python</a>
<a href="#anchor-07-06">7.6 Application: Securing Online Communications</a>
<h3>8. Analyzing Algorithm Running Time</h3>
<a href="#anchor-08-01">8.1 An Introduction to Running Time</a>
<a href="#anchor-08-02">8.2 Comparing Asymptotic Function Growth with Big-O</a>
<a href="#anchor-08-03">8.3 Big-O, Omega, Theta</a>
<a href="#anchor-08-04">8.4 Analyzing Algorithm Running Time</a>
<a href="#anchor-08-05">8.5 Analyzing Comprehensions and While Loops</a>
<a href="#anchor-08-06">8.6 Analyzing Built-In Data Type Operations</a>
<a href="#anchor-08-07">8.7 Worst-Case Running Time Analysis</a>
<a href="#anchor-08-08">8.8 Testing Functions IV: Efficiency</a>
<h3>9. Abstraction, Classes, and Software Design</h3>
<a href="#anchor-09-01">9.1 An Introduction to Abstraction</a>
<a href="#anchor-09-02">9.2 Defining Our Own Data Types, Part 3</a>
<a href="#anchor-09-03">9.3 Data Types, Abstract and Concrete</a>
<a href="#anchor-09-04">9.4 Stacks</a>
<a href="#anchor-09-05">9.5 Exceptions as a Part of the Public Interface</a>
<a href="#anchor-09-06">9.6 Queues</a>
<a href="#anchor-09-07">9.7 Priority Queues</a>
<a href="#anchor-09-08">9.8 Defining a Shared Public Interface with Inheritance</a>
<a href="#anchor-09-09">9.9 The <code>object</code> Superclass</a>
<h3>10. Building a Simulation</h3>
<a href="#anchor-10-01">10.1 The Problem Domain: Food Delivery Networks</a>
<a href="#anchor-10-02">10.2 Object-Oriented Modelling of Our Problem Domain</a>
<a href="#anchor-10-03">10.3 A “Manager” Class</a>
<a href="#anchor-10-04">10.4 Food Delivery Events</a>
<a href="#anchor-10-05">10.5 Creating a Discrete-Event Simulation</a>
<h3>A. Python Reference</h3>
<a href="#anchor-A--01">A.1 Python Built-In Function Reference</a>
<a href="#anchor-A--02">A.2 Python Built-In Data Types Reference</a>
<a href="#anchor-A--03">A.3 Python Special Method Reference</a>
<a href="#anchor-A--04">A.4 Python Exceptions Reference</a>
<a href="#anchor-A--05">A.5 Python Syntax Diagrams</a>
<h3>B. Python Libraries</h3>
<a href="#anchor-B--01">B.1 <code>doctest</code></a>
<a href="#anchor-B--02">B.2 <code>pytest</code></a>
<a href="#anchor-B--03">B.3 <code>python-ta</code></a>
<a href="#anchor-B--04">B.4 <code>typing</code></a>
<a href="#anchor-B--05">B.5 <code>pdb</code></a>
<h3>C. Math Reference</h3>
<a href="#anchor-C--01">C.1 Summations and Products</a>
<a href="#anchor-C--02">C.2 Inequalities</a>
<a id="anchors-button" href="#anchor-links">Links</a>
</div>
<style>
a:link
{
text-decoration: underline;
background: unset;
text-shadow: unset;
}
.anchor-links a
{
display: block;
font-size: 1.2em;
text-decoration: none !important;
}
#anchors-button
{
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
position: fixed;
bottom: 20px;
left: 20px;
text-decoration: none !important;
width: 80px;
height: 45px;
font-family: 'Roboto', sans-serif;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 2px;
font-weight: 500;
color: #000;
background-color: #fff;
border: none;
border-radius: 45px;
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease 0s;
cursor: pointer;
outline: none;
}
#anchors-button:hover {
background-color: #2EE59D;
box-shadow: 0px 15px 20px rgba(46, 229, 157, 0.4);
color: #fff;
transform: translateY(-7px);
}
</style>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" type="text/javascript"></script>
</footer>
</body>
</html>