From c777e1001cf1a4cdb0b53e6083ae62b93c32a9d7 Mon Sep 17 00:00:00 2001 From: Ben Hutton Date: Tue, 30 Sep 2025 12:11:40 +0100 Subject: [PATCH 1/4] Created using Colab --- chapters/chap01.ipynb | 2824 ++++++++++++++++++++++------------------- 1 file changed, 1518 insertions(+), 1306 deletions(-) diff --git a/chapters/chap01.ipynb b/chapters/chap01.ipynb index bd3875d..ffd6454 100644 --- a/chapters/chap01.ipynb +++ b/chapters/chap01.ipynb @@ -1,1307 +1,1519 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "1331faa1", - "metadata": {}, - "source": [ - "You can order print and ebook versions of *Think Python 3e* from\n", - "[Bookshop.org](https://bookshop.org/a/98697/9781098155438) and\n", - "[Amazon](https://www.amazon.com/_/dp/1098155432?smid=ATVPDKIKX0DER&_encoding=UTF8&tag=oreilly20-20&_encoding=UTF8&tag=greenteapre01-20&linkCode=ur2&linkId=e2a529f94920295d27ec8a06e757dc7c&camp=1789&creative=9325)." - ] - }, - { - "cell_type": "markdown", - "id": "a14edb7e", - "metadata": { - "tags": [] - }, - "source": [ - "# Welcome\n", - "\n", - "This is the Jupyter notebook for Chapter 1 of [*Think Python*, 3rd edition](https://greenteapress.com/wp/think-python-3rd-edition), by Allen B. Downey.\n", - "\n", - "If you are not familiar with Jupyter notebooks,\n", - "[click here for a short introduction](https://colab.research.google.com/github/AllenDowney/ThinkPython/blob/v3/chapters/jupyter_intro.ipynb).\n", - "\n", - "Then, if you are not already running this notebook on Colab, [click here to run this notebook on Colab](https://colab.research.google.com/github/AllenDowney/ThinkPython/blob/v3/chapters/chap01.ipynb)." - ] - }, - { - "cell_type": "markdown", - "id": "3b4a1f57", - "metadata": { - "tags": [] - }, - "source": [ - "The following cell downloads a file and runs some code that is used specifically for this book.\n", - "You don't have to understand this code yet, but you should run it before you do anything else in this notebook.\n", - "Remember that you can run the code by selecting the cell and pressing the play button (a triangle in a circle) or hold down `Shift` and press `Enter`." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "213f9d96", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from os.path import basename, exists\n", - "\n", - "def download(url):\n", - " filename = basename(url)\n", - " if not exists(filename):\n", - " from urllib.request import urlretrieve\n", - "\n", - " local, _ = urlretrieve(url, filename)\n", - " print(\"Downloaded \" + str(local))\n", - " return filename\n", - "\n", - "download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');\n", - "\n", - "import thinkpython" - ] - }, - { - "cell_type": "markdown", - "id": "333a6fc9", - "metadata": { - "tags": [] - }, - "source": [ - "# Programming as a way of thinking\n", - "\n", - "The first goal of this book is to teach you how to program in Python.\n", - "But learning to program means learning a new way to think, so the second goal of this book is to help you think like a computer scientist.\n", - "This way of thinking combines some of the best features of mathematics, engineering, and natural science.\n", - "Like mathematicians, computer scientists use formal languages to denote ideas -- specifically computations.\n", - "Like engineers, they design things, assembling components into systems and evaluating trade-offs among alternatives.\n", - "Like scientists, they observe the behavior of complex systems, form hypotheses, and test predictions.\n", - "\n", - "We will start with the most basic elements of programming and work our way up.\n", - "In this chapter, we'll see how Python represents numbers, letters, and words.\n", - "And you'll learn to perform arithmetic operations.\n", - "\n", - "You will also start to learn the vocabulary of programming, including terms like operator, expression, value, and type.\n", - "This vocabulary is important -- you will need it to understand the rest of the book, to communicate with other programmers, and to use and understand virtual assistants." - ] - }, - { - "cell_type": "markdown", - "id": "a371aea3", - "metadata": {}, - "source": [ - "## Arithmetic operators\n", - "\n", - "An **arithmetic operator** is a symbol that represents an arithmetic computation. For example, the plus sign, `+`, performs addition." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "2568ec84", - "metadata": {}, - "outputs": [], - "source": [ - "30 + 12" - ] - }, - { - "cell_type": "markdown", - "id": "fc0e7ce8", - "metadata": {}, - "source": [ - "The minus sign, `-`, is the operator that performs subtraction." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "c4e75456", - "metadata": {}, - "outputs": [], - "source": [ - "43 - 1" - ] - }, - { - "cell_type": "markdown", - "id": "63e4e780", - "metadata": {}, - "source": [ - "The asterisk, `*`, performs multiplication." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "022a7b16", - "metadata": {}, - "outputs": [], - "source": [ - "6 * 7" - ] - }, - { - "cell_type": "markdown", - "id": "a6192d13", - "metadata": {}, - "source": [ - "And the forward slash, `/`, performs division:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "05ae1098", - "metadata": {}, - "outputs": [], - "source": [ - "84 / 2" - ] - }, - { - "cell_type": "markdown", - "id": "641ad233", - "metadata": {}, - "source": [ - "Notice that the result of the division is `42.0` rather than `42`. That's because there are two types of numbers in Python: \n", - "\n", - "* **integers**, which represent numbers with no fractional or decimal part, and \n", - "\n", - "* **floating-point numbers**, which represent integers and numbers with a decimal point.\n", - "\n", - "If you add, subtract, or multiply two integers, the result is an integer.\n", - "But if you divide two integers, the result is a floating-point number.\n", - "Python provides another operator, `//`, that performs **integer division**.\n", - "The result of integer division is always an integer." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "4df5bcaa", - "metadata": {}, - "outputs": [], - "source": [ - "84 // 2" - ] - }, - { - "cell_type": "markdown", - "id": "b2a620ab", - "metadata": {}, - "source": [ - "Integer division is also called \"floor division\" because it always rounds down (toward the \"floor\"). " - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "ef08d549", - "metadata": {}, - "outputs": [], - "source": [ - "85 // 2" - ] - }, - { - "cell_type": "markdown", - "id": "41e2886a", - "metadata": {}, - "source": [ - "Finally, the operator `**` performs exponentiation; that is, it raises a\n", - "number to a power:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "df933e80", - "metadata": {}, - "outputs": [], - "source": [ - "7 ** 2" - ] - }, - { - "cell_type": "markdown", - "id": "b2502fb6", - "metadata": {}, - "source": [ - "In some other languages, the caret, `^`, is used for exponentiation, but in Python\n", - "it is a bitwise operator called XOR.\n", - "If you are not familiar with bitwise operators, the result might be unexpected:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "306b6b88", - "metadata": {}, - "outputs": [], - "source": [ - "7 ^ 2" - ] - }, - { - "cell_type": "markdown", - "id": "30078370", - "metadata": {}, - "source": [ - "I won't cover bitwise operators in this book, but you can read about\n", - "them at ." - ] - }, - { - "cell_type": "markdown", - "id": "0f5b7e97", - "metadata": {}, - "source": [ - "## Expressions\n", - "\n", - "A collection of operators and numbers is called an **expression**.\n", - "An expression can contain any number of operators and numbers.\n", - "For example, here's an expression that contains two operators." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "6e68101d", - "metadata": {}, - "outputs": [], - "source": [ - "6 + 6 ** 2" - ] - }, - { - "cell_type": "markdown", - "id": "8e95039c", - "metadata": {}, - "source": [ - "Notice that exponentiation happens before addition.\n", - "Python follows the order of operations you might have learned in a math class: exponentiation happens before multiplication and division, which happen before addition and subtraction.\n", - "\n", - "In the following example, multiplication happens before addition." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ffc25598", - "metadata": {}, - "outputs": [], - "source": [ - "12 + 5 * 6" - ] - }, - { - "cell_type": "markdown", - "id": "914a60d8", - "metadata": {}, - "source": [ - "If you want the addition to happen first, you can use parentheses." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "8dd1bd9a", - "metadata": {}, - "outputs": [], - "source": [ - "(12 + 5) * 6" - ] - }, - { - "cell_type": "markdown", - "id": "67ae0ae9", - "metadata": {}, - "source": [ - "Every expression has a **value**.\n", - "For example, the expression `6 * 7` has the value `42`." - ] - }, - { - "cell_type": "markdown", - "id": "caebaa51", - "metadata": {}, - "source": [ - "## Arithmetic functions\n", - "\n", - "In addition to the arithmetic operators, Python provides a few **functions** that work with numbers.\n", - "For example, the `round` function takes a floating-point number and rounds it off to the nearest integer." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "1e3d5e01", - "metadata": {}, - "outputs": [], - "source": [ - "round(42.4)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "d1b220b9", - "metadata": {}, - "outputs": [], - "source": [ - "round(42.6)" - ] - }, - { - "cell_type": "markdown", - "id": "f5738b4b", - "metadata": {}, - "source": [ - "The `abs` function computes the absolute value of a number.\n", - "For a positive number, the absolute value is the number itself." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "ff742476", - "metadata": {}, - "outputs": [], - "source": [ - "abs(42)" - ] - }, - { - "cell_type": "markdown", - "id": "e518494a", - "metadata": {}, - "source": [ - "For a negative number, the absolute value is positive." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "9247c1a3", - "metadata": {}, - "outputs": [], - "source": [ - "abs(-42)" - ] - }, - { - "cell_type": "markdown", - "id": "6969ce45", - "metadata": {}, - "source": [ - "When we use a function like this, we say we're **calling** the function.\n", - "An expression that calls a function is a **function call**.\n", - "\n", - "When you call a function, the parentheses are required.\n", - "If you leave them out, you get an error message." - ] - }, - { - "cell_type": "markdown", - "id": "5a73bfd5", - "metadata": { - "tags": [] - }, - "source": [ - "NOTE: The following cell uses `%%expect`, which is a Jupyter \"magic command\" that means we expect the code in this cell to produce an error. For more on this topic, see the\n", - "[Jupyter notebook introduction](https://colab.research.google.com/github/AllenDowney/ThinkPython/blob/v3/chapters/jupyter_intro.ipynb)." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "4674b7ca", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect SyntaxError\n", - "\n", - "abs 42" - ] - }, - { - "cell_type": "markdown", - "id": "7d356f1b", - "metadata": {}, - "source": [ - "You can ignore the first line of this message; it doesn't contain any information we need to understand right now.\n", - "The second line is the code that contains the error, with a caret (`^`) beneath it to indicate where the error was discovered.\n", - "\n", - "The last line indicates that this is a **syntax error**, which means that there is something wrong with the structure of the expression.\n", - "In this example, the problem is that a function call requires parentheses.\n", - "\n", - "Let's see what happens if you leave out the parentheses *and* the value." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "7d3e8127", - "metadata": {}, - "outputs": [], - "source": [ - "abs" - ] - }, - { - "cell_type": "markdown", - "id": "94478885", - "metadata": {}, - "source": [ - "A function name all by itself is a legal expression that has a value.\n", - "When it's displayed, the value indicates that `abs` is a function, and it includes some additional information I'll explain later." - ] - }, - { - "cell_type": "markdown", - "id": "31a85d17", - "metadata": {}, - "source": [ - "## Strings\n", - "\n", - "In addition to numbers, Python can also represent sequences of letters, which are called **strings** because the letters are strung together like beads on a necklace.\n", - "To write a string, we can put a sequence of letters inside straight quotation marks." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "bd8ae45f", - "metadata": {}, - "outputs": [], - "source": [ - "'Hello'" - ] - }, - { - "cell_type": "markdown", - "id": "d20050d8", - "metadata": {}, - "source": [ - "It is also legal to use double quotation marks." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "01d0055e", - "metadata": {}, - "outputs": [], - "source": [ - "\"world\"" - ] - }, - { - "cell_type": "markdown", - "id": "76f5edb7", - "metadata": {}, - "source": [ - "Double quotes make it easy to write a string that contains an apostrophe, which is the same symbol as a straight quote." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "0295acab", - "metadata": {}, - "outputs": [], - "source": [ - "\"it's a small \"" - ] - }, - { - "cell_type": "markdown", - "id": "d62d4b1c", - "metadata": {}, - "source": [ - "Strings can also contain spaces, punctuation, and digits." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "cf918917", - "metadata": {}, - "outputs": [], - "source": [ - "'Well, '" - ] - }, - { - "cell_type": "markdown", - "id": "9ad47f7a", - "metadata": {}, - "source": [ - "The `+` operator works with strings; it joins two strings into a single string, which is called **concatenation**" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "aefe6af1", - "metadata": {}, - "outputs": [], - "source": [ - "'Well, ' + \"it's a small \" + 'world.'" - ] - }, - { - "cell_type": "markdown", - "id": "0ad969a3", - "metadata": {}, - "source": [ - "The `*` operator also works with strings; it makes multiple copies of a string and concatenates them." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "42e9e4e2", - "metadata": {}, - "outputs": [], - "source": [ - "'Spam, ' * 4" - ] - }, - { - "cell_type": "markdown", - "id": "dfba16a5", - "metadata": {}, - "source": [ - "The other arithmetic operators don't work with strings.\n", - "\n", - "Python provides a function called `len` that computes the length of a string." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "a5e837db", - "metadata": {}, - "outputs": [], - "source": [ - "len('Spam')" - ] - }, - { - "cell_type": "markdown", - "id": "d91e00b3", - "metadata": {}, - "source": [ - "Notice that `len` counts the letters between the quotes, but not the quotes.\n", - "\n", - "When you create a string, be sure to use straight quotes.\n", - "The back quote, also known as a backtick, causes a syntax error." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "e3f65f19", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect SyntaxError\n", - "\n", - "`Hello`" - ] - }, - { - "cell_type": "markdown", - "id": "40d893d1", - "metadata": {}, - "source": [ - "Smart quotes, also known as curly quotes, are also illegal." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "a705b980", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect SyntaxError\n", - "\n", - "‘Hello’" - ] - }, - { - "cell_type": "markdown", - "id": "5471d4f8", - "metadata": {}, - "source": [ - "## Values and types\n", - "\n", - "So far we've seen three kinds of values:\n", - "\n", - "* `2` is an integer,\n", - "\n", - "* `42.0` is a floating-point number, and \n", - "\n", - "* `'Hello'` is a string.\n", - "\n", - "A kind of value is called a **type**.\n", - "Every value has a type -- or we sometimes say it \"belongs to\" a type.\n", - "\n", - "Python provides a function called `type` that tells you the type of any value.\n", - "The type of an integer is `int`." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "3df8e2c5", - "metadata": {}, - "outputs": [], - "source": [ - "type(2)" - ] - }, - { - "cell_type": "markdown", - "id": "b137814c", - "metadata": {}, - "source": [ - "The type of a floating-point number is `float`." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "c4732c8d", - "metadata": {}, - "outputs": [], - "source": [ - "type(42.0)" - ] - }, - { - "cell_type": "markdown", - "id": "266dea4e", - "metadata": {}, - "source": [ - "And the type of a string is `str`." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "8f65ac45", - "metadata": {}, - "outputs": [], - "source": [ - "type('Hello, World!')" - ] - }, - { - "cell_type": "markdown", - "id": "76d216ed", - "metadata": {}, - "source": [ - "The types `int`, `float`, and `str` can be used as functions.\n", - "For example, `int` can take a floating-point number and convert it to an integer (always rounding down)." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "84b22f2f", - "metadata": {}, - "outputs": [], - "source": [ - "int(42.9)" - ] - }, - { - "cell_type": "markdown", - "id": "dcd8d114", - "metadata": {}, - "source": [ - "And `float` can convert an integer to a floating-point value." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "9b66ee21", - "metadata": {}, - "outputs": [], - "source": [ - "float(42)" - ] - }, - { - "cell_type": "markdown", - "id": "eda70b61", - "metadata": {}, - "source": [ - "Now, here's something that can be confusing.\n", - "What do you get if you put a sequence of digits in quotes?" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "f64e107c", - "metadata": {}, - "outputs": [], - "source": [ - "'126'" - ] - }, - { - "cell_type": "markdown", - "id": "fdded653", - "metadata": {}, - "source": [ - "It looks like a number, but it is actually a string." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "609a8153", - "metadata": {}, - "outputs": [], - "source": [ - "type('126')" - ] - }, - { - "cell_type": "markdown", - "id": "2683ac35", - "metadata": {}, - "source": [ - "If you try to use it like a number, you might get an error." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "1cf21da4", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect TypeError\n", - "\n", - "'126' / 3" - ] - }, - { - "cell_type": "markdown", - "id": "32c11cc4", - "metadata": {}, - "source": [ - "This example generates a `TypeError`, which means that the values in the expression, which are called **operands**, have the wrong type.\n", - "The error message indicates that the `/` operator does not support the types of these values, which are `str` and `int`.\n", - "\n", - "If you have a string that contains digits, you can use `int` to convert it to an integer." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "d45e6a60", - "metadata": {}, - "outputs": [], - "source": [ - "int('126') / 3" - ] - }, - { - "cell_type": "markdown", - "id": "86935d56", - "metadata": {}, - "source": [ - "If you have a string that contains digits and a decimal point, you can use `float` to convert it to a floating-point number." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "db30b719", - "metadata": {}, - "outputs": [], - "source": [ - "float('12.6')" - ] - }, - { - "cell_type": "markdown", - "id": "03103ef4", - "metadata": {}, - "source": [ - "When you write a large integer, you might be tempted to use commas\n", - "between groups of digits, as in `1,000,000`.\n", - "This is a legal expression in Python, but the result is not an integer." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "d72b6af1", - "metadata": {}, - "outputs": [], - "source": [ - "1,000,000" - ] - }, - { - "cell_type": "markdown", - "id": "3d24af71", - "metadata": {}, - "source": [ - "Python interprets `1,000,000` as a comma-separated sequence of integers.\n", - "We'll learn more about this kind of sequence later.\n", - "\n", - "You can use underscores to make large numbers easier to read." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "id": "e19bf7e7", - "metadata": {}, - "outputs": [], - "source": [ - "1_000_000" - ] - }, - { - "cell_type": "markdown", - "id": "1761cbac", - "metadata": {}, - "source": [ - "## Formal and natural languages\n", - "\n", - "**Natural languages** are the languages people speak, like English, Spanish, and French. They were not designed by people; they evolved naturally.\n", - "\n", - "**Formal languages** are languages that are designed by people for specific applications. \n", - "For example, the notation that mathematicians use is a formal language that is particularly good at denoting relationships among numbers and symbols.\n", - "Similarly, programming languages are formal languages that have been designed to express computations." - ] - }, - { - "cell_type": "markdown", - "id": "1bf3d2dc", - "metadata": {}, - "source": [ - "Although formal and natural languages have some features in\n", - "common there are important differences:\n", - "\n", - "* Ambiguity: Natural languages are full of ambiguity, which people deal with by\n", - " using contextual clues and other information. Formal languages are\n", - " designed to be nearly or completely unambiguous, which means that\n", - " any program has exactly one meaning, regardless of context.\n", - "\n", - "* Redundancy: In order to make up for ambiguity and reduce misunderstandings,\n", - " natural languages use redundancy. As a result, they are\n", - " often verbose. Formal languages are less redundant and more concise.\n", - "\n", - "* Literalness: Natural languages are full of idiom and metaphor. Formal languages mean exactly what they say." - ] - }, - { - "cell_type": "markdown", - "id": "78a1cec8", - "metadata": {}, - "source": [ - "Because we all grow up speaking natural languages, it is sometimes hard to adjust to formal languages.\n", - "Formal languages are more dense than natural languages, so it takes longer to read them.\n", - "Also, the structure is important, so it is not always best to read from top to bottom, left to right.\n", - "Finally, the details matter. Small errors in spelling and\n", - "punctuation, which you can get away with in natural languages, can make\n", - "a big difference in a formal language." - ] - }, - { - "cell_type": "markdown", - "id": "4358fa9a", - "metadata": {}, - "source": [ - "## Debugging\n", - "\n", - "Programmers make mistakes. For whimsical reasons, programming errors are called **bugs** and the process of tracking them down is called **debugging**.\n", - "\n", - "Programming, and especially debugging, sometimes brings out strong emotions. If you are struggling with a difficult bug, you might feel angry, sad, or embarrassed.\n", - "\n", - "Preparing for these reactions might help you deal with them. One approach is to think of the computer as an employee with certain strengths, like speed and precision, and particular weaknesses, like lack of empathy and inability to grasp the big picture.\n", - "\n", - "Your job is to be a good manager: find ways to take advantage of the strengths and mitigate the weaknesses. And find ways to use your emotions to engage with the problem, without letting your reactions interfere with your ability to work effectively.\n", - "\n", - "Learning to debug can be frustrating, but it is a valuable skill that is useful for many activities beyond programming. At the end of each chapter there is a section, like this one, with my suggestions for debugging. I hope they help!" - ] - }, - { - "cell_type": "markdown", - "id": "33b8ad00", - "metadata": {}, - "source": [ - "## Glossary\n", - "\n", - "**arithmetic operator:**\n", - "A symbol, like `+` and `*`, that denotes an arithmetic operation like addition or multiplication.\n", - "\n", - "**integer:**\n", - "A type that represents numbers with no fractional or decimal part.\n", - "\n", - "**floating-point:**\n", - "A type that represents integers and numbers with decimal parts.\n", - "\n", - "**integer division:**\n", - "An operator, `//`, that divides two numbers and rounds down to an integer.\n", - "\n", - "**expression:**\n", - "A combination of variables, values, and operators.\n", - "\n", - "**value:**\n", - "An integer, floating-point number, or string -- or one of other kinds of values we will see later.\n", - "\n", - "**function:**\n", - "A named sequence of statements that performs some useful operation.\n", - "Functions may or may not take arguments and may or may not produce a result.\n", - "\n", - "**function call:**\n", - "An expression -- or part of an expression -- that runs a function.\n", - "It consists of the function name followed by an argument list in parentheses.\n", - "\n", - "**syntax error:**\n", - "An error in a program that makes it impossible to parse -- and therefore impossible to run.\n", - "\n", - "**string:**\n", - " A type that represents sequences of characters.\n", - "\n", - "**concatenation:**\n", - "Joining two strings end-to-end.\n", - "\n", - "**type:**\n", - "A category of values.\n", - "The types we have seen so far are integers (type `int`), floating-point numbers (type ` float`), and strings (type `str`).\n", - "\n", - "**operand:**\n", - "One of the values on which an operator operates.\n", - "\n", - "**natural language:**\n", - "Any of the languages that people speak that evolved naturally.\n", - "\n", - "**formal language:**\n", - "Any of the languages that people have designed for specific purposes, such as representing mathematical ideas or computer programs.\n", - "All programming languages are formal languages.\n", - "\n", - "**bug:**\n", - "An error in a program.\n", - "\n", - "**debugging:**\n", - "The process of finding and correcting errors." - ] - }, - { - "cell_type": "markdown", - "id": "ed4ec01b", - "metadata": {}, - "source": [ - "## Exercises" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "id": "06d3e72c", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# This cell tells Jupyter to provide detailed debugging information\n", - "# when a runtime error occurs. Run it before working on the exercises.\n", - "\n", - "%xmode Verbose" - ] - }, - { - "cell_type": "markdown", - "id": "23adf208", - "metadata": {}, - "source": [ - "### Ask a virtual assistant\n", - "\n", - "As you work through this book, there are several ways you can use a virtual assistant or chatbot to help you learn.\n", - "\n", - "* If you want to learn more about a topic in the chapter, or anything is unclear, you can ask for an explanation.\n", - "\n", - "* If you are having a hard time with any of the exercises, you can ask for help.\n", - "\n", - "In each chapter, I'll suggest exercises you can do with a virtual assistant, but I encourage you to try things on your own and see what works for you." - ] - }, - { - "cell_type": "markdown", - "id": "ebf1a451", - "metadata": {}, - "source": [ - "Here are some topics you could ask a virtual assistant about:\n", - "\n", - "* Earlier I mentioned bitwise operators but I didn't explain why the value of `7 ^ 2` is 5. Try asking \"What are the bitwise operators in Python?\" or \"What is the value of `7 XOR 2`?\"\n", - "\n", - "* I also mentioned the order of operations. For more details, ask \"What is the order of operations in Python?\"\n", - "\n", - "* The `round` function, which we used to round a floating-point number to the nearest integer, can take a second argument. Try asking \"What are the arguments of the round function?\" or \"How do I round pi off to three decimal places?\"\n", - "\n", - "* There's one more arithmetic operator I didn't mention; try asking \"What is the modulus operator in Python?\"" - ] - }, - { - "cell_type": "markdown", - "id": "9be3e1c7", - "metadata": {}, - "source": [ - "Most virtual assistants know about Python, so they answer questions like this pretty reliably.\n", - "But remember that these tools make mistakes.\n", - "If you get code from a chatbot, test it!" - ] - }, - { - "cell_type": "markdown", - "id": "03c1ef93", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "You might wonder what `round` does if a number ends in `0.5`.\n", - "The answer is that it sometimes rounds up and sometimes rounds down.\n", - "Try these examples and see if you can figure out what rule it follows." - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "id": "5d358f37", - "metadata": {}, - "outputs": [], - "source": [ - "round(42.5)" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "id": "12aa59a3", - "metadata": {}, - "outputs": [], - "source": [ - "round(43.5)" - ] - }, - { - "cell_type": "markdown", - "id": "dd2f890e", - "metadata": {}, - "source": [ - "If you are curious, ask a virtual assistant, \"If a number ends in 0.5, does Python round up or down?\"" - ] - }, - { - "cell_type": "markdown", - "id": "2cd03bcb", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "When you learn about a new feature, you should try it out and make mistakes on purpose.\n", - "That way, you learn the error messages, and when you see them again, you will know what they mean.\n", - "It is better to make mistakes now and deliberately than later and accidentally.\n", - "\n", - "1. You can use a minus sign to make a negative number like `-2`. What happens if you put a plus sign before a number? What about `2++2`?\n", - "\n", - "2. What happens if you have two values with no operator between them, like `4 2`?\n", - "\n", - "3. If you call a function like `round(42.5)`, what happens if you leave out one or both parentheses?" - ] - }, - { - "cell_type": "markdown", - "id": "1fb0adfe", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "Recall that every expression has a value, every value has a type, and we can use the `type` function to find the type of any value.\n", - "\n", - "What is the type of the value of the following expressions? Make your best guess for each one, and then use `type` to find out.\n", - "\n", - "* `765`\n", - "\n", - "* `2.718`\n", - "\n", - "* `'2 pi'`\n", - "\n", - "* `abs(-7)`\n", - "\n", - "* `abs(-7.0)`\n", - "\n", - "* `abs`\n", - "\n", - "* `int`\n", - "\n", - "* `type`" - ] - }, - { - "cell_type": "markdown", - "id": "23762eec", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "The following questions give you a chance to practice writing arithmetic expressions.\n", - "\n", - "1. How many seconds are there in 42 minutes 42 seconds?\n", - "\n", - "2. How many miles are there in 10 kilometers? Hint: there are 1.61 kilometers in a mile.\n", - "\n", - "3. If you run a 10 kilometer race in 42 minutes 42 seconds, what is your average pace in seconds per mile? \n", - " \n", - "4. What is your average pace in minutes and seconds per mile?\n", - "\n", - "5. What is your average speed in miles per hour?\n", - "\n", - "If you already know about variables, you can use them for this exercise.\n", - "If you don't, you can do the exercise without them -- and then we'll see them in the next chapter." - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "id": "8fb50f30", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "id": "5eceb4fb", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "id": "fee97d8d", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "id": "a998258c", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "id": "2e0fc7a9", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "id": "d25268d8", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "id": "523d9b0f", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ca083ccf", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "a7f4edf8", - "metadata": { - "tags": [] - }, - "source": [ - "[Think Python: 3rd Edition](https://allendowney.github.io/ThinkPython/index.html)\n", - "\n", - "Copyright 2024 [Allen B. Downey](https://allendowney.com)\n", - "\n", - "Code license: [MIT License](https://mit-license.org/)\n", - "\n", - "Text license: [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "1331faa1", + "metadata": { + "id": "1331faa1" + }, + "source": [ + "You can order print and ebook versions of *Think Python 3e* from\n", + "[Bookshop.org](https://bookshop.org/a/98697/9781098155438) and\n", + "[Amazon](https://www.amazon.com/_/dp/1098155432?smid=ATVPDKIKX0DER&_encoding=UTF8&tag=oreilly20-20&_encoding=UTF8&tag=greenteapre01-20&linkCode=ur2&linkId=e2a529f94920295d27ec8a06e757dc7c&camp=1789&creative=9325)." + ] + }, + { + "cell_type": "markdown", + "id": "a14edb7e", + "metadata": { + "tags": [], + "id": "a14edb7e" + }, + "source": [ + "# Welcome\n", + "\n", + "This is the Jupyter notebook for Chapter 1 of [*Think Python*, 3rd edition](https://greenteapress.com/wp/think-python-3rd-edition), by Allen B. Downey.\n", + "\n", + "If you are not familiar with Jupyter notebooks,\n", + "[click here for a short introduction](https://colab.research.google.com/github/AllenDowney/ThinkPython/blob/v3/chapters/jupyter_intro.ipynb).\n", + "\n", + "Then, if you are not already running this notebook on Colab, [click here to run this notebook on Colab](https://colab.research.google.com/github/AllenDowney/ThinkPython/blob/v3/chapters/chap01.ipynb)." + ] + }, + { + "cell_type": "markdown", + "id": "3b4a1f57", + "metadata": { + "tags": [], + "id": "3b4a1f57" + }, + "source": [ + "The following cell downloads a file and runs some code that is used specifically for this book.\n", + "You don't have to understand this code yet, but you should run it before you do anything else in this notebook.\n", + "Remember that you can run the code by selecting the cell and pressing the play button (a triangle in a circle) or hold down `Shift` and press `Enter`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "213f9d96", + "metadata": { + "tags": [], + "id": "213f9d96" + }, + "outputs": [], + "source": [ + "from os.path import basename, exists\n", + "\n", + "def download(url):\n", + " filename = basename(url)\n", + " if not exists(filename):\n", + " from urllib.request import urlretrieve\n", + "\n", + " local, _ = urlretrieve(url, filename)\n", + " print(\"Downloaded \" + str(local))\n", + " return filename\n", + "\n", + "download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');\n", + "\n", + "import thinkpython" + ] + }, + { + "cell_type": "markdown", + "id": "333a6fc9", + "metadata": { + "tags": [], + "id": "333a6fc9" + }, + "source": [ + "# Programming as a way of thinking\n", + "\n", + "The first goal of this book is to teach you how to program in Python.\n", + "But learning to program means learning a new way to think, so the second goal of this book is to help you think like a computer scientist.\n", + "This way of thinking combines some of the best features of mathematics, engineering, and natural science.\n", + "Like mathematicians, computer scientists use formal languages to denote ideas -- specifically computations.\n", + "Like engineers, they design things, assembling components into systems and evaluating trade-offs among alternatives.\n", + "Like scientists, they observe the behavior of complex systems, form hypotheses, and test predictions.\n", + "\n", + "We will start with the most basic elements of programming and work our way up.\n", + "In this chapter, we'll see how Python represents numbers, letters, and words.\n", + "And you'll learn to perform arithmetic operations.\n", + "\n", + "You will also start to learn the vocabulary of programming, including terms like operator, expression, value, and type.\n", + "This vocabulary is important -- you will need it to understand the rest of the book, to communicate with other programmers, and to use and understand virtual assistants." + ] + }, + { + "cell_type": "markdown", + "id": "a371aea3", + "metadata": { + "id": "a371aea3" + }, + "source": [ + "## Arithmetic operators\n", + "\n", + "An **arithmetic operator** is a symbol that represents an arithmetic computation. For example, the plus sign, `+`, performs addition." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2568ec84", + "metadata": { + "id": "2568ec84" + }, + "outputs": [], + "source": [ + "30 + 12" + ] + }, + { + "cell_type": "markdown", + "id": "fc0e7ce8", + "metadata": { + "id": "fc0e7ce8" + }, + "source": [ + "The minus sign, `-`, is the operator that performs subtraction." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4e75456", + "metadata": { + "id": "c4e75456" + }, + "outputs": [], + "source": [ + "43 - 1" + ] + }, + { + "cell_type": "markdown", + "id": "63e4e780", + "metadata": { + "id": "63e4e780" + }, + "source": [ + "The asterisk, `*`, performs multiplication." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "022a7b16", + "metadata": { + "id": "022a7b16" + }, + "outputs": [], + "source": [ + "6 * 7" + ] + }, + { + "cell_type": "markdown", + "id": "a6192d13", + "metadata": { + "id": "a6192d13" + }, + "source": [ + "And the forward slash, `/`, performs division:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05ae1098", + "metadata": { + "id": "05ae1098" + }, + "outputs": [], + "source": [ + "84 / 2" + ] + }, + { + "cell_type": "markdown", + "id": "641ad233", + "metadata": { + "id": "641ad233" + }, + "source": [ + "Notice that the result of the division is `42.0` rather than `42`. That's because there are two types of numbers in Python:\n", + "\n", + "* **integers**, which represent numbers with no fractional or decimal part, and\n", + "\n", + "* **floating-point numbers**, which represent integers and numbers with a decimal point.\n", + "\n", + "If you add, subtract, or multiply two integers, the result is an integer.\n", + "But if you divide two integers, the result is a floating-point number.\n", + "Python provides another operator, `//`, that performs **integer division**.\n", + "The result of integer division is always an integer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4df5bcaa", + "metadata": { + "id": "4df5bcaa" + }, + "outputs": [], + "source": [ + "84 // 2" + ] + }, + { + "cell_type": "markdown", + "id": "b2a620ab", + "metadata": { + "id": "b2a620ab" + }, + "source": [ + "Integer division is also called \"floor division\" because it always rounds down (toward the \"floor\")." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef08d549", + "metadata": { + "id": "ef08d549" + }, + "outputs": [], + "source": [ + "85 // 2" + ] + }, + { + "cell_type": "markdown", + "id": "41e2886a", + "metadata": { + "id": "41e2886a" + }, + "source": [ + "Finally, the operator `**` performs exponentiation; that is, it raises a\n", + "number to a power:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df933e80", + "metadata": { + "id": "df933e80" + }, + "outputs": [], + "source": [ + "7 ** 2" + ] + }, + { + "cell_type": "markdown", + "id": "b2502fb6", + "metadata": { + "id": "b2502fb6" + }, + "source": [ + "In some other languages, the caret, `^`, is used for exponentiation, but in Python\n", + "it is a bitwise operator called XOR.\n", + "If you are not familiar with bitwise operators, the result might be unexpected:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "306b6b88", + "metadata": { + "id": "306b6b88" + }, + "outputs": [], + "source": [ + "7 ^ 2" + ] + }, + { + "cell_type": "markdown", + "id": "30078370", + "metadata": { + "id": "30078370" + }, + "source": [ + "I won't cover bitwise operators in this book, but you can read about\n", + "them at ." + ] + }, + { + "cell_type": "markdown", + "id": "0f5b7e97", + "metadata": { + "id": "0f5b7e97" + }, + "source": [ + "## Expressions\n", + "\n", + "A collection of operators and numbers is called an **expression**.\n", + "An expression can contain any number of operators and numbers.\n", + "For example, here's an expression that contains two operators." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e68101d", + "metadata": { + "id": "6e68101d" + }, + "outputs": [], + "source": [ + "6 + 6 ** 2" + ] + }, + { + "cell_type": "markdown", + "id": "8e95039c", + "metadata": { + "id": "8e95039c" + }, + "source": [ + "Notice that exponentiation happens before addition.\n", + "Python follows the order of operations you might have learned in a math class: exponentiation happens before multiplication and division, which happen before addition and subtraction.\n", + "\n", + "In the following example, multiplication happens before addition." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ffc25598", + "metadata": { + "id": "ffc25598" + }, + "outputs": [], + "source": [ + "12 + 5 * 6" + ] + }, + { + "cell_type": "markdown", + "id": "914a60d8", + "metadata": { + "id": "914a60d8" + }, + "source": [ + "If you want the addition to happen first, you can use parentheses." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8dd1bd9a", + "metadata": { + "id": "8dd1bd9a" + }, + "outputs": [], + "source": [ + "(12 + 5) * 6" + ] + }, + { + "cell_type": "markdown", + "id": "67ae0ae9", + "metadata": { + "id": "67ae0ae9" + }, + "source": [ + "Every expression has a **value**.\n", + "For example, the expression `6 * 7` has the value `42`." + ] + }, + { + "cell_type": "markdown", + "id": "caebaa51", + "metadata": { + "id": "caebaa51" + }, + "source": [ + "## Arithmetic functions\n", + "\n", + "In addition to the arithmetic operators, Python provides a few **functions** that work with numbers.\n", + "For example, the `round` function takes a floating-point number and rounds it off to the nearest integer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e3d5e01", + "metadata": { + "id": "1e3d5e01" + }, + "outputs": [], + "source": [ + "round(42.4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d1b220b9", + "metadata": { + "id": "d1b220b9" + }, + "outputs": [], + "source": [ + "round(42.6)" + ] + }, + { + "cell_type": "markdown", + "id": "f5738b4b", + "metadata": { + "id": "f5738b4b" + }, + "source": [ + "The `abs` function computes the absolute value of a number.\n", + "For a positive number, the absolute value is the number itself." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff742476", + "metadata": { + "id": "ff742476" + }, + "outputs": [], + "source": [ + "abs(42)" + ] + }, + { + "cell_type": "markdown", + "id": "e518494a", + "metadata": { + "id": "e518494a" + }, + "source": [ + "For a negative number, the absolute value is positive." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9247c1a3", + "metadata": { + "id": "9247c1a3" + }, + "outputs": [], + "source": [ + "abs(-42)" + ] + }, + { + "cell_type": "markdown", + "id": "6969ce45", + "metadata": { + "id": "6969ce45" + }, + "source": [ + "When we use a function like this, we say we're **calling** the function.\n", + "An expression that calls a function is a **function call**.\n", + "\n", + "When you call a function, the parentheses are required.\n", + "If you leave them out, you get an error message." + ] + }, + { + "cell_type": "markdown", + "id": "5a73bfd5", + "metadata": { + "tags": [], + "id": "5a73bfd5" + }, + "source": [ + "NOTE: The following cell uses `%%expect`, which is a Jupyter \"magic command\" that means we expect the code in this cell to produce an error. For more on this topic, see the\n", + "[Jupyter notebook introduction](https://colab.research.google.com/github/AllenDowney/ThinkPython/blob/v3/chapters/jupyter_intro.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4674b7ca", + "metadata": { + "tags": [], + "id": "4674b7ca" + }, + "outputs": [], + "source": [ + "%%expect SyntaxError\n", + "\n", + "abs 42" + ] + }, + { + "cell_type": "markdown", + "id": "7d356f1b", + "metadata": { + "id": "7d356f1b" + }, + "source": [ + "You can ignore the first line of this message; it doesn't contain any information we need to understand right now.\n", + "The second line is the code that contains the error, with a caret (`^`) beneath it to indicate where the error was discovered.\n", + "\n", + "The last line indicates that this is a **syntax error**, which means that there is something wrong with the structure of the expression.\n", + "In this example, the problem is that a function call requires parentheses.\n", + "\n", + "Let's see what happens if you leave out the parentheses *and* the value." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d3e8127", + "metadata": { + "id": "7d3e8127" + }, + "outputs": [], + "source": [ + "abs" + ] + }, + { + "cell_type": "markdown", + "id": "94478885", + "metadata": { + "id": "94478885" + }, + "source": [ + "A function name all by itself is a legal expression that has a value.\n", + "When it's displayed, the value indicates that `abs` is a function, and it includes some additional information I'll explain later." + ] + }, + { + "cell_type": "markdown", + "id": "31a85d17", + "metadata": { + "id": "31a85d17" + }, + "source": [ + "## Strings\n", + "\n", + "In addition to numbers, Python can also represent sequences of letters, which are called **strings** because the letters are strung together like beads on a necklace.\n", + "To write a string, we can put a sequence of letters inside straight quotation marks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd8ae45f", + "metadata": { + "id": "bd8ae45f" + }, + "outputs": [], + "source": [ + "'Hello'" + ] + }, + { + "cell_type": "markdown", + "id": "d20050d8", + "metadata": { + "id": "d20050d8" + }, + "source": [ + "It is also legal to use double quotation marks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01d0055e", + "metadata": { + "id": "01d0055e" + }, + "outputs": [], + "source": [ + "\"world\"" + ] + }, + { + "cell_type": "markdown", + "id": "76f5edb7", + "metadata": { + "id": "76f5edb7" + }, + "source": [ + "Double quotes make it easy to write a string that contains an apostrophe, which is the same symbol as a straight quote." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0295acab", + "metadata": { + "id": "0295acab" + }, + "outputs": [], + "source": [ + "\"it's a small \"" + ] + }, + { + "cell_type": "markdown", + "id": "d62d4b1c", + "metadata": { + "id": "d62d4b1c" + }, + "source": [ + "Strings can also contain spaces, punctuation, and digits." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf918917", + "metadata": { + "id": "cf918917" + }, + "outputs": [], + "source": [ + "'Well, '" + ] + }, + { + "cell_type": "markdown", + "id": "9ad47f7a", + "metadata": { + "id": "9ad47f7a" + }, + "source": [ + "The `+` operator works with strings; it joins two strings into a single string, which is called **concatenation**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aefe6af1", + "metadata": { + "id": "aefe6af1" + }, + "outputs": [], + "source": [ + "'Well, ' + \"it's a small \" + 'world.'" + ] + }, + { + "cell_type": "markdown", + "id": "0ad969a3", + "metadata": { + "id": "0ad969a3" + }, + "source": [ + "The `*` operator also works with strings; it makes multiple copies of a string and concatenates them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42e9e4e2", + "metadata": { + "id": "42e9e4e2" + }, + "outputs": [], + "source": [ + "'Spam, ' * 4" + ] + }, + { + "cell_type": "markdown", + "id": "dfba16a5", + "metadata": { + "id": "dfba16a5" + }, + "source": [ + "The other arithmetic operators don't work with strings.\n", + "\n", + "Python provides a function called `len` that computes the length of a string." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a5e837db", + "metadata": { + "id": "a5e837db" + }, + "outputs": [], + "source": [ + "len('Spam')" + ] + }, + { + "cell_type": "markdown", + "id": "d91e00b3", + "metadata": { + "id": "d91e00b3" + }, + "source": [ + "Notice that `len` counts the letters between the quotes, but not the quotes.\n", + "\n", + "When you create a string, be sure to use straight quotes.\n", + "The back quote, also known as a backtick, causes a syntax error." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3f65f19", + "metadata": { + "tags": [], + "id": "e3f65f19" + }, + "outputs": [], + "source": [ + "%%expect SyntaxError\n", + "\n", + "`Hello`" + ] + }, + { + "cell_type": "markdown", + "id": "40d893d1", + "metadata": { + "id": "40d893d1" + }, + "source": [ + "Smart quotes, also known as curly quotes, are also illegal." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a705b980", + "metadata": { + "tags": [], + "id": "a705b980" + }, + "outputs": [], + "source": [ + "%%expect SyntaxError\n", + "\n", + "‘Hello’" + ] + }, + { + "cell_type": "markdown", + "id": "5471d4f8", + "metadata": { + "id": "5471d4f8" + }, + "source": [ + "## Values and types\n", + "\n", + "So far we've seen three kinds of values:\n", + "\n", + "* `2` is an integer,\n", + "\n", + "* `42.0` is a floating-point number, and\n", + "\n", + "* `'Hello'` is a string.\n", + "\n", + "A kind of value is called a **type**.\n", + "Every value has a type -- or we sometimes say it \"belongs to\" a type.\n", + "\n", + "Python provides a function called `type` that tells you the type of any value.\n", + "The type of an integer is `int`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3df8e2c5", + "metadata": { + "id": "3df8e2c5" + }, + "outputs": [], + "source": [ + "type(2)" + ] + }, + { + "cell_type": "markdown", + "id": "b137814c", + "metadata": { + "id": "b137814c" + }, + "source": [ + "The type of a floating-point number is `float`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4732c8d", + "metadata": { + "id": "c4732c8d" + }, + "outputs": [], + "source": [ + "type(42.0)" + ] + }, + { + "cell_type": "markdown", + "id": "266dea4e", + "metadata": { + "id": "266dea4e" + }, + "source": [ + "And the type of a string is `str`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f65ac45", + "metadata": { + "id": "8f65ac45" + }, + "outputs": [], + "source": [ + "type('Hello, World!')" + ] + }, + { + "cell_type": "markdown", + "id": "76d216ed", + "metadata": { + "id": "76d216ed" + }, + "source": [ + "The types `int`, `float`, and `str` can be used as functions.\n", + "For example, `int` can take a floating-point number and convert it to an integer (always rounding down)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "84b22f2f", + "metadata": { + "id": "84b22f2f" + }, + "outputs": [], + "source": [ + "int(42.9)" + ] + }, + { + "cell_type": "markdown", + "id": "dcd8d114", + "metadata": { + "id": "dcd8d114" + }, + "source": [ + "And `float` can convert an integer to a floating-point value." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b66ee21", + "metadata": { + "id": "9b66ee21" + }, + "outputs": [], + "source": [ + "float(42)" + ] + }, + { + "cell_type": "markdown", + "id": "eda70b61", + "metadata": { + "id": "eda70b61" + }, + "source": [ + "Now, here's something that can be confusing.\n", + "What do you get if you put a sequence of digits in quotes?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f64e107c", + "metadata": { + "id": "f64e107c" + }, + "outputs": [], + "source": [ + "'126'" + ] + }, + { + "cell_type": "markdown", + "id": "fdded653", + "metadata": { + "id": "fdded653" + }, + "source": [ + "It looks like a number, but it is actually a string." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "609a8153", + "metadata": { + "id": "609a8153" + }, + "outputs": [], + "source": [ + "type('126')" + ] + }, + { + "cell_type": "markdown", + "id": "2683ac35", + "metadata": { + "id": "2683ac35" + }, + "source": [ + "If you try to use it like a number, you might get an error." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cf21da4", + "metadata": { + "tags": [], + "id": "1cf21da4" + }, + "outputs": [], + "source": [ + "%%expect TypeError\n", + "\n", + "'126' / 3" + ] + }, + { + "cell_type": "markdown", + "id": "32c11cc4", + "metadata": { + "id": "32c11cc4" + }, + "source": [ + "This example generates a `TypeError`, which means that the values in the expression, which are called **operands**, have the wrong type.\n", + "The error message indicates that the `/` operator does not support the types of these values, which are `str` and `int`.\n", + "\n", + "If you have a string that contains digits, you can use `int` to convert it to an integer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d45e6a60", + "metadata": { + "id": "d45e6a60" + }, + "outputs": [], + "source": [ + "int('126') / 3" + ] + }, + { + "cell_type": "markdown", + "id": "86935d56", + "metadata": { + "id": "86935d56" + }, + "source": [ + "If you have a string that contains digits and a decimal point, you can use `float` to convert it to a floating-point number." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "db30b719", + "metadata": { + "id": "db30b719" + }, + "outputs": [], + "source": [ + "float('12.6')" + ] + }, + { + "cell_type": "markdown", + "id": "03103ef4", + "metadata": { + "id": "03103ef4" + }, + "source": [ + "When you write a large integer, you might be tempted to use commas\n", + "between groups of digits, as in `1,000,000`.\n", + "This is a legal expression in Python, but the result is not an integer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d72b6af1", + "metadata": { + "id": "d72b6af1" + }, + "outputs": [], + "source": [ + "1,000,000" + ] + }, + { + "cell_type": "markdown", + "id": "3d24af71", + "metadata": { + "id": "3d24af71" + }, + "source": [ + "Python interprets `1,000,000` as a comma-separated sequence of integers.\n", + "We'll learn more about this kind of sequence later.\n", + "\n", + "You can use underscores to make large numbers easier to read." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e19bf7e7", + "metadata": { + "id": "e19bf7e7" + }, + "outputs": [], + "source": [ + "1_000_000" + ] + }, + { + "cell_type": "markdown", + "id": "1761cbac", + "metadata": { + "id": "1761cbac" + }, + "source": [ + "## Formal and natural languages\n", + "\n", + "**Natural languages** are the languages people speak, like English, Spanish, and French. They were not designed by people; they evolved naturally.\n", + "\n", + "**Formal languages** are languages that are designed by people for specific applications.\n", + "For example, the notation that mathematicians use is a formal language that is particularly good at denoting relationships among numbers and symbols.\n", + "Similarly, programming languages are formal languages that have been designed to express computations." + ] + }, + { + "cell_type": "markdown", + "id": "1bf3d2dc", + "metadata": { + "id": "1bf3d2dc" + }, + "source": [ + "Although formal and natural languages have some features in\n", + "common there are important differences:\n", + "\n", + "* Ambiguity: Natural languages are full of ambiguity, which people deal with by\n", + " using contextual clues and other information. Formal languages are\n", + " designed to be nearly or completely unambiguous, which means that\n", + " any program has exactly one meaning, regardless of context.\n", + "\n", + "* Redundancy: In order to make up for ambiguity and reduce misunderstandings,\n", + " natural languages use redundancy. As a result, they are\n", + " often verbose. Formal languages are less redundant and more concise.\n", + "\n", + "* Literalness: Natural languages are full of idiom and metaphor. Formal languages mean exactly what they say." + ] + }, + { + "cell_type": "markdown", + "id": "78a1cec8", + "metadata": { + "id": "78a1cec8" + }, + "source": [ + "Because we all grow up speaking natural languages, it is sometimes hard to adjust to formal languages.\n", + "Formal languages are more dense than natural languages, so it takes longer to read them.\n", + "Also, the structure is important, so it is not always best to read from top to bottom, left to right.\n", + "Finally, the details matter. Small errors in spelling and\n", + "punctuation, which you can get away with in natural languages, can make\n", + "a big difference in a formal language." + ] + }, + { + "cell_type": "markdown", + "id": "4358fa9a", + "metadata": { + "id": "4358fa9a" + }, + "source": [ + "## Debugging\n", + "\n", + "Programmers make mistakes. For whimsical reasons, programming errors are called **bugs** and the process of tracking them down is called **debugging**.\n", + "\n", + "Programming, and especially debugging, sometimes brings out strong emotions. If you are struggling with a difficult bug, you might feel angry, sad, or embarrassed.\n", + "\n", + "Preparing for these reactions might help you deal with them. One approach is to think of the computer as an employee with certain strengths, like speed and precision, and particular weaknesses, like lack of empathy and inability to grasp the big picture.\n", + "\n", + "Your job is to be a good manager: find ways to take advantage of the strengths and mitigate the weaknesses. And find ways to use your emotions to engage with the problem, without letting your reactions interfere with your ability to work effectively.\n", + "\n", + "Learning to debug can be frustrating, but it is a valuable skill that is useful for many activities beyond programming. At the end of each chapter there is a section, like this one, with my suggestions for debugging. I hope they help!" + ] + }, + { + "cell_type": "markdown", + "id": "33b8ad00", + "metadata": { + "id": "33b8ad00" + }, + "source": [ + "## Glossary\n", + "\n", + "**arithmetic operator:**\n", + "A symbol, like `+` and `*`, that denotes an arithmetic operation like addition or multiplication.\n", + "\n", + "**integer:**\n", + "A type that represents numbers with no fractional or decimal part.\n", + "\n", + "**floating-point:**\n", + "A type that represents integers and numbers with decimal parts.\n", + "\n", + "**integer division:**\n", + "An operator, `//`, that divides two numbers and rounds down to an integer.\n", + "\n", + "**expression:**\n", + "A combination of variables, values, and operators.\n", + "\n", + "**value:**\n", + "An integer, floating-point number, or string -- or one of other kinds of values we will see later.\n", + "\n", + "**function:**\n", + "A named sequence of statements that performs some useful operation.\n", + "Functions may or may not take arguments and may or may not produce a result.\n", + "\n", + "**function call:**\n", + "An expression -- or part of an expression -- that runs a function.\n", + "It consists of the function name followed by an argument list in parentheses.\n", + "\n", + "**syntax error:**\n", + "An error in a program that makes it impossible to parse -- and therefore impossible to run.\n", + "\n", + "**string:**\n", + " A type that represents sequences of characters.\n", + "\n", + "**concatenation:**\n", + "Joining two strings end-to-end.\n", + "\n", + "**type:**\n", + "A category of values.\n", + "The types we have seen so far are integers (type `int`), floating-point numbers (type ` float`), and strings (type `str`).\n", + "\n", + "**operand:**\n", + "One of the values on which an operator operates.\n", + "\n", + "**natural language:**\n", + "Any of the languages that people speak that evolved naturally.\n", + "\n", + "**formal language:**\n", + "Any of the languages that people have designed for specific purposes, such as representing mathematical ideas or computer programs.\n", + "All programming languages are formal languages.\n", + "\n", + "**bug:**\n", + "An error in a program.\n", + "\n", + "**debugging:**\n", + "The process of finding and correcting errors." + ] + }, + { + "cell_type": "markdown", + "id": "ed4ec01b", + "metadata": { + "id": "ed4ec01b" + }, + "source": [ + "## Exercises" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06d3e72c", + "metadata": { + "tags": [], + "id": "06d3e72c" + }, + "outputs": [], + "source": [ + "# This cell tells Jupyter to provide detailed debugging information\n", + "# when a runtime error occurs. Run it before working on the exercises.\n", + "\n", + "%xmode Verbose" + ] + }, + { + "cell_type": "markdown", + "id": "23adf208", + "metadata": { + "id": "23adf208" + }, + "source": [ + "### Ask a virtual assistant\n", + "\n", + "As you work through this book, there are several ways you can use a virtual assistant or chatbot to help you learn.\n", + "\n", + "* If you want to learn more about a topic in the chapter, or anything is unclear, you can ask for an explanation.\n", + "\n", + "* If you are having a hard time with any of the exercises, you can ask for help.\n", + "\n", + "In each chapter, I'll suggest exercises you can do with a virtual assistant, but I encourage you to try things on your own and see what works for you." + ] + }, + { + "cell_type": "markdown", + "id": "ebf1a451", + "metadata": { + "id": "ebf1a451" + }, + "source": [ + "Here are some topics you could ask a virtual assistant about:\n", + "\n", + "* Earlier I mentioned bitwise operators but I didn't explain why the value of `7 ^ 2` is 5. Try asking \"What are the bitwise operators in Python?\" or \"What is the value of `7 XOR 2`?\"\n", + "\n", + "* I also mentioned the order of operations. For more details, ask \"What is the order of operations in Python?\"\n", + "\n", + "* The `round` function, which we used to round a floating-point number to the nearest integer, can take a second argument. Try asking \"What are the arguments of the round function?\" or \"How do I round pi off to three decimal places?\"\n", + "\n", + "* There's one more arithmetic operator I didn't mention; try asking \"What is the modulus operator in Python?\"" + ] + }, + { + "cell_type": "markdown", + "id": "9be3e1c7", + "metadata": { + "id": "9be3e1c7" + }, + "source": [ + "Most virtual assistants know about Python, so they answer questions like this pretty reliably.\n", + "But remember that these tools make mistakes.\n", + "If you get code from a chatbot, test it!" + ] + }, + { + "cell_type": "markdown", + "id": "03c1ef93", + "metadata": { + "id": "03c1ef93" + }, + "source": [ + "### Exercise\n", + "\n", + "You might wonder what `round` does if a number ends in `0.5`.\n", + "The answer is that it sometimes rounds up and sometimes rounds down.\n", + "Try these examples and see if you can figure out what rule it follows." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d358f37", + "metadata": { + "id": "5d358f37" + }, + "outputs": [], + "source": [ + "round(42.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12aa59a3", + "metadata": { + "id": "12aa59a3" + }, + "outputs": [], + "source": [ + "round(43.5)" + ] + }, + { + "cell_type": "markdown", + "id": "dd2f890e", + "metadata": { + "id": "dd2f890e" + }, + "source": [ + "If you are curious, ask a virtual assistant, \"If a number ends in 0.5, does Python round up or down?\"" + ] + }, + { + "cell_type": "markdown", + "id": "2cd03bcb", + "metadata": { + "id": "2cd03bcb" + }, + "source": [ + "### Exercise\n", + "\n", + "When you learn about a new feature, you should try it out and make mistakes on purpose.\n", + "That way, you learn the error messages, and when you see them again, you will know what they mean.\n", + "It is better to make mistakes now and deliberately than later and accidentally.\n", + "\n", + "1. You can use a minus sign to make a negative number like `-2`. What happens if you put a plus sign before a number? What about `2++2`?\n", + "\n", + "2. What happens if you have two values with no operator between them, like `4 2`?\n", + "\n", + "3. If you call a function like `round(42.5)`, what happens if you leave out one or both parentheses?" + ] + }, + { + "cell_type": "markdown", + "id": "1fb0adfe", + "metadata": { + "id": "1fb0adfe" + }, + "source": [ + "### Exercise\n", + "\n", + "Recall that every expression has a value, every value has a type, and we can use the `type` function to find the type of any value.\n", + "\n", + "What is the type of the value of the following expressions? Make your best guess for each one, and then use `type` to find out.\n", + "\n", + "* `765`\n", + "\n", + "* `2.718`\n", + "\n", + "* `'2 pi'`\n", + "\n", + "* `abs(-7)`\n", + "\n", + "* `abs(-7.0)`\n", + "\n", + "* `abs`\n", + "\n", + "* `int`\n", + "\n", + "* `type`" + ] + }, + { + "cell_type": "markdown", + "id": "23762eec", + "metadata": { + "id": "23762eec" + }, + "source": [ + "### Exercise\n", + "\n", + "The following questions give you a chance to practice writing arithmetic expressions.\n", + "\n", + "1. How many seconds are there in 42 minutes 42 seconds?\n", + "\n", + "2. How many miles are there in 10 kilometers? Hint: there are 1.61 kilometers in a mile.\n", + "\n", + "3. If you run a 10 kilometer race in 42 minutes 42 seconds, what is your average pace in seconds per mile?\n", + " \n", + "4. What is your average pace in minutes and seconds per mile?\n", + "\n", + "5. What is your average speed in miles per hour?\n", + "\n", + "If you already know about variables, you can use them for this exercise.\n", + "If you don't, you can do the exercise without them -- and then we'll see them in the next chapter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8fb50f30", + "metadata": { + "id": "8fb50f30" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5eceb4fb", + "metadata": { + "id": "5eceb4fb" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fee97d8d", + "metadata": { + "id": "fee97d8d" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a998258c", + "metadata": { + "id": "a998258c" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e0fc7a9", + "metadata": { + "id": "2e0fc7a9" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d25268d8", + "metadata": { + "id": "d25268d8" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "523d9b0f", + "metadata": { + "id": "523d9b0f" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ca083ccf", + "metadata": { + "id": "ca083ccf" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "a7f4edf8", + "metadata": { + "tags": [], + "id": "a7f4edf8" + }, + "source": [ + "[Think Python: 3rd Edition](https://allendowney.github.io/ThinkPython/index.html)\n", + "\n", + "Copyright 2024 [Allen B. Downey](https://allendowney.com)\n", + "\n", + "Code license: [MIT License](https://mit-license.org/)\n", + "\n", + "Text license: [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file From e16dfe0c9c9933135c56403a617ba3aa7fbbe7b5 Mon Sep 17 00:00:00 2001 From: Ben Hutton Date: Tue, 30 Sep 2025 13:48:55 +0100 Subject: [PATCH 2/4] Created using Colab --- chapters/chap01.ipynb | 537 +++++++++++++++++++++++++++++++++--------- 1 file changed, 424 insertions(+), 113 deletions(-) diff --git a/chapters/chap01.ipynb b/chapters/chap01.ipynb index ffd6454..128c785 100644 --- a/chapters/chap01.ipynb +++ b/chapters/chap01.ipynb @@ -45,7 +45,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 5, "id": "213f9d96", "metadata": { "tags": [], @@ -108,12 +108,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "2568ec84", "metadata": { - "id": "2568ec84" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2568ec84", + "outputId": "4de0cc54-5c08-426e-9451-8c974e8b71dc" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 6 + } + ], "source": [ "30 + 12" ] @@ -250,12 +265,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "df933e80", "metadata": { - "id": "df933e80" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "df933e80", + "outputId": "7945ef68-3d5d-43a1-f5cc-1c903cf18bb8" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "49" + ] + }, + "metadata": {}, + "execution_count": 7 + } + ], "source": [ "7 ** 2" ] @@ -311,12 +341,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "6e68101d", "metadata": { - "id": "6e68101d" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6e68101d", + "outputId": "f612ee07-2011-48be-a325-a1989540e487" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 8 + } + ], "source": [ "6 + 6 ** 2" ] @@ -451,12 +496,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "9247c1a3", "metadata": { - "id": "9247c1a3" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9247c1a3", + "outputId": "0f03aeee-cf64-42ef-9981-99c860fbe4f1" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 9 + } + ], "source": [ "abs(-42)" ] @@ -489,13 +549,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "4674b7ca", "metadata": { "tags": [], - "id": "4674b7ca" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + }, + "id": "4674b7ca", + "outputId": "a5fbe594-3534-44f4-8599-72de909ac513" + }, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "invalid syntax (ipython-input-3827346253.py, line 1)", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-3827346253.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m abs 42\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], "source": [ "%%expect SyntaxError\n", "\n", @@ -556,12 +630,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "bd8ae45f", "metadata": { - "id": "bd8ae45f" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/", + "height": 36 + }, + "id": "bd8ae45f", + "outputId": "83d48691-5f06-4269-eabd-fc1cdb9bf3d9" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'Hello'" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {}, + "execution_count": 11 + } + ], "source": [ "'Hello'" ] @@ -644,12 +737,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "aefe6af1", "metadata": { - "id": "aefe6af1" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/", + "height": 36 + }, + "id": "aefe6af1", + "outputId": "f3be148d-2f3b-4404-8c1f-c12f8c6b018a" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "\"Well, it's a small world.\"" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {}, + "execution_count": 12 + } + ], "source": [ "'Well, ' + \"it's a small \" + 'world.'" ] @@ -666,12 +778,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "42e9e4e2", "metadata": { - "id": "42e9e4e2" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/", + "height": 36 + }, + "id": "42e9e4e2", + "outputId": "547cf862-8af2-4632-f4aa-a0545a73a131" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'Spam, Spam, Spam, Spam, '" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {}, + "execution_count": 13 + } + ], "source": [ "'Spam, ' * 4" ] @@ -690,12 +821,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "a5e837db", "metadata": { - "id": "a5e837db" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "a5e837db", + "outputId": "59dde103-43aa-44ec-ed6c-306ecd9842c6" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "4" + ] + }, + "metadata": {}, + "execution_count": 14 + } + ], "source": [ "len('Spam')" ] @@ -715,13 +861,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "e3f65f19", "metadata": { "tags": [], - "id": "e3f65f19" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + }, + "id": "e3f65f19", + "outputId": "36aa3cab-943b-4616-c906-de630c77f386" + }, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "invalid syntax (ipython-input-1580190030.py, line 1)", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-1580190030.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m `Hello`\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], "source": [ "%%expect SyntaxError\n", "\n", @@ -740,13 +900,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "a705b980", "metadata": { "tags": [], - "id": "a705b980" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + }, + "id": "a705b980", + "outputId": "fa1a301c-67f4-4bef-b320-a2b3fcf545f8" + }, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "invalid character '‘' (U+2018) (ipython-input-232449189.py, line 1)", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-232449189.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m ‘Hello’\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid character '‘' (U+2018)\n" + ] + } + ], "source": [ "%%expect SyntaxError\n", "\n", @@ -1194,13 +1368,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "06d3e72c", "metadata": { "tags": [], - "id": "06d3e72c" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "06d3e72c", + "outputId": "9793418d-c95a-4795-b599-2aa7dd5e2358" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Exception reporting mode: Verbose\n" + ] + } + ], "source": [ "# This cell tells Jupyter to provide detailed debugging information\n", "# when a runtime error occurs. Run it before working on the exercises.\n", @@ -1272,24 +1458,54 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "5d358f37", "metadata": { - "id": "5d358f37" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5d358f37", + "outputId": "1c054665-04e4-450b-f51a-c64e95d62c40" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 18 + } + ], "source": [ "round(42.5)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "12aa59a3", "metadata": { - "id": "12aa59a3" - }, - "outputs": [], + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "12aa59a3", + "outputId": "620a503b-5b6f-496c-9100-f177bb3a0c00" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "44" + ] + }, + "metadata": {}, + "execution_count": 19 + } + ], "source": [ "round(43.5)" ] @@ -1324,6 +1540,33 @@ "3. If you call a function like `round(42.5)`, what happens if you leave out one or both parentheses?" ] }, + { + "cell_type": "code", + "source": [ + "round(42.5)" + ], + "metadata": { + "id": "tXQpDGAlWtcP", + "outputId": "200fb014-6310-494b-9060-ee8e61c77b4d", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "id": "tXQpDGAlWtcP", + "execution_count": 23, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 23 + } + ] + }, { "cell_type": "markdown", "id": "1fb0adfe", @@ -1354,6 +1597,33 @@ "* `type`" ] }, + { + "cell_type": "code", + "source": [ + "type(type)" + ], + "metadata": { + "id": "bxmmvb82abjy", + "outputId": "cf62dacc-e413-4881-cc6e-9837f5bd5eb0", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "id": "bxmmvb82abjy", + "execution_count": 33, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "type" + ] + }, + "metadata": {}, + "execution_count": 33 + } + ] + }, { "cell_type": "markdown", "id": "23762eec", @@ -1381,98 +1651,139 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "id": "8fb50f30", "metadata": { - "id": "8fb50f30" + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8fb50f30", + "outputId": "f434fa33-5d0a-4141-8226-81d6073219b2" }, - "outputs": [], + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "2562" + ] + }, + "metadata": {}, + "execution_count": 35 + } + ], "source": [ - "# Solution goes here" + "42+(42*60)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "id": "5eceb4fb", "metadata": { - "id": "5eceb4fb" + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5eceb4fb", + "outputId": "332048be-dbf1-4111-f94a-d2f15430e81b" }, - "outputs": [], + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "16.1" + ] + }, + "metadata": {}, + "execution_count": 36 + } + ], "source": [ - "# Solution goes here" + "10*1.61" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 45, "id": "fee97d8d", "metadata": { - "id": "fee97d8d" + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "fee97d8d", + "outputId": "35f69763-4d8f-4f50-e527-895b3d0caa2f" }, - "outputs": [], + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "159.1304347826087" + ] + }, + "metadata": {}, + "execution_count": 45 + } + ], "source": [ - "# Solution goes here" + "(42*60+42)/16.1" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "id": "a998258c", "metadata": { - "id": "a998258c" + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "a998258c", + "outputId": "03e9a14e-8067-4762-b18e-95e8e253d39a" }, - "outputs": [], + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "2.652173913043478" + ] + }, + "metadata": {}, + "execution_count": 49 + } + ], "source": [ - "# Solution goes here" + "((42*60+42)/16.1)/60" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 50, "id": "2e0fc7a9", "metadata": { - "id": "2e0fc7a9" - }, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d25268d8", - "metadata": { - "id": "d25268d8" - }, - "outputs": [], - "source": [ - "# Solution goes here" + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2e0fc7a9", + "outputId": "856cc4f7-4358-4666-b650-4e1fa8dc2aa4" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "0.04420289855072464" + ] + }, + "metadata": {}, + "execution_count": 50 + } + ], + "source": [ + "((42*60+42)/16.1)/60/60" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "523d9b0f", - "metadata": { - "id": "523d9b0f" - }, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ca083ccf", - "metadata": { - "id": "ca083ccf" - }, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "a7f4edf8", From 03641498427b4e3f523788980e0955f5ee432c88 Mon Sep 17 00:00:00 2001 From: Ben Hutton Date: Tue, 30 Sep 2025 14:38:16 +0100 Subject: [PATCH 3/4] Created using Colab --- chapters/chap02.ipynb | 3237 +++++++++++++++++++++++++---------------- 1 file changed, 1984 insertions(+), 1253 deletions(-) diff --git a/chapters/chap02.ipynb b/chapters/chap02.ipynb index fb2369f..6763b0e 100644 --- a/chapters/chap02.ipynb +++ b/chapters/chap02.ipynb @@ -1,1254 +1,1985 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "1331faa1", - "metadata": {}, - "source": [ - "You can order print and ebook versions of *Think Python 3e* from\n", - "[Bookshop.org](https://bookshop.org/a/98697/9781098155438) and\n", - "[Amazon](https://www.amazon.com/_/dp/1098155432?smid=ATVPDKIKX0DER&_encoding=UTF8&tag=oreilly20-20&_encoding=UTF8&tag=greenteapre01-20&linkCode=ur2&linkId=e2a529f94920295d27ec8a06e757dc7c&camp=1789&creative=9325)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "1a0a6ff4", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from os.path import basename, exists\n", - "\n", - "def download(url):\n", - " filename = basename(url)\n", - " if not exists(filename):\n", - " from urllib.request import urlretrieve\n", - "\n", - " local, _ = urlretrieve(url, filename)\n", - " print(\"Downloaded \" + str(local))\n", - " return filename\n", - "\n", - "download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');\n", - "download('https://github.com/AllenDowney/ThinkPython/raw/v3/diagram.py');\n", - "\n", - "import thinkpython" - ] - }, - { - "cell_type": "markdown", - "id": "d0286422", - "metadata": {}, - "source": [ - "# Variables and Statements\n", - "\n", - "In the previous chapter, we used operators to write expressions that perform arithmetic computations.\n", - "\n", - "In this chapter, you'll learn about variables and statements, the `import` statement, and the `print` function.\n", - "And I'll introduce more of the vocabulary we use to talk about programs, including \"argument\" and \"module\".\n" - ] - }, - { - "cell_type": "markdown", - "id": "4ac44f0c", - "metadata": {}, - "source": [ - "## Variables\n", - "\n", - "A **variable** is a name that refers to a value.\n", - "To create a variable, we can write a **assignment statement** like this." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "59f6db42", - "metadata": {}, - "outputs": [], - "source": [ - "n = 17" - ] - }, - { - "cell_type": "markdown", - "id": "52f187f1", - "metadata": {}, - "source": [ - "An assignment statement has three parts: the name of the variable on the left, the equals operator, `=`, and an expression on the right.\n", - "In this example, the expression is an integer.\n", - "In the following example, the expression is a floating-point number." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "1301f6af", - "metadata": {}, - "outputs": [], - "source": [ - "pi = 3.141592653589793" - ] - }, - { - "cell_type": "markdown", - "id": "3e27e65c", - "metadata": {}, - "source": [ - "And in the following example, the expression is a string." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "f7adb732", - "metadata": {}, - "outputs": [], - "source": [ - "message = 'And now for something completely different'" - ] - }, - { - "cell_type": "markdown", - "id": "cb5916ea", - "metadata": {}, - "source": [ - "When you run an assignment statement, there is no output.\n", - "Python creates the variable and gives it a value, but the assignment statement has no visible effect.\n", - "However, after creating a variable, you can use it as an expression.\n", - "So we can display the value of `message` like this:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "6bcc0a66", - "metadata": {}, - "outputs": [], - "source": [ - "message" - ] - }, - { - "cell_type": "markdown", - "id": "e3fd81de", - "metadata": {}, - "source": [ - "You can also use a variable as part of an expression with arithmetic operators." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "3f11f497", - "metadata": {}, - "outputs": [], - "source": [ - "n + 25" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "6b2dafea", - "metadata": {}, - "outputs": [], - "source": [ - "2 * pi" - ] - }, - { - "cell_type": "markdown", - "id": "97396e7d", - "metadata": {}, - "source": [ - "And you can use a variable when you call a function." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "72c45ac5", - "metadata": {}, - "outputs": [], - "source": [ - "round(pi)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "6bf81c52", - "metadata": {}, - "outputs": [], - "source": [ - "len(message)" - ] - }, - { - "cell_type": "markdown", - "id": "397d9da3", - "metadata": {}, - "source": [ - "## State diagrams\n", - "\n", - "A common way to represent variables on paper is to write the name with\n", - "an arrow pointing to its value. " - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "2c25e84e", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "import math\n", - "\n", - "from diagram import make_binding, Frame\n", - "\n", - "binding = make_binding(\"message\", 'And now for something completely different')\n", - "binding2 = make_binding(\"n\", 17)\n", - "binding3 = make_binding(\"pi\", 3.141592653589793)\n", - "\n", - "frame = Frame([binding2, binding3, binding])" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "5b27a635", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from diagram import diagram, adjust\n", - "\n", - "\n", - "width, height, x, y = [3.62, 1.01, 0.6, 0.76]\n", - "ax = diagram(width, height)\n", - "bbox = frame.draw(ax, x, y, dy=-0.25)\n", - "# adjust(x, y, bbox)" - ] - }, - { - "cell_type": "markdown", - "id": "6f40da93", - "metadata": {}, - "source": [ - "This kind of figure is called a **state diagram** because it shows what state each of the variables is in (think of it as the variable's state of mind).\n", - "We'll use state diagrams throughout the book to represent a model of how Python stores variables and their values." - ] - }, - { - "cell_type": "markdown", - "id": "ba252c85", - "metadata": {}, - "source": [ - "## Variable names\n", - "\n", - "Variable names can be as long as you like. They can contain both letters and numbers, but they can't begin with a number. \n", - "It is legal to use uppercase letters, but it is conventional to use only lower case for\n", - "variable names.\n", - "\n", - "The only punctuation that can appear in a variable name is the underscore character, `_`. It is often used in names with multiple words, such as `your_name` or `airspeed_of_unladen_swallow`.\n", - "\n", - "If you give a variable an illegal name, you get a syntax error.\n", - "The name `million!` is illegal because it contains punctuation." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "ac2620ef", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect SyntaxError\n", - "\n", - "million! = 1000000" - ] - }, - { - "cell_type": "markdown", - "id": "a1cefe3e", - "metadata": {}, - "source": [ - "`76trombones` is illegal because it starts with a number." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "1a8b8382", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect SyntaxError\n", - "\n", - "76trombones = 'big parade'" - ] - }, - { - "cell_type": "markdown", - "id": "94aa7e60", - "metadata": {}, - "source": [ - "`class` is also illegal, but it might not be obvious why." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "b6938851", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect SyntaxError\n", - "\n", - "class = 'Self-Defence Against Fresh Fruit'" - ] - }, - { - "cell_type": "markdown", - "id": "784cfb5c", - "metadata": {}, - "source": [ - "It turns out that `class` is a **keyword**, which is a special word used to specify the structure of a program.\n", - "Keywords can't be used as variable names.\n", - "\n", - "Here's a complete list of Python's keywords:" - ] - }, - { - "cell_type": "markdown", - "id": "127c07e8", - "metadata": {}, - "source": [ - "```\n", - "False await else import pass\n", - "None break except in raise\n", - "True class finally is return\n", - "and continue for lambda try\n", - "as def from nonlocal while\n", - "assert del global not with\n", - "async elif if or yield\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "4a8f4b3e", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from keyword import kwlist\n", - "\n", - "len(kwlist)" - ] - }, - { - "cell_type": "markdown", - "id": "6f14d301", - "metadata": {}, - "source": [ - "You don't have to memorize this list. In most development environments,\n", - "keywords are displayed in a different color; if you try to use one as a\n", - "variable name, you'll know." - ] - }, - { - "cell_type": "markdown", - "id": "c954a3b0", - "metadata": {}, - "source": [ - "## The import statement\n", - "\n", - "In order to use some Python features, you have to **import** them.\n", - "For example, the following statement imports the `math` module." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "98c268e9", - "metadata": {}, - "outputs": [], - "source": [ - "import math" - ] - }, - { - "cell_type": "markdown", - "id": "ea4f75ec", - "metadata": {}, - "source": [ - "A **module** is a collection of variables and functions.\n", - "The math module provides a variable called `pi` that contains the value of the mathematical constant denoted $\\pi$.\n", - "We can display its value like this." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "47bc17c9", - "metadata": {}, - "outputs": [], - "source": [ - "math.pi" - ] - }, - { - "cell_type": "markdown", - "id": "c96106e4", - "metadata": {}, - "source": [ - "To use a variable in a module, you have to use the **dot operator** (`.`) between the name of the module and the name of the variable.\n", - "\n", - "The math module also contains functions.\n", - "For example, `sqrt` computes square roots." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "fd1cec63", - "metadata": {}, - "outputs": [], - "source": [ - "math.sqrt(25)" - ] - }, - { - "cell_type": "markdown", - "id": "185e94a3", - "metadata": {}, - "source": [ - "And `pow` raises one number to the power of a second number." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "87316ddd", - "metadata": {}, - "outputs": [], - "source": [ - "math.pow(5, 2)" - ] - }, - { - "cell_type": "markdown", - "id": "5df25a9a", - "metadata": {}, - "source": [ - "At this point we've seen two ways to raise a number to a power: we can use the `math.pow` function or the exponentiation operator, `**`.\n", - "Either one is fine, but the operator is used more often than the function." - ] - }, - { - "cell_type": "markdown", - "id": "6538f22b", - "metadata": {}, - "source": [ - "## Expressions and statements\n", - "\n", - "So far, we've seen a few kinds of expressions.\n", - "An expression can be a single value, like an integer, floating-point number, or string.\n", - "It can also be a collection of values and operators.\n", - "And it can include variable names and function calls.\n", - "Here's an expression that includes several of these elements." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "7f0b92df", - "metadata": {}, - "outputs": [], - "source": [ - "19 + n + round(math.pi) * 2" - ] - }, - { - "cell_type": "markdown", - "id": "000dd2ba", - "metadata": {}, - "source": [ - "We have also seen a few kind of statements.\n", - "A **statement** is a unit of code that has an effect, but no value.\n", - "For example, an assignment statement creates a variable and gives it a value, but the statement itself has no value." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "b882c340", - "metadata": {}, - "outputs": [], - "source": [ - "n = 17" - ] - }, - { - "cell_type": "markdown", - "id": "cff0414b", - "metadata": {}, - "source": [ - "Similarly, an import statement has an effect -- it imports a module so we can use the variables and functions it contains -- but it has no visible effect." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "299817d8", - "metadata": {}, - "outputs": [], - "source": [ - "import math" - ] - }, - { - "cell_type": "markdown", - "id": "2aeb1000", - "metadata": {}, - "source": [ - "Computing the value of an expression is called **evaluation**.\n", - "Running a statement is called **execution**." - ] - }, - { - "cell_type": "markdown", - "id": "f61601e4", - "metadata": {}, - "source": [ - "## The print function\n", - "\n", - "When you evaluate an expression, the result is displayed." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "805977c6", - "metadata": {}, - "outputs": [], - "source": [ - "n + 1" - ] - }, - { - "cell_type": "markdown", - "id": "efacf0fa", - "metadata": {}, - "source": [ - "But if you evaluate more than one expression, only the value of the last one is displayed." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "962e08ab", - "metadata": {}, - "outputs": [], - "source": [ - "n + 2\n", - "n + 3" - ] - }, - { - "cell_type": "markdown", - "id": "cf2b991d", - "metadata": {}, - "source": [ - "To display more than one value, you can use the `print` function." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "a797e44d", - "metadata": {}, - "outputs": [], - "source": [ - "print(n+2)\n", - "print(n+3)" - ] - }, - { - "cell_type": "markdown", - "id": "29af1f89", - "metadata": {}, - "source": [ - "It also works with floating-point numbers and strings." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "73428520", - "metadata": {}, - "outputs": [], - "source": [ - "print('The value of pi is approximately')\n", - "print(math.pi)" - ] - }, - { - "cell_type": "markdown", - "id": "8b4d7f4a", - "metadata": {}, - "source": [ - "You can also use a sequence of expressions separated by commas." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "9ad5bddd", - "metadata": {}, - "outputs": [], - "source": [ - "print('The value of pi is approximately', math.pi)" - ] - }, - { - "cell_type": "markdown", - "id": "af447ec4", - "metadata": {}, - "source": [ - "Notice that the `print` function puts a space between the values." - ] - }, - { - "cell_type": "markdown", - "id": "7c73a2fa", - "metadata": {}, - "source": [ - "## Arguments\n", - "\n", - "When you call a function, the expression in parenthesis is called an **argument**.\n", - "Normally I would explain why, but in this case the technical meaning of a term has almost nothing to do with the common meaning of the word, so I won't even try.\n", - "\n", - "Some of the functions we've seen so far take only one argument, like `int`." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "060c60cf", - "metadata": {}, - "outputs": [], - "source": [ - "int('101')" - ] - }, - { - "cell_type": "markdown", - "id": "c4ad4f2c", - "metadata": {}, - "source": [ - "Some take two, like `math.pow`." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "2875d9e0", - "metadata": {}, - "outputs": [], - "source": [ - "math.pow(5, 2)" - ] - }, - { - "cell_type": "markdown", - "id": "17293749", - "metadata": {}, - "source": [ - "Some can take additional arguments that are optional. \n", - "For example, `int` can take a second argument that specifies the base of the number." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "43b9cf38", - "metadata": {}, - "outputs": [], - "source": [ - "int('101', 2)" - ] - }, - { - "cell_type": "markdown", - "id": "c95589a1", - "metadata": {}, - "source": [ - "The sequence of digits `101` in base 2 represents the number 5 in base 10.\n", - "\n", - "`round` also takes an optional second argument, which is the number of decimal places to round off to." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "e8a21d05", - "metadata": {}, - "outputs": [], - "source": [ - "round(math.pi, 3)" - ] - }, - { - "cell_type": "markdown", - "id": "21e4a448", - "metadata": {}, - "source": [ - "Some functions can take any number of arguments, like `print`." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "724128f4", - "metadata": {}, - "outputs": [], - "source": [ - "print('Any', 'number', 'of', 'arguments')" - ] - }, - { - "cell_type": "markdown", - "id": "667cff14", - "metadata": {}, - "source": [ - "If you call a function and provide too many arguments, that's a `TypeError`." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "69295e52", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect TypeError\n", - "\n", - "float('123.0', 2)" - ] - }, - { - "cell_type": "markdown", - "id": "5103368e", - "metadata": {}, - "source": [ - "If you provide too few arguments, that's also a `TypeError`." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "edec7064", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect TypeError\n", - "\n", - "math.pow(2)" - ] - }, - { - "cell_type": "markdown", - "id": "5333c416", - "metadata": {}, - "source": [ - "And if you provide an argument with a type the function can't handle, that's a `TypeError`, too." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "f86b2896", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect TypeError\n", - "\n", - "math.sqrt('123')" - ] - }, - { - "cell_type": "markdown", - "id": "548828af", - "metadata": {}, - "source": [ - "This kind of checking can be annoying when you are getting started, but it helps you detect and correct errors." - ] - }, - { - "cell_type": "markdown", - "id": "be2b6a9b", - "metadata": {}, - "source": [ - "## Comments\n", - "\n", - "As programs get bigger and more complicated, they get more difficult to read.\n", - "Formal languages are dense, and it is often difficult to look at a piece of code and figure out what it is doing and why.\n", - "\n", - "For this reason, it is a good idea to add notes to your programs to explain in natural language what the program is doing. \n", - "These notes are called **comments**, and they start with the `#` symbol." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "607893a6", - "metadata": {}, - "outputs": [], - "source": [ - "# number of seconds in 42:42\n", - "seconds = 42 * 60 + 42" - ] - }, - { - "cell_type": "markdown", - "id": "519c83a9", - "metadata": {}, - "source": [ - "In this case, the comment appears on a line by itself. You can also put\n", - "comments at the end of a line:" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "615a11e7", - "metadata": {}, - "outputs": [], - "source": [ - "miles = 10 / 1.61 # 10 kilometers in miles" - ] - }, - { - "cell_type": "markdown", - "id": "87c8d10c", - "metadata": {}, - "source": [ - "Everything from the `#` to the end of the line is ignored---it has no\n", - "effect on the execution of the program.\n", - "\n", - "Comments are most useful when they document non-obvious features of the code.\n", - "It is reasonable to assume that the reader can figure out *what* the code does; it is more useful to explain *why*.\n", - "\n", - "This comment is redundant with the code and useless:" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "cc7fe2e6", - "metadata": {}, - "outputs": [], - "source": [ - "v = 8 # assign 8 to v" - ] - }, - { - "cell_type": "markdown", - "id": "eb83b14a", - "metadata": {}, - "source": [ - "This comment contains useful information that is not in the code:" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "id": "7c93a00d", - "metadata": {}, - "outputs": [], - "source": [ - "v = 8 # velocity in miles per hour " - ] - }, - { - "cell_type": "markdown", - "id": "6cd60d4f", - "metadata": {}, - "source": [ - "Good variable names can reduce the need for comments, but long names can\n", - "make complex expressions hard to read, so there is a tradeoff." - ] - }, - { - "cell_type": "markdown", - "id": "7d61e416", - "metadata": {}, - "source": [ - "## Debugging\n", - "\n", - "Three kinds of errors can occur in a program: syntax errors, runtime errors, and semantic errors.\n", - "It is useful to distinguish between them in order to track them down more quickly.\n", - "\n", - "* **Syntax error**: \"Syntax\" refers to the structure of a program and the rules about that structure. If there is a syntax error anywhere in your program, Python does not run the program. It displays an error message immediately.\n", - "\n", - "* **Runtime error**: If there are no syntax errors in your program, it can start running. But if something goes wrong, Python displays an error message and stops. This type of error is called a runtime error. It is also called an **exception** because it indicates that something exceptional has happened.\n", - "\n", - "* **Semantic error**: The third type of error is \"semantic\", which means related to meaning. If there is a semantic error in your program, it runs without generating error messages, but it does not do what you intended. Identifying semantic errors can be tricky because it requires you to work backward by looking at the output of the program and trying to figure out what it is doing." - ] - }, - { - "cell_type": "markdown", - "id": "6cd52721", - "metadata": {}, - "source": [ - "As we've seen, an illegal variable name is a syntax error." - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "id": "86f07f6e", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect SyntaxError\n", - "\n", - "million! = 1000000" - ] - }, - { - "cell_type": "markdown", - "id": "b8971d33", - "metadata": {}, - "source": [ - "If you use an operator with a type it doesn't support, that's a runtime error. " - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "id": "682395ea", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect TypeError\n", - "\n", - "'126' / 3" - ] - }, - { - "cell_type": "markdown", - "id": "e51fa6e2", - "metadata": {}, - "source": [ - "Finally, here's an example of a semantic error.\n", - "Suppose we want to compute the average of `1` and `3`, but we forget about the order of operations and write this:" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "id": "2ff25bda", - "metadata": {}, - "outputs": [], - "source": [ - "1 + 3 / 2" - ] - }, - { - "cell_type": "markdown", - "id": "0828afc0", - "metadata": {}, - "source": [ - "When this expression is evaluated, it does not produce an error message, so there is no syntax error or runtime error.\n", - "But the result is not the average of `1` and `3`, so the program is not correct.\n", - "This is a semantic error because the program runs but it doesn't do what's intended." - ] - }, - { - "cell_type": "markdown", - "id": "07396f3d", - "metadata": {}, - "source": [ - "## Glossary\n", - "\n", - "**variable:**\n", - "A name that refers to a value.\n", - "\n", - "**assignment statement:**\n", - "A statement that assigns a value to a variable.\n", - "\n", - "**state diagram:**\n", - "A graphical representation of a set of variables and the values they refer to.\n", - "\n", - "**keyword:**\n", - "A special word used to specify the structure of a program.\n", - "\n", - "**import statement:**\n", - "A statement that reads a module file so we can use the variables and functions it contains.\n", - "\n", - "**module:**\n", - "A file that contains Python code, including function definitions and sometimes other statements.\n", - "\n", - "**dot operator:**\n", - "The operator, `.`, used to access a function in another module by specifying the module name followed by a dot and the function name.\n", - "\n", - "**evaluate:**\n", - "Perform the operations in an expression in order to compute a value.\n", - "\n", - "**statement:**\n", - "One or more lines of code that represent a command or action.\n", - "\n", - "**execute:**\n", - "Run a statement and do what it says.\n", - "\n", - "**argument:**\n", - "A value provided to a function when the function is called.\n", - "\n", - "**comment:**\n", - "Text included in a program that provides information about the program but has no effect on its execution.\n", - "\n", - "**runtime error:**\n", - "An error that causes a program to display an error message and exit.\n", - "\n", - "**exception:**\n", - "An error that is detected while the program is running.\n", - "\n", - "**semantic error:**\n", - "An error that causes a program to do the wrong thing, but not to display an error message." - ] - }, - { - "cell_type": "markdown", - "id": "70ee273d", - "metadata": {}, - "source": [ - "## Exercises" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "id": "c9e6cab4", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# This cell tells Jupyter to provide detailed debugging information\n", - "# when a runtime error occurs. Run it before working on the exercises.\n", - "\n", - "%xmode Verbose" - ] - }, - { - "cell_type": "markdown", - "id": "7256a9b2", - "metadata": {}, - "source": [ - "### Ask a virtual assistant\n", - "\n", - "Again, I encourage you to use a virtual assistant to learn more about any of the topics in this chapter.\n", - "\n", - "If you are curious about any of keywords I listed, you could ask \"Why is class a keyword?\" or \"Why can't variable names be keywords?\"\n", - "\n", - "You might have noticed that `int`, `float`, and `str` are not Python keywords.\n", - "They are variables that represent types, and they can be used as functions.\n", - "So it is *legal* to have a variable or function with one of those names, but it is strongly discouraged. Ask an assistant \"Why is it bad to use int, float, and str as variable names?\"\n", - "\n", - "Also ask, \"What are the built-in functions in Python?\"\n", - "If you are curious about any of them, ask for more information.\n", - "\n", - "In this chapter we imported the `math` module and used some of the variable and functions it provides. Ask an assistant, \"What variables and functions are in the math module?\" and \"Other than math, what modules are considered core Python?\"" - ] - }, - { - "cell_type": "markdown", - "id": "f92afde0", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "Repeating my advice from the previous chapter, whenever you learn a new feature, you should make errors on purpose to see what goes wrong.\n", - "\n", - "- We've seen that `n = 17` is legal. What about `17 = n`?\n", - "\n", - "- How about `x = y = 1`?\n", - "\n", - "- In some languages every statement ends with a semi-colon (`;`). What\n", - " happens if you put a semi-colon at the end of a Python statement?\n", - "\n", - "- What if you put a period at the end of a statement?\n", - "\n", - "- What happens if you spell the name of a module wrong and try to import `maath`?" - ] - }, - { - "cell_type": "markdown", - "id": "9d562609", - "metadata": {}, - "source": [ - "### Exercise\n", - "Practice using the Python interpreter as a calculator:\n", - "\n", - "**Part 1.** The volume of a sphere with radius $r$ is $\\frac{4}{3} \\pi r^3$.\n", - "What is the volume of a sphere with radius 5? Start with a variable named `radius` and then assign the result to a variable named `volume`. Display the result. Add comments to indicate that `radius` is in centimeters and `volume` in cubic centimeters." - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "id": "18de7d96", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "markdown", - "id": "6449b12b", - "metadata": {}, - "source": [ - "**Part 2.** A rule of trigonometry says that for any value of $x$, $(\\cos x)^2 + (\\sin x)^2 = 1$. Let's see if it's true for a specific value of $x$ like 42.\n", - "\n", - "Create a variable named `x` with this value.\n", - "Then use `math.cos` and `math.sin` to compute the sine and cosine of $x$, and the sum of their squared.\n", - "\n", - "The result should be close to 1. It might not be exactly 1 because floating-point arithmetic is not exact---it is only approximately correct." - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "id": "de812cff", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "markdown", - "id": "4986801f", - "metadata": {}, - "source": [ - "**Part 3.** In addition to `pi`, the other variable defined in the `math` module is `e`, which represents the base of the natural logarithm, written in math notation as $e$. If you are not familiar with this value, ask a virtual assistant \"What is `math.e`?\" Now let's compute $e^2$ three ways:\n", - "\n", - "* Use `math.e` and the exponentiation operator (`**`).\n", - "\n", - "* Use `math.pow` to raise `math.e` to the power `2`.\n", - "\n", - "* Use `math.exp`, which takes as an argument a value, $x$, and computes $e^x$.\n", - "\n", - "You might notice that the last result is slightly different from the other two.\n", - "See if you can find out which is correct." - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "id": "b4ada618", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "id": "4424940f", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "id": "50e8393a", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "91e5a869", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "a7f4edf8", - "metadata": { - "tags": [] - }, - "source": [ - "[Think Python: 3rd Edition](https://allendowney.github.io/ThinkPython/index.html)\n", - "\n", - "Copyright 2024 [Allen B. Downey](https://allendowney.com)\n", - "\n", - "Code license: [MIT License](https://mit-license.org/)\n", - "\n", - "Text license: [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - }, - "vscode": { - "interpreter": { - "hash": "357b915890fbc73e00b3ee3cc7035b34e6189554c2854644fe780ff20c2fdfc0" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "1331faa1", + "metadata": { + "id": "1331faa1" + }, + "source": [ + "You can order print and ebook versions of *Think Python 3e* from\n", + "[Bookshop.org](https://bookshop.org/a/98697/9781098155438) and\n", + "[Amazon](https://www.amazon.com/_/dp/1098155432?smid=ATVPDKIKX0DER&_encoding=UTF8&tag=oreilly20-20&_encoding=UTF8&tag=greenteapre01-20&linkCode=ur2&linkId=e2a529f94920295d27ec8a06e757dc7c&camp=1789&creative=9325)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1a0a6ff4", + "metadata": { + "tags": [], + "id": "1a0a6ff4", + "outputId": "c0643996-24f2-4044-ee05-5f9c2f322718", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Downloaded thinkpython.py\n", + "Downloaded diagram.py\n" + ] + } + ], + "source": [ + "from os.path import basename, exists\n", + "\n", + "def download(url):\n", + " filename = basename(url)\n", + " if not exists(filename):\n", + " from urllib.request import urlretrieve\n", + "\n", + " local, _ = urlretrieve(url, filename)\n", + " print(\"Downloaded \" + str(local))\n", + " return filename\n", + "\n", + "download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');\n", + "download('https://github.com/AllenDowney/ThinkPython/raw/v3/diagram.py');\n", + "\n", + "import thinkpython" + ] + }, + { + "cell_type": "markdown", + "id": "d0286422", + "metadata": { + "id": "d0286422" + }, + "source": [ + "# Variables and Statements\n", + "\n", + "In the previous chapter, we used operators to write expressions that perform arithmetic computations.\n", + "\n", + "In this chapter, you'll learn about variables and statements, the `import` statement, and the `print` function.\n", + "And I'll introduce more of the vocabulary we use to talk about programs, including \"argument\" and \"module\".\n" + ] + }, + { + "cell_type": "markdown", + "id": "4ac44f0c", + "metadata": { + "id": "4ac44f0c" + }, + "source": [ + "## Variables\n", + "\n", + "A **variable** is a name that refers to a value.\n", + "To create a variable, we can write a **assignment statement** like this." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "59f6db42", + "metadata": { + "id": "59f6db42" + }, + "outputs": [], + "source": [ + "n = 17" + ] + }, + { + "cell_type": "markdown", + "id": "52f187f1", + "metadata": { + "id": "52f187f1" + }, + "source": [ + "An assignment statement has three parts: the name of the variable on the left, the equals operator, `=`, and an expression on the right.\n", + "In this example, the expression is an integer.\n", + "In the following example, the expression is a floating-point number." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1301f6af", + "metadata": { + "id": "1301f6af" + }, + "outputs": [], + "source": [ + "pi = 3.141592653589793" + ] + }, + { + "cell_type": "markdown", + "id": "3e27e65c", + "metadata": { + "id": "3e27e65c" + }, + "source": [ + "And in the following example, the expression is a string." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f7adb732", + "metadata": { + "id": "f7adb732" + }, + "outputs": [], + "source": [ + "message = 'And now for something completely different'" + ] + }, + { + "cell_type": "markdown", + "id": "cb5916ea", + "metadata": { + "id": "cb5916ea" + }, + "source": [ + "When you run an assignment statement, there is no output.\n", + "Python creates the variable and gives it a value, but the assignment statement has no visible effect.\n", + "However, after creating a variable, you can use it as an expression.\n", + "So we can display the value of `message` like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6bcc0a66", + "metadata": { + "id": "6bcc0a66", + "outputId": "bb7df901-ec92-46bf-f2c1-8716a82f1059", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 36 + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'And now for something completely different'" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {}, + "execution_count": 4 + } + ], + "source": [ + "message" + ] + }, + { + "cell_type": "markdown", + "id": "e3fd81de", + "metadata": { + "id": "e3fd81de" + }, + "source": [ + "You can also use a variable as part of an expression with arithmetic operators." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "3f11f497", + "metadata": { + "id": "3f11f497", + "outputId": "7eddbee9-2369-48ba-adf3-2e5008fbea8c", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 7 + } + ], + "source": [ + "n + 25" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6b2dafea", + "metadata": { + "id": "6b2dafea", + "outputId": "67c52392-b84e-443b-b917-671c13736897", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "6.283185307179586" + ] + }, + "metadata": {}, + "execution_count": 8 + } + ], + "source": [ + "2 * pi" + ] + }, + { + "cell_type": "markdown", + "id": "97396e7d", + "metadata": { + "id": "97396e7d" + }, + "source": [ + "And you can use a variable when you call a function." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "72c45ac5", + "metadata": { + "id": "72c45ac5", + "outputId": "e143f5ec-844a-4be6-d81f-6b03f926d1c4", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "3" + ] + }, + "metadata": {}, + "execution_count": 9 + } + ], + "source": [ + "round(pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "6bf81c52", + "metadata": { + "id": "6bf81c52", + "outputId": "2b73eea5-16c9-46b9-d29b-f54a6e73076c", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 10 + } + ], + "source": [ + "len(message)" + ] + }, + { + "cell_type": "markdown", + "id": "397d9da3", + "metadata": { + "id": "397d9da3" + }, + "source": [ + "## State diagrams\n", + "\n", + "A common way to represent variables on paper is to write the name with\n", + "an arrow pointing to its value." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2c25e84e", + "metadata": { + "tags": [], + "id": "2c25e84e" + }, + "outputs": [], + "source": [ + "import math\n", + "\n", + "from diagram import make_binding, Frame\n", + "\n", + "binding = make_binding(\"message\", 'And now for something completely different')\n", + "binding2 = make_binding(\"n\", 17)\n", + "binding3 = make_binding(\"pi\", 3.141592653589793)\n", + "\n", + "frame = Frame([binding2, binding3, binding])" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "5b27a635", + "metadata": { + "tags": [], + "id": "5b27a635", + "outputId": "26869ea0-8306-4125-d714-f08a04824f8e", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 138 + } + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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\n" + }, + "metadata": {} + } + ], + "source": [ + "from diagram import diagram, adjust\n", + "\n", + "\n", + "width, height, x, y = [3.62, 1.01, 0.6, 0.76]\n", + "ax = diagram(width, height)\n", + "bbox = frame.draw(ax, x, y, dy=-0.25)\n", + "# adjust(x, y, bbox)" + ] + }, + { + "cell_type": "markdown", + "id": "6f40da93", + "metadata": { + "id": "6f40da93" + }, + "source": [ + "This kind of figure is called a **state diagram** because it shows what state each of the variables is in (think of it as the variable's state of mind).\n", + "We'll use state diagrams throughout the book to represent a model of how Python stores variables and their values." + ] + }, + { + "cell_type": "markdown", + "id": "ba252c85", + "metadata": { + "id": "ba252c85" + }, + "source": [ + "## Variable names\n", + "\n", + "Variable names can be as long as you like. They can contain both letters and numbers, but they can't begin with a number.\n", + "It is legal to use uppercase letters, but it is conventional to use only lower case for\n", + "variable names.\n", + "\n", + "The only punctuation that can appear in a variable name is the underscore character, `_`. It is often used in names with multiple words, such as `your_name` or `airspeed_of_unladen_swallow`.\n", + "\n", + "If you give a variable an illegal name, you get a syntax error.\n", + "The name `million!` is illegal because it contains punctuation." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "ac2620ef", + "metadata": { + "tags": [], + "id": "ac2620ef", + "outputId": "a052aee1-5c01-4921-f2b8-45c5017e21e1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + } + }, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "invalid syntax (ipython-input-4061783710.py, line 1)", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-4061783710.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m million! = 1000000\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "%%expect SyntaxError\n", + "\n", + "million! = 1000000" + ] + }, + { + "cell_type": "markdown", + "id": "a1cefe3e", + "metadata": { + "id": "a1cefe3e" + }, + "source": [ + "`76trombones` is illegal because it starts with a number." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "1a8b8382", + "metadata": { + "tags": [], + "id": "1a8b8382", + "outputId": "f1b205e6-2f36-41da-d4d7-36876b9fc218", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + } + }, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "invalid decimal literal (ipython-input-3636686625.py, line 1)", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-3636686625.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m 76trombones = 'big parade'\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid decimal literal\n" + ] + } + ], + "source": [ + "%%expect SyntaxError\n", + "\n", + "76trombones = 'big parade'" + ] + }, + { + "cell_type": "markdown", + "id": "94aa7e60", + "metadata": { + "id": "94aa7e60" + }, + "source": [ + "`class` is also illegal, but it might not be obvious why." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "b6938851", + "metadata": { + "tags": [], + "id": "b6938851", + "outputId": "7bace0da-fa89-477b-e8e6-b0ba56cad55b", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + } + }, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "invalid syntax (ipython-input-3285659805.py, line 1)", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-3285659805.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m class = 'Self-Defence Against Fresh Fruit'\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "%%expect SyntaxError\n", + "\n", + "class = 'Self-Defence Against Fresh Fruit'" + ] + }, + { + "cell_type": "markdown", + "id": "784cfb5c", + "metadata": { + "id": "784cfb5c" + }, + "source": [ + "It turns out that `class` is a **keyword**, which is a special word used to specify the structure of a program.\n", + "Keywords can't be used as variable names.\n", + "\n", + "Here's a complete list of Python's keywords:" + ] + }, + { + "cell_type": "markdown", + "id": "127c07e8", + "metadata": { + "id": "127c07e8" + }, + "source": [ + "```\n", + "False await else import pass\n", + "None break except in raise\n", + "True class finally is return\n", + "and continue for lambda try\n", + "as def from nonlocal while\n", + "assert del global not with\n", + "async elif if or yield\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "4a8f4b3e", + "metadata": { + "tags": [], + "id": "4a8f4b3e", + "outputId": "1fd2fd6d-3307-4063-e9a4-b78a9f9d76cd", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "35" + ] + }, + "metadata": {}, + "execution_count": 16 + } + ], + "source": [ + "from keyword import kwlist\n", + "\n", + "len(kwlist)" + ] + }, + { + "cell_type": "markdown", + "id": "6f14d301", + "metadata": { + "id": "6f14d301" + }, + "source": [ + "You don't have to memorize this list. In most development environments,\n", + "keywords are displayed in a different color; if you try to use one as a\n", + "variable name, you'll know." + ] + }, + { + "cell_type": "markdown", + "id": "c954a3b0", + "metadata": { + "id": "c954a3b0" + }, + "source": [ + "## The import statement\n", + "\n", + "In order to use some Python features, you have to **import** them.\n", + "For example, the following statement imports the `math` module." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "98c268e9", + "metadata": { + "id": "98c268e9" + }, + "outputs": [], + "source": [ + "import math" + ] + }, + { + "cell_type": "markdown", + "id": "ea4f75ec", + "metadata": { + "id": "ea4f75ec" + }, + "source": [ + "A **module** is a collection of variables and functions.\n", + "The math module provides a variable called `pi` that contains the value of the mathematical constant denoted $\\pi$.\n", + "We can display its value like this." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "47bc17c9", + "metadata": { + "id": "47bc17c9", + "outputId": "3ee2c4ad-0563-44c1-e759-cbd592b1a5f9", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "3.141592653589793" + ] + }, + "metadata": {}, + "execution_count": 18 + } + ], + "source": [ + "math.pi" + ] + }, + { + "cell_type": "markdown", + "id": "c96106e4", + "metadata": { + "id": "c96106e4" + }, + "source": [ + "To use a variable in a module, you have to use the **dot operator** (`.`) between the name of the module and the name of the variable.\n", + "\n", + "The math module also contains functions.\n", + "For example, `sqrt` computes square roots." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "fd1cec63", + "metadata": { + "id": "fd1cec63", + "outputId": "37e8e385-1df5-4059-821b-f9c282ec2314", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "5.0" + ] + }, + "metadata": {}, + "execution_count": 19 + } + ], + "source": [ + "math.sqrt(25)" + ] + }, + { + "cell_type": "markdown", + "id": "185e94a3", + "metadata": { + "id": "185e94a3" + }, + "source": [ + "And `pow` raises one number to the power of a second number." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "87316ddd", + "metadata": { + "id": "87316ddd", + "outputId": "57118d5e-97ae-4836-90e9-8afc384721ec", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "25.0" + ] + }, + "metadata": {}, + "execution_count": 20 + } + ], + "source": [ + "math.pow(5, 2)" + ] + }, + { + "cell_type": "markdown", + "id": "5df25a9a", + "metadata": { + "id": "5df25a9a" + }, + "source": [ + "At this point we've seen two ways to raise a number to a power: we can use the `math.pow` function or the exponentiation operator, `**`.\n", + "Either one is fine, but the operator is used more often than the function." + ] + }, + { + "cell_type": "markdown", + "id": "6538f22b", + "metadata": { + "id": "6538f22b" + }, + "source": [ + "## Expressions and statements\n", + "\n", + "So far, we've seen a few kinds of expressions.\n", + "An expression can be a single value, like an integer, floating-point number, or string.\n", + "It can also be a collection of values and operators.\n", + "And it can include variable names and function calls.\n", + "Here's an expression that includes several of these elements." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "7f0b92df", + "metadata": { + "id": "7f0b92df", + "outputId": "e87195dc-c8e6-4583-a24d-77cfcd3d07d1", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "42" + ] + }, + "metadata": {}, + "execution_count": 21 + } + ], + "source": [ + "19 + n + round(math.pi) * 2" + ] + }, + { + "cell_type": "markdown", + "id": "000dd2ba", + "metadata": { + "id": "000dd2ba" + }, + "source": [ + "We have also seen a few kind of statements.\n", + "A **statement** is a unit of code that has an effect, but no value.\n", + "For example, an assignment statement creates a variable and gives it a value, but the statement itself has no value." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "b882c340", + "metadata": { + "id": "b882c340" + }, + "outputs": [], + "source": [ + "n = 17" + ] + }, + { + "cell_type": "markdown", + "id": "cff0414b", + "metadata": { + "id": "cff0414b" + }, + "source": [ + "Similarly, an import statement has an effect -- it imports a module so we can use the variables and functions it contains -- but it has no visible effect." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "299817d8", + "metadata": { + "id": "299817d8" + }, + "outputs": [], + "source": [ + "import math" + ] + }, + { + "cell_type": "markdown", + "id": "2aeb1000", + "metadata": { + "id": "2aeb1000" + }, + "source": [ + "Computing the value of an expression is called **evaluation**.\n", + "Running a statement is called **execution**." + ] + }, + { + "cell_type": "markdown", + "id": "f61601e4", + "metadata": { + "id": "f61601e4" + }, + "source": [ + "## The print function\n", + "\n", + "When you evaluate an expression, the result is displayed." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "805977c6", + "metadata": { + "id": "805977c6", + "outputId": "0a3972f1-0508-4ceb-ee54-34c172a07c0f", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "18" + ] + }, + "metadata": {}, + "execution_count": 24 + } + ], + "source": [ + "n + 1" + ] + }, + { + "cell_type": "markdown", + "id": "efacf0fa", + "metadata": { + "id": "efacf0fa" + }, + "source": [ + "But if you evaluate more than one expression, only the value of the last one is displayed." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "962e08ab", + "metadata": { + "id": "962e08ab", + "outputId": "053f0712-09fe-4f92-b2a8-5011d197d5d5", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "20" + ] + }, + "metadata": {}, + "execution_count": 25 + } + ], + "source": [ + "n + 2\n", + "n + 3" + ] + }, + { + "cell_type": "markdown", + "id": "cf2b991d", + "metadata": { + "id": "cf2b991d" + }, + "source": [ + "To display more than one value, you can use the `print` function." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "a797e44d", + "metadata": { + "id": "a797e44d", + "outputId": "9b0462b6-8399-4ffb-e7f0-c38aa8a5013e", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "19\n", + "20\n" + ] + } + ], + "source": [ + "print(n+2)\n", + "print(n+3)" + ] + }, + { + "cell_type": "markdown", + "id": "29af1f89", + "metadata": { + "id": "29af1f89" + }, + "source": [ + "It also works with floating-point numbers and strings." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "73428520", + "metadata": { + "id": "73428520", + "outputId": "b6c93e5d-202b-478d-c7e2-cdce11d3e701", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "The value of pi is approximately\n", + "3.141592653589793\n" + ] + } + ], + "source": [ + "print('The value of pi is approximately')\n", + "print(math.pi)" + ] + }, + { + "cell_type": "markdown", + "id": "8b4d7f4a", + "metadata": { + "id": "8b4d7f4a" + }, + "source": [ + "You can also use a sequence of expressions separated by commas." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "9ad5bddd", + "metadata": { + "id": "9ad5bddd", + "outputId": "209f4824-f280-451e-a683-f220f7137a13", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "The value of pi is approximately 3.141592653589793\n" + ] + } + ], + "source": [ + "print('The value of pi is approximately', math.pi)" + ] + }, + { + "cell_type": "markdown", + "id": "af447ec4", + "metadata": { + "id": "af447ec4" + }, + "source": [ + "Notice that the `print` function puts a space between the values." + ] + }, + { + "cell_type": "markdown", + "id": "7c73a2fa", + "metadata": { + "id": "7c73a2fa" + }, + "source": [ + "## Arguments\n", + "\n", + "When you call a function, the expression in parenthesis is called an **argument**.\n", + "Normally I would explain why, but in this case the technical meaning of a term has almost nothing to do with the common meaning of the word, so I won't even try.\n", + "\n", + "Some of the functions we've seen so far take only one argument, like `int`." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "060c60cf", + "metadata": { + "id": "060c60cf", + "outputId": "63edf69a-2294-404b-acab-056d3b9f04ed", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "101" + ] + }, + "metadata": {}, + "execution_count": 29 + } + ], + "source": [ + "int('101')" + ] + }, + { + "cell_type": "markdown", + "id": "c4ad4f2c", + "metadata": { + "id": "c4ad4f2c" + }, + "source": [ + "Some take two, like `math.pow`." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "2875d9e0", + "metadata": { + "id": "2875d9e0", + "outputId": "88ca24ac-6f94-444c-df16-182ffd79dd2d", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "25.0" + ] + }, + "metadata": {}, + "execution_count": 30 + } + ], + "source": [ + "math.pow(5, 2)" + ] + }, + { + "cell_type": "markdown", + "id": "17293749", + "metadata": { + "id": "17293749" + }, + "source": [ + "Some can take additional arguments that are optional.\n", + "For example, `int` can take a second argument that specifies the base of the number." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "43b9cf38", + "metadata": { + "id": "43b9cf38", + "outputId": "6e29e14d-8263-498e-c857-5f99594a4a84", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "5" + ] + }, + "metadata": {}, + "execution_count": 31 + } + ], + "source": [ + "int('101', 2)" + ] + }, + { + "cell_type": "markdown", + "id": "c95589a1", + "metadata": { + "id": "c95589a1" + }, + "source": [ + "The sequence of digits `101` in base 2 represents the number 5 in base 10.\n", + "\n", + "`round` also takes an optional second argument, which is the number of decimal places to round off to." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "e8a21d05", + "metadata": { + "id": "e8a21d05", + "outputId": "63a4bb96-5451-4adb-c89c-05076ba1aba3", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "3.142" + ] + }, + "metadata": {}, + "execution_count": 32 + } + ], + "source": [ + "round(math.pi, 3)" + ] + }, + { + "cell_type": "markdown", + "id": "21e4a448", + "metadata": { + "id": "21e4a448" + }, + "source": [ + "Some functions can take any number of arguments, like `print`." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "724128f4", + "metadata": { + "id": "724128f4", + "outputId": "a18e7105-8c8e-4642-e87c-c23dc7211389", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Any number of arguments\n" + ] + } + ], + "source": [ + "print('Any', 'number', 'of', 'arguments')" + ] + }, + { + "cell_type": "markdown", + "id": "667cff14", + "metadata": { + "id": "667cff14" + }, + "source": [ + "If you call a function and provide too many arguments, that's a `TypeError`." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "69295e52", + "metadata": { + "tags": [], + "id": "69295e52", + "outputId": "ea8cf690-6cc7-49c4-be3b-cea42a751aa0", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 55 + } + }, + "outputs": [ + { + "output_type": "error", + "ename": "TypeError", + "evalue": "float expected at most 1 argument, got 2", + "traceback": [ + "\u001b[0;31mTypeError\u001b[0m\u001b[0;31m:\u001b[0m float expected at most 1 argument, got 2\n" + ] + } + ], + "source": [ + "%%expect TypeError\n", + "\n", + "float('123.0', 2)" + ] + }, + { + "cell_type": "markdown", + "id": "5103368e", + "metadata": { + "id": "5103368e" + }, + "source": [ + "If you provide too few arguments, that's also a `TypeError`." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "edec7064", + "metadata": { + "tags": [], + "id": "edec7064", + "outputId": "eb284c27-d256-4b61-97f6-07a78882f58c", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 55 + } + }, + "outputs": [ + { + "output_type": "error", + "ename": "TypeError", + "evalue": "pow expected 2 arguments, got 1", + "traceback": [ + "\u001b[0;31mTypeError\u001b[0m\u001b[0;31m:\u001b[0m pow expected 2 arguments, got 1\n" + ] + } + ], + "source": [ + "%%expect TypeError\n", + "\n", + "math.pow(2)" + ] + }, + { + "cell_type": "markdown", + "id": "5333c416", + "metadata": { + "id": "5333c416" + }, + "source": [ + "And if you provide an argument with a type the function can't handle, that's a `TypeError`, too." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "f86b2896", + "metadata": { + "tags": [], + "id": "f86b2896", + "outputId": "74d9f6be-291a-4efb-ba86-c536a4d5835e", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 55 + } + }, + "outputs": [ + { + "output_type": "error", + "ename": "TypeError", + "evalue": "must be real number, not str", + "traceback": [ + "\u001b[0;31mTypeError\u001b[0m\u001b[0;31m:\u001b[0m must be real number, not str\n" + ] + } + ], + "source": [ + "%%expect TypeError\n", + "\n", + "math.sqrt('123')" + ] + }, + { + "cell_type": "markdown", + "id": "548828af", + "metadata": { + "id": "548828af" + }, + "source": [ + "This kind of checking can be annoying when you are getting started, but it helps you detect and correct errors." + ] + }, + { + "cell_type": "markdown", + "id": "be2b6a9b", + "metadata": { + "id": "be2b6a9b" + }, + "source": [ + "## Comments\n", + "\n", + "As programs get bigger and more complicated, they get more difficult to read.\n", + "Formal languages are dense, and it is often difficult to look at a piece of code and figure out what it is doing and why.\n", + "\n", + "For this reason, it is a good idea to add notes to your programs to explain in natural language what the program is doing.\n", + "These notes are called **comments**, and they start with the `#` symbol." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "607893a6", + "metadata": { + "id": "607893a6" + }, + "outputs": [], + "source": [ + "# number of seconds in 42:42\n", + "seconds = 42 * 60 + 42" + ] + }, + { + "cell_type": "markdown", + "id": "519c83a9", + "metadata": { + "id": "519c83a9" + }, + "source": [ + "In this case, the comment appears on a line by itself. You can also put\n", + "comments at the end of a line:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "615a11e7", + "metadata": { + "id": "615a11e7" + }, + "outputs": [], + "source": [ + "miles = 10 / 1.61 # 10 kilometers in miles" + ] + }, + { + "cell_type": "markdown", + "id": "87c8d10c", + "metadata": { + "id": "87c8d10c" + }, + "source": [ + "Everything from the `#` to the end of the line is ignored---it has no\n", + "effect on the execution of the program.\n", + "\n", + "Comments are most useful when they document non-obvious features of the code.\n", + "It is reasonable to assume that the reader can figure out *what* the code does; it is more useful to explain *why*.\n", + "\n", + "This comment is redundant with the code and useless:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc7fe2e6", + "metadata": { + "id": "cc7fe2e6" + }, + "outputs": [], + "source": [ + "v = 8 # assign 8 to v" + ] + }, + { + "cell_type": "markdown", + "id": "eb83b14a", + "metadata": { + "id": "eb83b14a" + }, + "source": [ + "This comment contains useful information that is not in the code:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c93a00d", + "metadata": { + "id": "7c93a00d" + }, + "outputs": [], + "source": [ + "v = 8 # velocity in miles per hour" + ] + }, + { + "cell_type": "markdown", + "id": "6cd60d4f", + "metadata": { + "id": "6cd60d4f" + }, + "source": [ + "Good variable names can reduce the need for comments, but long names can\n", + "make complex expressions hard to read, so there is a tradeoff." + ] + }, + { + "cell_type": "markdown", + "id": "7d61e416", + "metadata": { + "id": "7d61e416" + }, + "source": [ + "## Debugging\n", + "\n", + "Three kinds of errors can occur in a program: syntax errors, runtime errors, and semantic errors.\n", + "It is useful to distinguish between them in order to track them down more quickly.\n", + "\n", + "* **Syntax error**: \"Syntax\" refers to the structure of a program and the rules about that structure. If there is a syntax error anywhere in your program, Python does not run the program. It displays an error message immediately.\n", + "\n", + "* **Runtime error**: If there are no syntax errors in your program, it can start running. But if something goes wrong, Python displays an error message and stops. This type of error is called a runtime error. It is also called an **exception** because it indicates that something exceptional has happened.\n", + "\n", + "* **Semantic error**: The third type of error is \"semantic\", which means related to meaning. If there is a semantic error in your program, it runs without generating error messages, but it does not do what you intended. Identifying semantic errors can be tricky because it requires you to work backward by looking at the output of the program and trying to figure out what it is doing." + ] + }, + { + "cell_type": "markdown", + "id": "6cd52721", + "metadata": { + "id": "6cd52721" + }, + "source": [ + "As we've seen, an illegal variable name is a syntax error." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "86f07f6e", + "metadata": { + "tags": [], + "id": "86f07f6e", + "outputId": "cc4aced4-c0a2-420d-93a1-3bf995f88db1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + } + }, + "outputs": [ + { + "output_type": "error", + "ename": "SyntaxError", + "evalue": "invalid syntax (ipython-input-4061783710.py, line 1)", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipython-input-4061783710.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m million! = 1000000\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "%%expect SyntaxError\n", + "\n", + "million! = 1000000" + ] + }, + { + "cell_type": "markdown", + "id": "b8971d33", + "metadata": { + "id": "b8971d33" + }, + "source": [ + "If you use an operator with a type it doesn't support, that's a runtime error." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "682395ea", + "metadata": { + "tags": [], + "id": "682395ea" + }, + "outputs": [], + "source": [ + "%%expect TypeError\n", + "\n", + "'126' / 3" + ] + }, + { + "cell_type": "markdown", + "id": "e51fa6e2", + "metadata": { + "id": "e51fa6e2" + }, + "source": [ + "Finally, here's an example of a semantic error.\n", + "Suppose we want to compute the average of `1` and `3`, but we forget about the order of operations and write this:" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "2ff25bda", + "metadata": { + "id": "2ff25bda", + "outputId": "b880178a-d7b5-4502-9dd3-77f94959d202", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "2.5" + ] + }, + "metadata": {}, + "execution_count": 38 + } + ], + "source": [ + "1 + 3 / 2" + ] + }, + { + "cell_type": "markdown", + "id": "0828afc0", + "metadata": { + "id": "0828afc0" + }, + "source": [ + "When this expression is evaluated, it does not produce an error message, so there is no syntax error or runtime error.\n", + "But the result is not the average of `1` and `3`, so the program is not correct.\n", + "This is a semantic error because the program runs but it doesn't do what's intended." + ] + }, + { + "cell_type": "markdown", + "id": "07396f3d", + "metadata": { + "id": "07396f3d" + }, + "source": [ + "## Glossary\n", + "\n", + "**variable:**\n", + "A name that refers to a value.\n", + "\n", + "**assignment statement:**\n", + "A statement that assigns a value to a variable.\n", + "\n", + "**state diagram:**\n", + "A graphical representation of a set of variables and the values they refer to.\n", + "\n", + "**keyword:**\n", + "A special word used to specify the structure of a program.\n", + "\n", + "**import statement:**\n", + "A statement that reads a module file so we can use the variables and functions it contains.\n", + "\n", + "**module:**\n", + "A file that contains Python code, including function definitions and sometimes other statements.\n", + "\n", + "**dot operator:**\n", + "The operator, `.`, used to access a function in another module by specifying the module name followed by a dot and the function name.\n", + "\n", + "**evaluate:**\n", + "Perform the operations in an expression in order to compute a value.\n", + "\n", + "**statement:**\n", + "One or more lines of code that represent a command or action.\n", + "\n", + "**execute:**\n", + "Run a statement and do what it says.\n", + "\n", + "**argument:**\n", + "A value provided to a function when the function is called.\n", + "\n", + "**comment:**\n", + "Text included in a program that provides information about the program but has no effect on its execution.\n", + "\n", + "**runtime error:**\n", + "An error that causes a program to display an error message and exit.\n", + "\n", + "**exception:**\n", + "An error that is detected while the program is running.\n", + "\n", + "**semantic error:**\n", + "An error that causes a program to do the wrong thing, but not to display an error message." + ] + }, + { + "cell_type": "markdown", + "id": "70ee273d", + "metadata": { + "id": "70ee273d" + }, + "source": [ + "## Exercises" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "c9e6cab4", + "metadata": { + "tags": [], + "id": "c9e6cab4", + "outputId": "299ae0d0-8029-4799-e776-573cb3093912", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Exception reporting mode: Verbose\n" + ] + } + ], + "source": [ + "# This cell tells Jupyter to provide detailed debugging information\n", + "# when a runtime error occurs. Run it before working on the exercises.\n", + "\n", + "%xmode Verbose" + ] + }, + { + "cell_type": "markdown", + "id": "7256a9b2", + "metadata": { + "id": "7256a9b2" + }, + "source": [ + "### Ask a virtual assistant\n", + "\n", + "Again, I encourage you to use a virtual assistant to learn more about any of the topics in this chapter.\n", + "\n", + "If you are curious about any of keywords I listed, you could ask \"Why is class a keyword?\" or \"Why can't variable names be keywords?\"\n", + "\n", + "You might have noticed that `int`, `float`, and `str` are not Python keywords.\n", + "They are variables that represent types, and they can be used as functions.\n", + "So it is *legal* to have a variable or function with one of those names, but it is strongly discouraged. Ask an assistant \"Why is it bad to use int, float, and str as variable names?\"\n", + "\n", + "Also ask, \"What are the built-in functions in Python?\"\n", + "If you are curious about any of them, ask for more information.\n", + "\n", + "In this chapter we imported the `math` module and used some of the variable and functions it provides. Ask an assistant, \"What variables and functions are in the math module?\" and \"Other than math, what modules are considered core Python?\"" + ] + }, + { + "cell_type": "markdown", + "id": "f92afde0", + "metadata": { + "id": "f92afde0" + }, + "source": [ + "### Exercise\n", + "\n", + "Repeating my advice from the previous chapter, whenever you learn a new feature, you should make errors on purpose to see what goes wrong.\n", + "\n", + "- We've seen that `n = 17` is legal. What about `17 = n`?\n", + "\n", + "- How about `x = y = 1`?\n", + "\n", + "- In some languages every statement ends with a semi-colon (`;`). What\n", + " happens if you put a semi-colon at the end of a Python statement?\n", + "\n", + "- What if you put a period at the end of a statement?\n", + "\n", + "- What happens if you spell the name of a module wrong and try to import `maath`?" + ] + }, + { + "cell_type": "markdown", + "id": "9d562609", + "metadata": { + "id": "9d562609" + }, + "source": [ + "### Exercise\n", + "Practice using the Python interpreter as a calculator:\n", + "\n", + "**Part 1.** The volume of a sphere with radius $r$ is $\\frac{4}{3} \\pi r^3$.\n", + "What is the volume of a sphere with radius 5? Start with a variable named `radius` and then assign the result to a variable named `volume`. Display the result. Add comments to indicate that `radius` is in centimeters and `volume` in cubic centimeters." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "18de7d96", + "metadata": { + "id": "18de7d96", + "outputId": "b97358e7-d7f0-441e-befc-d92560112c7c", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "523.5987755982989" + ] + }, + "metadata": {}, + "execution_count": 40 + } + ], + "source": [ + "# Solution goes here\n", + "r = 5\n", + "(4/3) * math.pi * pow(r,3)" + ] + }, + { + "cell_type": "markdown", + "id": "6449b12b", + "metadata": { + "id": "6449b12b" + }, + "source": [ + "**Part 2.** A rule of trigonometry says that for any value of $x$, $(\\cos x)^2 + (\\sin x)^2 = 1$. Let's see if it's true for a specific value of $x$ like 42.\n", + "\n", + "Create a variable named `x` with this value.\n", + "Then use `math.cos` and `math.sin` to compute the sine and cosine of $x$, and the sum of their squared.\n", + "\n", + "The result should be close to 1. It might not be exactly 1 because floating-point arithmetic is not exact---it is only approximately correct." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "de812cff", + "metadata": { + "id": "de812cff", + "outputId": "d59c84c9-4af8-4a6c-c9ca-6f4064f8415d", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "1.0" + ] + }, + "metadata": {}, + "execution_count": 48 + } + ], + "source": [ + "# Solution goes here\n", + "x = 42\n", + "\n", + "math.pow(math.cos(x), 2) + math.pow(math.sin(x), 2)" + ] + }, + { + "cell_type": "markdown", + "id": "4986801f", + "metadata": { + "id": "4986801f" + }, + "source": [ + "**Part 3.** In addition to `pi`, the other variable defined in the `math` module is `e`, which represents the base of the natural logarithm, written in math notation as $e$. If you are not familiar with this value, ask a virtual assistant \"What is `math.e`?\" Now let's compute $e^2$ three ways:\n", + "\n", + "* Use `math.e` and the exponentiation operator (`**`).\n", + "\n", + "* Use `math.pow` to raise `math.e` to the power `2`.\n", + "\n", + "* Use `math.exp`, which takes as an argument a value, $x$, and computes $e^x$.\n", + "\n", + "You might notice that the last result is slightly different from the other two.\n", + "See if you can find out which is correct." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "b4ada618", + "metadata": { + "id": "b4ada618", + "outputId": "f98ffd2e-abad-4342-90b8-4c09cb50fb4a", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "2.718281828459045" + ] + }, + "metadata": {}, + "execution_count": 49 + } + ], + "source": [ + "math.e" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "4424940f", + "metadata": { + "id": "4424940f", + "outputId": "3d2c3de2-23d8-47e4-b66d-5e4a420e3cff", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "7.3890560989306495" + ] + }, + "metadata": {}, + "execution_count": 53 + } + ], + "source": [ + "math.pow(math.e, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "50e8393a", + "metadata": { + "id": "50e8393a", + "outputId": "7cba2e49-f39c-4e3b-a8ea-dcddb7b4115f", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "7.38905609893065" + ] + }, + "metadata": {}, + "execution_count": 55 + } + ], + "source": [ + "math.exp(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91e5a869", + "metadata": { + "id": "91e5a869" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "a7f4edf8", + "metadata": { + "tags": [], + "id": "a7f4edf8" + }, + "source": [ + "[Think Python: 3rd Edition](https://allendowney.github.io/ThinkPython/index.html)\n", + "\n", + "Copyright 2024 [Allen B. Downey](https://allendowney.com)\n", + "\n", + "Code license: [MIT License](https://mit-license.org/)\n", + "\n", + "Text license: [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "vscode": { + "interpreter": { + "hash": "357b915890fbc73e00b3ee3cc7035b34e6189554c2854644fe780ff20c2fdfc0" + } + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file From 1b4e0d8800d8a34e23abdf2da4883f3619264eb0 Mon Sep 17 00:00:00 2001 From: Ben Hutton Date: Thu, 2 Oct 2025 09:17:39 +0100 Subject: [PATCH 4/4] Created using Colab --- chapters/chap03.ipynb | 2469 +++++++++++++++++++++++------------------ 1 file changed, 1380 insertions(+), 1089 deletions(-) diff --git a/chapters/chap03.ipynb b/chapters/chap03.ipynb index 5f2cb1d..2853f45 100644 --- a/chapters/chap03.ipynb +++ b/chapters/chap03.ipynb @@ -1,1090 +1,1381 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "1331faa1", - "metadata": {}, - "source": [ - "You can order print and ebook versions of *Think Python 3e* from\n", - "[Bookshop.org](https://bookshop.org/a/98697/9781098155438) and\n", - "[Amazon](https://www.amazon.com/_/dp/1098155432?smid=ATVPDKIKX0DER&_encoding=UTF8&tag=oreilly20-20&_encoding=UTF8&tag=greenteapre01-20&linkCode=ur2&linkId=e2a529f94920295d27ec8a06e757dc7c&camp=1789&creative=9325)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "103cbe3c", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from os.path import basename, exists\n", - "\n", - "def download(url):\n", - " filename = basename(url)\n", - " if not exists(filename):\n", - " from urllib.request import urlretrieve\n", - "\n", - " local, _ = urlretrieve(url, filename)\n", - " print(\"Downloaded \" + str(local))\n", - " return filename\n", - "\n", - "download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');\n", - "download('https://github.com/AllenDowney/ThinkPython/raw/v3/diagram.py');\n", - "\n", - "import thinkpython" - ] - }, - { - "cell_type": "markdown", - "id": "6bd858a8", - "metadata": {}, - "source": [ - "# Functions\n", - "\n", - "In the previous chapter we used several functions provided by Python, like `int` and `float`, and a few provided by the `math` module, like `sqrt` and `pow`.\n", - "In this chapter, you will learn how to create your own functions and run them.\n", - "And we'll see how one function can call another.\n", - "As examples, we'll display lyrics from Monty Python songs.\n", - "These silly examples demonstrate an important feature -- the ability to write your own functions is the foundation of programming.\n", - "\n", - "This chapter also introduces a new statement, the `for` loop, which is used to repeat a computation." - ] - }, - { - "cell_type": "markdown", - "id": "b4ea99c5", - "metadata": {}, - "source": [ - "## Defining new functions\n", - "\n", - "A **function definition** specifies the name of a new function and the sequence of statements that run when the function is called. Here's an example:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "d28f5c1a", - "metadata": {}, - "outputs": [], - "source": [ - "def print_lyrics():\n", - " print(\"I'm a lumberjack, and I'm okay.\")\n", - " print(\"I sleep all night and I work all day.\")" - ] - }, - { - "cell_type": "markdown", - "id": "0174fc41", - "metadata": {}, - "source": [ - "`def` is a keyword that indicates that this is a function definition.\n", - "The name of the function is `print_lyrics`.\n", - "Anything that's a legal variable name is also a legal function name.\n", - "\n", - "The empty parentheses after the name indicate that this function doesn't take any arguments.\n", - "\n", - "The first line of the function definition is called the **header** -- the rest is called the **body**.\n", - "The header has to end with a colon and the body has to be indented. By convention, indentation is always four spaces. \n", - "The body of this function is two print statements; in general, the body of a function can contain any number of statements of any kind.\n", - "\n", - "Defining a function creates a **function object**, which we can display like this." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "2850a402", - "metadata": {}, - "outputs": [], - "source": [ - "print_lyrics" - ] - }, - { - "cell_type": "markdown", - "id": "12bd0879", - "metadata": {}, - "source": [ - "The output indicates that `print_lyrics` is a function that takes no arguments.\n", - "`__main__` is the name of the module that contains `print_lyrics`.\n", - "\n", - "Now that we've defined a function, we can call it the same way we call built-in functions." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "9a048657", - "metadata": {}, - "outputs": [], - "source": [ - "print_lyrics()" - ] - }, - { - "cell_type": "markdown", - "id": "8f0fc45d", - "metadata": {}, - "source": [ - "When the function runs, it executes the statements in the body, which display the first two lines of \"The Lumberjack Song\"." - ] - }, - { - "cell_type": "markdown", - "id": "6d35193e", - "metadata": {}, - "source": [ - "## Parameters\n", - "\n", - "Some of the functions we have seen require arguments; for example, when you call `abs` you pass a number as an argument.\n", - "Some functions take more than one argument; for example, `math.pow` takes two, the base and the exponent.\n", - "\n", - "Here is a definition for a function that takes an argument." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "e5d00488", - "metadata": {}, - "outputs": [], - "source": [ - "def print_twice(string):\n", - " print(string)\n", - " print(string)" - ] - }, - { - "cell_type": "markdown", - "id": "1716e3dc", - "metadata": {}, - "source": [ - "The variable name in parentheses is a **parameter**.\n", - "When the function is called, the value of the argument is assigned to the parameter.\n", - "For example, we can call `print_twice` like this." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "a3ad5f46", - "metadata": {}, - "outputs": [], - "source": [ - "print_twice('Dennis Moore, ')" - ] - }, - { - "cell_type": "markdown", - "id": "f02be6d2", - "metadata": {}, - "source": [ - "Running this function has the same effect as assigning the argument to the parameter and then executing the body of the function, like this." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "042dfec1", - "metadata": {}, - "outputs": [], - "source": [ - "string = 'Dennis Moore, '\n", - "print(string)\n", - "print(string)" - ] - }, - { - "cell_type": "markdown", - "id": "ea8b8b6e", - "metadata": {}, - "source": [ - "You can also use a variable as an argument." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "8f078ad0", - "metadata": {}, - "outputs": [], - "source": [ - "line = 'Dennis Moore, '\n", - "print_twice(line)" - ] - }, - { - "cell_type": "markdown", - "id": "5c1884ad", - "metadata": {}, - "source": [ - "In this example, the value of `line` gets assigned to the parameter `string`." - ] - }, - { - "cell_type": "markdown", - "id": "a3e5a790", - "metadata": {}, - "source": [ - "## Calling functions\n", - "\n", - "Once you have defined a function, you can use it inside another function.\n", - "To demonstrate, we'll write functions that print the lyrics of \"The Spam Song\" ().\n", - "\n", - "> Spam, Spam, Spam, Spam, \n", - "> Spam, Spam, Spam, Spam, \n", - "> Spam, Spam, \n", - "> (Lovely Spam, Wonderful Spam!) \n", - "> Spam, Spam,\n", - "\n", - "We'll start with the following function, which takes two parameters.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "e86bb32c", - "metadata": {}, - "outputs": [], - "source": [ - "def repeat(word, n):\n", - " print(word * n)" - ] - }, - { - "cell_type": "markdown", - "id": "bdd4daa4", - "metadata": {}, - "source": [ - "We can use this function to print the first line of the song, like this." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "ec117999", - "metadata": {}, - "outputs": [], - "source": [ - "spam = 'Spam, '\n", - "repeat(spam, 4)" - ] - }, - { - "cell_type": "markdown", - "id": "c6f81e09", - "metadata": {}, - "source": [ - "To display the first two lines, we can define a new function that uses `repeat`." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "3731ffd8", - "metadata": {}, - "outputs": [], - "source": [ - "def first_two_lines():\n", - " repeat(spam, 4)\n", - " repeat(spam, 4)" - ] - }, - { - "cell_type": "markdown", - "id": "8058ffe4", - "metadata": {}, - "source": [ - "And then call it like this." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "6792e63b", - "metadata": {}, - "outputs": [], - "source": [ - "first_two_lines()" - ] - }, - { - "cell_type": "markdown", - "id": "07ca432a", - "metadata": {}, - "source": [ - "To display the last three lines, we can define another function, which also uses `repeat`." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "2dcb020a", - "metadata": {}, - "outputs": [], - "source": [ - "def last_three_lines():\n", - " repeat(spam, 2)\n", - " print('(Lovely Spam, Wonderful Spam!)')\n", - " repeat(spam, 2)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "9ff8c60e", - "metadata": {}, - "outputs": [], - "source": [ - "last_three_lines()" - ] - }, - { - "cell_type": "markdown", - "id": "d6456a19", - "metadata": {}, - "source": [ - "Finally, we can bring it all together with one function that prints the whole verse." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "78bf3a7b", - "metadata": {}, - "outputs": [], - "source": [ - "def print_verse():\n", - " first_two_lines()\n", - " last_three_lines()" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "ba5da431", - "metadata": {}, - "outputs": [], - "source": [ - "print_verse()" - ] - }, - { - "cell_type": "markdown", - "id": "d088fe68", - "metadata": {}, - "source": [ - "When we run `print_verse`, it calls `first_two_lines`, which calls `repeat`, which calls `print`.\n", - "That's a lot of functions.\n", - "\n", - "Of course, we could have done the same thing with fewer functions, but the point of this example is to show how functions can work together." - ] - }, - { - "cell_type": "markdown", - "id": "c3b16e3f", - "metadata": {}, - "source": [ - "## Repetition\n", - "\n", - "If we want to display more than one verse, we can use a `for` statement.\n", - "Here's a simple example." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "29b7eff3", - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(2):\n", - " print(i)" - ] - }, - { - "cell_type": "markdown", - "id": "bf320549", - "metadata": {}, - "source": [ - "The first line is a header that ends with a colon.\n", - "The second line is the body, which has to be indented.\n", - "\n", - "The header starts with the keyword `for`, a new variable named `i`, and another keyword, `in`. \n", - "It uses the `range` function to create a sequence of two values, which are `0` and `1`.\n", - "In Python, when we start counting, we usually start from `0`.\n", - "\n", - "When the `for` statement runs, it assigns the first value from `range` to `i` and then runs the `print` function in the body, which displays `0`.\n", - "\n", - "When it gets to the end of the body, it loops back around to the header, which is why this statement is called a **loop**.\n", - "The second time through the loop, it assigns the next value from `range` to `i`, and displays it.\n", - "Then, because that's the last value from `range`, the loop ends.\n", - "\n", - "Here's how we can use a `for` loop to print two verses of the song." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "038ad592", - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(2):\n", - " print(\"Verse\", i)\n", - " print_verse()\n", - " print()" - ] - }, - { - "cell_type": "markdown", - "id": "88a46733", - "metadata": {}, - "source": [ - "You can put a `for` loop inside a function.\n", - "For example, `print_n_verses` takes a parameter named `n`, which has to be an integer, and displays the given number of verses. " - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "8887637a", - "metadata": {}, - "outputs": [], - "source": [ - "def print_n_verses(n):\n", - " for i in range(n):\n", - " print_verse()\n", - " print()" - ] - }, - { - "cell_type": "markdown", - "id": "ad8060fe", - "metadata": {}, - "source": [ - "In this example, we don't use `i` in the body of the loop, but there has to be a variable name in the header anyway." - ] - }, - { - "cell_type": "markdown", - "id": "b320ec90", - "metadata": {}, - "source": [ - "## Variables and parameters are local\n", - "\n", - "When you create a variable inside a function, it is **local**, which\n", - "means that it only exists inside the function.\n", - "For example, the following function takes two arguments, concatenates them, and prints the result twice." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "0db8408e", - "metadata": {}, - "outputs": [], - "source": [ - "def cat_twice(part1, part2):\n", - " cat = part1 + part2\n", - " print_twice(cat)" - ] - }, - { - "cell_type": "markdown", - "id": "3a35a6d0", - "metadata": {}, - "source": [ - "Here's an example that uses it:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "1c556e48", - "metadata": {}, - "outputs": [], - "source": [ - "line1 = 'Always look on the '\n", - "line2 = 'bright side of life.'\n", - "cat_twice(line1, line2)" - ] - }, - { - "cell_type": "markdown", - "id": "4ab4e008", - "metadata": {}, - "source": [ - "When `cat_twice` runs, it creates a local variable named `cat`, which is destroyed when the function ends.\n", - "If we try to display it, we get a `NameError`:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "73f03eea", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect NameError\n", - "\n", - "print(cat)" - ] - }, - { - "cell_type": "markdown", - "id": "3ae36c29", - "metadata": {}, - "source": [ - "Outside of the function, `cat` is not defined. \n", - "\n", - "Parameters are also local.\n", - "For example, outside `cat_twice`, there is no such thing as `part1` or `part2`." - ] - }, - { - "cell_type": "markdown", - "id": "eabac8a6", - "metadata": {}, - "source": [ - "## Stack diagrams\n", - "\n", - "To keep track of which variables can be used where, it is sometimes useful to draw a **stack diagram**. \n", - "Like state diagrams, stack diagrams show the value of each variable, but they also show the function each variable belongs to.\n", - "\n", - "Each function is represented by a **frame**.\n", - "A frame is a box with the name of a function on the outside and the parameters and local variables of the function on the inside.\n", - "\n", - "Here's the stack diagram for the previous example." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "83df4e32", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from diagram import make_frame, Stack\n", - "\n", - "d1 = dict(line1=line1, line2=line2)\n", - "frame1 = make_frame(d1, name='__main__', dy=-0.3, loc='left')\n", - "\n", - "d2 = dict(part1=line1, part2=line2, cat=line1+line2)\n", - "frame2 = make_frame(d2, name='cat_twice', dy=-0.3, \n", - " offsetx=0.03, loc='left')\n", - "\n", - "d3 = dict(string=line1+line2)\n", - "frame3 = make_frame(d3, name='print_twice', \n", - " offsetx=0.04, offsety=-0.3, loc='left')\n", - "\n", - "d4 = {\"?\": line1+line2}\n", - "frame4 = make_frame(d4, name='print', \n", - " offsetx=-0.22, offsety=0, loc='left')\n", - "\n", - "stack = Stack([frame1, frame2, frame3, frame4], dy=-0.8)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "bcd5e1df", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from diagram import diagram, adjust\n", - "\n", - "\n", - "width, height, x, y = [3.77, 2.9, 1.1, 2.65]\n", - "ax = diagram(width, height)\n", - "bbox = stack.draw(ax, x, y)\n", - "# adjust(x, y, bbox)\n", - "\n", - "import matplotlib.pyplot as plt\n", - "plt.savefig('chap03_stack_diagram.png', dpi=300)" - ] - }, - { - "cell_type": "markdown", - "id": "854fee12", - "metadata": {}, - "source": [ - "The frames are arranged in a stack that indicates which function called\n", - "which, and so on. Reading from the bottom, `print` was called by `print_twice`, which was called by `cat_twice`, which was called by `__main__` -- which is a special name for the topmost frame.\n", - "When you create a variable outside of any function, it belongs to `__main__`.\n", - "\n", - "In the frame for `print`, the question mark indicates that we don't know the name of the parameter.\n", - "If you are curious, ask a virtual assistant, \"What are the parameters of the Python print function?\"" - ] - }, - { - "cell_type": "markdown", - "id": "5690cfc0", - "metadata": {}, - "source": [ - "## Tracebacks\n", - "\n", - "When a runtime error occurs in a function, Python displays the name of the function that was running, the name of the function that called it, and so on, up the stack.\n", - "To see an example, I'll define a version of `print_twice` that contains an error -- it tries to print `cat`, which is a local variable in another function." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "886519cf", - "metadata": {}, - "outputs": [], - "source": [ - "def print_twice(string):\n", - " print(cat) # NameError\n", - " print(cat)" - ] - }, - { - "cell_type": "markdown", - "id": "d7c0713b", - "metadata": {}, - "source": [ - "Now here's what happens when we run `cat_twice`." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "1fe8ee82", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# This cell tells Jupyter to provide detailed debugging information\n", - "# when a runtime error occurs, including a traceback.\n", - "\n", - "%xmode Verbose" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "d9082f88", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%expect NameError\n", - "\n", - "cat_twice(line1, line2)" - ] - }, - { - "cell_type": "markdown", - "id": "2f4defcf", - "metadata": {}, - "source": [ - "The error message includes a **traceback**, which shows the function that was running when the error occurred, the function that called it, and so on.\n", - "In this example, it shows that `cat_twice` called `print_twice`, and the error occurred in a `print_twice`.\n", - "\n", - "The order of the functions in the traceback is the same as the order of the frames in the stack diagram.\n", - "The function that was running is at the bottom." - ] - }, - { - "cell_type": "markdown", - "id": "374b4696", - "metadata": {}, - "source": [ - "## Why functions?\n", - "\n", - "It may not be clear yet why it is worth the trouble to divide a program into\n", - "functions.\n", - "There are several reasons:\n", - "\n", - "- Creating a new function gives you an opportunity to name a group of\n", - " statements, which makes your program easier to read and debug.\n", - "\n", - "- Functions can make a program smaller by eliminating repetitive code.\n", - " Later, if you make a change, you only have to make it in one place.\n", - "\n", - "- Dividing a long program into functions allows you to debug the parts\n", - " one at a time and then assemble them into a working whole.\n", - "\n", - "- Well-designed functions are often useful for many programs. Once you\n", - " write and debug one, you can reuse it." - ] - }, - { - "cell_type": "markdown", - "id": "c6dd486e", - "metadata": {}, - "source": [ - "## Debugging\n", - "\n", - "Debugging can be frustrating, but it is also challenging, interesting, and sometimes even fun.\n", - "And it is one of the most important skills you can learn.\n", - "\n", - "In some ways debugging is like detective work.\n", - "You are given clues and you have to infer the events that led to the\n", - "results you see.\n", - "\n", - "Debugging is also like experimental science.\n", - "Once you have an idea about what is going wrong, you modify your program and try again.\n", - "If your hypothesis was correct, you can predict the result of the modification, and you take a step closer to a working program.\n", - "If your hypothesis was wrong, you have to come up with a new one.\n", - "\n", - "For some people, programming and debugging are the same thing; that is, programming is the process of gradually debugging a program until it does what you want.\n", - "The idea is that you should start with a working program and make small modifications, debugging them as you go.\n", - "\n", - "If you find yourself spending a lot of time debugging, that is often a sign that you are writing too much code before you start tests.\n", - "If you take smaller steps, you might find that you can move faster." - ] - }, - { - "cell_type": "markdown", - "id": "d4e95e63", - "metadata": {}, - "source": [ - "## Glossary\n", - "\n", - "**function definition:**\n", - "A statement that creates a function.\n", - "\n", - "**header:**\n", - " The first line of a function definition.\n", - "\n", - "**body:**\n", - " The sequence of statements inside a function definition.\n", - "\n", - "**function object:**\n", - "A value created by a function definition.\n", - "The name of the function is a variable that refers to a function object.\n", - "\n", - "**parameter:**\n", - " A name used inside a function to refer to the value passed as an argument.\n", - "\n", - "**loop:**\n", - " A statement that runs one or more statements, often repeatedly.\n", - "\n", - "**local variable:**\n", - "A variable defined inside a function, and which can only be accessed inside the function.\n", - "\n", - "**stack diagram:**\n", - "A graphical representation of a stack of functions, their variables, and the values they refer to.\n", - "\n", - "**frame:**\n", - " A box in a stack diagram that represents a function call.\n", - " It contains the local variables and parameters of the function.\n", - "\n", - "**traceback:**\n", - " A list of the functions that are executing, printed when an exception occurs." - ] - }, - { - "cell_type": "markdown", - "id": "eca485f2", - "metadata": {}, - "source": [ - "## Exercises" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "3f77b428", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# This cell tells Jupyter to provide detailed debugging information\n", - "# when a runtime error occurs. Run it before working on the exercises.\n", - "\n", - "%xmode Verbose" - ] - }, - { - "cell_type": "markdown", - "id": "82951027", - "metadata": {}, - "source": [ - "### Ask a virtual assistant\n", - "\n", - "The statements in a function or a `for` loop are indented by four spaces, by convention.\n", - "But not everyone agrees with that convention.\n", - "If you are curious about the history of this great debate, ask a virtual assistant to \"tell me about spaces and tabs in Python\".\n", - "\n", - "Virtual assistant are pretty good at writing small functions.\n", - "\n", - "1. Ask your favorite VA to \"Write a function called repeat that takes a string and an integer and prints the string the given number of times.\" \n", - "\n", - "2. If the result uses a `for` loop, you could ask, \"Can you do it without a for loop?\"\n", - "\n", - "3. Pick any other function in this chapter and ask a VA to write it. The challenge is to describe the function precisely enough to get what you want. Use the vocabulary you have learned so far in this book.\n", - "\n", - "Virtual assistants are also pretty good at debugging functions.\n", - "\n", - "1. Ask a VA what's wrong with this version of `print_twice`.\n", - "\n", - " ```\n", - " def print_twice(string):\n", - " print(cat)\n", - " print(cat)\n", - " ```\n", - " \n", - "And if you get stuck on any of the exercises below, consider asking a VA for help." - ] - }, - { - "cell_type": "markdown", - "id": "b7157b09", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "Write a function named `print_right` that takes a string named `text` as a parameter and prints the string with enough leading spaces that the last letter of the string is in the 40th column of the display." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "a6004271", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "markdown", - "id": "428fbee5", - "metadata": {}, - "source": [ - "Hint: Use the `len` function, the string concatenation operator (`+`) and the string repetition operator (`*`).\n", - "\n", - "Here's an example that shows how it should work." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "f142ce6a", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "print_right(\"Monty\")\n", - "print_right(\"Python's\")\n", - "print_right(\"Flying Circus\")" - ] - }, - { - "cell_type": "markdown", - "id": "b47467fa", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "Write a function called `triangle` that takes a string and an integer and draws a pyramid with the given height, made up using copies of the string. Here's an example of a pyramid with `5` levels, using the string `'L'`." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "7aa95014", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "b8146a0d", - "metadata": { - "scrolled": true, - "tags": [] - }, - "outputs": [], - "source": [ - "triangle('L', 5)" - ] - }, - { - "cell_type": "markdown", - "id": "4a28f635", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "Write a function called `rectangle` that takes a string and two integers and draws a rectangle with the given width and height, made up using copies of the string. Here's an example of a rectangle with width `5` and height `4`, made up of the string `'H'`." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "bcedab79", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "73b0c0f6", - "metadata": { - "scrolled": true, - "tags": [] - }, - "outputs": [], - "source": [ - "rectangle('H', 5, 4)" - ] - }, - { - "cell_type": "markdown", - "id": "44a5de6f", - "metadata": {}, - "source": [ - "### Exercise\n", - "\n", - "The song \"99 Bottles of Beer\" starts with this verse:\n", - "\n", - "> 99 bottles of beer on the wall \n", - "> 99 bottles of beer \n", - "> Take one down, pass it around \n", - "> 98 bottles of beer on the wall \n", - "\n", - "Then the second verse is the same, except that it starts with 98 bottles and ends with 97. The song continues -- for a very long time -- until there are 0 bottles of beer.\n", - "\n", - "Write a function called `bottle_verse` that takes a number as a parameter and displays the verse that starts with the given number of bottles.\n", - "\n", - "Hint: Consider starting with a function that can print the first, second, or last line of the verse, and then use it to write `bottle_verse`." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "53424b43", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "61010ffb", - "metadata": {}, - "outputs": [], - "source": [ - "# Solution goes here" - ] - }, - { - "cell_type": "markdown", - "id": "ee0076dd", - "metadata": { - "tags": [] - }, - "source": [ - "Use this function call to display the first verse." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "47a91c7d", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "bottle_verse(99)" - ] - }, - { - "cell_type": "markdown", - "id": "42c237c6", - "metadata": { - "tags": [] - }, - "source": [ - "If you want to print the whole song, you can use this `for` loop, which counts down from `99` to `1`.\n", - "You don't have to completely understand this example---we'll learn more about `for` loops and the `range` function later." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "336cdfa2", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "for n in range(99, 0, -1):\n", - " bottle_verse(n)\n", - " print()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4b02510c", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "a7f4edf8", - "metadata": { - "tags": [] - }, - "source": [ - "[Think Python: 3rd Edition](https://allendowney.github.io/ThinkPython/index.html)\n", - "\n", - "Copyright 2024 [Allen B. Downey](https://allendowney.com)\n", - "\n", - "Code license: [MIT License](https://mit-license.org/)\n", - "\n", - "Text license: [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "1331faa1", + "metadata": { + "id": "1331faa1" + }, + "source": [ + "You can order print and ebook versions of *Think Python 3e* from\n", + "[Bookshop.org](https://bookshop.org/a/98697/9781098155438) and\n", + "[Amazon](https://www.amazon.com/_/dp/1098155432?smid=ATVPDKIKX0DER&_encoding=UTF8&tag=oreilly20-20&_encoding=UTF8&tag=greenteapre01-20&linkCode=ur2&linkId=e2a529f94920295d27ec8a06e757dc7c&camp=1789&creative=9325)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "103cbe3c", + "metadata": { + "tags": [], + "id": "103cbe3c", + "outputId": "30990dfe-eb5f-424e-dcbf-c67223a8c156", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Downloaded thinkpython.py\n", + "Downloaded diagram.py\n" + ] + } + ], + "source": [ + "from os.path import basename, exists\n", + "\n", + "def download(url):\n", + " filename = basename(url)\n", + " if not exists(filename):\n", + " from urllib.request import urlretrieve\n", + "\n", + " local, _ = urlretrieve(url, filename)\n", + " print(\"Downloaded \" + str(local))\n", + " return filename\n", + "\n", + "download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');\n", + "download('https://github.com/AllenDowney/ThinkPython/raw/v3/diagram.py');\n", + "\n", + "import thinkpython" + ] + }, + { + "cell_type": "markdown", + "id": "6bd858a8", + "metadata": { + "id": "6bd858a8" + }, + "source": [ + "# Functions\n", + "\n", + "In the previous chapter we used several functions provided by Python, like `int` and `float`, and a few provided by the `math` module, like `sqrt` and `pow`.\n", + "In this chapter, you will learn how to create your own functions and run them.\n", + "And we'll see how one function can call another.\n", + "As examples, we'll display lyrics from Monty Python songs.\n", + "These silly examples demonstrate an important feature -- the ability to write your own functions is the foundation of programming.\n", + "\n", + "This chapter also introduces a new statement, the `for` loop, which is used to repeat a computation." + ] + }, + { + "cell_type": "markdown", + "id": "b4ea99c5", + "metadata": { + "id": "b4ea99c5" + }, + "source": [ + "## Defining new functions\n", + "\n", + "A **function definition** specifies the name of a new function and the sequence of statements that run when the function is called. Here's an example:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d28f5c1a", + "metadata": { + "id": "d28f5c1a" + }, + "outputs": [], + "source": [ + "def print_lyrics():\n", + " print(\"I'm a lumberjack, and I'm okay.\")\n", + " print(\"I sleep all night and I work all day.\")" + ] + }, + { + "cell_type": "markdown", + "id": "0174fc41", + "metadata": { + "id": "0174fc41" + }, + "source": [ + "`def` is a keyword that indicates that this is a function definition.\n", + "The name of the function is `print_lyrics`.\n", + "Anything that's a legal variable name is also a legal function name.\n", + "\n", + "The empty parentheses after the name indicate that this function doesn't take any arguments.\n", + "\n", + "The first line of the function definition is called the **header** -- the rest is called the **body**.\n", + "The header has to end with a colon and the body has to be indented. By convention, indentation is always four spaces.\n", + "The body of this function is two print statements; in general, the body of a function can contain any number of statements of any kind.\n", + "\n", + "Defining a function creates a **function object**, which we can display like this." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2850a402", + "metadata": { + "id": "2850a402", + "outputId": "b1a31504-afce-41aa-a88b-989b3fc5dbc0", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 104 + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "
\n", + "
print_lyrics
def print_lyrics()
/tmp/ipython-input-1878418926.py<no docstring>
" + ] + }, + "metadata": {}, + "execution_count": 3 + } + ], + "source": [ + "print_lyrics" + ] + }, + { + "cell_type": "markdown", + "id": "12bd0879", + "metadata": { + "id": "12bd0879" + }, + "source": [ + "The output indicates that `print_lyrics` is a function that takes no arguments.\n", + "`__main__` is the name of the module that contains `print_lyrics`.\n", + "\n", + "Now that we've defined a function, we can call it the same way we call built-in functions." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9a048657", + "metadata": { + "id": "9a048657", + "outputId": "de233b37-9572-4926-dbf7-a4b624ec8cc6", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "I'm a lumberjack, and I'm okay.\n", + "I sleep all night and I work all day.\n" + ] + } + ], + "source": [ + "print_lyrics()" + ] + }, + { + "cell_type": "markdown", + "id": "8f0fc45d", + "metadata": { + "id": "8f0fc45d" + }, + "source": [ + "When the function runs, it executes the statements in the body, which display the first two lines of \"The Lumberjack Song\"." + ] + }, + { + "cell_type": "markdown", + "id": "6d35193e", + "metadata": { + "id": "6d35193e" + }, + "source": [ + "## Parameters\n", + "\n", + "Some of the functions we have seen require arguments; for example, when you call `abs` you pass a number as an argument.\n", + "Some functions take more than one argument; for example, `math.pow` takes two, the base and the exponent.\n", + "\n", + "Here is a definition for a function that takes an argument." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e5d00488", + "metadata": { + "id": "e5d00488" + }, + "outputs": [], + "source": [ + "def print_twice(string):\n", + " print(string)\n", + " print(string)" + ] + }, + { + "cell_type": "markdown", + "id": "1716e3dc", + "metadata": { + "id": "1716e3dc" + }, + "source": [ + "The variable name in parentheses is a **parameter**.\n", + "When the function is called, the value of the argument is assigned to the parameter.\n", + "For example, we can call `print_twice` like this." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a3ad5f46", + "metadata": { + "id": "a3ad5f46", + "outputId": "0f980668-7d76-4b44-9b0d-50d167576e7d", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Dennis Moore, \n", + "Dennis Moore, \n" + ] + } + ], + "source": [ + "print_twice('Dennis Moore, ')" + ] + }, + { + "cell_type": "markdown", + "id": "f02be6d2", + "metadata": { + "id": "f02be6d2" + }, + "source": [ + "Running this function has the same effect as assigning the argument to the parameter and then executing the body of the function, like this." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "042dfec1", + "metadata": { + "id": "042dfec1", + "outputId": "1f9ec348-7a32-4e00-ba1b-30107e20ee9f", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Dennis Moore, \n", + "Dennis Moore, \n" + ] + } + ], + "source": [ + "string = 'Dennis Moore, '\n", + "print(string)\n", + "print(string)" + ] + }, + { + "cell_type": "markdown", + "id": "ea8b8b6e", + "metadata": { + "id": "ea8b8b6e" + }, + "source": [ + "You can also use a variable as an argument." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "8f078ad0", + "metadata": { + "id": "8f078ad0", + "outputId": "993c9a8f-5f6a-4863-d837-d690cd7dcc57", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Dennis Moore, \n", + "Dennis Moore, \n" + ] + } + ], + "source": [ + "line = 'Dennis Moore, '\n", + "print_twice(line)" + ] + }, + { + "cell_type": "markdown", + "id": "5c1884ad", + "metadata": { + "id": "5c1884ad" + }, + "source": [ + "In this example, the value of `line` gets assigned to the parameter `string`." + ] + }, + { + "cell_type": "markdown", + "id": "a3e5a790", + "metadata": { + "id": "a3e5a790" + }, + "source": [ + "## Calling functions\n", + "\n", + "Once you have defined a function, you can use it inside another function.\n", + "To demonstrate, we'll write functions that print the lyrics of \"The Spam Song\" ().\n", + "\n", + "> Spam, Spam, Spam, Spam, \n", + "> Spam, Spam, Spam, Spam, \n", + "> Spam, Spam, \n", + "> (Lovely Spam, Wonderful Spam!) \n", + "> Spam, Spam,\n", + "\n", + "We'll start with the following function, which takes two parameters.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e86bb32c", + "metadata": { + "id": "e86bb32c" + }, + "outputs": [], + "source": [ + "def repeat(word, n):\n", + " print(word * n)" + ] + }, + { + "cell_type": "markdown", + "id": "bdd4daa4", + "metadata": { + "id": "bdd4daa4" + }, + "source": [ + "We can use this function to print the first line of the song, like this." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ec117999", + "metadata": { + "id": "ec117999", + "outputId": "8a93709f-b745-4f66-e4f6-8cdb019185c5", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Spam, Spam, Spam, Spam, \n" + ] + } + ], + "source": [ + "spam = 'Spam, '\n", + "repeat(spam, 4)" + ] + }, + { + "cell_type": "markdown", + "id": "c6f81e09", + "metadata": { + "id": "c6f81e09" + }, + "source": [ + "To display the first two lines, we can define a new function that uses `repeat`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "3731ffd8", + "metadata": { + "id": "3731ffd8" + }, + "outputs": [], + "source": [ + "def first_two_lines():\n", + " repeat(spam, 4)\n", + " repeat(spam, 4)" + ] + }, + { + "cell_type": "markdown", + "id": "8058ffe4", + "metadata": { + "id": "8058ffe4" + }, + "source": [ + "And then call it like this." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "6792e63b", + "metadata": { + "id": "6792e63b", + "outputId": "15c32fbf-db63-47a9-a60e-384abc0be09a", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Spam, Spam, Spam, Spam, \n", + "Spam, Spam, Spam, Spam, \n" + ] + } + ], + "source": [ + "first_two_lines()" + ] + }, + { + "cell_type": "markdown", + "id": "07ca432a", + "metadata": { + "id": "07ca432a" + }, + "source": [ + "To display the last three lines, we can define another function, which also uses `repeat`." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "2dcb020a", + "metadata": { + "id": "2dcb020a" + }, + "outputs": [], + "source": [ + "def last_three_lines():\n", + " repeat(spam, 2)\n", + " print('(Lovely Spam, Wonderful Spam!)')\n", + " repeat(spam, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9ff8c60e", + "metadata": { + "id": "9ff8c60e", + "outputId": "a14425e4-e4a0-4e70-f32d-fc55cfba6bf1", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Spam, Spam, \n", + "(Lovely Spam, Wonderful Spam!)\n", + "Spam, Spam, \n" + ] + } + ], + "source": [ + "last_three_lines()" + ] + }, + { + "cell_type": "markdown", + "id": "d6456a19", + "metadata": { + "id": "d6456a19" + }, + "source": [ + "Finally, we can bring it all together with one function that prints the whole verse." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78bf3a7b", + "metadata": { + "id": "78bf3a7b" + }, + "outputs": [], + "source": [ + "def print_verse():\n", + " first_two_lines()\n", + " last_three_lines()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba5da431", + "metadata": { + "id": "ba5da431" + }, + "outputs": [], + "source": [ + "print_verse()" + ] + }, + { + "cell_type": "markdown", + "id": "d088fe68", + "metadata": { + "id": "d088fe68" + }, + "source": [ + "When we run `print_verse`, it calls `first_two_lines`, which calls `repeat`, which calls `print`.\n", + "That's a lot of functions.\n", + "\n", + "Of course, we could have done the same thing with fewer functions, but the point of this example is to show how functions can work together." + ] + }, + { + "cell_type": "markdown", + "id": "c3b16e3f", + "metadata": { + "id": "c3b16e3f" + }, + "source": [ + "## Repetition\n", + "\n", + "If we want to display more than one verse, we can use a `for` statement.\n", + "Here's a simple example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29b7eff3", + "metadata": { + "id": "29b7eff3" + }, + "outputs": [], + "source": [ + "for i in range(2):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "bf320549", + "metadata": { + "id": "bf320549" + }, + "source": [ + "The first line is a header that ends with a colon.\n", + "The second line is the body, which has to be indented.\n", + "\n", + "The header starts with the keyword `for`, a new variable named `i`, and another keyword, `in`.\n", + "It uses the `range` function to create a sequence of two values, which are `0` and `1`.\n", + "In Python, when we start counting, we usually start from `0`.\n", + "\n", + "When the `for` statement runs, it assigns the first value from `range` to `i` and then runs the `print` function in the body, which displays `0`.\n", + "\n", + "When it gets to the end of the body, it loops back around to the header, which is why this statement is called a **loop**.\n", + "The second time through the loop, it assigns the next value from `range` to `i`, and displays it.\n", + "Then, because that's the last value from `range`, the loop ends.\n", + "\n", + "Here's how we can use a `for` loop to print two verses of the song." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "038ad592", + "metadata": { + "id": "038ad592" + }, + "outputs": [], + "source": [ + "for i in range(2):\n", + " print(\"Verse\", i)\n", + " print_verse()\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "id": "88a46733", + "metadata": { + "id": "88a46733" + }, + "source": [ + "You can put a `for` loop inside a function.\n", + "For example, `print_n_verses` takes a parameter named `n`, which has to be an integer, and displays the given number of verses." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8887637a", + "metadata": { + "id": "8887637a" + }, + "outputs": [], + "source": [ + "def print_n_verses(n):\n", + " for i in range(n):\n", + " print_verse()\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "id": "ad8060fe", + "metadata": { + "id": "ad8060fe" + }, + "source": [ + "In this example, we don't use `i` in the body of the loop, but there has to be a variable name in the header anyway." + ] + }, + { + "cell_type": "markdown", + "id": "b320ec90", + "metadata": { + "id": "b320ec90" + }, + "source": [ + "## Variables and parameters are local\n", + "\n", + "When you create a variable inside a function, it is **local**, which\n", + "means that it only exists inside the function.\n", + "For example, the following function takes two arguments, concatenates them, and prints the result twice." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0db8408e", + "metadata": { + "id": "0db8408e" + }, + "outputs": [], + "source": [ + "def cat_twice(part1, part2):\n", + " cat = part1 + part2\n", + " print_twice(cat)" + ] + }, + { + "cell_type": "markdown", + "id": "3a35a6d0", + "metadata": { + "id": "3a35a6d0" + }, + "source": [ + "Here's an example that uses it:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c556e48", + "metadata": { + "id": "1c556e48" + }, + "outputs": [], + "source": [ + "line1 = 'Always look on the '\n", + "line2 = 'bright side of life.'\n", + "cat_twice(line1, line2)" + ] + }, + { + "cell_type": "markdown", + "id": "4ab4e008", + "metadata": { + "id": "4ab4e008" + }, + "source": [ + "When `cat_twice` runs, it creates a local variable named `cat`, which is destroyed when the function ends.\n", + "If we try to display it, we get a `NameError`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73f03eea", + "metadata": { + "tags": [], + "id": "73f03eea" + }, + "outputs": [], + "source": [ + "%%expect NameError\n", + "\n", + "print(cat)" + ] + }, + { + "cell_type": "markdown", + "id": "3ae36c29", + "metadata": { + "id": "3ae36c29" + }, + "source": [ + "Outside of the function, `cat` is not defined.\n", + "\n", + "Parameters are also local.\n", + "For example, outside `cat_twice`, there is no such thing as `part1` or `part2`." + ] + }, + { + "cell_type": "markdown", + "id": "eabac8a6", + "metadata": { + "id": "eabac8a6" + }, + "source": [ + "## Stack diagrams\n", + "\n", + "To keep track of which variables can be used where, it is sometimes useful to draw a **stack diagram**.\n", + "Like state diagrams, stack diagrams show the value of each variable, but they also show the function each variable belongs to.\n", + "\n", + "Each function is represented by a **frame**.\n", + "A frame is a box with the name of a function on the outside and the parameters and local variables of the function on the inside.\n", + "\n", + "Here's the stack diagram for the previous example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "83df4e32", + "metadata": { + "tags": [], + "id": "83df4e32" + }, + "outputs": [], + "source": [ + "from diagram import make_frame, Stack\n", + "\n", + "d1 = dict(line1=line1, line2=line2)\n", + "frame1 = make_frame(d1, name='__main__', dy=-0.3, loc='left')\n", + "\n", + "d2 = dict(part1=line1, part2=line2, cat=line1+line2)\n", + "frame2 = make_frame(d2, name='cat_twice', dy=-0.3,\n", + " offsetx=0.03, loc='left')\n", + "\n", + "d3 = dict(string=line1+line2)\n", + "frame3 = make_frame(d3, name='print_twice',\n", + " offsetx=0.04, offsety=-0.3, loc='left')\n", + "\n", + "d4 = {\"?\": line1+line2}\n", + "frame4 = make_frame(d4, name='print',\n", + " offsetx=-0.22, offsety=0, loc='left')\n", + "\n", + "stack = Stack([frame1, frame2, frame3, frame4], dy=-0.8)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bcd5e1df", + "metadata": { + "tags": [], + "id": "bcd5e1df" + }, + "outputs": [], + "source": [ + "from diagram import diagram, adjust\n", + "\n", + "\n", + "width, height, x, y = [3.77, 2.9, 1.1, 2.65]\n", + "ax = diagram(width, height)\n", + "bbox = stack.draw(ax, x, y)\n", + "# adjust(x, y, bbox)\n", + "\n", + "import matplotlib.pyplot as plt\n", + "plt.savefig('chap03_stack_diagram.png', dpi=300)" + ] + }, + { + "cell_type": "markdown", + "id": "854fee12", + "metadata": { + "id": "854fee12" + }, + "source": [ + "The frames are arranged in a stack that indicates which function called\n", + "which, and so on. Reading from the bottom, `print` was called by `print_twice`, which was called by `cat_twice`, which was called by `__main__` -- which is a special name for the topmost frame.\n", + "When you create a variable outside of any function, it belongs to `__main__`.\n", + "\n", + "In the frame for `print`, the question mark indicates that we don't know the name of the parameter.\n", + "If you are curious, ask a virtual assistant, \"What are the parameters of the Python print function?\"" + ] + }, + { + "cell_type": "markdown", + "id": "5690cfc0", + "metadata": { + "id": "5690cfc0" + }, + "source": [ + "## Tracebacks\n", + "\n", + "When a runtime error occurs in a function, Python displays the name of the function that was running, the name of the function that called it, and so on, up the stack.\n", + "To see an example, I'll define a version of `print_twice` that contains an error -- it tries to print `cat`, which is a local variable in another function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "886519cf", + "metadata": { + "id": "886519cf" + }, + "outputs": [], + "source": [ + "def print_twice(string):\n", + " print(cat) # NameError\n", + " print(cat)" + ] + }, + { + "cell_type": "markdown", + "id": "d7c0713b", + "metadata": { + "id": "d7c0713b" + }, + "source": [ + "Now here's what happens when we run `cat_twice`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1fe8ee82", + "metadata": { + "tags": [], + "id": "1fe8ee82" + }, + "outputs": [], + "source": [ + "# This cell tells Jupyter to provide detailed debugging information\n", + "# when a runtime error occurs, including a traceback.\n", + "\n", + "%xmode Verbose" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9082f88", + "metadata": { + "tags": [], + "id": "d9082f88" + }, + "outputs": [], + "source": [ + "%%expect NameError\n", + "\n", + "cat_twice(line1, line2)" + ] + }, + { + "cell_type": "markdown", + "id": "2f4defcf", + "metadata": { + "id": "2f4defcf" + }, + "source": [ + "The error message includes a **traceback**, which shows the function that was running when the error occurred, the function that called it, and so on.\n", + "In this example, it shows that `cat_twice` called `print_twice`, and the error occurred in a `print_twice`.\n", + "\n", + "The order of the functions in the traceback is the same as the order of the frames in the stack diagram.\n", + "The function that was running is at the bottom." + ] + }, + { + "cell_type": "markdown", + "id": "374b4696", + "metadata": { + "id": "374b4696" + }, + "source": [ + "## Why functions?\n", + "\n", + "It may not be clear yet why it is worth the trouble to divide a program into\n", + "functions.\n", + "There are several reasons:\n", + "\n", + "- Creating a new function gives you an opportunity to name a group of\n", + " statements, which makes your program easier to read and debug.\n", + "\n", + "- Functions can make a program smaller by eliminating repetitive code.\n", + " Later, if you make a change, you only have to make it in one place.\n", + "\n", + "- Dividing a long program into functions allows you to debug the parts\n", + " one at a time and then assemble them into a working whole.\n", + "\n", + "- Well-designed functions are often useful for many programs. Once you\n", + " write and debug one, you can reuse it." + ] + }, + { + "cell_type": "markdown", + "id": "c6dd486e", + "metadata": { + "id": "c6dd486e" + }, + "source": [ + "## Debugging\n", + "\n", + "Debugging can be frustrating, but it is also challenging, interesting, and sometimes even fun.\n", + "And it is one of the most important skills you can learn.\n", + "\n", + "In some ways debugging is like detective work.\n", + "You are given clues and you have to infer the events that led to the\n", + "results you see.\n", + "\n", + "Debugging is also like experimental science.\n", + "Once you have an idea about what is going wrong, you modify your program and try again.\n", + "If your hypothesis was correct, you can predict the result of the modification, and you take a step closer to a working program.\n", + "If your hypothesis was wrong, you have to come up with a new one.\n", + "\n", + "For some people, programming and debugging are the same thing; that is, programming is the process of gradually debugging a program until it does what you want.\n", + "The idea is that you should start with a working program and make small modifications, debugging them as you go.\n", + "\n", + "If you find yourself spending a lot of time debugging, that is often a sign that you are writing too much code before you start tests.\n", + "If you take smaller steps, you might find that you can move faster." + ] + }, + { + "cell_type": "markdown", + "id": "d4e95e63", + "metadata": { + "id": "d4e95e63" + }, + "source": [ + "## Glossary\n", + "\n", + "**function definition:**\n", + "A statement that creates a function.\n", + "\n", + "**header:**\n", + " The first line of a function definition.\n", + "\n", + "**body:**\n", + " The sequence of statements inside a function definition.\n", + "\n", + "**function object:**\n", + "A value created by a function definition.\n", + "The name of the function is a variable that refers to a function object.\n", + "\n", + "**parameter:**\n", + " A name used inside a function to refer to the value passed as an argument.\n", + "\n", + "**loop:**\n", + " A statement that runs one or more statements, often repeatedly.\n", + "\n", + "**local variable:**\n", + "A variable defined inside a function, and which can only be accessed inside the function.\n", + "\n", + "**stack diagram:**\n", + "A graphical representation of a stack of functions, their variables, and the values they refer to.\n", + "\n", + "**frame:**\n", + " A box in a stack diagram that represents a function call.\n", + " It contains the local variables and parameters of the function.\n", + "\n", + "**traceback:**\n", + " A list of the functions that are executing, printed when an exception occurs." + ] + }, + { + "cell_type": "markdown", + "id": "eca485f2", + "metadata": { + "id": "eca485f2" + }, + "source": [ + "## Exercises" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f77b428", + "metadata": { + "tags": [], + "id": "3f77b428" + }, + "outputs": [], + "source": [ + "# This cell tells Jupyter to provide detailed debugging information\n", + "# when a runtime error occurs. Run it before working on the exercises.\n", + "\n", + "%xmode Verbose" + ] + }, + { + "cell_type": "markdown", + "id": "82951027", + "metadata": { + "id": "82951027" + }, + "source": [ + "### Ask a virtual assistant\n", + "\n", + "The statements in a function or a `for` loop are indented by four spaces, by convention.\n", + "But not everyone agrees with that convention.\n", + "If you are curious about the history of this great debate, ask a virtual assistant to \"tell me about spaces and tabs in Python\".\n", + "\n", + "Virtual assistant are pretty good at writing small functions.\n", + "\n", + "1. Ask your favorite VA to \"Write a function called repeat that takes a string and an integer and prints the string the given number of times.\"\n", + "\n", + "2. If the result uses a `for` loop, you could ask, \"Can you do it without a for loop?\"\n", + "\n", + "3. Pick any other function in this chapter and ask a VA to write it. The challenge is to describe the function precisely enough to get what you want. Use the vocabulary you have learned so far in this book.\n", + "\n", + "Virtual assistants are also pretty good at debugging functions.\n", + "\n", + "1. Ask a VA what's wrong with this version of `print_twice`.\n", + "\n", + " ```\n", + " def print_twice(string):\n", + " print(cat)\n", + " print(cat)\n", + " ```\n", + " \n", + "And if you get stuck on any of the exercises below, consider asking a VA for help." + ] + }, + { + "cell_type": "markdown", + "id": "b7157b09", + "metadata": { + "id": "b7157b09" + }, + "source": [ + "### Exercise\n", + "\n", + "Write a function named `print_right` that takes a string named `text` as a parameter and prints the string with enough leading spaces that the last letter of the string is in the 40th column of the display." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6004271", + "metadata": { + "id": "a6004271" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "markdown", + "id": "428fbee5", + "metadata": { + "id": "428fbee5" + }, + "source": [ + "Hint: Use the `len` function, the string concatenation operator (`+`) and the string repetition operator (`*`).\n", + "\n", + "Here's an example that shows how it should work." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f142ce6a", + "metadata": { + "tags": [], + "id": "f142ce6a" + }, + "outputs": [], + "source": [ + "print_right(\"Monty\")\n", + "print_right(\"Python's\")\n", + "print_right(\"Flying Circus\")" + ] + }, + { + "cell_type": "markdown", + "id": "b47467fa", + "metadata": { + "id": "b47467fa" + }, + "source": [ + "### Exercise\n", + "\n", + "Write a function called `triangle` that takes a string and an integer and draws a pyramid with the given height, made up using copies of the string. Here's an example of a pyramid with `5` levels, using the string `'L'`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7aa95014", + "metadata": { + "id": "7aa95014" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8146a0d", + "metadata": { + "scrolled": true, + "tags": [], + "id": "b8146a0d" + }, + "outputs": [], + "source": [ + "triangle('L', 5)" + ] + }, + { + "cell_type": "markdown", + "id": "4a28f635", + "metadata": { + "id": "4a28f635" + }, + "source": [ + "### Exercise\n", + "\n", + "Write a function called `rectangle` that takes a string and two integers and draws a rectangle with the given width and height, made up using copies of the string. Here's an example of a rectangle with width `5` and height `4`, made up of the string `'H'`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bcedab79", + "metadata": { + "id": "bcedab79" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73b0c0f6", + "metadata": { + "scrolled": true, + "tags": [], + "id": "73b0c0f6" + }, + "outputs": [], + "source": [ + "rectangle('H', 5, 4)" + ] + }, + { + "cell_type": "markdown", + "id": "44a5de6f", + "metadata": { + "id": "44a5de6f" + }, + "source": [ + "### Exercise\n", + "\n", + "The song \"99 Bottles of Beer\" starts with this verse:\n", + "\n", + "> 99 bottles of beer on the wall \n", + "> 99 bottles of beer \n", + "> Take one down, pass it around \n", + "> 98 bottles of beer on the wall \n", + "\n", + "Then the second verse is the same, except that it starts with 98 bottles and ends with 97. The song continues -- for a very long time -- until there are 0 bottles of beer.\n", + "\n", + "Write a function called `bottle_verse` that takes a number as a parameter and displays the verse that starts with the given number of bottles.\n", + "\n", + "Hint: Consider starting with a function that can print the first, second, or last line of the verse, and then use it to write `bottle_verse`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53424b43", + "metadata": { + "id": "53424b43" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "61010ffb", + "metadata": { + "id": "61010ffb" + }, + "outputs": [], + "source": [ + "# Solution goes here" + ] + }, + { + "cell_type": "markdown", + "id": "ee0076dd", + "metadata": { + "tags": [], + "id": "ee0076dd" + }, + "source": [ + "Use this function call to display the first verse." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47a91c7d", + "metadata": { + "tags": [], + "id": "47a91c7d" + }, + "outputs": [], + "source": [ + "bottle_verse(99)" + ] + }, + { + "cell_type": "markdown", + "id": "42c237c6", + "metadata": { + "tags": [], + "id": "42c237c6" + }, + "source": [ + "If you want to print the whole song, you can use this `for` loop, which counts down from `99` to `1`.\n", + "You don't have to completely understand this example---we'll learn more about `for` loops and the `range` function later." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "336cdfa2", + "metadata": { + "tags": [], + "id": "336cdfa2" + }, + "outputs": [], + "source": [ + "for n in range(99, 0, -1):\n", + " bottle_verse(n)\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b02510c", + "metadata": { + "id": "4b02510c" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "a7f4edf8", + "metadata": { + "tags": [], + "id": "a7f4edf8" + }, + "source": [ + "[Think Python: 3rd Edition](https://allendowney.github.io/ThinkPython/index.html)\n", + "\n", + "Copyright 2024 [Allen B. Downey](https://allendowney.com)\n", + "\n", + "Code license: [MIT License](https://mit-license.org/)\n", + "\n", + "Text license: [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file