{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a8b68fec",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# MPCS 51042: Python Programming\n",
    "# Week 1: Course Overview / Python Basics\n",
    "\n",
    "## Today\n",
    "- Course Overview\n",
    "- What is Python?\n",
    "- Running Python\n",
    "- Basic Syntax & Data Types\n",
    "- Functions\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b4be250",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Course Overview\n",
    "\n",
    "Course Website: https://mpcs51042.netlify.app/\n",
    "\n",
    "[UChicago CS Student Resource Guide](https://uchicago-cs.github.io/student-resource-guide/)\n",
    "\n",
    "\n",
    "**Unix Bootcamp**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7586bb22",
   "metadata": {},
   "source": [
    "## Goals of this Course\n",
    "\n",
    "- Learn to write **readable** & **idiomatic**, Python .\n",
    "- Gain exposure to different programming **paradigms**: procedural, functional, object-oriented.\n",
    "- Enable future growth as Python programmer via deep fundamentals & gateway to Python ecosystem."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23ec581f",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Introduction to Python\n",
    "\n",
    "### What kind of language is Python?\n",
    "\n",
    "In a typical Python introduction you'll see it described as an **intepreted & dynamically typed** language.\n",
    "\n",
    "You'll also sometimes hear languages defined in terms of being **object-oriented, functional, or procedural**. Python, like many of its modern peers, is somewhat agnostic on this front. This course will take advantage of that fact to introduce you to these three styles of programming.\n",
    "\n",
    "Python is also written with a focus on **readability**. You'll see people talk about code being **Pythonic**. These ideas shape the culture of Python."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "388c0b92",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "These things together make Python what it is: a language that is both good for beginners but powerful and expressive enough to e used across nearly all fields.\n",
    "\n",
    "- Science: CERN, NASA, etc.\n",
    "- Big Tech: Google, YouTube, Mozilla, Instagram\n",
    "- Journalism/Government: New York Times, Washington Post, USDS (FEC, CFPB, etc.)\n",
    "- Film & Games: Firaxis Games, Industrial Light & Magic, Blender\n",
    "\n",
    "Learning Python in 2024 will open up a world of possibilities to you:\n",
    "\n",
    "- the most-used libraries for data science & visualization (polars, pandas, altair, matplotlib)\n",
    "- several of the most popular backend web frameworks in use today (Django, Flask, FastAPI)\n",
    "- thousands of unique libraries for any imaginable purpose: astronomical calculation, encryption, image processing, game programming, machine learning\n",
    "\n",
    "By the end of this course, you will be able to dive into those libraries; understanding their documentation and how to use them to enhance your own programs"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfceee96",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Python Versions\n",
    "\n",
    "#### **1994** - Python 1.0\n",
    "\n",
    "First major public release. Guido was working on the Computer Programming 4 Everyone (CP4E) initiative at Corporation for National Research Initiatives in Reston, VA.\n",
    "\n",
    "#### **2000**  - Python 2.0\n",
    "\n",
    "The switch to being truly community-driven and the language started down its functional path. Many of the functional elements of Python were introduced around this time.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e163c293",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "#### **2008** - Python 3.0\n",
    "\n",
    "The first release containing major breaking changes since Python 2.0. Focused on fixing some long-standing pain points in the language, at the cost of people needing to update their code.\n",
    "\n",
    "Most people in the community hope that there will be no Python 4.0 in that sense, no time that all of the code written needs to be migrated.  (This is particularly important because there is so much more Python code being written in all industries today.)\n",
    "\n",
    "#### Python 3.10, 3.11, 3.12, etc.\n",
    "\n",
    "A new minor Python release comes out every October and is supported for ~5 years.\n",
    "\n",
    "New releases add features:\n",
    "\n",
    "- 3.9, 3.10, 3.11 had a focus on type-checking and improved concurrency\n",
    "- 3.12 and 3.13 have introduced *major performance enhancements*, also improved error messages (which may be useful to beginners)\n",
    "\n",
    "Each version adds a lot more than this, see <https://docs.python.org/3.13/whatsnew/3.13.html> for an example.\n",
    "\n",
    "This course will use **Python 3.10** as our minimum version.  3.11-3.13 have not introduced new features that are important for this course."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91c6dd03",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Depending on what they measure, Python is either the 1st or 2nd most used language today in most surveys.  (JavaScript would be the other.)"
   ]
  },
  {
   "attachments": {
    "551cc367-52cd-49a7-bedd-4612ee77c664.png": {
     "image/png": "[encoded data, 269344 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "ba61408f",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "![Screenshot 2024-09-29 at 4.29.51 PM.png](attachment:551cc367-52cd-49a7-bedd-4612ee77c664.png)\n",
    "\n",
    "**Note: Logarithmic scale**\n",
    "\n",
    "Source: PopularitY of Programming Language Index, https://pypl.github.io/PYPL.html"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf43cf02-131f-4db3-899c-b728286f32d7",
   "metadata": {},
   "source": [
    "### Python Community\n",
    "\n",
    "As an open source project mostly managed and led by volunteers, Python has a **community** with a **culture**.\n",
    "\n",
    "Some of the key values of Python's culture:\n",
    "\n",
    "- Python's community started as beginner-friendly and has strived to keep that tone. The community takes being **welcoming and inclusive** seriously.\n",
    "- The community embraces **openness**, proposals to improve the language come from all over, and there's a focus on encouraging users to contribute back to the project.\n",
    "- Python is a language that values **readability**, code is written for people as much as it is for computers to understand, Python takes this extremely seriously."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "829a1a1c",
   "metadata": {
    "scrolled": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "import this"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "665e3ed6",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Running Python\n",
    "\n",
    "Python is an **interpreted** language. If you've used a language like Java or C you're used to having to compile your code. Python is instead typically translated to an intermediate representation (bytecode) and immediately executed.\n",
    "\n",
    "`python` usually points to `python2.7` for historical reasons.\n",
    "\n",
    "`python3` will point to the latest version of Python installed\n",
    "\n",
    "`python3 -V` to see version   *# Python 3.10.12 on linux.cs.uchicago.edu*\n",
    "\n",
    "\n",
    "### REPL & Python Files Demo\n",
    "\n",
    "REPL: Read-Eval-Print Loop\n",
    "\n",
    "`python3`                # opens REPL\n",
    "\n",
    "`python3 filename.py`    # runs script and exits"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7f7ed2f",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### IPython Demo\n",
    "\n",
    "`ipython` - improved REPL\n",
    "\n",
    "### Jupyter Notebook\n",
    "\n",
    "What I'm presenting in.  Works a bit differently than REPL since you can execute different cells in any order.  I'd advise starting with `ipython`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8625b025",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(\n",
    "    \"Hi\", 2 * 3 * 47 * 181, \"!\"\n",
    ")  # the advantage is that I can mix code in with my notes"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19f894d2-21af-4801-a8f0-1efba34afa5b",
   "metadata": {},
   "source": [
    "### Exercise: Create a `python-demos` repository.\n",
    "\n",
    "As you'll see in the first assignment, we are going to use a tool called `uv`.\n",
    "\n",
    "I would suggest starting with `ipython` as your REPL, and creating a directory where you can easily try things out.\n",
    "\n",
    "- Connect to the mpcs51042-N.cs.uchicago.edu server\n",
    "- `mkdir python-demos`\n",
    "- `cd python-demos`\n",
    "- `uv init`\n",
    "- `uv add ipython`\n",
    "- `uv run ipython` (`exit()` to quit)\n",
    "\n",
    "Now you can create small `.py` files inside that directory to experiment with, and you can use `uv run ipython` or `uv run ipython your-file.py` to try things out."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cef4f2f6",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Expressions & Variables\n",
    "\n",
    "Python programs are made up of a series of **expressions** and **statements.**.\n",
    "\n",
    "Though you will never see these words explicitly in Python syntax, understanding the difference between them is important.\n",
    "\n",
    "An expression is a sequence of tokens that evaluates to some *value*.\n",
    "\n",
    "**Some Expressions**\n",
    "\n",
    "- `3.145`\n",
    "- `\"hello\"`\n",
    "- `3 + 4`\n",
    "- `func(3 + 4)`\n",
    "- `person.age * 4`\n",
    "\n",
    "All of these can be said to represent some value, some directly and some require further evaluation (addition, or a function call) to be resolved, but ultimately result in a value.\n",
    "\n",
    "This means that **all expressions can be assigned to variables**.  In fact, in Python, all that we need to create a variable is an expression and a name.\n",
    "\n",
    "**Variables:**\n",
    "\n",
    "- must have an **expression** on the right hand side.\n",
    "- Do not require declaration.\n",
    "- Written in `snake_case`, with words separated by underscores. (as opposed to `camelCase`)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "518585f8",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "radius = 2\n",
    "area = 12.57\n",
    "name = \"James\"\n",
    "in_class = True"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "360f2bcc",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Types\n",
    "\n",
    "We don't need to specify types the way we do in languages like C++ or Java.\n",
    "\n",
    "But our variables still do have types, they are just inferred."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21a26675",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(type(radius))\n",
    "print(type(area))\n",
    "print(type(name))\n",
    "print(type(in_class))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "378750d1",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Scalar Types\n",
    "\n",
    "Python has several built in scalar types.  (Scalar types can have *one* value at a time.)\n",
    "\n",
    "Numeric: `int`, `float`, `complex`\n",
    "\n",
    "Bool: `bool`\n",
    "\n",
    "None: `None`\n",
    "\n",
    "Types are in part defined by what can be done with them, let's look at some **operators**:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84c1be08",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Numeric Operators & Functions\n",
    "\n",
    "| Operation | Result |\n",
    "|-----------|--------|\n",
    "| `x + y`   | sum    |\n",
    "| `x - y`   | difference |\n",
    "| `x * y`   | product |\n",
    "| `x / y`   | quotient |\n",
    "| `x // y`  | floored quotient |\n",
    "| `x % y`   | remainder of `x / y` (modulo) |\n",
    "| `x ** y`  | `x` to the power of `y`\n",
    "| `-x`      | negation of `x` |\n",
    "| `abs(x)`  | absolute value / magnitude of `x` |\n",
    "| `int(x)`  | `x` converted to integer (floor) |\n",
    "| `divmod(x, y)` | the pair `(x // y, x % y)` |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f90c1a9a-0ed9-461d-a297-9316dc1c23eb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4eacde7e-b220-4824-b989-19e6446b3d59",
   "metadata": {},
   "outputs": [],
   "source": [
    "3 / 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6e57206-9c4d-49d8-87b7-76ffb293581d",
   "metadata": {},
   "outputs": [],
   "source": [
    "3 % 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da630935-8a59-4d97-b4d0-c22be20227e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "divmod(3, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f8f0a556",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# examples\n",
    "\n",
    "x = 2.999\n",
    "print(int(2.999))\n",
    "\n",
    "print(1 + 2)\n",
    "\n",
    "print(100 // 2)\n",
    "\n",
    "m = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2\n",
    "n = 3628800  # 10!\n",
    "print(n % 11)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea02cc07-cd7e-471a-8875-9e897142c718",
   "metadata": {},
   "source": [
    "#### Aside: Floating Point Precision\n",
    "\n",
    "On all computers floating point numbers have limited precision, as demonstrated below.\n",
    "\n",
    "For this reason, instead of strict equality checking, it is correct to compare that the error is less than some very small epsilon value.\n",
    "\n",
    "**Question** What problems could this cause?  What can be done about it?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2c29f15d-4979-4387-b9a4-71875228ccfc",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "(0.1 + 0.2) == 0.3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52efb0d2-5e52-4a8b-a9b2-67fde816c917",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "0.1 + 0.2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "30470527",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "print(0.1 + 0.2 == 0.3)\n",
    "\n",
    "episilon = 0.000000001\n",
    "abs((0.1 + 0.2) - 0.3) < episilon\n",
    "\n",
    "bank_account_hundredths_of_cent = 1000000000"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a37ab302",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Shorthand Operators\n",
    "\n",
    "| Operation | Result | \n",
    "|-----------|--------|\n",
    "|  `a += b `  | `a = a + b` |\n",
    "|  `a -= b `  | `a = a - b` |\n",
    "|  `a /= b ` | `a = a / b` |\n",
    "|  `a *= b `  | `a = a * b` |\n",
    "|  `a //= b`  | `a = a // b` |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5c6638c4",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# examples\n",
    "\n",
    "x = 64\n",
    "x *= 2\n",
    "print(x)\n",
    "\n",
    "\n",
    "s = \"Hello\"\n",
    "s += \" Class\"\n",
    "s /= \"l\"\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa991f93",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Conversion\n",
    "\n",
    "If mixing numeric types in arithmetic, Python will automatically upconvert numeric types to the type that can represent more data:\n",
    "\n",
    "- int, int -> int\n",
    "- int, float -> float\n",
    "- float, complex -> complex\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "daaf3577-10a8-4cfb-b536-6f27e6ad0496",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Conversion Demo\n",
    "\n",
    "y = 4.1\n",
    "x = int(3 + y)\n",
    "\n",
    "print(x, type(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5332fa6-a989-4958-8a50-5cfc5c6cbb88",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "x = 2 // 1\n",
    "print(x, type(x))\n",
    "\n",
    "x = 2 / 1\n",
    "print(x, type(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "849ede7d",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Relational Operators\n",
    "\n",
    "| Syntax     | Definition                                                      |\n",
    "| ---        | ---                                                             |\n",
    "| ``x > y``  | ``True`` if left operand is greater than the right              |\n",
    "| ``x < y``  | ``True`` if left operand is less than the right                 |\n",
    "| ``x == y`` | ``True`` if both operands are equal                             |\n",
    "| ``x != y`` | ``True`` if both operands are not equal                         |\n",
    "| ``x >= y`` | ``True`` if left operand is greater than or equal to the right  |\n",
    "| ``x <= y`` | ``True`` if left operand is less than or equal to the right     |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c22cb6d9-ea09-4561-8491-112cd2362ce0",
   "metadata": {},
   "outputs": [],
   "source": [
    "True, False"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c9ca38f",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Booleans\n",
    "\n",
    "Resulting type of any of the relational operators.\n",
    "\n",
    "Only two possible values: `True`, `False`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa7c9769",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Logical Operators\n",
    "\n",
    "  - Operators that perform logical AND, OR, and NOT \n",
    "  - These operators *short-circuit* (i.e., when an expression is stopped being evaluated as soon as its outcome is determined.) \n",
    "\n",
    "| Syntax      | Definition                                         |\n",
    "| ---         | ---                                                |\n",
    "| ``x and y`` | ``True`` if both the operands are true             |\n",
    "| ``x or y``  | ``True`` if either of the operands is true         |\n",
    "| ``not x``   | ``True`` True if operand is false                  |\n",
    "\n",
    "\n",
    "**Note: these are not `&` or `|` like in Java/C!** \n",
    "Those have a different purpose in Python and will not work as intended."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "403c3e5d",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# short circuit example\n",
    "\n",
    "a = True and print(\"a\")\n",
    "b = False and print(\"b\")\n",
    "c = False or print(\"c\")\n",
    "d = True or print(\"d\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f19f8d55-a9a5-4c1e-be17-d71ff8bd263e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# this cell is not part of notes, needed for next example\n",
    "# we'll discuss how to write functions/etc. soon\n",
    "import time\n",
    "\n",
    "\n",
    "def short_func():\n",
    "    print(\"short_func\")\n",
    "    return False\n",
    "\n",
    "\n",
    "def long_func():\n",
    "    print(\"long_func\")\n",
    "    time.sleep(3)\n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11e69d98-813d-43ae-b4c1-55050213577a",
   "metadata": {},
   "outputs": [],
   "source": [
    "result = long_func() and short_func()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b89c375-ebb4-4164-88ad-8cbe2948d4ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "result = short_func() and long_func()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6cf6cd5",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### None\n",
    "\n",
    "Represents the absence of a value.  We'll talk more about uses of `None` as the course progresses."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb24dfd3",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "x = None\n",
    "print(x)\n",
    "print(type(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84deb07c",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Sequence Types\n",
    "\n",
    "Whereas scalar types have a single value, sequences can store multiple values in an organized & efficient way.\n",
    "\n",
    "We'll take a look at `str`, `list`, and `tuple`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16fb91a6",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Strings\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81978ba8",
   "metadata": {
    "scrolled": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Can use 'single' or \"double\", or \"\"\"triple for multi-line strings\"\"\"\n",
    "\n",
    "s1 = \"Molly's Idea\"\n",
    "\n",
    "s2 = '\"I think, therefore I am\" - Descartes'\n",
    "\n",
    "s3 = \"\"\"From time to time\n",
    "The clouds give rest\n",
    "To the moon-beholders.\n",
    "\n",
    "- Matsuo Bashō\n",
    "\"\"\"\n",
    "\n",
    "print(s3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "970918ff",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Escape Characters\n",
    "\n",
    "# Like many languages, Python supports special 'escape characters'.\n",
    "\n",
    "# print(\"Another way to \\\"quote\\\" something.\")\n",
    "\n",
    "# print('An alternate apostrophe: \\' ')\n",
    "\n",
    "print(\"Newline character: \\n starts a new line.\")\n",
    "\n",
    "print(\"Sometimes you need a \\\\ backslash. \\\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9c05896",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "| Character | Meaning |\n",
    "|-----------|---------|\n",
    "|  \\n       | New Line|\n",
    "|  \\t       | Tab     |\n",
    "|  \\\\\\\\\\\\\\       | \\ (backslash) |\n",
    "|  \\\\\\'       | ' (apostrophe) |\n",
    "|  \\\\\\\"       | \" (quote) |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98cf6515",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Raw Strings\n",
    "\n",
    "# Sometimes it is undesirable to escape every backslash.\n",
    "\n",
    "# Two common examples are when dealing with file paths on Windows or Regular Expressions.\n",
    "\n",
    "# In this case we can use r\"\" to denote a raw string.\n",
    "\n",
    "error = \"C:\\\\new\\\\test.py\"\n",
    "print(error)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d487e5c",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "fixed = r\"C:\\new\\test.py\"\n",
    "print(fixed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "afebe22c-6308-47c4-b919-18a112e86904",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "type(fixed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23359927",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### String Formatting\n",
    "\n",
    "You'll often need to create strings comprised of other values.\n",
    "\n",
    "There are two common ways to do this, `.format` and f-strings:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50640ab5",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# format example 1: implicit\n",
    "\n",
    "fmt = \"{}@{}.{}\"\n",
    "email = fmt.format(\"jturk\", \"uchicago\", \"edu\")\n",
    "print(email)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d806059f",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# format example 2: positional\n",
    "\n",
    "template = \"Hi {0}, you are user {1}! \\n Bye {0}!\"\n",
    "message = template.format(\"James\", 2.5)\n",
    "print(message)\n",
    "\n",
    "# note that integer was converted automatically\n",
    "# most useful if you want to use the same value multiple times"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc04cf6c",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "# format example 3: keyword\n",
    "\n",
    "message = \"Hi {user}, you are user {num}! \\n Bye {user}!\".format(user=\"Sam\", num=1390)\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "864319ee",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# f-strings example (Added in Python 3.6)\n",
    "\n",
    "user = \"James\"\n",
    "num = 1234\n",
    "message = f\"Hi {user}, you are user {num}! \\n Bye {user}!\"\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "37a71346",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# f-strings debug example (Added in Python 3.8)\n",
    "user = \"James\"\n",
    "num = 1234\n",
    "\n",
    "print(\"user is \", user)\n",
    "\n",
    "print(f\"{user=} {num=}\")\n",
    "# same as f\"user={user} num={num}\" but less repetition\n",
    "\n",
    "# = is a format specifier, there are many others for aligning output, truncating decimals, etc.\n",
    "\n",
    "for i in range(10):\n",
    "    print(f\"{i=}\")\n",
    "    if i == 4:\n",
    "        i / 0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42f1b056",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Lists\n",
    "\n",
    "One of the most useful sequence is `list`.  Lists are:\n",
    "\n",
    "- A great data structure if you need to hold a collection of positionally-ordered and arbitrarily-typed values.\n",
    "\n",
    "- Mutable (i.e., they can be modified in-place)\n",
    "    \n",
    "- Dynamically Sized (i.e. shortened & extended as needed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a78b262e",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "# List Demo\n",
    "\n",
    "things = []\n",
    "\n",
    "# lists can contain items of different types\n",
    "\n",
    "things = [123, \"abc\", 1.23j + 4.5]\n",
    "\n",
    "# lists can contain other lists\n",
    "\n",
    "meals = [[\"egg\", \"toast\"], [\"sandwich\", \"chips\"], [\"fish\", \"salad\", \"cake\"]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49656dd9-7097-4ab9-9b31-76efb00975d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(things)\n",
    "print(meals)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a65282f6",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Tuples\n",
    "\n",
    "Tuples work very similarly to lists but are immutable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3b01815",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Tuple Demo\n",
    "\n",
    "empty_tuple = ()\n",
    "\n",
    "one_item_tuple = (1 + 2,)  # why is the comma necessary?\n",
    "\n",
    "bad_tuple = (1 + 492)\n",
    "\n",
    "print(bad_tuple)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f6c54b13",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "multi_item = (1, 2.0, \"three\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "310a20b3-ef99-43cf-a9eb-60674beb8967",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(multi_item)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bdf6553",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Sequence Operations\n",
    "\n",
    "All of these sequence types support some useful operations:\n",
    "\n",
    "|operation | name | description |\n",
    "|------|-----|-----|\n",
    "| `len(seq)` |  Length |  gets number of items in sequence.\n",
    "| `seq1 + seq2` |  Concatenation |  to concatenate together (make a new sequence).\n",
    "| `seq * N` |  Repetition |  creates a new sequence that repeats seq, N times.\n",
    "| `item in seq` |  Containment |  tests for whether or not a given value appears in a sequence.\n",
    "| `seq[N]` |  Indexing | gets Nth value from sequence.\n",
    "| `seq[N:M]` | Sliced Indexing | returns a new sequence that is a \"slice\" of the original."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e0eae96",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# length demo\n",
    "s1 = \"Hello World\"\n",
    "l1 = [1, [\"a\", \"b\", \"c\"], 3, None, 4]\n",
    "t1 = ()\n",
    "\n",
    "print(len(s1))\n",
    "print(len(l1))\n",
    "print(len(t1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55a8e5ba",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# concatenation & repetition demo\n",
    "s2 = \"*\" * 5\n",
    "t2 = (True, False) * 3\n",
    "l2 = [\"a\", \"b\", \"c\"] * 4\n",
    "print(s2)\n",
    "print(t2)\n",
    "print(l2)\n",
    "\n",
    "\n",
    "\n",
    "# x = (\"a\", \"b\", \"c\")\n",
    "# y = (\"z\", \"z\", \"z\")\n",
    "# z = x + y\n",
    "# z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1727cd1e-fe51-4e29-8d57-9ab7c70f5b50",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# concatenation & repetition demo\n",
    "s2 = \"*\" * 5\n",
    "t2 = (True, False) * 3\n",
    "l2 = [\"a\", \"b\", \"c\"] * 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3a1e0f6-d4aa-4610-aee0-482747edc493",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(s2, \"\\n\", t2, \"\\n\", l2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2218bc31",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "cities = [\n",
    "    \"Tokyo\",\n",
    "    \"Delhi\",\n",
    "    \"Shanghai\",\n",
    "    \"São Paulo\",\n",
    "    \"Mexico City\",\n",
    "    \"Cairo\",\n",
    "    \"Mumbai\",\n",
    "    \"Beijing\",\n",
    "    \"Dhaka\",\n",
    "    \"Osaka\",\n",
    "]\n",
    "text = \"Four score and seven years ago our fathers brought forth, upon this continent, a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal\"\n",
    "ids = (123, 555, 81, 110, 44, 12, 16)\n",
    "ids[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c90c4d5",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# containment\n",
    "\n",
    "print(\"Shanghai\" in cities)\n",
    "print(\"Delhi\" in cities)\n",
    "print(\" seven \" in text)\n",
    "print(\"7\" in text)\n",
    "print(123 in ids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1c358fe-a341-4930-8e4c-5559d13901b3",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "# indexing\n",
    "print(cities)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42d592fd-4563-4133-aa30-6aa531d3525f",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "#print(cities[0])\n",
    "#print(cities[-4])\n",
    "\n",
    "# print(text[0])\n",
    "\n",
    "print(cities[2:-4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "46401f82-8a3e-4d28-b54f-725b76f7ddf8",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"hello world\"[2:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a96b78d",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# slicing\n",
    "# print(cities)\n",
    "print(cities[8:])\n",
    "# print(cities[:4])\n",
    "# print(cities[8:])\n",
    "# print(cities[4:-3])\n",
    "\n",
    "# print(text)\n",
    "# print(text[0:4])\n",
    "# print(text[:])\n",
    "\n",
    "# print(ids[1:4])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3917fd33",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### Indexing / Slicing Rules\n",
    "\n",
    "`s = \"Hello!\"`\n",
    "\n",
    "| Letter | Index | -Index |\n",
    "|--------|-------|--------|\n",
    "|    H   |   0   |   -6   |\n",
    "|    e   |   1   |   -5   |\n",
    "|    l   |   2   |   -4   |\n",
    "|    l   |   3   |   -3   |\n",
    "|    o   |   4   |   -2   |\n",
    "|    !   |   5   |   -1   |\n",
    "\n",
    "First element is 0.\n",
    "\n",
    "Last element is -1.\n",
    "\n",
    "Slice boundaries are inclusive of first, exclude last."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f1d567c",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### mutable sequence methods (for now just `list`)\n",
    "\n",
    "| Operation   | Result | \n",
    "|-------------|--------|\n",
    "|  `s[i] = x` | Replace element `i` in sequence with `x`. |\n",
    "|  `s.append(x)` | Add item to end of sequence. |\n",
    "|  `s.clear()`  | Remove all items from sequence. |\n",
    "|  `s.copy()`  | Create a (shallow) copy of sequence. |\n",
    "|  `s.insert(i, x)` | Insert an item `x` at position `i`. |\n",
    "|  `s.pop()` or `s.pop(i)` | Retrieve item at position `i` and remove it.  (Defaults to -1 if not provided) |\n",
    "|  `s.reverse()` | Reverse items of `s` in place. |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75689768-425f-48ea-aaad-b1af5ad90a92",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# list demo\n",
    "letters = [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\"]\n",
    "\n",
    "letters.append(\"H\")\n",
    "print(letters)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "417c67b1-bde2-4775-b338-ae247a0034f6",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "letters.insert(0, \"*\") \n",
    "\n",
    "letters.pop()\n",
    "letters.pop(4)\n",
    "\n",
    "print(letters)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1273e3ee-68a5-4316-8013-2cad121a3e64",
   "metadata": {},
   "outputs": [],
   "source": [
    "letters = [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\"]\n",
    "print(letters)\n",
    "letters.reverse()\n",
    "print(letters)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49867913",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### common string methods\n",
    "\n",
    "| Method                 | Description |\n",
    "|------------------------|-------------|\n",
    "| s.find(sub)            | Finds first occurence of substring `sub` or -1 if not found |\n",
    "| s.lower()              | Converts the string to lowercase. |\n",
    "| s.upper()              | Converts the string to uppercase. |\n",
    "| s.replace(old, new)    | Replaces occurences of old with new. |\n",
    "| s.strip()              | Remove leading & trailing whitespace. |\n",
    "| s.startswith(prefix)   | Checks if a string starts with prefix. |\n",
    "| s.endswith(suffix)     | Checks if a string ends with suffix. |\n",
    "| s.split(sep)           | Split a string using `sep` as delimiter. |\n",
    "\n",
    "\n",
    "(Credit: Python Distilled, Table 1.6)\n",
    "\n",
    "Not a complete list, see https://docs.python.org/3/library/stdtypes.html#string-methods"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "440ba853-a8a9-4d63-af3d-2797854d14b5",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# string method demo\n",
    "s = \"Hello world!\"\n",
    "\n",
    "# find\n",
    "pos = s.find(\"world\")\n",
    "print(pos)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01e4299c-1c4f-4a4e-b6fe-5e050897d374",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(s[pos:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6759991d-4bbd-4d6e-a33d-7c9177452e15",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "222177ff-7277-41a8-ba88-156f9930b7ed",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "new_string = s.upper()\n",
    "\n",
    "print(\"s=\", s)\n",
    "print(\"new_string=\", new_string)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e2eaef9a",
   "metadata": {},
   "outputs": [],
   "source": [
    "s.replace(\"world\", \"class\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84a2c895-1c93-43ee-aaa0-cd24e2ff228e",
   "metadata": {},
   "outputs": [],
   "source": [
    "s"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "000b7f60",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Statements\n",
    "\n",
    "We said earlier that everything in Python was either a **statement** or an **expression**.\n",
    "\n",
    "Up until now almost everything we've seen has been an **expression**, now we'll look at statements.\n",
    "\n",
    "Statements are used for **control flow**.  Without them our programs would just execute one line after the next.\n",
    "\n",
    "### Indentation\n",
    "\n",
    "Perhaps the most jarring change for C/Java/JavaScript programmers: Python does not use braces.\n",
    "\n",
    "Instead, indentation signifies code block boundaries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f82b31c",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from __future__ import braces"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c85cf457",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### `if, elif, else` Statements\n",
    "\n",
    "```python\n",
    "if condition:\n",
    "    statement1\n",
    "    statement2\n",
    "elif condition:    # else if\n",
    "    statement3\n",
    "else:\n",
    "    statement4\n",
    "    statement5\n",
    "```\n",
    "\n",
    "- Note the colon after each condition.\n",
    "- `elif` and `else` are optional\n",
    "- parenthesis around the expression are optional\n",
    "- each line should be indented four spaces\n",
    "\n",
    "This is a statement because you don't write\n",
    "\n",
    "```\n",
    "x = if ...:\n",
    "        ...\n",
    "    else:\n",
    "        ...\n",
    "    else:\n",
    "        ...\n",
    "```\n",
    "\n",
    "Instead, these lines of code are evaluated conditionally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ab2cece2",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# if example\n",
    "\n",
    "x = 100\n",
    "\n",
    "if x < 0:\n",
    "    print(\"negative\")\n",
    "    print(\"second line\")\n",
    "elif x == 0:\n",
    "    print(\"zero\")\n",
    "elif x == 4:\n",
    "    print(\"four\")\n",
    "else:\n",
    "    print(\"positive\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c604a4d1",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### `while` statement\n",
    "\n",
    "```python\n",
    "while condition:\n",
    "    statement1\n",
    "    statement2\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed48db1e",
   "metadata": {
    "scrolled": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "time_left = 10\n",
    "\n",
    "while time_left != 0:\n",
    "    print(f\"{time_left}...\")\n",
    "    time_left -= 1\n",
    "\n",
    "print(\"blast off!\") "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03cf2197",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "### `for` statement\n",
    "\n",
    "```python\n",
    "for var in iterable:\n",
    "    statement1\n",
    "    statement2\n",
    "```\n",
    "\n",
    "This looks a bit different from C/Java.\n",
    "\n",
    "Also, what is an iterable?\n",
    "\n",
    "For now, just know that sequences are iterables, we'll cover iterables soon."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9adbf6f-b13c-40d6-b1d9-20d2b86c2b26",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(cities)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cdf183e0-1ea9-41c2-b00d-eadde73500ec",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "for city in cities:\n",
    "    if city == \"Cairo\":\n",
    "        # we don't need to print cairo out\n",
    "        break\n",
    "    print(city)\n",
    "\n",
    "seconds_left = 7"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a192c46d-be0a-481d-81bf-18bdf5c454f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "for city in cities:\n",
    "    need_to_break = False\n",
    "    for letter in city:\n",
    "        if letter == \"y\":\n",
    "            need_to_break = True\n",
    "            break\n",
    "        print(letter)\n",
    "    if need_to_break:\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9317a80f",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### `break & continue`\n",
    "\n",
    "You may have seen `break` and `continue` in other languages.\n",
    "\n",
    "If so, they work the same way in Python.\n",
    "\n",
    "`break` - exit a loop immediately\n",
    "\n",
    "`continue` - immediately begin next iteration of loop\n",
    "\n",
    "`else` statement after `for` or `while` - executes only if no break was called"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c02cfdd0",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# break demo\n",
    "\n",
    "time_left = 10\n",
    "abort_at = -1\n",
    "\n",
    "while time_left > 0:\n",
    "    print(f\"{time_left}...\")\n",
    "    time_left -= 1\n",
    "    if time_left == abort_at:\n",
    "        print(\"Launch Aborted\")\n",
    "        break\n",
    "else:\n",
    "    # this only runs if we don't break\n",
    "    print(\"blast off!\")\n",
    "\n",
    "# can we use else to fix this?\n",
    "\n",
    "\n",
    "seconds_left = 7"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cffb8cde",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "s = \"Hello class, my name is James\"\n",
    "\n",
    "for ch in s:\n",
    "    if ch == \",\":\n",
    "        print(\"found a comma!\")\n",
    "        break\n",
    "else:\n",
    "    print(\"no comma found!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "04bafad6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "997816f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(cities)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b0770bf",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "# continue demo\n",
    "\n",
    "visited = [\"Chicago\", \"Mexico City\", \"Shanghai\"]\n",
    "\n",
    "for city in cities:\n",
    "    if city in visited:\n",
    "        continue\n",
    "    print(f\"I would like to visit {city}\")\n",
    "\n",
    "# when would we use continue in practice?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d81f6ac8-0d6a-4f63-919f-97c3c400a142",
   "metadata": {},
   "outputs": [],
   "source": [
    "items = [\"hello\", \"world\"]\n",
    "found = False\n",
    "\n",
    "for item in items:\n",
    "    for letter in item:\n",
    "        if letter == \"e\":\n",
    "            found = True\n",
    "            break\n",
    "        print(letter)\n",
    "    if found:\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b39cab79",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "#### idiom: \"infinite\" loops\n",
    "\n",
    "```python\n",
    "while True:\n",
    "    do_something()\n",
    "    if condition:\n",
    "        break\n",
    "```\n",
    "\n",
    "Similar to a `do while`loop in C/C++"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "725314db",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### range\n",
    "\n",
    "Another iterable!\n",
    "\n",
    "`range(stop)` # goes from 0 to (stop-1)\n",
    "\n",
    "`range(start, stop)` # goes from start to (stop-1)\n",
    "\n",
    "Same rules as slice, always **inclusive** of start, **exclusive** of stop.\n",
    "\n",
    "*or as you'd write mathematically:* ```[start, stop)```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ca2055d5",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "for x in range(5, 25):\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b10e481e-75c0-476b-8189-d56651dfa61b",
   "metadata": {},
   "outputs": [],
   "source": [
    "s = \"hello\"\n",
    "for i in range(len(s)):\n",
    "    print(i, s[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "112c7618",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### `enumerate`\n",
    "\n",
    "Another iterable, for when we need the index along with the object.\n",
    "\n",
    "Gives us two element tuples:\n",
    "\n",
    "`(index, element)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db633289",
   "metadata": {
    "scrolled": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "s = \"Hello world\"\n",
    "print(s.find(\"world\"))\n",
    "\n",
    "for i, letter in enumerate(s):\n",
    "    if letter == \"w\":\n",
    "        print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19fceab4-0220-4482-81fc-6980bd2285fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "for tup in enumerate(s):\n",
    "    if tup[1] == \"w\":\n",
    "        print(tup[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0b2b527-44b5-4f79-8c1b-f9e5dd34fa3a",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Functions\n",
    "\n",
    "A function is a set of statements that can be called more than once.\n",
    "\n",
    "Benefits of functions:\n",
    "\n",
    "- Encapsulation: package logic for use in multiple places\n",
    "- Allows programmer to avoid copy/paste to repeat same task, which helps maximize code reuse and minimize redundancy\n",
    "- Procedural decomposition: split our program into subtasks (i.e., functions) with separate roles.\n",
    "- Make life easier for debugging, testing, doing maintenance on code\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74ff7f39",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "```python\n",
    "def function_name(arg1: int, arg2: float, arg3: tuple) -> None:\n",
    "    \"\"\"\n",
    "         Description of function task \n",
    "\n",
    "         Inputs: \n",
    "             arg1: description of arg1 \n",
    "             arg2: description of arg2\n",
    "             arg3: description of arg2\n",
    "\n",
    "         Outputs:\n",
    "             Description of what this function returns \n",
    "    \"\"\"\n",
    "    statement1\n",
    "    statement2\n",
    "    statement3\n",
    "    return value  # optional\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53afdf59",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### return\n",
    "\n",
    "- `return` may appear anywhere in a function body, including multiple times.\n",
    "\n",
    "- The first `return` encountered exits the function.\n",
    "\n",
    "- Every function in python returns a value. \n",
    "\n",
    "- If no `return` statement is present, `None` is implicitly returned."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b11eec38",
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_even(num):\n",
    "    return num % 2 == 0\n",
    "\n",
    "\n",
    "print(is_even(3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc9cab52-e50a-4726-87c3-ecfb669513ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "def bad_return(num):\n",
    "    if num > 10000: \n",
    "        return False\n",
    "    return None\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f7e4e6a7-ccd1-49dd-ae1c-3d0ab0210652",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(bad_return(1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "240a7d13-1874-4814-9d12-be3f2d63828b",
   "metadata": {},
   "outputs": [],
   "source": [
    "if x:\n",
    "    pass\n",
    "else:\n",
    "    print(\"not x\")    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd24eb29-52ef-4b61-860e-146e090c3d68",
   "metadata": {},
   "outputs": [],
   "source": [
    "def func():\n",
    "    return \"123\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99c8aff1-e0bf-4f20-9e9a-98abf551b8fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "x, y, z = func()\n",
    "print(x, y, z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9be98bd4-e156-41d8-aace-b015bf8b15c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "if x:\n",
    "    pass\n",
    "else:\n",
    "    print(\"y\")    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20ae7bfb",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "###  `pass` statement\n",
    "\n",
    "Can be used whenever you need to leave a block empty.  Usually temporarily.\n",
    "\n",
    "```python\n",
    "\n",
    "if x < 0:\n",
    "    pass # TODO: figure this out later\n",
    "\n",
    "\n",
    "if x >= 0:\n",
    "    do_work()\n",
    "\n",
    "\n",
    "def implement_me():\n",
    "    pass\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebc0274c-56dd-41a1-b65f-451547a5c3b7",
   "metadata": {},
   "source": [
    "#### Type Annotations\n",
    "\n",
    "Type annotations are a newer Python feature.\n",
    "They exist to provide *hints* as to what types a function takes.\n",
    "\n",
    "You will start seeing them in assignments and documentation, and we'll discuss them more later in the quarter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "25a1c74a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# I've broken this function into multiple lines, which is allowed\n",
    "# due to the parentheses.\n",
    "\n",
    "\n",
    "def find_value(\n",
    "    a_list: list[list[str]],  # this parameter is a list of integers\n",
    "    num: int,           # this parameter is a single integer\n",
    ") -> (\n",
    "    int | None\n",
    "):  # this annotation \"-> int | None\" indicates return type can be int or None\n",
    "    pass\n",
    "\n",
    "def find_value(a_list: list[str], num: int) -> int | None:  \n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "57bf5143-d33e-4083-b02b-c1f78e80717f",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = find_value(3.0, \"hello\")\n",
    "x[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cfe779a8",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### docstrings\n",
    "\n",
    "Function comments should be done in the form of a docstring, i.e., a multi-line string (delimited by triple quotes, ''') after the function header.\n",
    "\n",
    "This comment must contain information specific to what a function does. It should also include a description of the purpose and expected input arguments, the expected output values, and how error conditions are handled.\n",
    "\n",
    "Example:\n",
    "```python\n",
    "def hypotenuse(a, b):\n",
    "    '''\n",
    "    This function solves Pythagorean theorem a^2 + b^2 = c^2\n",
    "    for the value of c.\n",
    "\n",
    "    Inputs:\n",
    "      a, b (float): the lengths of sides of a right triangle.\n",
    "\n",
    "    Returns:\n",
    "      (float) the length of the hypotenuse.\n",
    "    '''\n",
    "\n",
    "    return math.sqrt(a**2 + b**2)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8535fae",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Homework #0\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f3ef637-bc1e-4026-b756-5b606b0b6624",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "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.15"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "434.4px"
   },
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
