diff --git a/.gitignore b/.gitignore
index abd7c5a..847c97b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,107 @@
~$*.pptx
-*.pyc
\ No newline at end of file
+
+# below is the github gitignore for python
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
\ No newline at end of file
diff --git a/04_jupyter_and_python_intro/.ipynb_checkpoints/L2.Simple_Breakout-checkpoint.ipynb b/04_jupyter_and_python_intro/.ipynb_checkpoints/L2.Simple_Breakout-checkpoint.ipynb
deleted file mode 100644
index 3cd68d5..0000000
--- a/04_jupyter_and_python_intro/.ipynb_checkpoints/L2.Simple_Breakout-checkpoint.ipynb
+++ /dev/null
@@ -1,620 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Breakout: Simple Math in Python"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The purpose of this breakout is to help you familiarize yourself with executing Python code in the Jupyter notebook, and along the way familiarize yourself with some of the mathematical functionality available in Python.\n",
- "\n",
- "As with many breakouts in this course, you should **do the following with a partner**.\n",
- "One of you should have your fingers on the keyboard, while the other watches and helps decide what to type."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Some Basic Notebook Navigation"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Jupyter notebooks combine text and executable code: a code cell looks like this, and you can run it by pressing enter/return **while holding the shift key**. Try it out here:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "1 + 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Additionally, you'll sometimes want to insert a new cell to add more code. You can do this by using the **[+]** button which is second from the left at the top of the notebook page.\n",
- "Before you continue, insert a new cell below this one to make sure you see how it works."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "*Note* We'll learn more about _Markdown_ later but if you'd like to learn how to incorporate equations into your notebook, google _Markdown_ and _LaTex_"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exploring Arithmetic Operators in Python\n",
- "\n",
- "Python can be used quite straightforwardly as a calculator.\n",
- "Among other commands, it recognizes ``+``, ``-``, ``*``, ``/``, and ``()`` with their typical mathematical meanings.\n",
- "With this in mind, we're going to quickly practice using Python as a calculator.\n",
- "\n",
- "Use Python to solve the following arithmetic problems:"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $4235 + 3154$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $4235 - 3154$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $4235 \\times 3154$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\frac{4235}{3154}$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\frac{4235 - 3154}{2752 + 5013}$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\frac{-(4315 + 378)}{2(65 - 328)}$"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exploring More Specialized Arithmetic\n",
- "\n",
- "Some other useful operators are ``//``, ``%``, and ``**``."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is ``4235 // 3154``?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try the ``//`` operator with some other inputs: can you figure out its meaning?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is ``4235 % 3154``?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try the ``%`` operator with some other inputs: can you figure out its meaning?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is ``4235 ** 3154``?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try the ``**`` operator with some other inputs: can you figure out its meaning?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exploring other Operators\n",
- "\n",
- "There's another class of operators recognized by Python: ``&``, ``|``, ``^``, and ``~``.\n",
- "\n",
- "Play around with these four operators: can you discover their meaning?\n",
- "(Don't worry if you can't: these are quite a bit more obscure than the ones above!)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The ``math`` Module\n",
- "\n",
- "**Please switch roles now, so the second person has fingers-on-keyboard**\n",
- "\n",
- "Along with the basic arithmetic operators, Python has some more sophisticated mathematical operations in the *``math`` module*.\n",
- "A module in Python is a collection of functionality that can be *imported* and used in your script.\n",
- "Importing functionality from modules is *extremely* easy in Python compared to some other languages, and it has an incredible array of standard functionality available through these imports.\n",
- "\n",
- "A popular XKCD comic draws from this idea:\n",
- "\n",
- "\n",
- "\n",
- "The way you import a module, like in this xkcd comic, is to use the ``import`` statement. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import antigravity"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import math"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "With this done, we can now access elements of the ``math`` module using ``math.XXX``, where we replace ``XXX`` with the name of the variable, function, or other object we're interested in.\n",
- "\n",
- "For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# variable containing the value of π\n",
- "math.pi"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# function to compute the square root of a number\n",
- "math.sqrt(2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Use functions in the math module to compute the following:"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sin(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\cos(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\exp(2)$ (otherwise known as $e^2$)?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\log(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sin^2(2) + \\cos^2(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sin(2\\pi)$? (do you notice anything strange?)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exploring Packages with Jupyter"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The Jupyter notebook includes a very convenient way to explore the contents of a module.\n",
- "\n",
- "- If you type ``math.`` followed by the tab key, it will give you a list of valid completions, which in this case consists of a list of all functions and variables in the math module.\n",
- "\n",
- "- If you type any function followed by a question mark (e.g. ``math.cos?``) then shift-enter, it will give you a documentation string"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Use these two convenience features to explore the ``math`` module.\n",
- "\n",
- "Can you find a statement that computes $\\sqrt{x^2 + y^2}$ efficiently in a single line?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sqrt{4235^2 + 3154^2}$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $e^x - 1$ for $x = 10^{-20}$? (Hint: it's not zero!)\n",
- "Can you find a function in the ``math`` module that computes this function accurately?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Please put a yellow post-it on your laptop, so we know that you've finished the exploration.**\n",
- "\n",
- "While you are waiting for others to finish, continue exploring the ``math`` module to see what functionality is available."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "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.7.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/04_jupyter_and_python_intro/.ipynb_checkpoints/L5.Procedural_Python-checkpoint.ipynb b/04_jupyter_and_python_intro/.ipynb_checkpoints/L5.Procedural_Python-checkpoint.ipynb
deleted file mode 100644
index 103eaaf..0000000
--- a/04_jupyter_and_python_intro/.ipynb_checkpoints/L5.Procedural_Python-checkpoint.ipynb
+++ /dev/null
@@ -1,1706 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Procedural programming in python\n",
- "\n",
- "## Topics\n",
- "* Tuples, lists and dictionaries\n",
- "* Flow control, part 1\n",
- " * If\n",
- " * For\n",
- " * range() function\n",
- "* Some hacky hack time\n",
- "* Flow control, part 2\n",
- " * Functions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "
"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Tuples\n",
- "\n",
- "Let's begin by creating a tuple called `my_tuple` that contains three elements."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple = ('I', 'like', 'cake')\n",
- "my_tuple"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Tuples are simple containers for data. They are ordered, meaining the order the elements are in when the tuple is created are preserved. We can get values from our tuple by using array indexing, similar to what we were doing with pandas."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[0]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Recall that Python indexes start at 0. So the first element in a tuple is 0 and the last is array length - 1. You can also address from the `end` to the `front` by using negative (`-`) indexes, e.g."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[-1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can also access a range of elements, e.g. the first two, the first three, by using the `:` to expand a range. This is called ``slicing``."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[0:2]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[0:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What do you notice about how the upper bound is referenced?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Without either end, the ``:`` expands to the entire list."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[1:]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[:-1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[:]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Tuples have a key feature that distinguishes them from other types of object containers in Python. They are _immutable_. This means that once the values are set, they cannot change."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[2]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So what happens if I decide that I really prefer pie over cake?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "#my_tuple[2] = 'pie'"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Facts about tuples:\n",
- "* You can't add elements to a tuple. Tuples have no append or extend method.\n",
- "* You can't remove elements from a tuple. Tuples have no remove or pop method.\n",
- "* You can also use the in operator to check if an element exists in the tuple.\n",
- "\n",
- "So then, what are the use cases of tuples? \n",
- "* Speed\n",
- "* `Write-protects` data that other pieces of code should not alter"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can alter the value of a tuple variable, e.g. change the tuple it holds, but you can't modify it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple = ('I', 'love', 'pie')\n",
- "my_tuple"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is a really handy operator ``in`` that can be used with tuples that will return `True` if an element is present in a tuple and `False` otherwise."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'love' in my_tuple"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Finally, tuples can contain different types of data, not just strings."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import math\n",
- "my_second_tuple = (42, 'Elephants', 'ate', math.pi)\n",
- "my_second_tuple"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numerical operators work... Sort of. What happens when you add? \n",
- "\n",
- "``my_second_tuple + 'plus'``"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Not what you expects? What about adding two tuples?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_second_tuple + my_tuple"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Other operators: -, /, *"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Questions about tuples before we move on?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "
\n",
- "\n",
- "### Lists\n",
- "\n",
- "Let's begin by creating a list called `my_list` that contains three elements."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list = ['I', 'like', 'cake']\n",
- "my_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "At first glance, tuples and lists look pretty similar. Notice the lists use '[' and ']' instead of '(' and ')'. But indexing and refering to the first entry as 0 and the last as -1 still works the same."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[0]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[-1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[0:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Lists, however, unlike tuples, are mutable. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[2] = 'pie'\n",
- "my_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Multiple elements in the list can even be changed at once!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[1:] = ['love', 'puppies']\n",
- "my_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can still use the `in` operator."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'puppies' in my_list"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'kittens' in my_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So when to use a tuple and when to use a list?\n",
- "\n",
- "* Use a list when you will modify it after it is created?\n",
- "\n",
- "Ways to modify a list? You have already seen by index. Let's start with an empty list."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_new_list = []\n",
- "my_new_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can add to the list using the append method on it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_new_list.append('Now')\n",
- "my_new_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can use the `+` operator to create a longer list by adding the contents of two lists together."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_new_list + my_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "One of the useful things to know about a list how many elements are in it. This can be found with the `len` function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "len(my_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Some other handy functions with lists:\n",
- "* max\n",
- "* min\n",
- "* cmp"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Sometimes you have a tuple and you need to make it a list. You can `cast` the tuple to a list with ``list(my_tuple)``"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "list(my_tuple)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What in the above told us it was a list? \n",
- "\n",
- "You can also use the ``type`` function to figure out the type."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "type(tuple)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "type(list(my_tuple))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There are other useful methods on lists, including:\n",
- "\n",
- "| methods | description |\n",
- "|---|---|\n",
- "| list.append(obj) | Appends object obj to list |\n",
- "| list.count(obj)| Returns count of how many times obj occurs in list |\n",
- "| list.extend(seq) | Appends the contents of seq to list |\n",
- "| list.index(obj) | Returns the lowest index in list that obj appears |\n",
- "| list.insert(index, obj) | Inserts object obj into list at offset index |\n",
- "| list.pop(obj=list[-1]) | Removes and returns last object or obj from list |\n",
- "| list.remove(obj) | Removes object obj from list |\n",
- "| list.reverse() | Reverses objects of list in place |\n",
- "| list.sort([func]) | Sort objects of list, use compare func, if given |\n",
- "\n",
- "Try some of them now.\n",
- "\n",
- "```\n",
- "my_list.count('I')\n",
- "my_list\n",
- "\n",
- "my_list.append('I')\n",
- "my_list\n",
- "\n",
- "my_list.count('I')\n",
- "my_list\n",
- "\n",
- "#my_list.index(42)\n",
- "\n",
- "my_list.index('puppies')\n",
- "my_list\n",
- "\n",
- "my_list.insert(my_list.index('puppies'), 'furry')\n",
- "my_list\n",
- "```"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list.count('I')\n",
- "my_list\n",
- "\n",
- "my_list.append('I')\n",
- "my_list\n",
- "\n",
- "my_list.count('I')\n",
- "my_list\n",
- "\n",
- "#my_list.index(42)\n",
- "\n",
- "my_list.index('puppies')\n",
- "my_list\n",
- "\n",
- "my_list.insert(my_list.index('puppies'), 'furry')\n",
- "my_list\n",
- "\n",
- "my_list.pop()\n",
- "my_list\n",
- "\n",
- "my_list.remove('puppies')\n",
- "my_list\n",
- "\n",
- "my_list.append('cabbages')\n",
- "my_list"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Any questions about lists before we move on?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "
\n",
- "\n",
- "### Dictionaries\n",
- "\n",
- "Dictionaries are similar to tuples and lists in that they hold a collection of objects. Dictionaries, however, allow an additional indexing mode: keys. Think of a real dictionary where the elements in it are the definitions of the words and the keys to retrieve the entries are the words themselves.\n",
- "\n",
- "| word | definition |\n",
- "|------|------------|\n",
- "| tuple | An immutable collection of ordered objects |\n",
- "| list | A mutable collection of ordered objects |\n",
- "| dictionary | A mutable collection of named objects |\n",
- "\n",
- "Let's create this data structure now. Dictionaries, like tuples and elements use a unique referencing method, '{' and its evil twin '}'."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict = { 'tuple' : 'An immutable collection of ordered objects',\n",
- " 'list' : 'A mutable collection of ordered objects',\n",
- " 'dictionary' : 'A mutable collection of objects' }\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We access items in the dictionary by name, e.g. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['dictionary']"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Since the dictionary is mutable, you can change the entries."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['dictionary'] = 'A mutable collection of named objects'\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice that ordering is not preserved!\n",
- "#### As of Python 3.7 the ordering is garunteed to be insertion order but that does not mean alphabetical or otherwise sorted.\n",
- "\n",
- "And we can add new items to the list."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['cabbage'] = 'Green leafy plant in the Brassica family'\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To delete an entry, we can't just set it to ``None``"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['cabbage'] = None\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To delete it propery, we need to pop that specific entry."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict.pop('cabbage', None)\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can use other objects as names, but that is a topic for another time. You can mix and match key types, e.g."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_new_dict = {}\n",
- "my_new_dict[1] = 'One'\n",
- "my_new_dict['42'] = 42\n",
- "my_new_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can get a list of keys in the dictionary by using the ``keys`` method."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict.keys()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Similarly the contents of the dictionary with the ``items`` method."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict.items()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can use the keys list for fun stuff, e.g. with the ``in`` operator."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'dictionary' in my_dict.keys()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is a synonym for `in my_dict`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'dictionary' in my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice, it doesn't work for elements."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'A mutable collection of ordered objects' in my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Other dictionary methods:\n",
- "\n",
- "| methods | description |\n",
- "|---|---|\n",
- "| dict.clear() | Removes all elements from dict |\n",
- "| dict.get(key, default=None) | For ``key`` key, returns value or ``default`` if key doesn't exist in dict | \n",
- "| dict.items() | Returns a list of dicts (key, value) tuple pairs | \n",
- "| dict.keys() | Returns a list of dictionary keys |\n",
- "| dict.setdefault(key, default=None) | Similar to get, but set the value of key if it doesn't exist in dict |\n",
- "| dict.update(dict2) | Add the key / value pairs in dict2 to dict |\n",
- "| dict.values | Returns a list of dictionary values|\n",
- "\n",
- "Feel free to experiment..."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "
\n",
- "## Flow control\n",
- "\n",
- "Flow control figure\n",
- "\n",
- "Flow control refers how to programs do loops, conditional execution, and order of functional operations. Let's start with conditionals, or the venerable ``if`` statement.\n",
- "\n",
- "Let's start with a simple list of instructors for these classes."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "instructors = ['Dave', 'Bernease', 'Dorkus the Clown']\n",
- "instructors"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### If\n",
- "If statements can be use to execute some lines or block of code if a particular condition is satisfied. E.g. Let's print something based on the entries in the list."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "if 'Dorkus the Clown' in instructors:\n",
- " print('#fakeinstructor')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Usually we want conditional logic on both sides of a binary condition, e.g. some action when ``True`` and some when ``False``"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "if 'Dorkus the Clown' in instructors:\n",
- " print('There are fake names for class instructors in your list!')\n",
- "else:\n",
- " print(\"Nothing to see here\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is a special do nothing word: `pass` that skips over some arm of a conditional, e.g."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "ename": "NameError",
- "evalue": "name 'instructors' is not defined",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0;34m'Bernease'\u001b[0m \u001b[0;32min\u001b[0m \u001b[0minstructors\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Congratulations! Bernease is teaching, your class won't stink!\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mNameError\u001b[0m: name 'instructors' is not defined"
- ]
- }
- ],
- "source": [
- "if 'Bernease' in instructors:\n",
- " print(\"Congratulations! Bernease is teaching, your class won't stink!\")\n",
- "else:\n",
- " pass"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "_Note_: what have you noticed in this session about quotes? What is the difference between ``'`` and ``\"``?\n",
- "\n",
- "\n",
- "Another simple example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "scrolled": true
- },
- "outputs": [],
- "source": [
- "if True is False:\n",
- " print(\"I'm so confused\")\n",
- "else:\n",
- " print(\"Everything is right with the world\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It is always good practice to handle all cases explicity. `Conditional fall through` is a common source of bugs.\n",
- "\n",
- "Sometimes we wish to test multiple conditions. Use `if`, `elif`, and `else`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_favorite = 'pie'\n",
- "\n",
- "if my_favorite is 'cake':\n",
- " print(\"He likes cake! I'll start making a double chocolate velvet cake right now!\")\n",
- "elif my_favorite is 'pie':\n",
- " print(\"He likes pie! I'll start making a cherry pie right now!\")\n",
- "else:\n",
- " print(\"He likes \" + my_favorite + \". I don't know how to make that.\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Conditionals can take ``and`` and ``or`` and ``not``. E.g."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_favorite = 'pie'\n",
- "\n",
- "if my_favorite is 'cake' or my_favorite is 'pie':\n",
- " print(my_favorite + \" : I have a recipe for that!\")\n",
- "else:\n",
- " print(\"Ew! Who eats that?\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## For\n",
- "\n",
- "For loops are the standard loop, though `while` is also common. For has the general form:\n",
- "```\n",
- "for items in list:\n",
- " do stuff\n",
- "```\n",
- "\n",
- "For loops and collections like tuples, lists and dictionaries are natural friends."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for instructor in instructors:\n",
- " print(instructor)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can combine loops and conditionals:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for instructor in instructors:\n",
- " if instructor.endswith('Clown'):\n",
- " print(instructor + \" doesn't sound like a real instructor name!\")\n",
- " else:\n",
- " print(instructor + \" is so smart... all those gooey brains!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Dictionaries can use the `keys` method for iterating."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for key in my_dict.keys():\n",
- " if len(key) > 5:\n",
- " print(my_dict[key])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### range()\n",
- "\n",
- "Since for operates over lists, it is common to want to do something like:\n",
- "```\n",
- "NOTE: C-like\n",
- "for (i = 0; i < 3; ++i) {\n",
- " print(i);\n",
- "}\n",
- "```\n",
- "\n",
- "The Python equivalent is:\n",
- "\n",
- "```\n",
- "for i in [0, 1, 2]:\n",
- " do something with i\n",
- "```\n",
- "\n",
- "What happens when the range you want to sample is big, e.g.\n",
- "```\n",
- "NOTE: C-like\n",
- "for (i = 0; i < 1000000000; ++i) {\n",
- " print(i);\n",
- "}\n",
- "```\n",
- "\n",
- "That would be a real pain in the rear to have to write out the entire list from 1 to 1000000000.\n",
- "\n",
- "Enter, the `range()` function. E.g.\n",
- " ```range(3) is [0, 1, 2]```"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "range(3)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice that Python (in the newest versions, e.g. 3+) has an object type that is a range. This saves memory and speeds up calculations vs. an explicit representation of a range as a list - but it can be automagically converted to a list on the fly by Python. To show the contents as a `list` we can use the type case like with the tuple above.\n",
- "\n",
- "Sometimes, in older Python docs, you will see `xrange`. This used the range object back in Python 2 and `range` returned an actual list. Beware of this!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "list(range(3))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Remember earlier with slicing, the syntax `:3` meant `[0, 1, 2]`? Well, the same upper bound philosophy applies here.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for index in range(3):\n",
- " instructor = instructors[index]\n",
- " if instructor.endswith('Clown'):\n",
- " print(instructor + \" doesn't sound like a real instructor name!\")\n",
- " else:\n",
- " print(instructor + \" is so smart... all those gooey brains!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This would probably be better written as"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for index in range(len(instructors)):\n",
- " instructor = instructors[index]\n",
- " if instructor.endswith('Clown'):\n",
- " print(instructor + \" doesn't sound like a real instructor name!\")\n",
- " else:\n",
- " print(instructor + \" is so smart... all those gooey brains!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "But in all, it isn't very Pythonesque to use indexes like that (unless you have another reason in the loop) and you would opt instead for the `instructor in instructors` form. \n",
- "\n",
- "More often, you are doing something with the numbers that requires them to be integers, e.g. math."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "sum = 0\n",
- "for i in range(10):\n",
- " sum += i\n",
- "print(sum)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### For loops can be nested\n",
- "\n",
- "_Note_: for more on formatting strings, see: [https://pyformat.info](https://pyformat.info)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for i in range(1, 4):\n",
- " for j in range(1, 4):\n",
- " print('%d * %d = %d' % (i, j, i*j)) # Note string formatting here, %d means an integer"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### You can exit loops early if a condition is met:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for i in range(10):\n",
- " if i == 4:\n",
- " break\n",
- "i"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### You can skip stuff in a loop with `continue`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "sum = 0\n",
- "for i in range(10):\n",
- " if (i == 5):\n",
- " continue\n",
- " else:\n",
- " sum += i\n",
- "print(sum)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### There is a unique language feature call ``for...else``"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "sum = 0\n",
- "for i in range(10):\n",
- " sum += i\n",
- "else:\n",
- " print('final i = %d, and sum = %d' % (i, sum))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### You can iterate over letters in a string"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_string = \"DIRECT\"\n",
- "for c in my_string:\n",
- " print(c)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "
"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Functions\n",
- "\n",
- "For loops let you repeat some code for every item in a list. Functions are similar in that they run the same lines of code for new values of some variable. They are different in that functions are not limited to looping over items.\n",
- "\n",
- "Functions are a critical part of writing easy to read, reusable code.\n",
- "\n",
- "Create a function like:\n",
- "```\n",
- "def function_name (parameters):\n",
- " \"\"\"\n",
- " optional docstring\n",
- " \"\"\"\n",
- " function expressions\n",
- " return [variable]\n",
- "```\n",
- "\n",
- "_Note:_ Sometimes I use the word argument in place of parameter.\n",
- "\n",
- "Here is a simple example. It prints a string that was passed in and returns nothing."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def print_string(str):\n",
- " \"\"\"This prints out a string passed as the parameter.\"\"\"\n",
- " print(str)\n",
- " return"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To call the function, use:\n",
- "```\n",
- "print_string(\"Dave is awesome!\")\n",
- "```\n",
- "\n",
- "_Note:_ The function has to be defined before you can call it!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print_string(\"Dave is awesome!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you don't provide an argument or too many, you get an error."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Parameters (or arguments) in Python are all passed by reference. This means that if you modify the parameters in the function, they are modified outside of the function.\n",
- "\n",
- "See the following example:\n",
- "\n",
- "```\n",
- "def change_list(my_list):\n",
- " \"\"\"This changes a passed list into this function\"\"\"\n",
- " my_list.append('four');\n",
- " print('list inside the function: ', my_list)\n",
- " return\n",
- "\n",
- "my_list = [1, 2, 3];\n",
- "print('list before the function: ', my_list)\n",
- "change_list(my_list);\n",
- "print('list after the function: ', my_list)\n",
- "```"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "list before the function: [1, 2, 3]\n",
- "list inside the function: [1, 2, 3, 'four']\n",
- "list after the function: [1, 2, 3, 'four']\n"
- ]
- }
- ],
- "source": [
- "def change_list(my_list):\n",
- " \"\"\"This changes a passed list into this function\"\"\"\n",
- " my_list.append('four');\n",
- " print('list inside the function: ', my_list)\n",
- " return\n",
- "\n",
- "my_list = [1, 2, 3];\n",
- "print('list before the function: ', my_list)\n",
- "change_list(my_list);\n",
- "print('list after the function: ', my_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Variables have scope: `global` and `local`\n",
- "\n",
- "In a function, new variables that you create are not saved when the function returns - these are `local` variables. Variables defined outside of the function can be accessed but not changed - these are `global` variables, _Note_ there is a way to do this with the `global` keyword. Generally, the use of `global` variables is not encouraged, instead use parameters.\n",
- "\n",
- "```\n",
- "my_global_1 = 'bad idea'\n",
- "my_global_2 = 'another bad one'\n",
- "my_global_3 = 'better idea'\n",
- "\n",
- "def my_function():\n",
- " print(my_global)\n",
- " my_global_2 = 'broke your global, man!'\n",
- " global my_global_3\n",
- " my_global_3 = 'still a better idea'\n",
- " return\n",
- " \n",
- "my_function()\n",
- "print(my_global_2)\n",
- "print(my_global_3)\n",
- "```"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In general, you want to use parameters to provide data to a function and return a result with the `return`. E.g.\n",
- "\n",
- "```\n",
- "def sum(x, y):\n",
- " my_sum = x + y\n",
- " return my_sum\n",
- "```\n",
- "\n",
- "If you are going to return multiple objects, what data structure that we talked about can be used? Give and example below."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Parameters have four different types:\n",
- "\n",
- "| type | behavior |\n",
- "|------|----------|\n",
- "| required | positional, must be present or error, e.g. `my_func(first_name, last_name)` |\n",
- "| keyword | position independent, e.g. `my_func(first_name, last_name)` can be called `my_func(first_name='Dave', last_name='Beck')` or `my_func(last_name='Beck', first_name='Dave')` |\n",
- "| default | keyword params that default to a value if not provided |\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def print_name(first, last='the Clown'):\n",
- " print('Your name is %s %s' % (first, last))\n",
- " return"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Play around with the above function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Functions can contain any code that you put anywhere else including:\n",
- "* if...elif...else\n",
- "* for...else\n",
- "* while\n",
- "* other function calls"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def print_name_age(first, last, age):\n",
- " print_name(first, last)\n",
- " print('Your age is %d' % (age))\n",
- " if age > 35:\n",
- " print('You are really old.')\n",
- " return"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print_name_age(age=44, last='Beck', first='Dave')"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "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.7.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/04_jupyter_and_python_intro/.ipynb_checkpoints/data_basics-checkpoint.ipynb b/04_jupyter_and_python_intro/.ipynb_checkpoints/data_basics-checkpoint.ipynb
deleted file mode 100644
index 59fe22a..0000000
--- a/04_jupyter_and_python_intro/.ipynb_checkpoints/data_basics-checkpoint.ipynb
+++ /dev/null
@@ -1,1108 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Data Basics\n",
- "\n",
- "## Overview\n",
- "- **Data basics**\n",
- " - Theory of types\n",
- " - Basic types\n",
- " - Composite types: Tuples, lists and dictionaries\n",
- "- Functions\n",
- " * range() function\n",
- " - read and write files\n",
- "- Flow of control\n",
- " - If\n",
- " - for"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Data Basics"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Core concepts\n",
- "- An **object** is an element used in and possibly maniuplated by software.\n",
- "- Objects have two kinds of **attributes**\n",
- " - **Properties** (\"values\")\n",
- " - **Methods** (\"functions\")\n",
- "- To access the attributes of a python object, use the dot (\".\") operator.\n",
- "- A **type** (or **class**) specifies a set of attributes supported by an object."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Basic types\n",
- "- int, float, string, bool\n",
- "- relating types"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "str"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Let's do something with strings\n",
- "a_string = \"Happy birthday\"\n",
- "type(a_string)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a_string.count(\"p\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [],
- "source": [
- "a = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "ename": "AttributeError",
- "evalue": "'int' object has no attribute 'count'",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# We can't count strings in an integer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcount\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"p\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mAttributeError\u001b[0m: 'int' object has no attribute 'count'"
- ]
- }
- ],
- "source": [
- "# We can't count strings in an integer\n",
- "a.count(\"p\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "bool"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "type(x)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = a > 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False"
- ]
- },
- "execution_count": 9,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "must be str, not int",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"3\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mx\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m: must be str, not int"
- ]
- }
- ],
- "source": [
- "x = \"3\"\n",
- "x + 2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Advanced types"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Tuples\n",
- "\n",
- "Let's begin by creating a tuple called `my_tuple` that contains three elements."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "('I', 'like', 'cake')"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_tuple = ('I', 'like', 'cake')\n",
- "my_tuple"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'like'"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_tuple[1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "('like', 'cake')"
- ]
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_tuple[1:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Tuples are simple containers for data. They are ordered, meaining the order the elements are in when the tuple is created are preserved. We can get values from our tuple by using array indexing, similar to what we were doing with pandas."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[0]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Recall that Python indexes start at 0. So the first element in a tuple is 0 and the last is array length - 1. You can also address from the `end` to the `front` by using negative (`-`) indexes, e.g."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[-1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can also access a range of elements, e.g. the first two, the first three, by using the `:` to expand a range. This is called ``slicing``."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[0:2]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[0:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What do you notice about how the upper bound is referenced?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Without either end, the ``:`` expands to the entire list."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[1:]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[:-1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[:]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Tuples have a key feature that distinguishes them from other types of object containers in Python. They are _immutable_. This means that once the values are set, they cannot change."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_tuple[2]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So what happens if I decide that I really prefer pie over cake?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "'tuple' object does not support item assignment",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmy_tuple\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'pie'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
- ]
- }
- ],
- "source": [
- "my_tuple[2] = 'pie'"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Facts about tuples:\n",
- "* You can't add elements to a tuple. Tuples have no append or extend method.\n",
- "* You can't remove elements from a tuple. Tuples have no remove or pop method.\n",
- "* You can also use the in operator to check if an element exists in the tuple.\n",
- "\n",
- "So then, what are the use cases of tuples? \n",
- "* Speed\n",
- "* `Write-protects` data that other pieces of code should not alter"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "
\n",
- "\n",
- "### Lists\n",
- "\n",
- "Let's begin by creating a list called `my_list` that contains three elements."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list = ['I', 'like', 'cake']\n",
- "a_tuple = ('I', 'like', 'cake')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'cake'"
- ]
- },
- "execution_count": 19,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_list[2]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "At first glance, tuples and lists look pretty similar. Notice the lists use '[' and ']' instead of '(' and ')'. But indexing and refering to the first entry as 0 and the last as -1 still works the same."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[0]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[-1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[0:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Lists, however, unlike tuples, are mutable. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list[2] = 'pie'\n",
- "my_list"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Some methods for lists\n",
- "my_list.index(\"cake\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['I', 'like', 'cake']"
- ]
- },
- "execution_count": 20,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_list"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list.append(\"very\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['I', 'like', 'cake', 'very']"
- ]
- },
- "execution_count": 24,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_list"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_list.sort()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['I', 'cake', 'like', 'very']"
- ]
- },
- "execution_count": 30,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_list"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There are other useful methods on lists, including:\n",
- "\n",
- "| methods | description |\n",
- "|---|---|\n",
- "| list.append(obj) | Appends object obj to list |\n",
- "| list.count(obj)| Returns count of how many times obj occurs in list |\n",
- "| list.extend(seq) | Appends the contents of seq to list |\n",
- "| list.index(obj) | Returns the lowest index in list that obj appears |\n",
- "| list.insert(index, obj) | Inserts object obj into list at offset index |\n",
- "| list.pop(obj=list[-1]) | Removes and returns last object or obj from list |\n",
- "| list.remove(obj) | Removes object obj from list |\n",
- "| list.reverse() | Reverses objects of list in place |\n",
- "| list.sort([func]) | Sort objects of list, use compare func, if given |\n",
- "\n",
- "Try some of them now.\n",
- "\n",
- "```\n",
- "my_list.count('I')\n",
- "my_list\n",
- "\n",
- "my_list.append('I')\n",
- "my_list\n",
- "\n",
- "my_list.count('I')\n",
- "my_list\n",
- "\n",
- "#my_list.index(42)\n",
- "\n",
- "my_list.index('puppies')\n",
- "my_list\n",
- "\n",
- "my_list.insert(my_list.index('puppies'), 'furry')\n",
- "my_list\n",
- "```"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Dictionaries\n",
- "
\n",
- "\n",
- "Dictionaries are similar to tuples and lists in that they hold a collection of objects. Dictionaries, however, allow an additional indexing mode: keys. Think of a real dictionary where the elements in it are the definitions of the words and the keys to retrieve the entries are the words themselves.\n",
- "\n",
- "| word | definition |\n",
- "|------|------------|\n",
- "| tuple | An immutable collection of ordered objects |\n",
- "| list | A mutable collection of ordered objects |\n",
- "| dictionary | A mutable collection of named objects |\n",
- "\n",
- "Let's create this data structure now. Dictionaries, like tuples and elements use a unique referencing method, '{' and its evil twin '}'."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict = {\"birthday\": \"Jan 1\", \"present\": \"vacine\"}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dict_keys(['birthday', 'present'])"
- ]
- },
- "execution_count": 33,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_dict.keys()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dict_values(['Jan 1', 'vacine'])"
- ]
- },
- "execution_count": 34,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "my_dict.values()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict = { 'tuple' : 'An immutable collection of ordered objects',\n",
- " 'list' : 'A mutable collection of ordered objects',\n",
- " 'dictionary' : 'A mutable collection of objects' }\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We access items in the dictionary by name, e.g. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['dictionary']"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Since the dictionary is mutable, you can change the entries."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['dictionary'] = 'A mutable collection of named objects'\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice that ordering is not preserved!\n",
- "\n",
- "And we can add new items to the list."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['cabbage'] = 'Green leafy plant in the Brassica family'\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To delete an entry, we can't just set it to ``None``"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict['cabbage'] = None\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To delete it propery, we need to pop that specific entry."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict.pop('cabbage', None)\n",
- "my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can use other objects as names, but that is a topic for another time. You can mix and match key types, e.g."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_new_dict = {}\n",
- "my_new_dict[1] = 'One'\n",
- "my_new_dict['42'] = 42\n",
- "my_new_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can get a list of keys in the dictionary by using the ``keys`` method."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict.keys()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Similarly the contents of the dictionary with the ``items`` method."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "my_dict.items()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can use the keys list for fun stuff, e.g. with the ``in`` operator."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'dictionary' in my_dict.keys()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is a synonym for `in my_dict`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'dictionary' in my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice, it doesn't work for elements."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "'A mutable collection of ordered objects' in my_dict"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Other dictionary methods:\n",
- "\n",
- "| methods | description |\n",
- "|---|---|\n",
- "| dict.clear() | Removes all elements from dict |\n",
- "| dict.get(key, default=None) | For ``key`` key, returns value or ``default`` if key doesn't exist in dict | \n",
- "| dict.items() | Returns a list of dicts (key, value) tuple pairs | \n",
- "| dict.keys() | Returns a list of dictionary keys |\n",
- "| dict.setdefault(key, default=None) | Similar to get, but set the value of key if it doesn't exist in dict |\n",
- "| dict.update(dict2) | Add the key / value pairs in dict2 to dict |\n",
- "| dict.values | Returns a list of dictionary values|"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Help on class dict in module builtins:\n",
- "\n",
- "class dict(object)\n",
- " | dict() -> new empty dictionary\n",
- " | dict(mapping) -> new dictionary initialized from a mapping object's\n",
- " | (key, value) pairs\n",
- " | dict(iterable) -> new dictionary initialized as if via:\n",
- " | d = {}\n",
- " | for k, v in iterable:\n",
- " | d[k] = v\n",
- " | dict(**kwargs) -> new dictionary initialized with the name=value pairs\n",
- " | in the keyword argument list. For example: dict(one=1, two=2)\n",
- " | \n",
- " | Methods defined here:\n",
- " | \n",
- " | __contains__(self, key, /)\n",
- " | True if D has a key k, else False.\n",
- " | \n",
- " | __delitem__(self, key, /)\n",
- " | Delete self[key].\n",
- " | \n",
- " | __eq__(self, value, /)\n",
- " | Return self==value.\n",
- " | \n",
- " | __ge__(self, value, /)\n",
- " | Return self>=value.\n",
- " | \n",
- " | __getattribute__(self, name, /)\n",
- " | Return getattr(self, name).\n",
- " | \n",
- " | __getitem__(...)\n",
- " | x.__getitem__(y) <==> x[y]\n",
- " | \n",
- " | __gt__(self, value, /)\n",
- " | Return self>value.\n",
- " | \n",
- " | __init__(self, /, *args, **kwargs)\n",
- " | Initialize self. See help(type(self)) for accurate signature.\n",
- " | \n",
- " | __iter__(self, /)\n",
- " | Implement iter(self).\n",
- " | \n",
- " | __le__(self, value, /)\n",
- " | Return self<=value.\n",
- " | \n",
- " | __len__(self, /)\n",
- " | Return len(self).\n",
- " | \n",
- " | __lt__(self, value, /)\n",
- " | Return self size of D in memory, in bytes\n",
- " | \n",
- " | clear(...)\n",
- " | D.clear() -> None. Remove all items from D.\n",
- " | \n",
- " | copy(...)\n",
- " | D.copy() -> a shallow copy of D\n",
- " | \n",
- " | fromkeys(iterable, value=None, /) from builtins.type\n",
- " | Returns a new dict with keys from iterable and values equal to value.\n",
- " | \n",
- " | get(...)\n",
- " | D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.\n",
- " | \n",
- " | items(...)\n",
- " | D.items() -> a set-like object providing a view on D's items\n",
- " | \n",
- " | keys(...)\n",
- " | D.keys() -> a set-like object providing a view on D's keys\n",
- " | \n",
- " | pop(...)\n",
- " | D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n",
- " | If key is not found, d is returned if given, otherwise KeyError is raised\n",
- " | \n",
- " | popitem(...)\n",
- " | D.popitem() -> (k, v), remove and return some (key, value) pair as a\n",
- " | 2-tuple; but raise KeyError if D is empty.\n",
- " | \n",
- " | setdefault(...)\n",
- " | D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D\n",
- " | \n",
- " | update(...)\n",
- " | D.update([E, ]**F) -> None. Update D from dict/iterable E and F.\n",
- " | If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]\n",
- " | If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v\n",
- " | In either case, this is followed by: for k in F: D[k] = F[k]\n",
- " | \n",
- " | values(...)\n",
- " | D.values() -> an object providing a view on D's values\n",
- " | \n",
- " | ----------------------------------------------------------------------\n",
- " | Data and other attributes defined here:\n",
- " | \n",
- " | __hash__ = None\n",
- "\n"
- ]
- }
- ],
- "source": [
- "help( dict)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "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.7.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/04_jupyter_and_python_intro/.ipynb_checkpoints/jupyter_and_python_breakout-checkpoint.ipynb b/04_jupyter_and_python_intro/.ipynb_checkpoints/jupyter_and_python_breakout-checkpoint.ipynb
deleted file mode 100644
index 3cd68d5..0000000
--- a/04_jupyter_and_python_intro/.ipynb_checkpoints/jupyter_and_python_breakout-checkpoint.ipynb
+++ /dev/null
@@ -1,620 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Breakout: Simple Math in Python"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The purpose of this breakout is to help you familiarize yourself with executing Python code in the Jupyter notebook, and along the way familiarize yourself with some of the mathematical functionality available in Python.\n",
- "\n",
- "As with many breakouts in this course, you should **do the following with a partner**.\n",
- "One of you should have your fingers on the keyboard, while the other watches and helps decide what to type."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Some Basic Notebook Navigation"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Jupyter notebooks combine text and executable code: a code cell looks like this, and you can run it by pressing enter/return **while holding the shift key**. Try it out here:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "1 + 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Additionally, you'll sometimes want to insert a new cell to add more code. You can do this by using the **[+]** button which is second from the left at the top of the notebook page.\n",
- "Before you continue, insert a new cell below this one to make sure you see how it works."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "*Note* We'll learn more about _Markdown_ later but if you'd like to learn how to incorporate equations into your notebook, google _Markdown_ and _LaTex_"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exploring Arithmetic Operators in Python\n",
- "\n",
- "Python can be used quite straightforwardly as a calculator.\n",
- "Among other commands, it recognizes ``+``, ``-``, ``*``, ``/``, and ``()`` with their typical mathematical meanings.\n",
- "With this in mind, we're going to quickly practice using Python as a calculator.\n",
- "\n",
- "Use Python to solve the following arithmetic problems:"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $4235 + 3154$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $4235 - 3154$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $4235 \\times 3154$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\frac{4235}{3154}$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\frac{4235 - 3154}{2752 + 5013}$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\frac{-(4315 + 378)}{2(65 - 328)}$"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exploring More Specialized Arithmetic\n",
- "\n",
- "Some other useful operators are ``//``, ``%``, and ``**``."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is ``4235 // 3154``?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try the ``//`` operator with some other inputs: can you figure out its meaning?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is ``4235 % 3154``?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try the ``%`` operator with some other inputs: can you figure out its meaning?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is ``4235 ** 3154``?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try the ``**`` operator with some other inputs: can you figure out its meaning?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exploring other Operators\n",
- "\n",
- "There's another class of operators recognized by Python: ``&``, ``|``, ``^``, and ``~``.\n",
- "\n",
- "Play around with these four operators: can you discover their meaning?\n",
- "(Don't worry if you can't: these are quite a bit more obscure than the ones above!)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The ``math`` Module\n",
- "\n",
- "**Please switch roles now, so the second person has fingers-on-keyboard**\n",
- "\n",
- "Along with the basic arithmetic operators, Python has some more sophisticated mathematical operations in the *``math`` module*.\n",
- "A module in Python is a collection of functionality that can be *imported* and used in your script.\n",
- "Importing functionality from modules is *extremely* easy in Python compared to some other languages, and it has an incredible array of standard functionality available through these imports.\n",
- "\n",
- "A popular XKCD comic draws from this idea:\n",
- "\n",
- "\n",
- "\n",
- "The way you import a module, like in this xkcd comic, is to use the ``import`` statement. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import antigravity"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import math"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "With this done, we can now access elements of the ``math`` module using ``math.XXX``, where we replace ``XXX`` with the name of the variable, function, or other object we're interested in.\n",
- "\n",
- "For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# variable containing the value of π\n",
- "math.pi"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# function to compute the square root of a number\n",
- "math.sqrt(2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Use functions in the math module to compute the following:"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sin(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\cos(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\exp(2)$ (otherwise known as $e^2$)?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\log(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sin^2(2) + \\cos^2(2)$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sin(2\\pi)$? (do you notice anything strange?)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exploring Packages with Jupyter"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The Jupyter notebook includes a very convenient way to explore the contents of a module.\n",
- "\n",
- "- If you type ``math.`` followed by the tab key, it will give you a list of valid completions, which in this case consists of a list of all functions and variables in the math module.\n",
- "\n",
- "- If you type any function followed by a question mark (e.g. ``math.cos?``) then shift-enter, it will give you a documentation string"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Use these two convenience features to explore the ``math`` module.\n",
- "\n",
- "Can you find a statement that computes $\\sqrt{x^2 + y^2}$ efficiently in a single line?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $\\sqrt{4235^2 + 3154^2}$?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What is $e^x - 1$ for $x = 10^{-20}$? (Hint: it's not zero!)\n",
- "Can you find a function in the ``math`` module that computes this function accurately?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Please put a yellow post-it on your laptop, so we know that you've finished the exploration.**\n",
- "\n",
- "While you are waiting for others to finish, continue exploring the ``math`` module to see what functionality is available."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "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.7.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/04_jupyter_and_python_intro/python_vars_and_flow_control.ipynb b/04_jupyter_and_python_intro/python_vars_and_flow_control.ipynb
index ad9282e..7e7a370 100755
--- a/04_jupyter_and_python_intro/python_vars_and_flow_control.ipynb
+++ b/04_jupyter_and_python_intro/python_vars_and_flow_control.ipynb
@@ -695,9 +695,11 @@
"metadata": {},
"outputs": [],
"source": [
- "my_dict = { 'tuple' : 'An immutable collection of ordered objects',\n",
- " 'list' : 'A mutable collection of ordered objects',\n",
- " 'dictionary' : 'A mutable collection of objects' }\n",
+ "my_dict = {\n",
+ " 'tuple' : 'An immutable collection of ordered objects',\n",
+ " 'list' : 'A mutable collection of ordered objects',\n",
+ " 'dictionary' : 'A mutable collection of objects'\n",
+ "}\n",
"my_dict"
]
},
@@ -1261,8 +1263,8 @@
"outputs": [],
"source": [
"sum = 0\n",
- "for i in range(10):\n",
- " sum += i\n",
+ "for index in range(10):\n",
+ " sum += index\n",
"print(sum)"
]
},
@@ -1272,7 +1274,7 @@
"source": [
"#### For loops can be nested\n",
"\n",
- "_Note_: for more on formatting strings, see: [https://pyformat.info](https://pyformat.info)"
+ "_Note_: for more on formatting strings, see: [https://realpython.com/python-string-formatting/](https://realpython.com/python-string-formatting/)"
]
},
{
@@ -1281,9 +1283,9 @@
"metadata": {},
"outputs": [],
"source": [
- "for i in range(1, 4):\n",
- " for j in range(1, 4):\n",
- " print('%d * %d = %d' % (i, j, i*j)) # Note string formatting here, %d means an integer"
+ "for index in range(1, 4):\n",
+ " for index2 in range(1, 4):\n",
+ " print(f'{index} * {index2} = {index * index2}')"
]
},
{
@@ -1299,10 +1301,10 @@
"metadata": {},
"outputs": [],
"source": [
- "for i in range(10):\n",
- " if i == 4:\n",
+ "for index in range(10):\n",
+ " if index == 4:\n",
" break\n",
- "i"
+ "index"
]
},
{
@@ -1319,11 +1321,11 @@
"outputs": [],
"source": [
"sum = 0\n",
- "for i in range(10):\n",
- " if (i == 5):\n",
+ "for index in range(10):\n",
+ " if (index == 5):\n",
" continue\n",
" else:\n",
- " sum += i\n",
+ " sum += index\n",
"print(sum)"
]
},
@@ -1341,10 +1343,10 @@
"outputs": [],
"source": [
"sum = 0\n",
- "for i in range(10):\n",
- " sum += i\n",
+ "for index in range(10):\n",
+ " sum += index\n",
"else:\n",
- " print('final i = %d, and sum = %d' % (i, sum))"
+ " print(f'final index = {index}, and sum = {sum}')"
]
},
{
@@ -1361,8 +1363,8 @@
"outputs": [],
"source": [
"my_string = \"SEDS\"\n",
- "for c in my_string:\n",
- " print(c)"
+ "for char in my_string:\n",
+ " print(char)"
]
},
{
@@ -1559,7 +1561,7 @@
"outputs": [],
"source": [
"def print_name(first, last='the Clown'):\n",
- " print('Your name is %s %s' % (first, last))\n",
+ " print(f'Your name is {first} {last}')\n",
" return"
]
},
@@ -1610,7 +1612,7 @@
"source": [
"def print_name_age(first, last, age):\n",
" print_name(first, last)\n",
- " print('Your age is %d' % (age))\n",
+ " print(f'Your age is (age)')\n",
" if age > 55:\n",
" print('You are really old.')\n",
" return"
@@ -1642,7 +1644,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.5"
+ "version": "3.13.0"
}
},
"nbformat": 4,
diff --git a/05_pandas_more_git/data_manipulation.ipynb b/05_pandas_more_git/data_manipulation.ipynb
index ef1cfc4..dae33e9 100755
--- a/05_pandas_more_git/data_manipulation.ipynb
+++ b/05_pandas_more_git/data_manipulation.ipynb
@@ -85,6 +85,13 @@
"import numpy as np"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -1040,15 +1047,6 @@
"Whenever you do plotting in the IPython notebook, you will want to first run this *magic command* which configures the notebook to work well with plots:"
]
},
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%matplotlib inline"
- ]
- },
{
"cell_type": "markdown",
"metadata": {},
@@ -1281,7 +1279,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.5"
+ "version": "3.13.0"
}
},
"nbformat": 4,
diff --git a/07_debug_exceptions_testing/.ipynb_checkpoints/Debugging-checkpoint.ipynb b/07_debug_exceptions_testing/.ipynb_checkpoints/Debugging-checkpoint.ipynb
deleted file mode 100644
index 9b84c4a..0000000
--- a/07_debug_exceptions_testing/.ipynb_checkpoints/Debugging-checkpoint.ipynb
+++ /dev/null
@@ -1,564 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Errors, or bugs, in your software\n",
- "\n",
- "Today we'll cover dealing with errors in your Python code, an important aspect of writing software.\n",
- "\n",
- "#### What is a software bug?\n",
- "\n",
- "According to [Wikipedia](https://en.wikipedia.org/wiki/Software_bug) (accessed 16 Oct 2018), a software bug is an error, flaw, failure, or fault in a computer program or system that causes it to produce an incorrect or unexpected result, or behave in unintended ways.\n",
- "\n",
- "#### Where did the terminology come from?\n",
- "\n",
- "Engineers have used the term well before electronic computers and software. Sometimes Thomas Edison is credited with the first recorded use of bug in that fashion. [[Wikipedia](https://en.wikipedia.org/wiki/Software_bug#Etymology)]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### If incorrect code is never executed, is it a bug?\n",
- "\n",
- "This is the software equivalent to \"If a tree falls and no one hears it, does it make a sound?\". "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Three classes of bugs\n",
- "\n",
- "Let's discuss three major types of bugs in your code, from easiest to most difficult to diagnose:\n",
- "\n",
- "1. **Syntax errors:** Errors where the code is not written in a valid way. (Generally easiest to fix.)\n",
- "1. **Runtime errors:** Errors where code is syntactically valid, but fails to execute. Often throwing exceptions here. (Sometimes easy to fix, harder when in other's code.)\n",
- "1. **Semantic errors:** Errors where code is syntactically valid, but contain errors in logic. (Can be difficult to fix.)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Syntax errors"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "ename": "SyntaxError",
- "evalue": "Missing parentheses in call to 'print'. Did you mean print(\"This should only work in Python 2.x, not 3.x used in this class.)? (, line 1)",
- "output_type": "error",
- "traceback": [
- "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m print \"This should only work in Python 2.x, not 3.x used in this class.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m Missing parentheses in call to 'print'. Did you mean print(\"This should only work in Python 2.x, not 3.x used in this class.)?\n"
- ]
- }
- ],
- "source": [
- "print \"This should only work in Python 2.x, not 3.x used in this class."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "tags": [
- "hide"
- ]
- },
- "source": [
- "## INSTRUCTOR NOTE:\n",
- "\n",
- "1. Run as-is. Run. Error. Returns `SyntaxError: Missing parentheses in call to print.`\n",
- "1. Add parentheses. Run. Still an error. Returns `SyntaxError: EOL while scanning string literal`.\n",
- "1. Add closing quotation mark. Run. Should be successful."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = 1; y = 2\n",
- "b = x == y # Boolean variable that is true when x & y have the same value\n",
- "b = 1 = 2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## INSTRUCTOR NOTE:\n",
- "\n",
- "1. Emphasize the difference between the single and double equal operator."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Runtime errors"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "scrolled": false
- },
- "outputs": [],
- "source": [
- "# invalid operation\n",
- "try:\n",
- " a = 0\n",
- " 5/a # Division by zero"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# invalid operation\n",
- "input = '40'\n",
- "input/11 # Incompatiable types for the operation"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Semantic errors\n",
- "\n",
- "Say we're trying to confirm that a trigonometric identity holds. Let's use the basic relationship between sine and cosine, given by the Pythagorean identity\"\n",
- "\n",
- "$$\n",
- "\\sin^2 \\theta + \\cos^2 \\theta = 1\n",
- "$$\n",
- "\n",
- "We can write a function to check this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import math\n",
- "\n",
- "'''Checks that Pythagorean identity holds for one input, theta'''\n",
- "def check_pythagorean_identity(theta):\n",
- " return math.sin(theta)**2 + math.cos(theta)**2 == 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "check_pythagorean_identity(.4)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## How to find and resolve bugs?\n",
- "\n",
- "Debugging has the following steps:\n",
- "\n",
- "1. **Detection** of an exception or invalid results. \n",
- "2. **Isolation** of where the program causes the error. This is often the most difficult step.\n",
- "3. **Resolution** of how to change the code to eliminate the error. Mostly, it's not too bad, but sometimes this can cause major revisions in codes.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Detection of Bugs\n",
- "\n",
- "The detection of bugs is too often done by chance. While running your Python code, you encounter unexpected functionality, exceptions, or syntax errors. While we'll focus on this in today's lecture, you should never leave this up to chance in the future.\n",
- "\n",
- "Software testing practices allow for thoughtful detection of bugs in software. We'll discuss more in the lecture on testing."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "### Isolation of Bugs\n",
- "\n",
- "There are three main methods commonly used for bug isolation:\n",
- "1. The \"thought\" method. Think about how your code is structured and so what part of your could would most likely lead to the exception or invalid result.\n",
- "2. Inserting ``print`` statements (or other logging techniques)\n",
- "3. Using a line-by-line debugger like ``pdb``.\n",
- "\n",
- "Typically, all three are used in combination, often repeatedly."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Using `print` statements\n",
- "\n",
- "Say we're trying to compute the **entropy** of a set of probabilities. The\n",
- "form of the equation is\n",
- "\n",
- "$$\n",
- "H = -\\sum_i p_i \\log(p_i)\n",
- "$$\n",
- "\n",
- "We can write the function like this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def entropy(p):\n",
- " \"\"\"\n",
- " arg p: list of float\n",
- " \"\"\"\n",
- " check1 = []\n",
- " for ele in p:\n",
- " check1.append((ele <= 1) and (ele >= 0))\n",
- " check2 = 1 == sum(p)\n",
- " if all(check1) and check2:\n",
- " items = p * np.log(p)\n",
- " return -np.sum(items)\n",
- " else:\n",
- " return -1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "p = [1.0]\n",
- "items = p * np.log(p)\n",
- "print(items)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "-sum(items)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(entropy([0.5, 0.5]))\n",
- "print(entropy([0.25, 0.25, 0.25, 0.25]))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "entropy([1.0, 0])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If we can't easily see the bug here, let's add print statements to see the variables change over time."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## INSTRUCTOR NOTE:\n",
- "\n",
- "1. Add print statements in tiered way, starting with simple print statements.\n",
- "1. Point out that may need slight refactor on result.\n",
- "\n",
- " ```python\n",
- " def entropy(p):\n",
- " print(p)\n",
- " items = p * np.log(p)\n",
- " print(items)\n",
- " result = -np.sum(items)\n",
- " print(result)\n",
- " return result\n",
- " ```\n",
- "\n",
- "1. Show complication of reading multiple print statements without labels.\n",
- "1. Add labels so code looks like below.\n",
- "\n",
- " ```python\n",
- " def entropy(p):\n",
- " print(\"p=%s\" % p)\n",
- " items = p * np.log(p)\n",
- " print(\"items=%s\" % items)\n",
- " result = -np.sum(items)\n",
- " print(\"result=%s\" % result)\n",
- " return result\n",
- " ```"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "np.add?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Note that the print statements significantly reduce legibility of the code. We would like to remove them when we're done debugging."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def entropy(p):\n",
- " items = p * np.log(p)\n",
- " return -np.sum(items)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "p = [0.1, 0.3, 0.5, 0.7, 0.9]\n",
- "entropy(p)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now it works fine for the first set of inputs. Let's try other inputs."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We should have documented the inputs to the function!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Create a vector of probabilities.\n",
- "p = np.arange(start=5., stop=-1., step=-0.5)\n",
- "p /= np.sum(p)\n",
- "p"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "entropy(p)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We get ``nan``, which stands for \"Not a Number\". What's going on here?\n",
- "\n",
- "Let's add our print statements again, but it only fails later in the range of numbers. We may choose to print only if we find a `nan`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def entropy1(p):\n",
- " print(\"p=%s\" % str(p))\n",
- " items = p * np.log(p)\n",
- " if [np.isnan(el) for el in items]:\n",
- " print(items)\n",
- " return -np.sum(items)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "entropy1([.1, .2])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "entropy1(p)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "By printing some of the intermediate items, we see the problem: 0 * np.log(0) is resulting in a NaN. Though mathematically it's true that limx→0[xlog(x)]=0limx→0[xlog(x)]=0, the fact that we're performing the computation numerically means that we don't obtain this result.\n",
- "\n",
- "Often, inserting a few print statements can be enough to figure out what's going on.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def entropy2(p):\n",
- " p = np.asarray(p) # convert p to array if necessary\n",
- " print(p)\n",
- " items = []\n",
- " for val in p:\n",
- " item = val * np.log(val)\n",
- " if np.isnan(item):\n",
- " print(\"%f makes a nan\" % val)\n",
- " items.append(item)\n",
- " #items = p * np.log(ps)\n",
- " return -np.sum(items)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "entropy2(p)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Using Python's debugger, `pdb`\n",
- "\n",
- "Python comes with a built-in debugger called [pdb](http://docs.python.org/2/library/pdb.html). It allows you to step line-by-line through a computation and examine what's happening at each step. Note that this should probably be your last resort in tracing down a bug. I've probably used it a dozen times or so in five years of coding. But it can be a useful tool to have in your toolbelt.\n",
- "\n",
- "You can use the debugger by inserting the line\n",
- "``` python\n",
- "import pdb; pdb.set_trace()\n",
- "```\n",
- "within your script. To leave the debugger, type \"exit()\". To see the commands you can use, type \"help\".\n",
- "\n",
- "Let's try this out:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def entropy(p):\n",
- " items = p * np.log(p)\n",
- " import pdb; pdb.set_trace()\n",
- " return -np.sum(items)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This can be a more convenient way to debug programs and step through the actual execution."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "p = [.1, -.2, .3]\n",
- "entropy(p)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "p = \"[0.1, 0.3, 0.5, 0.7, 0.9]\"\n",
- "entropy(p)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "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.8.3"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/07_debug_exceptions_testing/.ipynb_checkpoints/Exceptions-checkpoint.ipynb b/07_debug_exceptions_testing/.ipynb_checkpoints/Exceptions-checkpoint.ipynb
deleted file mode 100644
index 31e0b1f..0000000
--- a/07_debug_exceptions_testing/.ipynb_checkpoints/Exceptions-checkpoint.ipynb
+++ /dev/null
@@ -1,320 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Exceptions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.\n",
- "\n",
- "You've already seen some exceptions in the **Debugging** lesson.\n",
- "* "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Many programs want to know about exceptions when they occur. For example, if the input to a program is a file path. If the user inputs an invalid or non-existent path, the program generates an exception. It may be desired to provide a response to the user in this case."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It may also be that programs will *generate* exceptions. This is a way of indicating that there is an error in the inputs provided. In general, this is the preferred style for dealing with invalid inputs or states inside a python function rather than having an error return."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Catching Exceptions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Python provides a way to detect when an exception occurs. This is done by the use of a block of code surrounded by a \"try\" and \"except\" statement."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "def divide(numerator, denominator):\n",
- " result = numerator/denominator\n",
- " print(\"result = %f\" % result)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "result = 0.000000\n"
- ]
- }
- ],
- "source": [
- "divide(0, 1.0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "def divide1(numerator, denominator):\n",
- " try:\n",
- " result = numerator/denominator\n",
- " print(\"result = %f\" % result)\n",
- " except:\n",
- " print(\"You can't divide by 0!\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "You can't divide by 0!\n"
- ]
- }
- ],
- "source": [
- "divide1(1.0, 'a')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "divide1(1.0, 2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "divide1(\"x\", 2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [],
- "source": [
- "def divide2(numerator, denominator):\n",
- " try:\n",
- " result = numerator / denominator\n",
- " print(\"result = %f\" % result)\n",
- " except (ZeroDivisionError, TypeError) as err:\n",
- " print(\"Got an exception: %s\" % err)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Got an exception: unsupported operand type(s) for /: 'int' and 'str'\n"
- ]
- }
- ],
- "source": [
- "divide2(1, \"X\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "divide2(\"x, 2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Why didn't we catch this `SyntaxError`?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Handle division by 0 by using a small number\n",
- "SMALL_NUMBER = 1e-3\n",
- "def divide3(numerator, denominator):\n",
- " try:\n",
- " result = numerator/denominator\n",
- " except ZeroDivisionError:\n",
- " result = numerator/SMALL_NUMBER\n",
- " print(\"result = %f\" % result)\n",
- " except Exception as err:\n",
- " print(\"Different error than division by zero:\", err)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "divide3(1,0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "divide3(\"1\",0)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### What do you do when you get an exception?\n",
- "\n",
- "First, you can feel relieved that you caught a problematic element of your software! Yes, relieved. Silent fails are much worse. (Again, another plug for testing.)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Generating Exceptions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Why *generate* exceptions? (Don't I have enough unintentional errors?)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas as pd\n",
- "def validateDF(df):\n",
- " \"\"\"\"\n",
- " :param pd.DataFrame df: should have a column named \"hours\"\n",
- " \"\"\"\n",
- " if not \"hours\" in df.columns:\n",
- " raise ValueError(\"DataFrame should have a column named 'hours'.\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [],
- "source": [
- "df = pd.DataFrame({'hours': range(10) })\n",
- "validateDF(df)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "DataFrame should have a column named 'hours'.",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m-------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mdf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDataFrame\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'years'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mvalidateDF\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m\u001b[0m in \u001b[0;36mvalidateDF\u001b[0;34m(df)\u001b[0m\n\u001b[1;32m 5\u001b[0m \"\"\"\n\u001b[1;32m 6\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;34m\"hours\"\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcolumns\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"DataFrame should have a column named 'hours'.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m: DataFrame should have a column named 'hours'."
- ]
- }
- ],
- "source": [
- "df = pd.DataFrame({'years': range(10) })\n",
- "validateDF(df)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Class exercise\n",
- "Choose one of the functions from the last exercise. Create two new functions:\n",
- "- The first function throws an exception if there is a negative argument.\n",
- "- The second function catches an exception if the modulo operator (`%`) throws an exception and attempts to correct it by coercing the argument to a positive integer."
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "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.8.3"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/07_debug_exceptions_testing/.ipynb_checkpoints/unit-tests-checkpoint.ipynb b/07_debug_exceptions_testing/.ipynb_checkpoints/unit-tests-checkpoint.ipynb
deleted file mode 100644
index cd791f3..0000000
--- a/07_debug_exceptions_testing/.ipynb_checkpoints/unit-tests-checkpoint.ipynb
+++ /dev/null
@@ -1,769 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Unit Tests"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Overview and Principles\n",
- "Testing is the process by which you exercise your code to determine if it performs as expected. The code you are testing is referred to as the **code under test**. \n",
- "\n",
- "There are two parts to writing tests.\n",
- "1. invoking the code under test so that it is exercised in a particular way;\n",
- "1. evaluating the results of executing code under test to determine if it behaved as expected.\n",
- "\n",
- "The collection of tests performed are referred to as the **test cases**. The fraction of the code under test that is executed as a result of running the test cases is referred to as **test coverage**.\n",
- "\n",
- "For dynamical languages such as Python, it's extremely important to have a high test coverage. In fact, you should try to get 100% coverage. This is because little checking is done when the source code is read by the Python interpreter. For example, the code under test might contain a line that has a function that is undefined. This would not be detected until that line of code is executed.\n",
- "\n",
- "Test cases can be of several types. Below are listed some common classifications of test cases.\n",
- "- *Smoke test*. This is an invocation of the code under test to see if there is an unexpected exception. It's useful as a starting point, but this doesn't tell you anything about the correctness of the results of a computation.\n",
- "- *One-shot test*. In this case, you call the code under test with arguments for which you know the expected result.\n",
- "- *Edge test*. The code under test is invoked with arguments that should cause an exception, and you evaluate if the expected exception occurrs.\n",
- "- *Pattern test* - Based on your knowledge of the *calculation* (not implementation) of the code under test, you construct a suite of test cases for which the results are known or there are known patterns in these results that are used to evaluate the results returned.\n",
- "\n",
- "Another principle of testing is to limit what is done in a single test case. Generally, a test case should focus on one use of one function. Sometimes, this is a challenge since the function being tested may call other functions that you are testing. This means that bugs in the called functions may cause failures in the tests of the calling functions. Often, you sort this out by knowing the structure of the code and focusing first on failures in lower level tests. In other situations, you may use more advanced techniques called *mocking*. A discussion of mocking is beyond the scope of this course.\n",
- "\n",
- "A best practice is to develop your tests while you are developing your code. Indeed, one school of thought in software engineering, called **test-driven development**, advocates that you write the tests *before* you implement the code under test so that the test cases become a kind of specification for what the code under test should do."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Examples of Test Cases\n",
- "This section presents examples of test cases. The code under test is the calculation of entropy."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Entropy of a set of probabilities\n",
- "$$\n",
- "H = -\\sum_i p_i \\log(p_i)\n",
- "$$\n",
- "where $\\sum_i p_i = 1$."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "# Code Under Test\n",
- "def entropy(ps):\n",
- " if any([(p < 0.0) or (p > 1.0) for p in ps]):\n",
- " raise ValueError(\"Bad input.\")\n",
- " if sum(ps) > 1:\n",
- " raise ValueError(\"Bad input.\")\n",
- " items = ps * np.log(ps)\n",
- " new_items = []\n",
- " for item in items:\n",
- " if np.isnan(item):\n",
- " new_items.append(0)\n",
- " else:\n",
- " new_items.append(item)\n",
- " return np.abs(-np.sum(new_items))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[True, False]"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "ps = [.8, .2]\n",
- "ps = [ 1.00000001, 0]\n",
- "[(p < 0.0) or (p > 1.0) for p in ps]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.isclose(1.1, 1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.5004024235381879"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Smoke test\n",
- "entropy([0.2, 0.8])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- ":8: RuntimeWarning: divide by zero encountered in log\n",
- " items = ps * np.log(ps)\n",
- ":8: RuntimeWarning: invalid value encountered in multiply\n",
- " items = ps * np.log(ps)\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "0.0"
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# One shot test\n",
- "entropy([1, 0, 0, 0])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Suppose that all of the probability of a distribution is at one point. An example of this is a coin with two heads. Whenever you flip it, you always get heads. That is, the probability of a head is 1.\n",
- "\n",
- "What is the entropy of such a distribution? From the calculation above, we see that the entropy should be $log(1)$, which is 0. This means that we have a test case where we know the result!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Test completed!\n"
- ]
- }
- ],
- "source": [
- "# One-shot test. Need to know the correct answer.\n",
- "entries = [\n",
- " [0, [1]],\n",
- "]\n",
- "\n",
- "for entry in entries:\n",
- " ans = entry[0]\n",
- " prob = entry[1]\n",
- " if not np.isclose(entropy(prob), ans):\n",
- " print(\"Test failed!\")\n",
- "print (\"Test completed!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Question**: What is an example of another one-shot test? (Hint: You need to know the expected result.)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "One edge test of interest is to provide an input that is *not* a distribution in that probabilities don't sum to 1."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "Bad input.",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Edge test. This is something that should cause an exception.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mentropy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m\u001b[0m in \u001b[0;36mentropy\u001b[0;34m(ps)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mentropy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mps\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m0.0\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1.0\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mp\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mps\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Bad input.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mps\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Bad input.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mValueError\u001b[0m: Bad input."
- ]
- }
- ],
- "source": [
- "# Edge test. This is something that should cause an exception.\n",
- "entropy([-0.5])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's consider a pattern test. Examining the structure of the calculation of $H$, we consider a situation in which there are $n$ equal probabilities. That is, $p_i = \\frac{1}{n}$.\n",
- "$$\n",
- "H = -\\sum_{i=1}^{n} p_i \\log(p_i) \n",
- "= -\\sum_{i=1}^{n} \\frac{1}{n} \\log(\\frac{1}{n}) \n",
- "= n (-\\frac{1}{n} \\log(\\frac{1}{n}) )\n",
- "= -\\log(\\frac{1}{n})\n",
- "$$\n",
- "For example, entropy([0.5, 0.5]) should be $-log(0.5)$."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Worked!\n"
- ]
- }
- ],
- "source": [
- "# Pattern test\n",
- "def test_equal_probabilities(n):\n",
- " prob = 1.0/n\n",
- " ps = np.repeat(prob , n)\n",
- " if np.isclose(entropy(ps), -np.log(prob)):\n",
- " print(\"Worked!\")\n",
- " else:\n",
- " import pdb; pdb.set_trace()\n",
- " print (\"Bad result.\")\n",
- " \n",
- " \n",
- "# Run a test\n",
- "test_equal_probabilities(100000)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You see that there are many, many cases to test. So far, we've been writing special codes for each test case. We can do better."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Testing Data Producing Codes\n",
- "Much of your python (or R) codes will be creating and/or transforming dataframes. A dataframe is structured like a table with:\n",
- "\n",
- "- Columns that have values of the same type\n",
- "- Rows that have a value for each column\n",
- "- An index that uniquely identifies a row."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [],
- "source": [
- "def makeProbabilityMatrix(column_names, nrows):\n",
- " \"\"\"\n",
- " Makes a dataframe with the specified column names such that each\n",
- " cell is a value in [0, 1] and columns sum to 1.\n",
- " :param list-str column_names: names of the columns\n",
- " :param int nrows: number of rows\n",
- " \"\"\"\n",
- " df = pd.DataFrame(np.random.uniform(0, 1, (nrows, len(column_names))))\n",
- " df.columns = column_names\n",
- " for column in df.columns:\n",
- " df[column] = df[column]/df[column].sum()\n",
- " return df\n",
- " "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " a | \n",
- " b | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 0.166534 | \n",
- " 0.301116 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 0.648088 | \n",
- " 0.412220 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 0.185378 | \n",
- " 0.286663 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " a b\n",
- "0 0.166534 0.301116\n",
- "1 0.648088 0.412220\n",
- "2 0.185378 0.286663"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Smoke test\n",
- "makeProbabilityMatrix(['a', 'b'], 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Test 2: Check columns\n",
- "COLUMNS = ['a', 'b']\n",
- "df = makeProbabilityMatrix(COLUMNS, 3)\n",
- "set(COLUMNS) == set(df.columns)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise\n",
- "Write a function that tests the following:\n",
- "- The returned dataframe has the expected columns\n",
- "- The returned dataframe has the expected rows\n",
- "- Values in columns are of the correct type and range\n",
- "- Values in column sum to 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Unittest Infrastructure"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There are several reasons to use a test infrastructure:\n",
- "- If you have many test cases (which you should!), the test infrastructure will save you from writing a lot of code.\n",
- "- The infrastructure provides a uniform way to report test results, and to handle test failures.\n",
- "- A test infrastructure can tell you about coverage so you know what tests to add.\n",
- "\n",
- "We'll be using the `unittest` framework. This is a separate Python package. Using this infrastructure, requires the following:\n",
- "1. import the unittest module\n",
- "1. define a class that inherits from unittest.TestCase\n",
- "1. write methods that run the code to be tested and check the outcomes.\n",
- "\n",
- "The last item has two subparts. First, we must identify which methods in the class inheriting from unittest.TestCase are tests. You indicate that a method is to be run as a test by having the method name begin with \"test\".\n",
- "\n",
- "Second, the \"test methods\" should communicate with the infrastructure the results of evaluating output from the code under test. This is done by using `assert` statements. For example, `self.assertEqual` takes two arguments. If these are objects for which `==` returns `True`, then the test passes. Otherwise, the test fails."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "scrolled": true
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "...\n",
- "----------------------------------------------------------------------\n",
- "Ran 3 tests in 0.002s\n",
- "\n",
- "OK\n"
- ]
- }
- ],
- "source": [
- "import unittest\n",
- "\n",
- "# Define a class in which the tests will run\n",
- "class UnitTests(unittest.TestCase):\n",
- "\n",
- " # Each method in the class to execute a test\n",
- " def test_success(self):\n",
- " self.assertEqual(1, 1)\n",
- " \n",
- " def test_success1(self):\n",
- " self.assertTrue(1 == 1)\n",
- "\n",
- " def test_failure(self):\n",
- " self.assertLess(1, 2)\n",
- " \n",
- "suite = unittest.TestLoader().loadTestsFromTestCase(UnitTests)\n",
- "_ = unittest.TextTestRunner().run(suite)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Function the handles test loading"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Code for homework or your work should use test files.** In this lesson, we'll show how to write test codes in a Jupyter notebook. This is done for pedidogical reasons. It is **NOT** not something you should do in practice, except as an intermediate exploratory approach. "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As expected, the first test passes, but the second test fails."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise\n",
- "- Rewrite the above one-shot test for entropy using the unittest infrastructure."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Implementating a pattern test. Use functions in the test.\n",
- "import unittest\n",
- "\n",
- "# Define a class in which the tests will run\n",
- "class TestEntropy(unittest.TestCase):\n",
- " \n",
- " def test_equal_probability(self):\n",
- " def test(count):\n",
- " \"\"\"\n",
- " Invokes the entropy function for a number of values equal to count\n",
- " that have the same probability.\n",
- " :param int count:\n",
- " \"\"\"\n",
- " raise RuntimeError (\"Not implemented.\")\n",
- " #\n",
- " test(2)\n",
- " test(20)\n",
- " test(200)\n",
- "\n",
- "#test_setup(TestEntropy)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [],
- "source": [
- "import unittest\n",
- "\n",
- "# Define a class in which the tests will run\n",
- "class TestEntropy(unittest.TestCase):\n",
- " \"\"\"Write the full set of tests.\"\"\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Testing For Exceptions\n",
- "\n",
- "Edge test cases often involves handling exceptions. One approach is to code this directly."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [],
- "source": [
- "import unittest\n",
- "\n",
- "# Define a class in which the tests will run\n",
- "class TestEntropy(unittest.TestCase):\n",
- " \n",
- " def test_invalid_probability(self):\n",
- " try:\n",
- " entropy([0.1, 0.5])\n",
- " self.assertTrue(False)\n",
- " except ValueError:\n",
- " self.assertTrue(True)\n",
- " \n",
- "#test_setup(TestEntropy)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`unittest` provides help with testing exceptions."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "F\n",
- "======================================================================\n",
- "FAIL: test_invalid_probability (__main__.TestEntropy)\n",
- "----------------------------------------------------------------------\n",
- "Traceback (most recent call last):\n",
- " File \"\", line 8, in test_invalid_probability\n",
- " entropy([0.1, 0.5])\n",
- "AssertionError: ValueError not raised\n",
- "\n",
- "----------------------------------------------------------------------\n",
- "Ran 1 test in 0.001s\n",
- "\n",
- "FAILED (failures=1)\n"
- ]
- }
- ],
- "source": [
- "import unittest\n",
- "\n",
- "# Define a class in which the tests will run\n",
- "class TestEntropy(unittest.TestCase):\n",
- " \n",
- " def test_invalid_probability(self):\n",
- " with self.assertRaises(ValueError):\n",
- " entropy([0.1, 0.5])\n",
- " \n",
- "suite = unittest.TestLoader().loadTestsFromTestCase(TestEntropy)\n",
- "_ = unittest.TextTestRunner().run(suite)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Test Files\n",
- "Although I presented the elements of `unittest` in a notebook. **your tests should be in a file**. If the name of module with the code under test is `foo.py`, then the name of the test file should be `test_foo.py`.\n",
- "\n",
- "The structure of the test file will be very similar to cells above. You will import `unittest`. You must also import the module with the code under test. Take a look at `test_prime.py` in this directory to see an example."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Discussion\n",
- "**Question**: What tests would you write for a plotting function?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Test Driven Development\n",
- "Start by writing the tests. Then write the code.\n",
- "\n",
- "We illustrate this by considering a function geomean that takes a list of numbers as input and produces the geometric mean on output."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [],
- "source": [
- "import unittest\n",
- "\n",
- "# Define a class in which the tests will run\n",
- "class TestEntropy(unittest.TestCase):\n",
- " \n",
- " def test_oneshot(self):\n",
- " self.assertEqual(geomean([1,1]), 1)\n",
- " \n",
- " def test_oneshot2(self):\n",
- " self.assertEqual(geomean([3, 3, 3]), 3)\n",
- " \n",
- "#test_setup(TestGeomean)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "#def geomean(argument?):\n",
- "# return ?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Other infrastructures\n",
- "- pytest\n",
- "- nose\n",
- "- Use binary functions that being with \"test\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## References\n",
- "\n",
- "https://www.youtube.com/watch?v=GEqM9uJi64Q (Pydata 2015)\n",
- "https://www.youtube.com/watch?v=yACtdj1_IxE (Pycon 2017)\n",
- "\n",
- "The first talk mentions some packages:\n",
- "engarde - https://github.com/TomAugspurger/engarde\n",
- "Hypothesis - https://hypothesis.readthedocs.io/en/latest/\n",
- "Feature Forge - https://github.com/machinalis/featureforge\n",
- "\n",
- "\n",
- "Detlef Nauck talk: \n",
- "http://ukkdd.org.uk/2017/info/talks/nauck.pdf\n",
- "He also had a list of R tools but I could not find the slides form the talk I saw.\n",
- "\n",
- "Test Driven Data Analysis:\n",
- "https://www.youtube.com/watch?v=TGwZnZYg0jw\n",
- "\n",
- "Profiling for Pandas:\n",
- "https://github.com/pandas-profiling/pandas-profiling"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "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.8.3"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/07_debug_exceptions_testing/Debugging.ipynb b/07_debug_exceptions_testing/Debugging.ipynb
index 9eb7783..0175542 100755
--- a/07_debug_exceptions_testing/Debugging.ipynb
+++ b/07_debug_exceptions_testing/Debugging.ipynb
@@ -107,14 +107,12 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {
- "scrolled": false
- },
+ "metadata": {},
"outputs": [],
"source": [
"# invalid operation\n",
- "a = 0\n",
- "5/a # Division by zero"
+ "val = 0\n",
+ "5/val # Division by zero"
]
},
{
@@ -201,7 +199,10 @@
{
"cell_type": "markdown",
"metadata": {
- "collapsed": true
+ "collapsed": true,
+ "jupyter": {
+ "outputs_hidden": true
+ }
},
"source": [
"### Isolation of Bugs\n",
@@ -238,9 +239,9 @@
"metadata": {},
"outputs": [],
"source": [
- "def entropy(p):\n",
+ "def entropy(prob):\n",
" items = []\n",
- " for p_i in p:\n",
+ " for p_i in prob:\n",
" interm = p_i * np.log2(p_i)\n",
" items.append(interm)\n",
" return -np.sum(items)"
@@ -320,10 +321,10 @@
"metadata": {},
"outputs": [],
"source": [
- "def entropy(p):\n",
- " print(f\"p: {p}\")\n",
+ "def entropy(prob):\n",
+ " print(f\"prob: {prob}\")\n",
" items = []\n",
- " for p_i in p:\n",
+ " for p_i in prob:\n",
" print(f\"p_i: {p_i}\")\n",
" interm = p_i * np.log2(p_i)\n",
" print(f\"interm: {interm}\")\n",
@@ -356,23 +357,23 @@
"metadata": {},
"outputs": [],
"source": [
- "def entropy(p):\n",
+ "def entropy(prob):\n",
" \"\"\"\n",
" arg p: list of float\n",
" \"\"\"\n",
" # begin by checking all inputs are between 0 and 1 inclusive\n",
" check1 = []\n",
- " for ele in p:\n",
+ " for ele in prob:\n",
" check1.append((ele <= 1) and (ele >= 0))\n",
" else:\n",
" pass\n",
" # verify the sum of the probabilities is 1\n",
" # note, the use of np.isclose is correct but the following \n",
" # may not return the expected result\n",
- " # check2 = 1 == np.sum(p)\n",
- " check2 = np.isclose(1, np.sum(p), atol=1e-08)\n",
+ " # check2 = 1 == np.sum(prob)\n",
+ " check2 = np.isclose(1, np.sum(prob), atol=1e-08)\n",
" if all(check1) and check2:\n",
- " items = p * np.log2(p)\n",
+ " items = prob * np.log2(prob)\n",
" return -np.sum(items)\n",
" else:\n",
" return -1"
@@ -466,9 +467,9 @@
"1. Point out that may need slight refactor on result.\n",
"\n",
" ```python\n",
- " def entropy(p):\n",
- " print(p)\n",
- " items = p * np.log(p)\n",
+ " def entropy(prob):\n",
+ " print(prob)\n",
+ " items = prob * np.log(prob)\n",
" print(items)\n",
" result = -np.sum(items)\n",
" print(result)\n",
@@ -479,12 +480,12 @@
"1. Add labels so code looks like below.\n",
"\n",
" ```python\n",
- " def entropy(p):\n",
- " print(\"p=%s\" % p)\n",
- " items = p * np.log(p)\n",
- " print(\"items=%s\" % items)\n",
+ " def entropy(prob):\n",
+ " print(f\"prob={prob}\")\n",
+ " items = prob * np.log(prob)\n",
+ " print(f\"items={items}\")\n",
" result = -np.sum(items)\n",
- " print(\"result=%s\" % result)\n",
+ " print(f\"result={result}\")\n",
" return result\n",
" ```"
]
@@ -526,9 +527,9 @@
"outputs": [],
"source": [
"# Create a vector of probabilities.\n",
- "p = np.arange(start=5., stop=-1., step=-0.5)\n",
- "p /= np.sum(p)\n",
- "p"
+ "prob = np.arange(start=5., stop=-1., step=-0.5)\n",
+ "prob /= np.sum(prob)\n",
+ "prob"
]
},
{
@@ -537,7 +538,7 @@
"metadata": {},
"outputs": [],
"source": [
- "entropy(p)"
+ "entropy(prob)"
]
},
{
@@ -551,13 +552,13 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "def entropy1(p):\n",
- " print(\"p=%s\" % str(p))\n",
- " items = p * np.log2(p)\n",
+ "def entropy1(prob):\n",
+ " print(f\"prob={prob}\")\n",
+ " items = prob * np.log2(prob)\n",
" if [np.isnan(el) for el in items]:\n",
" print(items)\n",
" else:\n",
@@ -580,7 +581,7 @@
"metadata": {},
"outputs": [],
"source": [
- "entropy1(p)"
+ "entropy1(prob)"
]
},
{
@@ -598,11 +599,11 @@
"metadata": {},
"outputs": [],
"source": [
- "def entropy2(p):\n",
- " p = np.asarray(p) # convert p to array if necessary\n",
- " print(p)\n",
+ "def entropy2(prob):\n",
+ " prob = np.asarray(prob) # convert p to array if necessary\n",
+ " print(prob)\n",
" items = []\n",
- " for val in p:\n",
+ " for val in prob:\n",
" item = val * np.log2(val)\n",
" if np.isnan(item):\n",
" print(\"%f makes a nan\" % val)\n",
@@ -619,7 +620,7 @@
"metadata": {},
"outputs": [],
"source": [
- "entropy2(p)"
+ "entropy2(prob)"
]
},
{
@@ -645,8 +646,8 @@
"metadata": {},
"outputs": [],
"source": [
- "def entropy(p):\n",
- " items = p * np.log2(p)\n",
+ "def entropy(prob):\n",
+ " items = prob * np.log2(prob)\n",
" import pdb; pdb.set_trace()\n",
" return -np.sum(items)"
]
@@ -664,8 +665,8 @@
"metadata": {},
"outputs": [],
"source": [
- "p = [.1, -.2, .3]\n",
- "entropy(p)"
+ "prob = [.1, -.2, .3]\n",
+ "entropy(prob)"
]
},
{
@@ -674,14 +675,21 @@
"metadata": {},
"outputs": [],
"source": [
- "p = \"[0.1, 0.3, 0.5, 0.7, 0.9]\"\n",
- "entropy(p)"
+ "prob = \"[0.1, 0.3, 0.5, 0.7, 0.9]\"\n",
+ "entropy(prob)"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -695,9 +703,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.1"
+ "version": "3.13.0"
}
},
"nbformat": 4,
- "nbformat_minor": 1
+ "nbformat_minor": 4
}
diff --git a/07_debug_exceptions_testing/Exceptions.ipynb b/07_debug_exceptions_testing/Exceptions.ipynb
index 64aa475..e42dd17 100755
--- a/07_debug_exceptions_testing/Exceptions.ipynb
+++ b/07_debug_exceptions_testing/Exceptions.ipynb
@@ -61,7 +61,7 @@
"source": [
"def divide(numerator, denominator):\n",
" result = numerator/denominator\n",
- " print(\"result = %f\" % result)"
+ " print(f\"result = {result}\")"
]
},
{
@@ -82,7 +82,7 @@
"def divide1(numerator, denominator):\n",
" try:\n",
" result = numerator/denominator\n",
- " print(\"result = %f\" % result)\n",
+ " print(f\"result = {result}\")\n",
" except:\n",
" print(\"You can't divide by 0!\")"
]
@@ -137,9 +137,9 @@
"def divide2(numerator, denominator):\n",
" try:\n",
" result = numerator / denominator\n",
- " print(\"result = %f\" % result)\n",
+ " print(f\"result = {result}\")\n",
" except (ZeroDivisionError, TypeError) as err:\n",
- " print(\"Got an exception: %s\" % err)"
+ " print(f\"Got an exception: {err}\")"
]
},
{
@@ -194,7 +194,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -239,7 +239,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -253,9 +253,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.1"
+ "version": "3.13.0"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/07_debug_exceptions_testing/Unit-tests.ipynb b/07_debug_exceptions_testing/Unit-tests.ipynb
index 633ad4b..9c0c56f 100755
--- a/07_debug_exceptions_testing/Unit-tests.ipynb
+++ b/07_debug_exceptions_testing/Unit-tests.ipynb
@@ -12,7 +12,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -78,21 +78,21 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Code Under Test\n",
- "def entropy(ps):\n",
- " if any([(p < 0.0) or (p > 1.0) for p in ps]):\n",
+ "def entropy(prob):\n",
+ " if any([(p_i < 0.0) or (p_i > 1.0) for p_i in prob]):\n",
" raise ValueError(\"At least one input is out of range [0...1]\")\n",
" else:\n",
" pass\n",
- " if not np.isclose(1, np.sum(ps), atol=1e-08):\n",
+ " if not np.isclose(1, np.sum(prob), atol=1e-08):\n",
" raise ValueError(\"The list of input probabilities does not sum to 1\")\n",
" else:\n",
" pass\n",
- " items = ps * np.log2(ps)\n",
+ " items = prob * np.log2(prob)\n",
" new_items = []\n",
" for item in items:\n",
" if np.isnan(item):\n",
@@ -108,9 +108,9 @@
"metadata": {},
"outputs": [],
"source": [
- "ps = [.8, .2]\n",
+ "prob = [.8, .2]\n",
"#ps = [ 1.00000001, 0]\n",
- "[(p < 0.0) or (p > 1.0) for p in ps]"
+ "[(p_i < 0.0) or (p_i > 1.0) for p_i in prob]"
]
},
{
@@ -273,7 +273,7 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -319,14 +319,14 @@
"outputs": [],
"source": [
"# Pattern test\n",
- "def check_equal_probabilities(n):\n",
- " prob = 1.0/n\n",
- " ps = np.repeat(prob , n)\n",
+ "def check_equal_probabilities(count):\n",
+ " prob = 1.0/count\n",
+ " ps = np.repeat(prob, count)\n",
" if np.isclose(entropy(ps), -np.log2(prob)):\n",
- " print(f\"Test passed for n = {n}\")\n",
+ " print(f\"Test passed for count = {count}\")\n",
" else:\n",
" import pdb; pdb.set_trace()\n",
- " print (f\"Test failed for n = {n}\")\n",
+ " print (f\"Test failed for count = {count}\")\n",
" \n",
" \n",
"# Run a test\n",
@@ -354,7 +354,7 @@
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -452,7 +452,7 @@
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -463,7 +463,7 @@
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": null,
"metadata": {
"scrolled": true
},
@@ -564,7 +564,7 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -596,7 +596,7 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -649,7 +649,7 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -670,15 +670,6 @@
"execution_count": null,
"metadata": {},
"outputs": [],
- "source": [
- "ipytest.run()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [],
"source": [
"#def geomean(argument?):\n",
"# return ?"
@@ -739,7 +730,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "cse583",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},