From c4681032125d7df2eea9442decf0f14276d3321b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fl=C3=B6ck?= Date: Wed, 11 Sep 2019 15:39:37 +0200 Subject: [PATCH] init --- 00b_preparation.ipynb | 391 +++++ 01_var_string_num.ipynb | 2117 +++++++++++++++++++++++ 02_lists_tuples.ipynb | 2922 ++++++++++++++++++++++++++++++++ 03_dictionaries.ipynb | 1410 +++++++++++++++ 04_if_statements.ipynb | 825 +++++++++ 05_introducing_functions.ipynb | 688 ++++++++ 06_more_functions.ipynb | 1241 ++++++++++++++ 7 files changed, 9594 insertions(+) create mode 100644 00b_preparation.ipynb create mode 100644 01_var_string_num.ipynb create mode 100644 02_lists_tuples.ipynb create mode 100644 03_dictionaries.ipynb create mode 100644 04_if_statements.ipynb create mode 100644 05_introducing_functions.ipynb create mode 100644 06_more_functions.ipynb diff --git a/00b_preparation.ipynb b/00b_preparation.ipynb new file mode 100644 index 0000000..18159d7 --- /dev/null +++ b/00b_preparation.ipynb @@ -0,0 +1,391 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "# Big Data Module I: Introduction to Data Science with Python\n", + "\n", + "## Setting up Python\n", + "\n", + "Make yourself acquainted with the notebook environment. It's basically a webpage with executable code. Code is run by clicking the \"run\" button (looks similar to the play button).\n", + "\n", + "There are many great keyboard shortcuts. Press 'H' to see a cheat sheet (Jupyter Notebook, different in Juypter Lab).\n", + "\n", + "A good introduction is [this video right here](https://www.youtube.com/watch?v=HW29067qVWk). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Imports\n", + "\n", + "A central building block of Python, and especially the distribution of Anaconda you should have installed, is the ability to import additional modules, packages or libraries into your current script with the 'import' command. " + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1.3862943611198906" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "math.log(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-1.0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "math.cos(math.pi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sometimes you will want to use a short name for a library:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import math as mt" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1.3862943611198906" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mt.log(4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that you have to type the module name (\"math\" or \"mt\") before each function call. You can also import a specific function of a module. Then the explicit call is not necessary:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "from statistics import mean" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "28.25" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mean([2, 5, 6, 100])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we know the basics of importing, make yourself comfortable with using multiple libraries. NumPy, Pandas, and NetworkX are only three of the ones we will be using in the course.\n", + "\n", + "However, in our introductory tutorials on Python fundamentals, we will use only basic functions of Python." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### NumPy\n", + "\n", + "NumPy is the fundamental package for scientific computing with Python. More information and tutorials at:\n", + "\n", + "http://www.numpy.org/" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An example command:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "28.25" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = [2, 5, 6, 100]\n", + "np.mean(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Pandas\n", + "\n", + "Pandas provides data structures and data analysis tools. More information and tutorials at:\n", + "\n", + "http://pandas.pydata.org/" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0 1.0\n", + "1 3.0\n", + "2 5.0\n", + "3 NaN\n", + "4 6.0\n", + "5 8.0\n", + "dtype: float64" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = pd.Series([1, 3, 5, np.nan, 6, 8])\n", + "s" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some examples for extended markdown possibilities (double click on the cells to see the code)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$e^x=\\sum_{i=0}^\\infty \\frac{1}{i!}x^i$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "| This | is |\n", + "|------|------|\n", + "| a | table|" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introductory Tutorials for Preparation\n", + "\n", + "Now you are ready to start the tutorials. They are required preparation for the course. At the beginning of the course, we will only do a short recap.\n", + "\n", + "Open the first notebook, 01_var_string_num.ipynb, and go through the other five notebooks in order. **Do the exercises** to know you really understood the lessons." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "## Optional Materials for Preparation\n", + "\n", + "Via this link here you can open the Python Data Science Handbook project, and can work through this complete data science text book: **VanderPlas, J. (2016): *Python Data Science Handbook: Essential Tools for Working with Data*. O'Reilly Media.** The book can be found here: https://jakevdp.github.io/PythonDataScienceHandbook/\n", + "\n", + "A fine introduction for newcomers with a focus on data handling is: **McKinney, W. (2012): *Python for Data Analysis: Data Wrangling with Pandas, NumPy, and IPython*. O'Reilly Media.** This book is not as deep on the data analysis we will be dealing with as the book by VanderPlas.\n", + "\n", + "This is a data science textbook from the perspective of the social sciences: **Foster, I. , Ghani, R., Jarmin, R.S., Kreuter, F., and Lane, J. (eds) (2016): *Big Data and Social Science: A Practical Guide to Methods and Tools*. Chapman and Hall/CRC Press.**\n", + "\n", + "Finally, more basic tutorials can be found here.\n", + "\n", + "## Additional Resources (if you want to study more yourself, not mandatory)\n", + "\n", + "An example machine learning notebook: https://github.com/rhiever/Data-Analysis-and-Machine-Learning-Projects/blob/master/example-data-science-notebook/Example%20Machine%20Learning%20Notebook.ipynb\n", + "\n", + "Statistics visualisations with Java Script: http://students.brown.edu/seeing-theory/\n", + "\n", + "Coursera, e.g.: https://www.coursera.org/browse/data-science\n", + "\n", + "Berthold, M. and Hand, D. J. (eds.) (2002): *Intelligent Data Analysis: An Introduction*. Springer.\n", + "\n", + "Bishop, C. (2006): *Pattern Recognition and Machine Learning*. Springer.\n", + "\n", + "Ester, M. and Sander, J. (2000): *Knowledge Discovery in Databases: Techniken und Anwendungen*. Springer. **Deutschsprachig**.\n", + "\n", + "Hastie, T., Tibshirani, R., and Friedman, J. (2001): *The Elements of Statistical Learning*. Springer.\n", + "\n", + "Han, J. and Kamber, M. (2011): *Data Mining: Concepts and Techniques*. Morgan Kaufmann Publishers.\n", + "\n", + "Mitchell, T. M. (1997): *Machine Learning*. McGraw-Hill.\n", + "\n", + "Witten, I. H. and Frank, E. (2005): *Data Mining: Practical Machine Learning Tools and Techniques with Java Implementations*. Morgan Kaufmann Publishers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernel_info": { + "name": "python3" + }, + "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.3" + }, + "nav_menu": {}, + "nteract": { + "version": "0.8.4" + }, + "toc": { + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": false, + "toc_section_display": "block", + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/01_var_string_num.ipynb b/01_var_string_num.ipynb new file mode 100644 index 0000000..ec6b6fa --- /dev/null +++ b/01_var_string_num.ipynb @@ -0,0 +1,2117 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This lecture is adapted from the great 'Introduction to Python' course by Eric Matthes (http://introtopython.org/) by Fabian Flöck and Florian Lemmerich and, like the original, is available under an [MIT license](#License). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Variables, Strings, Numbers and Operators\n", + "===\n", + "\n", + "In this section, you will learn to store information in variables. You will learn about two types of data: strings, which are sets of characters, and numerical data types.\n", + "\n", + "*** A hint before you start: ***\n", + "\n", + "If you are not sure what a piece of code does, go to [pythontutor and visualize it](http://pythontutor.com/visualize.html#mode=edit) (click on \"Visualize Execution\"). That can be very helpful. " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "toc": "true" + }, + "source": [ + "# Table of Contents\n", + "

1  Variables, Strings, Numbers and Operators
2  Variables
2.1  Example
2.2  Naming rules
2.3  NameError
2.4  Exercises
2.4.0.1  Hello World - variable
2.4.0.2  One Variable, Two Messages:
3  Overview of the most basic data types
4  Strings
4.1  Single and double quotes
4.2  Changing case
4.3  Combining strings (concatenation)
4.4  Whitespace
4.4.1  Stripping whitespace
4.5  More string functions
4.6  Exercises
4.6.0.1  Someone Said
4.6.0.2  First Name Cases
4.6.0.3  Full Name
4.6.0.4  About This Person
4.6.0.5  Name Strip
5  Numbers
5.1  Integers
5.2  Floating-Point numbers
5.3  Exercises
5.3.0.1  Arithmetic
5.3.0.2  Order of Operations
5.3.0.3  Long Decimals
6  Jupyter's 'print', operators and simple function calls
7  Conversion between types
8  Comments
8.1  What makes a good comment?
8.2  When should you write comments?
8.3  Exercises
8.3.0.1  First Comments
9  OPTIONAL: Exploring the Python Community
10  License
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Variables\n", + "===\n", + "A variable holds a value." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Example\n", + "---" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello Python world!\n" + ] + } + ], + "source": [ + "message = \"Hello Python world!\"\n", + "print(message)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A variable holds a value. You can change the value of a variable at any point ('reassign' the variable)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello Python world!\n", + "Python is my favorite language!\n" + ] + } + ], + "source": [ + "message = \"Hello Python world!\"\n", + "print(message)\n", + "\n", + "message = \"Python is my favorite language!\"\n", + "print(message)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Naming rules\n", + "---\n", + "- Variables can only contain letters, numbers, and underscores. Variable names can start with a letter or an underscore, but can not start with a number.\n", + "- Spaces are not allowed in variable names, so we use underscores instead of spaces. For example, use student_name instead of \"student name\".\n", + "- You cannot use [Python keywords](http://docs.python.org/3/reference/lexical_analysis.html#keywords) as variable names.\n", + "- Variable names should be descriptive, without being too long. For example mc_wheels is better than just \"wheels\", and number_of_wheels_on_a_motorycle.\n", + "- Be careful about using the lowercase letter l and the uppercase letter O in places where they could be confused with the numbers 1 and 0." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "NameError\n", + "---\n", + "There is one common error when using variables, that you will almost certainly encounter at some point. Take a look at this code, and see if you can figure out why it causes an error." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'mesage' 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[1;32m 1\u001b[0m \u001b[0mmessage\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"Thank you for sharing Python with the world, Guido!\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmesage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'mesage' is not defined" + ] + } + ], + "source": [ + "message = \"Thank you for sharing Python with the world, Guido!\"\n", + "print(mesage)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's look through this error message. First, we see it is a NameError. Then we see the file that caused the error, and a green arrow shows us what line in that file caused the error. Then we get some more specific feedback, that \"name 'mesage' is not defined\".\n", + "\n", + "You may have already spotted the source of the error. We spelled message two different ways. Python does not care whether we use the variable name \"message\" or \"mesage\". Python only cares that the spellings of our variable names match every time we use them.\n", + "\n", + "This is pretty important, because it allows us to have a variable \"name\" with a single name in it, and then another variable \"names\" with a bunch of names in it.\n", + "\n", + "We can fix NameErrors by making sure all of our variable names are spelled consistently." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Thank you for sharing Python with the world, Guido!\n" + ] + } + ], + "source": [ + "message = \"Thank you for sharing Python with the world, Guido!\"\n", + "print(message)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In case you didn't know [Guido](http://en.wikipedia.org/wiki/Guido_van_Rossum) [van Rossum](http://www.python.org/~guido/) created the Python language over 20 years ago, and he is considered Python's [Benevolent Dictator for Life](http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life). Guido still signs off on all major changes to the core Python language." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Hello World - variable\n", + "\n", + "- Store your own version of the message \"Hello World\" in a variable, and print it.\n", + "\n", + "#### One Variable, Two Messages:\n", + "- Store a message in a variable, and then print that message.\n", + "- Store a new message in the same variable, and then print that new message." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Overview of the most basic data types\n", + "\n", + "| type | description |\n", + "|----|---|\n", + "| int | integer number |\n", + "| float | floating point number |\n", + "| bool | True or False |\n", + "| string | text |\n", + "\n", + "We can check the type of a variable with the \"type\" function." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "print(type(5))\n", + "print(type(5.0))\n", + "print(type(\"Hello World\"))\n", + "print(type('Hello World')) # \" \" and ' ' can be used equivalently" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Strings\n", + "===\n", + "Strings are sets of characters. Strings are easier to understand by looking at some examples." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Single and double quotes\n", + "---\n", + "Strings are contained by either single or double quotes." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "my_string = \"This is a double-quoted string.\"\n", + "my_string = 'This is a single-quoted string.'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This lets us make strings that contain quotations." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "quote = \"Linus Torvalds once said, 'Any program is only as good as it is useful.'\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Changing case\n", + "---\n", + "You can easily change the case of a string, to present it the way you want it to look." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "eric\n", + "Eric\n" + ] + } + ], + "source": [ + "first_name = 'eric'\n", + "\n", + "print(first_name)\n", + "print(first_name.title())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is often good to store data in lower case, and then change the case as you want to for presentation. This catches some TYpos. It also makes sure that 'eric', 'Eric', and 'ERIC' are not considered three different people.\n", + "\n", + "Some of the most common cases are lower, title, and upper." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "eric\n", + "Eric\n", + "ERIC\n", + "eric\n" + ] + } + ], + "source": [ + "first_name = 'eric'\n", + "\n", + "print(first_name)\n", + "print(first_name.title())\n", + "print(first_name.upper())\n", + "\n", + "first_name = 'Eric'\n", + "print(first_name.lower())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You will see this syntax quite often, where a variable name is followed by a dot and then the name of an action, followed by a set of parentheses. The parentheses may be empty, or they may contain some values.\n", + "\n", + "variable_name.action()\n", + "\n", + "In this example, the word \"action\" is the name of a method. A method is something that can be done to a variable. The methods 'lower', 'title', and 'upper' are all functions that have been written into the Python language, which do something to strings. Later on, you will learn to write your own methods." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Combining strings (concatenation)\n", + "---\n", + "It is often very useful to be able to combine strings into a message or page element that we want to display. Again, this is easier to understand through an example." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ada Lovelace\n" + ] + } + ], + "source": [ + "first_name = 'ada'\n", + "last_name = 'lovelace'\n", + "\n", + "full_name = first_name + ' ' + last_name\n", + "\n", + "print(full_name.title())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The plus sign combines two strings into one, which is called \"concatenation\". You can use as many plus signs as you want in composing messages. In fact, many web pages are written as giant strings which are put together through a long series of string concatenations." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ada Lovelace was considered the world's first computer programmer.\n" + ] + } + ], + "source": [ + "\n", + "first_name = 'ada'\n", + "last_name = 'lovelace'\n", + "full_name = first_name + ' ' + last_name\n", + "\n", + "message = full_name.title() + ' ' + \"was considered the world's first computer programmer.\"\n", + "\n", + "print(message)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you don't know who Ada Lovelace is, you might want to go read what [Wikipedia](http://en.wikipedia.org/wiki/Ada_Lovelace) or the [Computer History Museum](http://www.computerhistory.org/babbage/adalovelace/) have to say about her. Her life and her work are also the inspiration for the [Ada Initiative](http://adainitiative.org/faq/about-ada-lovelace/), which supports women who are involved in technical fields." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whitespace\n", + "---\n", + "The term \"whitespace\" refers to characters that the computer is aware of, but are invisible to readers. The most common whitespace characters are spaces, tabs, and newlines.\n", + "\n", + "Spaces are easy to create, because you have been using them as long as you have been using computers. Tabs and newlines are represented by special character combinations.\n", + "\n", + "The two-character combination \"\\t\" makes a tab appear in a string. Tabs can be used anywhere you like in a string." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello everyone!\n" + ] + } + ], + "source": [ + "print(\"Hello everyone!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\tHello everyone!\n" + ] + } + ], + "source": [ + "print(\"\\tHello everyone!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello \teveryone!\n" + ] + } + ], + "source": [ + "print(\"Hello \\teveryone!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The combination \"\\n\" makes a newline appear in a string. You can use newlines anywhere you like in a string." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello everyone!\n" + ] + } + ], + "source": [ + "print(\"Hello everyone!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Hello everyone!\n" + ] + } + ], + "source": [ + "print(\"\\nHello everyone!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello \n", + "everyone!\n" + ] + } + ], + "source": [ + "print(\"Hello \\neveryone!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n", + "Hello everyone!\n" + ] + } + ], + "source": [ + "print(\"\\n\\n\\nHello everyone!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Stripping whitespace\n", + "\n", + "Many times you will allow users to enter text into a box, and then you will read that text and use it. It is really easy for people to include extra whitespace at the beginning or end of their text. Whitespace includes spaces, tabs, and newlines.\n", + "\n", + "It is often a good idea to strip this whitespace from strings before you start working with them. For example, you might want to let people log in, and you probably want to treat 'eric ' as 'eric' when you are trying to see if I exist on your system.\n", + "\n", + "You can strip whitespace from the left side, the right side, or both sides of a string." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "eric \n", + " eric\n", + "eric\n" + ] + } + ], + "source": [ + "name = ' eric '\n", + "\n", + "print(name.lstrip())\n", + "print(name.rstrip())\n", + "print(name.strip())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's hard to see exactly what is happening, so maybe the following will make it a little more clear:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-eric -\n", + "- eric-\n", + "-eric-\n" + ] + } + ], + "source": [ + "name = ' eric '\n", + "\n", + "print('-' + name.lstrip() + '-')\n", + "print('-' + name.rstrip() + '-')\n", + "print('-' + name.strip() + '-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## More string functions" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "34" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = \"Python is my new favorite language\"\n", + "len(s) # 34 characters long" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.startswith('P')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.startswith('p') # Be careful, its case sensitive" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Python is your new favorite language'" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.replace(\"my\", \"your\")" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Python is my new f4vorite l4ngu4ge'" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.replace(\"a\", \"4\") # replaces all occurences" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python is my new favorite language\n" + ] + } + ], + "source": [ + "print(s) # but be careful: replace() (like the other functions) does not change the variable holding the string until you reassign 's', it just prints the result of the operation!" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "s = s.replace(\"a\", \"4\")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python is my new f4vorite l4ngu4ge\n" + ] + } + ], + "source": [ + "print(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Pyth0n is my new f4v0rite l4ngu4ge'" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.replace(\"4\", \"a\")\n", + "s.replace(\"o\", \"0\") # really try to understand what is happening here! 1. replace gets called on 's', and replaces all 4s with a's, but does not reassign 's'. \n", + "#2. Now 's' is called again, but the last replace is forgotten, so the end-result is a replace of o's with 0's, and the print-out of that. 's' is still the same. " + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Pyth0n is my new f4v0rite l4ngu4ge'" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.replace(\"a\", \"4\").replace(\"o\", \"0\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Python', 'is', 'my', 'new', 'f4vorite', 'l4ngu4ge']" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.split(\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can split strings at defined characters" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['I', 'like', 'cats', 'and', 'dogs,', 'but', \"I'd\", 'much', 'rather', 'own', 'a', 'dog.']\n" + ] + } + ], + "source": [ + "message = \"I like cats and dogs, but I'd much rather own a dog.\"\n", + "words = message.split(' ') #split at whitespaces\n", + "print(words)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the punctuation is left in the substrings.\n", + "\n", + "It is more common to split strings that are really lists, separated by something like a comma. The *split()* function gives you an easy way to turn comma-separated strings, which you can't do much with in Python, into lists. Once you have your data in a list, you can work with it in much more powerful ways." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['dog', ' cat', ' tiger', ' mouse', ' liger', ' bear']\n" + ] + } + ], + "source": [ + "animals = \"dog, cat, tiger, mouse, liger, bear\"\n", + "\n", + "# Rewrite the string as a list, and store it in the same variable\n", + "animals = animals.split(',')\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that in this case, the spaces are also ignored. It is a good idea to test the output of the split() function and make sure it is doing what you want with the data you are interested in.\n", + "One use of this is to work with spreadsheet data in your Python programs. Most spreadsheet applications allow you to dump your data into a comma-separated text file. You can read this file into your Python program, or even copy and paste from the text file into your program file, and then turn the data into a list. You can then process your spreadsheet data using a for loop." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Someone Said\n", + "- Find a quote that you like. Store the quote in a variable, with an appropriate introduction such as \"Ken Thompson once said, 'One of my most productive days was throwing away 1000 lines of code'\". Print the quote.\n", + "\n", + "#### First Name Cases\n", + "- Store your first name, in lowercase, in a variable.\n", + "- Using that one variable, print your name in lowercase, Titlecase, and UPPERCASE.\n", + "\n", + "#### Full Name\n", + "- Store your first name and last name in separate variables, and then combine them to print out your full name.\n", + "\n", + "#### About This Person\n", + "- Choose a person you look up to. Store their first and last names in separate variables.\n", + "- Use concatenation to make a sentence about this person, and store that sentence in a variable.-\n", + "- Print the sentence.\n", + "\n", + "#### Name Strip\n", + "- Store your first name in a variable, but include at least two kinds of whitespace on each side of your name.\n", + "- Print your name as it is stored.\n", + "- Print your name with whitespace stripped from the left side, then from the right side, then from both sides." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Numbers\n", + "===\n", + "Dealing with simple numerical data is fairly straightforward in Python, but there are a few things you should know about.\n", + "\n", + "Some Arithmetic Operators:\n", + "\n", + "| Symbol | Task Performed |\n", + "|----|---|\n", + "| + | Addition |\n", + "| - | Subtraction |\n", + "| / | division |\n", + "| // | integer division |\n", + "| * | multiplication |\n", + "| ** | to the power of |\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Integers\n", + "---\n", + "You can do all of the basic operations with integers, and everything should behave as you expect. Addition and subtraction use the standard plus and minus symbols. Multiplication uses the asterisk, and division uses a forward slash. Exponents use two asterisks." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n" + ] + } + ], + "source": [ + "print(3+2)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + } + ], + "source": [ + "print(3-2)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n" + ] + } + ], + "source": [ + "print(3*2)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.5\n" + ] + } + ], + "source": [ + "print(3/2)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "9\n" + ] + } + ], + "source": [ + "print(3**2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can use parentheses to modify the standard order of operations." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "14\n" + ] + } + ], + "source": [ + "standard_order = 2+3*4\n", + "print(standard_order)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20\n" + ] + } + ], + "source": [ + "my_order = (2+3)*4\n", + "print(my_order)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "34\n" + ] + } + ], + "source": [ + "print(my_order + standard_order)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.0\n" + ] + } + ], + "source": [ + "print(my_order / my_order)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Floating-Point numbers\n", + "---\n", + "Floating-point numbers refer to any number with a decimal point. Most of the time, you can think of floating point numbers as decimals, and they will behave as you expect them to." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.2\n" + ] + } + ], + "source": [ + "print(0.1+0.1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, sometimes you will get an answer with an unexpectly long decimal part:" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.30000000000000004\n" + ] + } + ], + "source": [ + "print(0.1+0.2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This happens because of the way computers represent numbers internally; this has nothing to do with Python itself. Basically, we are used to working in powers of ten, where one tenth plus two tenths is just three tenths. But computers work in powers of two. So your computer has to represent 0.1 in a power of two, and then 0.2 as a power of two, and express their sum as a power of two. There is no exact representation for 0.3 in powers of two, and we see that in the answer to 0.1+0.2.\n", + "\n", + "Python tries to hide this kind of stuff when possible. Don't worry about it much for now; just don't be surprised by it, and know that we will learn to clean up our results a little later on.\n", + "\n", + "You can also get the same kind of result with other operations." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.30000000000000004\n" + ] + } + ], + "source": [ + "print(3*0.1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Be sure you know what number type you get out of different operations." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.5\n" + ] + } + ], + "source": [ + "print(3/2)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + } + ], + "source": [ + "print(3//2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are getting numerical results that you don't expect for division, or that don't make sense, check if the version of Python you are using is treating integers differently than you expect.\n", + "**Our class will only use Python 3.0 and above!**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Arithmetic\n", + "- Write a program that prints out the results of at least one calculation for each of the basic operations: addition, subtraction, multiplication, division, and exponents.\n", + "\n", + "#### Order of Operations\n", + "- Find a calculation whose result depends on the order of operations.\n", + "- Print the result of this calculation using the standard order of operations.\n", + "- Use parentheses to force a nonstandard order of operations. Print the result of this calculation.\n", + "\n", + "#### Long Decimals\n", + "- On paper, 0.1+0.2=0.3. But you have seen that in Python, 0.1+0.2=0.30000000000000004.\n", + "- Find at least one other calculation that results in a long decimal like this.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Jupyter's 'print', operators and simple function calls\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Conveniently, in Jupyter the last statement of a cell gets printed automatically. Typically, in other Python interpreters/IDEs you have to use the print function instead, like we did above and will do in most of the remainder of this tutorial. " + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2 + 2" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'random string I just thought of'" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2 + 2\n", + "4 + 5\n", + "'random string I just thought of'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using 'print' explictly allows you multiple print-outs per cell." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "9\n", + "random string I just thought of\n" + ] + } + ], + "source": [ + "print(2 + 2)\n", + "print(4 + 5)\n", + "print('random string I just thought of')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python evaluates if a given statement is either True or False and return the corresponding boolean value. \n", + "\n", + "Some relational operators:\n", + "\n", + "| Symbol | Task Performed |\n", + "|----|---|\n", + "| == | True, if both sides are equal |\n", + "| != | True, if both sides are not equal |\n", + "| < |True, if the left side is smaller |\n", + "| > | True, if the left side is greater |\n", + "| <= | True, if the left side is smaller or equal to the right side |\n", + "| >= | True, if the left side is greater or equal to the right side |" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "5 == 3 #The difference to a single '=' is crucial!" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3 > 3" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3 >= 3" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "standard_order > 5 #we defined 'standard_order above! Remember that all variables get stored once assigned until you shutdown your notebook or overwrite them. " + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "standard_order != 66" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "6 == 'a random string'" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'a_variable_we_did_not_define_yet' 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;36m6\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0ma_variable_we_did_not_define_yet\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'a_variable_we_did_not_define_yet' is not defined" + ] + } + ], + "source": [ + "6 == a_variable_we_did_not_define_yet" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are several built-in function in Python that you can always call, see https://docs.python.org/3/library/functions.html for a full list" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "abs(-5)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "max(3, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'x' 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[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'x' is not defined" + ] + } + ], + "source": [ + "max(x, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use other types in a similar way as numbers, quite intuitively:" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "'A' < 'B'" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'zyx'" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "max(\"abc\", \"zyx\")" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'abc'" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "max(\"abc\", \"8\") " + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'>' not supported between instances of 'int' and 'str'", + "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[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"abc\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m8\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# mixing types doesn't work\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: '>' not supported between instances of 'int' and 'str'" + ] + } + ], + "source": [ + "max(\"abc\", 8) # mixing types doesn't work" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'abc'" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "max(\"abc\", str(8)) # so we have to transform (see below)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And of course, different data types allow for different functions:" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "24" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(\"How long is this string?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "object of type 'int' has no len()", + "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;36m10\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: object of type 'int' has no len()" + ] + } + ], + "source": [ + "x = 10\n", + "len(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Conversion between types\n", + "You can convert between these different by casting:" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "10\n", + "\n", + "10\n", + "2\n" + ] + } + ], + "source": [ + "x = 10\n", + "\n", + "print(type(x))\n", + "print(x)\n", + "x_as_string = str(x)\n", + "\n", + "print(type(x_as_string))\n", + "print(x_as_string)\n", + "print(len(x_as_string))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A typical conversion for prints:" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "My variable x is 10\n" + ] + } + ], + "source": [ + "print(\"My variable x is \" + str(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Comments\n", + "===\n", + "As you begin to write more complicated code, you will have to spend more time thinking about how to code solutions to the problems you want to solve. Once you come up with an idea, you will spend a fair amount of time troubleshooting your code, and revising your overall approach.\n", + "\n", + "Comments allow you to write in English, within your program. In Python, any line that starts with a pound (#) symbol is ignored by the Python interpreter." + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This line is not a comment, it is code.\n" + ] + } + ], + "source": [ + "# This line is a comment.\n", + "print(\"This line is not a comment, it is code.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What makes a good comment?\n", + "---\n", + "- It is short and to the point, but a complete thought. Most comments should be written in complete sentences.\n", + "- It explains your thinking, so that when you return to the code later you will understand how you were approaching the problem.\n", + "- It explains your thinking, so that others who work with your code will understand your overall approach to a problem.\n", + "- It explains particularly difficult sections of code in detail.\n", + "\n", + "When should you write comments?\n", + "---\n", + "- When you have to think about code before writing it.\n", + "- When you are likely to forget later exactly how you were approaching a problem.\n", + "- When there is more than one way to solve a problem.\n", + "- When others are unlikely to anticipate your way of thinking about a problem.\n", + "\n", + "Writing good comments is one of the clear signs of a good programmer. If you have any real interest in taking programming seriously, start using comments now. You will see them throughout the examples in these notebooks." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### First Comments\n", + "- Try commenting in different places in the code that we have written so far and explore what happens when you execute\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "# OPTIONAL: Exploring the Python Community\n", + "\n", + "The Python community is incredibly rich and diverse. Here are a couple resources to look at, if you want to do some exploring.\n", + "\n", + "- [The Python website](http://python.org/)\n", + "\n", + " The main Python website is probably not of too much interest to you at this point, but it is a great resource to know about as you start to learn more.\n", + " \n", + "\n", + "\n", + "- [PyCon](https://us.pycon.org/)\n", + "\n", + " The Python Conference (PyCon) is an incredible event, and the community is entirely welcoming to new programmers. They happen all over the world, throughout the year. If you can make your way to one of these conferences, you will learn a great deal and meet some really interesting people.\n", + "\n", + "\n", + " \n", + "- [PyLadies](http://www.pyladies.com/)\n", + "\n", + " Women and minorities are still under-represented in most technology fields, and the programming world is no different in this regard. That said, the Python community may well be the most welcoming and supportive programming community for women and minorities. There are a number of groups dedicated to bringing women and minorities together around programming in Python, and there are a number of explicit Codes of Conduct for Python-related events.\n", + "\n", + " PyLadies is one of the most visible of these organizations. They are a great resource, so go see what they do and what they have to offer.\n", + "\n", + "\n", + " \n", + "- [Python User Groups](https://wiki.python.org/moin/LocalUserGroups)\n", + "\n", + " Wherever there are a number of Python programmers, they will find a way to get together. Python user groups are regular meetings of Python users from a local area. Go take a look at the list of user groups, and see if there is one near you." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# License" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The MIT License (MIT)\n", + "\n", + "Original work Copyright (c) 2013 Eric Matthes \n", + "Modified work Copyright 2017 Fabian Flöck, Florian Lemmerich \n", + "\n", + "Permission is hereby granted, free of charge, to any person obtaining a copy of\n", + "this software and associated documentation files (the \"Software\"), to deal in\n", + "the Software without restriction, including without limitation the rights to\n", + "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n", + "the Software, and to permit persons to whom the Software is furnished to do so,\n", + "subject to the following conditions:\n", + "\n", + "The above copyright notice and this permission notice shall be included in all\n", + "copies or substantial portions of the Software.\n", + "\n", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n", + "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n", + "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n", + "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n", + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "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.3" + }, + "nav_menu": {}, + "toc": { + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": true, + "toc_section_display": "block", + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/02_lists_tuples.ipynb b/02_lists_tuples.ipynb new file mode 100644 index 0000000..fec0225 --- /dev/null +++ b/02_lists_tuples.ipynb @@ -0,0 +1,2922 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "toc": "true" + }, + "source": [ + "# Table of Contents\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This lecture is adapted from the great 'Introduction to Python' course from Eric Matthes (http://introtopython.org/) by Fabian Flöck and Florian Lemmerich and, like the original, is available under a [MIT license](#License). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lists and Tuples\n", + "===\n", + "In this notebook, you will learn to store more than one value in a single variable. This by itself is one of the most powerful ideas in programming, and it introduces a number of other central concepts such as loops. If this section ends up making sense to you, you will be able to start writing some interesting programs, and you can be more confident that you will be able to develop overall competence as a programmer." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Introducing Lists\n", + "===\n", + "Example\n", + "---\n", + "Lists are the most commonly used data structure. It represents an ordered, modifiable set of objects.\n", + "Lists are written as sequences of data, separated by a comma and enclosed in square brackets.\n", + "\n", + "Lists are declared by just equating a variable to '[ ]' or list." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "list_1 = []\n", + "\n", + "# a list with integer objects\n", + "list_2 = [3, 5, 7, 9]\n", + "\n", + "# a list of strings\n", + "list_3 = ['Monday', 'Tuesday', 'Wednesday',\n", + " 'Thursday', 'Friday', 'Saturday', 'Sunday']\n", + "\n", + "# a list of mixed types\n", + "list_4 = [2, 5, \"Elephant\", 6, 8.2, True]" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 5, 'Elephant', 6, 8.2, True]\n" + ] + } + ], + "source": [ + "print(list_4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Naming and defining a list\n", + "---\n", + "Since lists are collection of objects, it is good practice to give them a plural name. If each item in your list is a car, call the list 'cars'. If each item is a dog, call your list 'dogs'. This gives you a straightforward way to refer to the entire list ('dogs'), and to a single item in the list ('dog').\n", + "\n", + "In Python, square brackets designate a list. To define a list, you give the name of the list, the equals sign, and the values you want to include in your list within square brackets." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Accessing one item in a list\n", + "---\n", + "Items in a list are identified by their position in the list, starting with zero. This will almost certainly trip you up at some point. Programmers even joke about how often we all make \"off-by-one\" errors, so don't feel bad when you make this kind of error.\n", + "\n", + "To access the first element in a list, you give the name of the list, followed by a zero in square brackets." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "border collie\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "print(dogs[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The number in parentheses is called the **index** of the item. Because lists start at zero, the index of an item is always one less than its position in the list. So to get the second item in the list, we need to use an index of 1." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "australian cattle dog\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "dog = dogs[1]\n", + "print(dog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Accessing the last items in a list\n", + "You can probably see that to get the last item in this list, we would use an index of 2. This works, but it would only work because our list has exactly three items. To get the last item in a list, no matter how long the list is, you can use an index of -1." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "labrador retriever\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "dog = dogs[-1]\n", + "print(dog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This syntax also works for the second to last item, the third to last, and so forth." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "australian cattle dog\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "dog = dogs[-2]\n", + "print(dog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can't use a negative number larger than the length of the list, however." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "IndexError", + "evalue": "list index out of range", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\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[0mdogs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'border collie'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'australian cattle dog'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'labrador retriever'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mdog\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdogs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m4\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 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdog\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mIndexError\u001b[0m: list index out of range" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "dog = dogs[-4]\n", + "print(dog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### First List\n", + "- Store the values 'python', 'c', and 'java' in a list. Print each of these values out, using their position in the list.\n", + "\n", + "#### First Neat List\n", + "- Store the values 'python', 'c', and 'java' in a list. Print a statement about each of these values, using their position in the list.\n", + "- Your statement could simply be, 'A nice programming language is *value*.'\n", + "\n", + "#### Your First List\n", + "- Think of something you can store in a list. Make a list with three or four items, and then print a message that includes at least one item from your list. Your sentence could be as simple as, \"One item in my list is a ____.\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lists and Looping\n", + "===" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Accessing all elements in a list\n", + "---\n", + "This is one of the most important concepts related to lists. You can have a list with a million items in it, and in three lines of code you can write a sentence for each of those million items. If you want to understand lists, and become a competent programmer, make sure you take the time to understand this section.\n", + "\n", + "We use a loop to access all the elements in a list. A loop is a block of code that repeats itself until it runs out of items to work with, or until a certain condition is met. In this case, our loop will run once for every item in our list. With a list that is three items long, our loop will run three times.\n", + "\n", + "Let's take a look at how we access all the items in a list, and then try to understand how it works." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "border collie\n", + "australian cattle dog\n", + "labrador retriever\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "for dog in dogs:\n", + " print(dog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have already seen how to create a list, so we are really just trying to understand how the last two lines work. These last two lines make up a loop, and the language here can help us see what is happening:\n", + "\n", + " for dog in dogs:\n", + "\n", + "- The keyword \"for\" tells Python to get ready to use a loop.\n", + "- The variable \"dog\", with no \"s\" on it, is a temporary placeholder variable. This is the variable that Python will place each item in the list into, one at a time.\n", + "- The first time through the loop, the value of \"dog\" will be 'border collie'.\n", + "- The second time through the loop, the value of \"dog\" will be 'australian cattle dog'.\n", + "- The third time through, \"dog\" will be 'labrador retriever'.\n", + "- After this, there are no more items in the list, and the loop will end.\n", + "\n", + "The site pythontutor.com allows you to run Python code one line at a time. As you run the code, there is also a visualization on the screen that shows you how the variable \"dog\" holds different values as the loop progresses. There is also an arrow that moves around your code, showing you how some lines are run just once, while other lines are run multiple tiimes. If you would like to see this in action, click the Forward button and watch the visualization, and the output as it is printed to the screen. Tools like this are incredibly valuable for seeing what Python is doing with your code.\n", + "\n", + "### Doing more with each item\n", + "\n", + "We can do whatever we want with the value of \"dog\" inside the loop. In this case, we just print the name of the dog.\n", + "\n", + " print(dog)\n", + "\n", + "We are not limited to just printing the word dog. We can do whatever we want with this value, and this action will be carried out for every item in the list. Let's say something about each dog in our list." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I like border collies.\n", + "I like australian cattle dogs.\n", + "I like labrador retrievers.\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "for dog in dogs:\n", + " print('I like ' + dog + 's.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualize this on pythontutor.\n", + "\n", + "### Inside and outside the loop\n", + "\n", + "Python uses indentation to decide what is inside the loop and what is outside the loop. Code that is inside the loop will be run for every item in the list. Code that is not indented, which comes after the loop, will be run once just like regular code." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I like border collies.\n", + "No, I really really like border collies!\n", + "\n", + "I like australian cattle dogs.\n", + "No, I really really like australian cattle dogs!\n", + "\n", + "I like labrador retrievers.\n", + "No, I really really like labrador retrievers!\n", + "\n", + "\n", + "That's just how I feel about dogs.\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "for dog in dogs:\n", + " print('I like ' + dog + 's.')\n", + " print('No, I really really like ' + dog +'s!\\n')\n", + " \n", + "print(\"\\nThat's just how I feel about dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the last line only runs once, after the loop is completed. Also notice the use of newlines (\"\\n\") to make the output easier to read. Run this code on pythontutor." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Enumerating a list\n", + "---\n", + "When you are looping through a list, you may want to know the index of the current item. You could always use the *list.index(value)* syntax, but there is a simpler way. The *enumerate()* function tracks the index of each item for you, as it loops through the list:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Results for the dog show are as follows:\n", + "\n", + "Place: 0 Dog: border collie\n", + "Place: 1 Dog: australian cattle dog\n", + "Place: 2 Dog: labrador retriever\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "print(\"Results for the dog show are as follows:\\n\")\n", + "for index, dog in enumerate(dogs):\n", + " place = str(index)\n", + " print(\"Place: \" + place + \" Dog: \" + dog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To enumerate a list, you need to add an *index* variable to hold the current index. So instead of\n", + "\n", + " for dog in dogs:\n", + " \n", + "You have\n", + "\n", + " for index, dog in enumerate(dogs)\n", + " \n", + "The value in the variable *index* is always an integer. If you want to print it in a string, you have to turn the integer into a string:\n", + "\n", + " str(index)\n", + " \n", + "The index always starts at 0, so in this example the value of *place* should actually be the current index, plus one:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Results for the dog show are as follows:\n", + "\n", + "Place: 1 Dog: border collie\n", + "Place: 2 Dog: australian cattle dog\n", + "Place: 3 Dog: labrador retriever\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "print(\"Results for the dog show are as follows:\\n\")\n", + "for index, dog in enumerate(dogs):\n", + " place = str(index + 1)\n", + " print(\"Place: \" + place + \" Dog: \" + dog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A common looping error\n", + "One common looping error occurs when instead of using the single variable *dog* inside the loop, we accidentally use the variable that holds the entire list:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['border collie', 'australian cattle dog', 'labrador retriever']\n", + "['border collie', 'australian cattle dog', 'labrador retriever']\n", + "['border collie', 'australian cattle dog', 'labrador retriever']\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "for dog in dogs:\n", + " print(dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, instead of printing each dog in the list, we print the entire list every time we go through the loop. Python puts each individual item in the list into the variable *dog*, but we never use that variable. Sometimes you will just get an error if you try to do this:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "can only concatenate str (not \"list\") to str", + "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 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mdog\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdogs\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[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'I like '\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mdogs\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m's.'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: can only concatenate str (not \"list\") to str" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "for dog in dogs:\n", + " print('I like ' + dogs + 's.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Strings as lists ###" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Strings are treated similar to lists in Python, with single characters being the list items." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "t\n", + "h\n", + "i\n", + "s\n", + " \n", + "i\n", + "s\n", + " \n", + "a\n", + " \n", + "h\n", + "o\n", + "u\n", + "s\n", + "e\n" + ] + } + ], + "source": [ + "x = 'this is a house'\n", + "for i in x:\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### First List - Loop\n", + "- Repeat *First List*, but this time use a loop to print out each value in the list.\n", + "\n", + "#### First Neat List - Loop\n", + "- Repeat *First Neat List*, but this time use a loop to print out your statements. Make sure you are writing the same sentence for all values in your list. Loops are not effective when you are trying to generate different output for each value in your list.\n", + "\n", + "#### Your First List - Loop\n", + "- Repeat *Your First List*, but this time use a loop to print out your message for each item in your list. Again, if you came up with different messages for each value in your list, decide on one message to repeat for each value in your list." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Common List Operations\n", + "===" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Modifying elements in a list\n", + "---\n", + "You can change the value of any element in a list if you know the position of that item." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['australian shepherd', 'australian cattle dog', 'labrador retriever']\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "dogs[0] = 'australian shepherd'\n", + "print(dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finding an element in a list\n", + "---\n", + "If you want to find out the position of an element in a list, you can use the index() function." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "print(dogs.index('australian cattle dog'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This method returns a ValueError if the requested item is not in the list." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "'poodle' is not in list", + "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 2\u001b[0m \u001b[0mdogs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'border collie'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'australian cattle dog'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'labrador retriever'\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;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdogs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'poodle'\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;31mValueError\u001b[0m: 'poodle' is not in list" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "print(dogs.index('poodle'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Testing whether an item is in a list\n", + "---\n", + "You can test whether an item is in a list using the \"in\" keyword. This will become more useful after learning how to use if-else statements." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "\n", + "print('australian cattle dog' in dogs)\n", + "print('poodle' in dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding items to a list\n", + "---\n", + "### Appending items to the end of a list\n", + "We can add an item to a list using the append() method. This method adds the new item to the end of the list." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "border collies are cool.\n", + "australian cattle dogs are cool.\n", + "labrador retrievers are cool.\n", + "poodles are cool.\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "dogs.append('poodle')\n", + "\n", + "for dog in dogs:\n", + " print(dog + \"s are cool.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Inserting items into a list\n", + "We can also insert items anywhere we want in a list, using the **insert()** function. We specify the position we want the item to have, and everything from that point on is shifted one position to the right. In other words, the index of every item after the new item is increased by one." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['border collie', 'poodle', 'australian cattle dog', 'labrador retriever']\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "dogs.insert(1, 'poodle')\n", + "\n", + "print(dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that you have to give the position of the new item first, and then the value of the new item. If you do it in the reverse order, you will get an error." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Replacing items in a list\n", + "We can also just overwrite elements of a list" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['border collie', 'poodle', 'pug', 'labrador retriever']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dogs[2] = 'pug'\n", + "dogs" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "ename": "IndexError", + "evalue": "list assignment index out of range", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\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[0mdogs\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'maltese'\u001b[0m \u001b[0;31m# cannot set an element that does not exist yet\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m: list assignment index out of range" + ] + } + ], + "source": [ + "dogs[10] = 'maltese' # cannot set an element that does not exist yet" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Creating an empty list\n", + "---\n", + "Now that we know how to add items to a list after it is created, we can use lists more dynamically. We are no longer stuck defining our entire list at once.\n", + "\n", + "A common approach with lists is to define an empty list, and then let your program add items to the list as necessary. This approach works, for example, when starting to build an interactive web site. Your list of users might start out empty, and then as people register for the site it will grow. This is a simplified approach to how web sites actually work, but the idea is realistic.\n", + "\n", + "Here is a brief example of how to start with an empty list, start to fill it up, and work with the items in the list. The only new thing here is the way we define an empty list, which is just an empty set of square brackets." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Welcome, bernice!\n", + "Welcome, cody!\n", + "Welcome, aaron!\n" + ] + } + ], + "source": [ + "# Create an empty list to hold our users.\n", + "usernames = []\n", + "\n", + "# Add some users.\n", + "usernames.append('bernice')\n", + "usernames.append('cody')\n", + "usernames.append('aaron')\n", + "\n", + "# Greet all of our users.\n", + "for username in usernames:\n", + " print(\"Welcome, \" + username + '!')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we don't change the order in our list, we can use the list to figure out who our oldest and newest users are." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Welcome, bernice!\n", + "Welcome, cody!\n", + "Welcome, aaron!\n", + "\n", + "Thank you for being our very first user, bernice!\n", + "And a warm welcome to our newest user, aaron!\n" + ] + } + ], + "source": [ + "\n", + "# Create an empty list to hold our users.\n", + "usernames = []\n", + "\n", + "# Add some users.\n", + "usernames.append('bernice')\n", + "usernames.append('cody')\n", + "usernames.append('aaron')\n", + "\n", + "# Greet all of our users.\n", + "for username in usernames:\n", + " print(\"Welcome, \" + username + '!')\n", + "\n", + "# Recognize our first user, and welcome our newest user.\n", + "print(\"\\nThank you for being our very first user, \" + usernames[0] + '!')\n", + "print(\"And a warm welcome to our newest user, \" + usernames[-1] + '!')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the code welcoming our newest user will always work, because we have used the index -1. If we had used the index 2 we would always get the third user, even as our list of users grows and grows." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sorting a List\n", + "---\n", + "We can sort a list alphabetically, in either order." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Our students are currently in alphabetical order.\n", + "aaron\n", + "bernice\n", + "cody\n", + "\n", + "Our students are now in reverse alphabetical order.\n", + "cody\n", + "bernice\n", + "aaron\n" + ] + } + ], + "source": [ + "students = ['bernice', 'aaron', 'cody']\n", + "\n", + "# Put students in alphabetical order.\n", + "students.sort()\n", + "\n", + "# Display the list in its current order.\n", + "print(\"Our students are currently in alphabetical order.\")\n", + "for student in students:\n", + " print(student)\n", + "\n", + "#Put students in reverse alphabetical order.\n", + "students.sort(reverse=True)\n", + "\n", + "# Display the list in its current order.\n", + "print(\"\\nOur students are now in reverse alphabetical order.\")\n", + "for student in students:\n", + " print(student)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### *sorted()* vs. *sort()*\n", + "Whenever you consider sorting a list, keep in mind that you can not recover the original order. If you want to display a list in sorted order, but preserve the original order, you can use the *sorted()* function. The *sorted()* function also accepts the optional *reverse=True* argument." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here is the list in alphabetical order:\n", + "aaron\n", + "bernice\n", + "cody\n", + "\n", + "Here is the list in reverse alphabetical order:\n", + "cody\n", + "bernice\n", + "aaron\n", + "\n", + "Here is the list in its original order:\n", + "bernice\n", + "aaron\n", + "cody\n" + ] + } + ], + "source": [ + "students = ['bernice', 'aaron', 'cody']\n", + "\n", + "# Display students in alphabetical order, but keep the original order.\n", + "print(\"Here is the list in alphabetical order:\")\n", + "for student in sorted(students):\n", + " print(student)\n", + "\n", + "# Display students in reverse alphabetical order, but keep the original order.\n", + "print(\"\\nHere is the list in reverse alphabetical order:\")\n", + "for student in sorted(students, reverse=True):\n", + " print(student)\n", + "\n", + "print(\"\\nHere is the list in its original order:\")\n", + "# Show that the list is still in its original order.\n", + "for student in students:\n", + " print(student)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reversing a list\n", + "We have seen three possible orders for a list:\n", + "- The original order in which the list was created\n", + "- Alphabetical order\n", + "- Reverse alphabetical order\n", + "\n", + "There is one more order we can use, and that is the reverse of the original order of the list. The *reverse()* function gives us this order." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['cody', 'aaron', 'bernice']\n" + ] + } + ], + "source": [ + "students = ['bernice', 'aaron', 'cody']\n", + "students.reverse()\n", + "\n", + "print(students)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that reverse is permanent, although you could follow up with another call to *reverse()* and get back the original order of the list." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sorting a numerical list\n", + "All of the sorting functions work for numerical lists as well." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4]\n", + "[4, 3, 2, 1]\n" + ] + } + ], + "source": [ + "numbers = [1, 3, 4, 2]\n", + "\n", + "# sort() puts numbers in increasing order.\n", + "numbers.sort()\n", + "print(numbers)\n", + "\n", + "# sort(reverse=True) puts numbers in decreasing order.\n", + "numbers.sort(reverse=True)\n", + "print(numbers)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4]\n", + "[1, 3, 4, 2]\n" + ] + } + ], + "source": [ + "numbers = [1, 3, 4, 2]\n", + "\n", + "# sorted() preserves the original order of the list:\n", + "print(sorted(numbers))\n", + "print(numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 3, 1]\n" + ] + } + ], + "source": [ + "numbers = [1, 3, 4, 2]\n", + "\n", + "# The reverse() function also works for numerical lists.\n", + "numbers.reverse()\n", + "print(numbers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finding the length of a list\n", + "---\n", + "You can find the length of a list using the *len()* function." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "usernames = ['bernice', 'cody', 'aaron']\n", + "user_count = len(usernames)\n", + "\n", + "print(user_count)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are many situations where you might want to know how many items in a list. If you have a list that stores your users, you can find the length of your list at any time, and know how many users you have." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "We have 1 user!\n", + "We have 3 users!\n" + ] + } + ], + "source": [ + "# Create an empty list to hold our users.\n", + "usernames = []\n", + "\n", + "# Add some users, and report on how many users we have.\n", + "usernames.append('bernice')\n", + "user_count = len(usernames)\n", + "\n", + "print(\"We have \" + str(user_count) + \" user!\")\n", + "\n", + "usernames.append('cody')\n", + "usernames.append('aaron')\n", + "user_count = len(usernames)\n", + "\n", + "print(\"We have \" + str(user_count) + \" users!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On a technical note, the *len()* function returns an integer, which can't be printed directly with strings. We use the *str()* function to turn the integer into a string so that it prints nicely:" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "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 2\u001b[0m \u001b[0muser_count\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0musernames\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"This will cause an error: \"\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0muser_count\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: must be str, not int" + ] + } + ], + "source": [ + "usernames = ['bernice', 'cody', 'aaron']\n", + "user_count = len(usernames)\n", + "\n", + "print(\"This will cause an error: \" + user_count)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This will work: 3\n" + ] + } + ], + "source": [ + "\n", + "usernames = ['bernice', 'cody', 'aaron']\n", + "user_count = len(usernames)\n", + "\n", + "print(\"This will work: \" + str(user_count))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Working List\n", + "- Make a list that includes four careers, such as 'programmer' and 'truck driver'.\n", + "- Use the *list.index()* function to find the index of one career in your list.\n", + "- Use the *in* function to show that this career is in your list.\n", + "- Use the *append()* function to add a new career to your list.\n", + "- Use the *insert()* function to add a new career at the beginning of the list.\n", + "- Use a loop to show all the careers in your list.\n", + "\n", + "#### Starting From Empty\n", + "- Create the list you ended up with in *Working List*, but this time start your file with an empty list and fill it up using *append()* statements.\n", + "- Print a statement that tells us what the first career you thought of was.\n", + "- Print a statement that tells us what the last career you thought of was.\n", + "\n", + "#### Ordered Working List\n", + "- Start with the list you created in *Working List*.\n", + "- You are going to print out the list in a number of different orders.\n", + "- Each time you print the list, use a for loop rather than printing the raw list.\n", + "- Print a message each time telling us what order we should see the list in.\n", + " - Print the list in its original order.\n", + " - Print the list in alphabetical order.\n", + " - Print the list in its original order.\n", + " - Print the list in reverse alphabetical order.\n", + " - Print the list in its original order.\n", + " - Print the list in the reverse order from what it started.\n", + " - Print the list in its original order\n", + " - Permanently sort the list in alphabetical order, and then print it out.\n", + " - Permanently sort the list in reverse alphabetical order, and then print it out.\n", + "\n", + "#### Ordered Numbers\n", + "- Make a list of 5 numbers, in a random order.\n", + "- You are going to print out the list in a number of different orders.\n", + "- Each time you print the list, use a for loop rather than printing the raw list.\n", + "- Print a message each time telling us what order we should see the list in.\n", + " - Print the numbers in the original order.\n", + " - Print the numbers in increasing order.\n", + " - Print the numbers in the original order.\n", + " - Print the numbers in decreasing order.\n", + " - Print the numbers in their original order.\n", + " - Print the numbers in the reverse order from how they started.\n", + " - Print the numbers in the original order.\n", + " - Permanently sort the numbers in increasing order, and then print them out.\n", + " - Permanently sort the numbers in descreasing order, and then print them out.\n", + "\n", + "#### List Lengths\n", + "- Copy two or three of the lists you made from the previous exercises, or make up two or three new lists.\n", + "- Print out a series of statements that tell us how long each list is." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Removing Items from a List\n", + "===\n", + "Hopefully you can see by now that lists are a dynamic structure. We can define an empty list and then fill it up as information comes into our program. To become really dynamic, we need some ways to remove items from a list when we no longer need them. You can remove items from a list through their position, or through their value." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Removing items by position\n", + "---\n", + "If you know the position of an item in a list, you can remove that item using the *del* command. To use this approach, give the command *del* and the name of your list, with the index of the item you want to move in square brackets:" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['australian cattle dog', 'labrador retriever']\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "# Remove the first dog from the list.\n", + "del dogs[0]\n", + "\n", + "print(dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Removing items by value\n", + "---\n", + "You can also remove an item from a list if you know its value. To do this, we use the *remove()* function. Give the name of the list, followed by the word remove with the value of the item you want to remove in parentheses. Python looks through your list, finds the first item with this value, and removes it." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['border collie', 'labrador retriever']\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "# Remove australian cattle dog from the list.\n", + "dogs.remove('australian cattle dog')\n", + "\n", + "print(dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Be careful to note, however, that *only* the first item with this value is removed. If you have multiple items with the same value, you will have some items with this value left in your list." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['b', 'c', 'a', 'b', 'c']\n" + ] + } + ], + "source": [ + "letters = ['a', 'b', 'c', 'a', 'b', 'c']\n", + "# Remove the letter a from the list.\n", + "letters.remove('a')\n", + "\n", + "print(letters)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Popping items from a list\n", + "---\n", + "There is a cool concept in programming called \"popping\" items from a collection. Every programming language has some sort of data structure similar to Python's lists. All of these structures can be used as queues, and there are various ways of processing the items in a queue.\n", + "\n", + "One simple approach is to start with an empty list, and then add items to that list. When you want to work with the items in the list, you always take the last item from the list, do something with it, and then remove that item. The *pop()* function makes this easy. It removes the last item from the list, and gives it to us so we can work with it. This is easier to show with an example:" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "labrador retriever\n", + "['border collie', 'australian cattle dog']\n" + ] + } + ], + "source": [ + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "last_dog = dogs.pop()\n", + "\n", + "print(last_dog)\n", + "print(dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is an example of a first-in, last-out approach. The first item in the list would be the last item processed if you kept using this approach. We will see a full implementation of this approach later on, when we learn about *while* loops.\n", + "\n", + "You can actually pop any item you want from a list, by giving the index of the item you want to pop. So we could do a first-in, first-out approach by popping the first iem in the list:" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "border collie\n", + "['australian cattle dog', 'labrador retriever']\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", + "first_dog = dogs.pop(0)\n", + "\n", + "print(first_dog)\n", + "print(dogs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Famous People\n", + "- Make a list that includes the names of four famous people.\n", + "- Remove each person from the list, one at a time, using each of the four methods we have just seen:\n", + " - Pop the last item from the list, and pop any item except the last item.\n", + " - Remove one item by its position, and one item by its value.\n", + "- Print out a message that there are no famous people left in your list, and print your list to prove that it is empty." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Slicing a List\n", + "===\n", + "Since a list is a collection of items, we should be able to get any subset of those items. For example, if we want to get just the first three items from the list, we should be able to do so easily. The same should be true for any three items in the middle of the list, or the last three items, or any x items from anywhere in the list. These subsets of a list are called *slices*.\n", + "\n", + "To get a subset of a list, we give the position of the first item we want, and the position of the first item we do *not* want to include in the subset. So the slice *list[0:3]* will return a list containing items 0, 1, and 2, but not item 3. Here is how you get a batch containing the first three items." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bernice\n", + "cody\n", + "aaron\n" + ] + } + ], + "source": [ + "usernames = ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n", + "\n", + "# Grab the first three users in the list.\n", + "first_batch = usernames[0:3]\n", + "\n", + "for user in first_batch:\n", + " print(user)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want to grab everything up to a certain position in the list, you can also leave the first index blank:" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bernice\n", + "cody\n", + "aaron\n" + ] + } + ], + "source": [ + "\n", + "usernames = ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n", + "\n", + "# Grab the first three users in the list.\n", + "first_batch = usernames[:3]\n", + "\n", + "for user in first_batch:\n", + " print(user)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we grab a slice from a list, the original list is not affected:" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bernice\n", + "cody\n", + "aaron\n", + "ever\n", + "dalia\n" + ] + } + ], + "source": [ + "\n", + "usernames = ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n", + "\n", + "# Grab the first three users in the list.\n", + "first_batch = usernames[0:3]\n", + "\n", + "# The original list is unaffected.\n", + "for user in usernames:\n", + " print(user)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can get any segment of a list we want, using the slice method:" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cody\n", + "aaron\n", + "ever\n" + ] + } + ], + "source": [ + "usernames = ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n", + "\n", + "# Grab a batch from the middle of the list.\n", + "middle_batch = usernames[1:4]\n", + "\n", + "for user in middle_batch:\n", + " print(user)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To get all items from one position in the list to the end of the list, we can leave off the second index:" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "aaron\n", + "ever\n", + "dalia\n" + ] + } + ], + "source": [ + "usernames = ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n", + "\n", + "# Grab all users from the third to the end.\n", + "end_batch = usernames[2:]\n", + "\n", + "for user in end_batch:\n", + " print(user)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Copying a list\n", + "You can use the slice notation to make a copy of a list, by leaving out both the starting and the ending index. This causes the slice to consist of everything from the first item to the last, which is the entire list." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The full copied list:\n", + "\t ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n", + "\n", + "Two users removed from copied list:\n", + "\t ['aaron', 'ever', 'dalia']\n", + "\n", + "The original list:\n", + "\t ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n" + ] + } + ], + "source": [ + "usernames = ['bernice', 'cody', 'aaron', 'ever', 'dalia']\n", + "\n", + "# Make a copy of the list.\n", + "copied_usernames = usernames[:]\n", + "print(\"The full copied list:\\n\\t\", copied_usernames)\n", + "\n", + "# Remove the first two users from the copied list.\n", + "del copied_usernames[0]\n", + "del copied_usernames[0]\n", + "print(\"\\nTwo users removed from copied list:\\n\\t\", copied_usernames)\n", + "\n", + "# The original list is unaffected.\n", + "print(\"\\nThe original list:\\n\\t\", usernames)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Alphabet Slices\n", + "- Store the first ten letters of the alphabet in a list.\n", + "- Use a slice to print out the first three letters of the alphabet.\n", + "- Use a slice to print out any three letters from the middle of your list.\n", + "- Use a slice to print out the letters from any point in the middle of your list, to the end.\n", + "\n", + "#### Protected List\n", + "- Your goal in this exercise is to prove that copying a list protects the original list.\n", + "- Make a list with three people's names in it.\n", + "- Use a slice to make a copy of the entire list.\n", + "- Add at least two new names to the new copy of the list.\n", + "- Make a loop that prints out all of the names in the original list, along with a message that this is the original list.\n", + "- Make a loop that prints out all of the names in the copied list, along with a message that this is the copied list." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Numerical Lists\n", + "===\n", + "There is nothing special about lists of numbers, but there are some functions you can use to make working with numerical lists more efficient. Let's make a list of the first ten numbers, and start working with it to see how we can use numbers in a list." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n", + "9\n", + "10\n" + ] + } + ], + "source": [ + "# Print out the first ten numbers.\n", + "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", + "\n", + "for number in numbers:\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The *range()* function\n", + "---\n", + "This works, but it is not very efficient if we want to work with a large set of numbers. The *range()* function helps us generate long lists of numbers. Here are two ways to do the same thing, using the *range* function." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n", + "9\n", + "10\n" + ] + } + ], + "source": [ + "# Print the first ten numbers.\n", + "for number in range(1,11):\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The range function takes in a starting number, and an end number. You get all integers, up to but not including the end number. You can also add a *step* value, which tells the *range* function how big of a step to take between numbers:" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "3\n", + "5\n", + "7\n", + "9\n", + "11\n", + "13\n", + "15\n", + "17\n", + "19\n" + ] + } + ], + "source": [ + "# Print the first ten odd numbers.\n", + "for number in range(1,21,2):\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to store these numbers in a list, we can use the *list()* function. This function takes in a range, and turns it into a list:" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n" + ] + } + ], + "source": [ + "# Create a list of the first ten numbers.\n", + "numbers = list(range(1,11))\n", + "print(numbers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is incredibly powerful; we can now create a list of the first million numbers, just as easily as we made a list of the first ten numbers. It doesn't really make sense to print the million numbers here, but we can show that the list really does have one million items in it, and we can print the last ten items to show that the list is correct." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The list 'numbers' has 1000000 numbers in it.\n", + "\n", + "The last ten numbers in the list are:\n", + "999991\n", + "999992\n", + "999993\n", + "999994\n", + "999995\n", + "999996\n", + "999997\n", + "999998\n", + "999999\n", + "1000000\n" + ] + } + ], + "source": [ + "# Store the first million numbers in a list.\n", + "numbers = list(range(1,1000001))\n", + "\n", + "# Show the length of the list:\n", + "print(\"The list 'numbers' has \" + str(len(numbers)) + \" numbers in it.\")\n", + "\n", + "# Show the last ten numbers:\n", + "print(\"\\nThe last ten numbers in the list are:\")\n", + "for number in numbers[-10:]:\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are two things here that might be a little unclear. The expression\n", + "\n", + " str(len(numbers))\n", + "\n", + "takes the length of the *numbers* list, and turns it into a string that can be printed.\n", + "\n", + "The expression \n", + "\n", + " numbers[-10:]\n", + "\n", + "gives us a *slice* of the list. The index `-1` is the last item in the list, and the index `-10` is the item ten places from the end of the list. So the slice `numbers[-10:]` gives us everything from that item to the end of the list." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The *min()*, *max()*, and *sum()* functions\n", + "---\n", + "There are three functions you can easily use with numerical lists. As you might expect, the *min()* function returns the smallest number in the list, the *max()* function returns the largest number in the list, and the *sum()* function returns the total of all numbers in the list." + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Our youngest reader is 11 years old.\n", + "Our oldest reader is 38 years old.\n", + "Together, we have 149 years worth of life experience.\n" + ] + } + ], + "source": [ + "ages = [23, 16, 14, 28, 19, 11, 38]\n", + "\n", + "youngest = min(ages)\n", + "oldest = max(ages)\n", + "total_years = sum(ages)\n", + "\n", + "print(\"Our youngest reader is \" + str(youngest) + \" years old.\")\n", + "print(\"Our oldest reader is \" + str(oldest) + \" years old.\")\n", + "print(\"Together, we have \" + str(total_years) + \" years worth of life experience.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### First Twenty\n", + "- Use the *range()* function to store the first twenty numbers (1-20) in a list, and print them out.\n", + "\n", + "#### Larger Sets\n", + "- Take the *first\\_twenty.py* program you just wrote. Change your end number to a much larger number. How long does it take your computer to print out the first million numbers? (Most people will never see a million numbers scroll before their eyes. You can now see this!)\n", + "\n", + "#### Five Wallets\n", + "- Imagine five wallets with different amounts of cash in them. Store these five values in a list, and print out the following sentences:\n", + " - \"The fattest wallet has $ *value* in it.\"\n", + " - \"The skinniest wallet has $ *value* in it.\"\n", + " - \"All together, these wallets have $ *value* in them.\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Lists of Lists\n", + "Merge two lists" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n" + ] + } + ], + "source": [ + "list_1 = [1, 2, 3]\n", + "list_2 = [4, 5, 6]\n", + "list_3 = [7, 8, 9]\n", + "print(list_1 + list_2 + list_3)" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n" + ] + } + ], + "source": [ + "l = [list_1, list_2, list_3]\n", + "print(l)" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "print(l[0][2])" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(l)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a&b&c\n" + ] + } + ], + "source": [ + "li = ['a', 'b', 'c']\n", + "s = '&'.join(li) #--> this notation is somewhat out of the ordinary for Python, as the split/join character is not given in the function \n", + "#as e.g. li.join('&') , but we will not see this very often\n", + "print(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['a', 'b', 'c']" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.split(\"&\")" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n" + ] + } + ], + "source": [ + "list_of_lists = []\n", + "list_of_lists.append(list_1)\n", + "list_of_lists.append(list_2)\n", + "list_of_lists.append(list_3)\n", + "print(list_of_lists)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could have also created this directly:" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n" + ] + } + ], + "source": [ + "list_of_lists = [[1, 2, 3],\n", + " [4, 5, 6],\n", + " [7, 8, 9]]\n", + "print(list_of_lists)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Access works equivalently:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To access nested lists we can use indexing again." + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[4, 5, 6]" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list_of_lists[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list_of_lists[1][0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "List Comprehensions\n", + "===\n", + "If you are brand new to programming, list comprehensions may look confusing at first. They are a shorthand way of creating and working with lists. It is good to be aware of list comprehensions, because you will see them in other people's code, and they are really useful when you understand how to use them. That said, if they don't make sense to you yet, don't worry about using them right away. When you have worked with enough lists, you will want to use comprehensions. For now, it is good enough to know they exist, and to recognize them when you see them. If you like them, go ahead and start trying to use them now.\n", + "\n", + "Numerical Comprehensions\n", + "---\n", + "Let's consider how we might make a list of the first ten square numbers. We could do it like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "4\n", + "9\n", + "16\n", + "25\n", + "36\n", + "49\n", + "64\n", + "81\n", + "100\n" + ] + } + ], + "source": [ + "# Store the first ten square numbers in a list.\n", + "# Make an empty list that will hold our square numbers.\n", + "squares = []\n", + "\n", + "# Go through the first ten numbers, square them, and add them to our list.\n", + "for number in range(1,11):\n", + " new_square = number**2\n", + " squares.append(new_square)\n", + " \n", + "# Show that our list is correct.\n", + "for square in squares:\n", + " print(square)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This should make sense at this point. \n", + "Visualize it at [Pythontutor](https://goo.gl/Cmhfff)\n", + "\n", + "If it doesn't, go over the code with these thoughts in mind:\n", + "- We make an empty list called *squares* that will hold the values we are interested in.\n", + "- Using the *range()* function, we start a loop that will go through the numbers 1-10.\n", + "- Each time we pass through the loop, we find the square of the current number by raising it to the second power.\n", + "- We add this new value to our list *squares*.\n", + "- We go through our newly-defined list and print out each square.\n", + "\n", + "Now let's make this code more efficient. We don't really need to store the new square in its own variable *new_square*; we can just add it directly to the list of squares. The line\n", + "\n", + " new_square = number**2\n", + "\n", + "is taken out, and the next line takes care of the squaring:" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "4\n", + "9\n", + "16\n", + "25\n", + "36\n", + "49\n", + "64\n", + "81\n", + "100\n" + ] + } + ], + "source": [ + "# Store the first ten square numbers in a list.\n", + "# Make an empty list that will hold our square numbers.\n", + "squares = []\n", + "\n", + "# Go through the first ten numbers, square them, and add them to our list.\n", + "for number in range(1,11):\n", + " squares.append(number**2)\n", + " \n", + "# Show that our list is correct.\n", + "for square in squares:\n", + " print(square)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "List comprehensions allow us to collapse the first three lines of code into one line. Here's what it looks like:" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "4\n", + "9\n", + "16\n", + "25\n", + "36\n", + "49\n", + "64\n", + "81\n", + "100\n" + ] + } + ], + "source": [ + "\n", + "# Store the first ten square numbers in a list.\n", + "squares = [number**2 for number in range(1,11)]\n", + "\n", + "# Show that our list is correct.\n", + "for square in squares:\n", + " print(square)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It should be pretty clear that this code is more efficient than our previous approach, but it may not be clear what is happening. Let's take a look at everything that is happening in that first line:\n", + "\n", + "We define a list called *squares*.\n", + "\n", + "Look at the second part of what's in square brackets:\n", + "\n", + " for number in range(1,11)\n", + "\n", + "This sets up a loop that goes through the numbers 1-10, storing each value in the variable *number*. Now we can see what happens to each *number* in the loop:\n", + "\n", + " number**2\n", + "\n", + "Each number is raised to the second power, and this is the value that is stored in the list we defined. We might read this line in the following way:\n", + "\n", + "squares = [raise *number* to the second power, for each *number* in the range 1-10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Another example\n", + "It is probably helpful to see a few more examples of how comprehensions can be used. Let's try to make the first ten even numbers, the longer way:" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "4\n", + "6\n", + "8\n", + "10\n", + "12\n", + "14\n", + "16\n", + "18\n", + "20\n" + ] + } + ], + "source": [ + "# Make an empty list that will hold the even numbers.\n", + "evens = []\n", + "\n", + "# Loop through the numbers 1-10, double each one, and add it to our list.\n", + "for number in range(1,11):\n", + " evens.append(number*2)\n", + " \n", + "# Show that our list is correct:\n", + "for even in evens:\n", + " print(even)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's how we might think of doing the same thing, using a list comprehension:\n", + "\n", + "evens = [multiply each *number* by 2, for each *number* in the range 1-10]\n", + "\n", + "Here is the same line in code:" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "4\n", + "6\n", + "8\n", + "10\n", + "12\n", + "14\n", + "16\n", + "18\n", + "20\n" + ] + } + ], + "source": [ + "\n", + "# Make a list of the first ten even numbers.\n", + "evens = [number*2 for number in range(1,11)]\n", + "\n", + "for even in evens:\n", + " print(even)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Non-numerical comprehensions\n", + "---\n", + "We can use comprehensions with non-numerical lists as well. In this case, we will create an initial list, and then use a comprehension to make a second list from the first one. Here is a simple example, without using comprehensions:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, bernice the great!\n", + "Hello, aaron the great!\n", + "Hello, cody the great!\n" + ] + } + ], + "source": [ + "# Consider some students.\n", + "students = ['bernice', 'aaron', 'cody']\n", + "\n", + "# Let's turn them into great students.\n", + "great_students = []\n", + "for student in students:\n", + " great_students.append(student + \" the great!\")\n", + "\n", + "# Let's greet each great student.\n", + "for great_student in great_students:\n", + " print(\"Hello, \" + great_student)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To use a comprehension in this code, we want to write something like this:\n", + "\n", + "great_students = [add 'the great' to each *student*, for each *student* in the list of *students*]\n", + "\n", + "Here's what it looks like:" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, bernice the great!\n", + "Hello, aaron the great!\n", + "Hello, cody the great!\n" + ] + } + ], + "source": [ + "\n", + "# Consider some students.\n", + "students = ['bernice', 'aaron', 'cody']\n", + "\n", + "# Let's turn them into great students.\n", + "great_students = [student + \" the great!\" for student in students]\n", + "\n", + "# Let's greet each great student.\n", + "for great_student in great_students:\n", + " print(\"Hello, \" + great_student)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "If these examples are making sense, go ahead and try to do the following exercises using comprehensions. If not, try the exercises without comprehensions. You may figure out how to use comprehensions after you have solved each exercise the longer way.\n", + "\n", + "#### Multiples of Ten\n", + "- Make a list of the first ten multiples of ten (10, 20, 30... 90, 100). There are a number of ways to do this, but try to do it using a list comprehension. Print out your list.\n", + "\n", + "#### Cubes\n", + "- We saw how to make a list of the first ten squares. Make a list of the first ten cubes (1, 8, 27... 1000) using a list comprehension, and print them out.\n", + "\n", + "#### Awesomeness\n", + "- Store five names in a list. Make a second list that adds the phrase \"is awesome!\" to each name, using a list comprehension. Print out the awesome version of the names.\n", + "\n", + "#### Working Backwards\n", + "- Write out the following code without using a list comprehension:\n", + "\n", + " plus_thirteen = [number + 13 for number in range(1,11)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Tuples\n", + "===\n", + "Tuples are basically lists that can never be changed. Lists are quite dynamic; they can grow as you append and insert items, and they can shrink as you remove items. You can modify any element you want to in a list. Sometimes we like this behavior, but other times we may want to ensure that no user or no part of a program can change a list. That's what tuples are for.\n", + "\n", + "Technically, lists are *mutable* objects and tuples are *immutable* objects. Mutable objects can change (think of *mutations*), and immutable objects can not change.\n", + "\n", + "Defining tuples, and accessing elements\n", + "---\n", + "\n", + "You define a tuple just like you define a list, except you use parentheses instead of square brackets. Once you have a tuple, you can access individual elements just like you can with a list, and you can loop through the tuple with a *for* loop:" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The first color is: red\n", + "\n", + "The available colors are:\n", + "- red\n", + "- green\n", + "- blue\n" + ] + } + ], + "source": [ + "colors = ('red', 'green', 'blue')\n", + "print(\"The first color is: \" + colors[0])\n", + "\n", + "print(\"\\nThe available colors are:\")\n", + "for color in colors:\n", + " print(\"- \" + color)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you try to add something to a tuple, you will get an error:" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'tuple' object has no attribute 'append'", + "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[0mcolors\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'red'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'green'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'blue'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mcolors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'purple'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'tuple' object has no attribute 'append'" + ] + } + ], + "source": [ + "colors = ('red', 'green', 'blue')\n", + "colors.append('purple')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The same kind of thing happens when you try to remove something from a tuple, or modify one of its elements. Once you define a tuple, you can be confident that its values will not change." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "\n", + "#### Gymnast Scores\n", + "- A gymnast can earn a score between 1 and 10 from each judge; nothing lower, nothing higher. All scores are integer values; there are no decimal scores from a single judge.\n", + "- Store the possible scores a gymnast can earn from one judge in a tuple.\n", + "- Print out the sentence, \"The lowest possible score is \\_\\_\\_, and the highest possible score is \\_\\_\\_.\" Use the values from your tuple.\n", + "- Print out a series of sentences, \"A judge can give a gymnast ___ points.\"\n", + " - Don't worry if your first sentence reads \"A judge can give a gymnast 1 points.\"\n", + " - However, you get 1000 bonus internet points if you can use a for loop, and have correct grammar. [hint](#hints_gymnast_scores)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Sets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sets are similar to lists, but are not ordered and cannot contain the same element multiple times." + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{1, 2, 3, 4, 5}" + ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "st = set([5, 4, 3, 1, 5, 2, 3, 4, 5])\n", + "st" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'me', 'others', 'them', 'you'}" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list1 = ['me', 'you', 'them']\n", + "list2 = ['you', 'others', 'me']\n", + "st = set(list1+list2)\n", + "st" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hints\n", + "===\n", + "These are placed at the bottom, so you can have a chance to solve exercises without seeing any hints.\n", + "\n", + "\n", + "\n", + "#### Gymnast Scores\n", + "- Hint: Use a slice." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# License" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The MIT License (MIT)\n", + "\n", + "Original work Copyright (c) 2013 Eric Matthes \n", + "Modified work Copyright 2017 Fabian Flöck, Florian Lemmerich \n", + "\n", + "Permission is hereby granted, free of charge, to any person obtaining a copy of\n", + "this software and associated documentation files (the \"Software\"), to deal in\n", + "the Software without restriction, including without limitation the rights to\n", + "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n", + "the Software, and to permit persons to whom the Software is furnished to do so,\n", + "subject to the following conditions:\n", + "\n", + "The above copyright notice and this permission notice shall be included in all\n", + "copies or substantial portions of the Software.\n", + "\n", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n", + "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n", + "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n", + "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n", + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + } + ], + "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.3" + }, + "nav_menu": {}, + "toc": { + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": true, + "toc_section_display": "block", + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/03_dictionaries.ipynb b/03_dictionaries.ipynb new file mode 100644 index 0000000..f81ccdf --- /dev/null +++ b/03_dictionaries.ipynb @@ -0,0 +1,1410 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This lecture is adapted from the great 'Introduction to Python' course from Eric Matthes (http://introtopython.org/) by Fabian Flöck and Florian Lemmerich and, like the original, is available under a [MIT license](#License). " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "toc": "true" + }, + "source": [ + "# Table of Contents\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dictionaries\n", + "===\n", + "Dictionaries allow us to store connected bits of information. For example, you might store a person's name and age together." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What are dictionaries?\n", + "===\n", + "Dictionaries are Python’s built-in mapping type, a way to store information that is connected in some way. They map keys, which can be any immutable(unchanchable) type, to values, which can be any type, i.e., *key-value* pairs, so that any one piece of information in a dictionary is connected to at least one other piece of information.\n", + "\n", + " \n", + "Dictionaries do not store their information in any particular order, so you may not get your information back in the same order you entered it." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "General Syntax\n", + "---\n", + "A general dictionary in Python looks something like this:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```dictionary_name = {key_1: value_1, key_2: value_2, key_3: value_3}```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since the keys and values in dictionaries can be long, we often write just one key-value pair on a line. You might see dictionaries that look more like this:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```dictionary_name = {key_1: value_1,\n", + " key_2: value_2,\n", + " key_3: value_3,\n", + " }```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is a bit easier to read, especially if the values are long." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Example\n", + "---\n", + "A simple example involves modeling an actual dictionary." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'list': 'A collection of values that are not connected, but have an order.', 'dictionary': 'A collection of key-value pairs.', 'function': 'A named set of instructions that defines a set of actions in Python.'}\n" + ] + } + ], + "source": [ + "print(python_words)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(python_words)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can get individual items out of the dictionary, by giving the dictionary's name, and the key in square brackets:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A collection of values that are not connected, but have an order.\n", + "A named set of instructions that defines a set of actions in Python.\n", + "A collection of key-value pairs.\n" + ] + } + ], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }\n", + "\n", + "print(python_words['list'])\n", + "\n", + "print(python_words['function'])\n", + "\n", + "print(python_words['dictionary'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Pet Names\n", + "- Create a dictionary to hold information about pets. Each key is an animal's name, and each value is the kind of animal.\n", + " - For example, 'ziggy': 'canary'\n", + "- Put at least 3 key-value pairs in your dictionary.\n", + "\n", + "\n", + "#### Polling Friends\n", + "- Think of a question you could ask your friends. Create a dictionary where each key is a person's name, and each value is that person's response to your question.\n", + "- Store at least three responses in your dictionary.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Common operations with dictionaries\n", + "===\n", + "There are a few common things you will want to do with dictionaries. These include adding new key-value pairs, modifying information in the dictionary, and removing items from dictionaries." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding new key-value pairs\n", + "---\n", + "To add a new key-value pair, you give the dictionary name followed by the new key in square brackets, and set that equal to the new value. We will show this by starting with an empty dictionary, and re-creating the dictionary from the example above." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Word: list\n", + "Meaning: A collection of values that are not connected, but have an order.\n", + "\n", + "Word: dictionary\n", + "Meaning: A collection of key-value pairs.\n", + "\n", + "Word: function\n", + "Meaning: A named set of instructions that defines a set of actions in Python.\n" + ] + } + ], + "source": [ + "# Create an empty dictionary.\n", + "python_words = {}\n", + "\n", + "# Fill the dictionary, pair by pair.\n", + "python_words['list'] ='A collection of values that are not connected, but have an order.'\n", + "python_words['dictionary'] = 'A collection of key-value pairs.'\n", + "python_words['function'] = 'A named set of instructions that defines a set of actions in Python.'\n", + "\n", + "# Print out the items in the dictionary.\n", + "for word, meaning in python_words.items():\n", + " print(\"\\nWord: \" + word)\n", + " print(\"Meaning: \" + meaning)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also add another dict to your original dict. " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "dict1 = {'something_random': 'puppies', 'not_so_random':'kittens'}" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'list': 'A collection of values that are not connected, but have an order.', 'dictionary': 'A collection of key-value pairs.', 'function': 'A named set of instructions that defines a set of actions in Python.', 'something_random': 'puppies', 'not_so_random': 'kittens'}\n" + ] + } + ], + "source": [ + "python_words.update(dict1)\n", + "print(python_words)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hint: two special functions give you an overview of of all the elements in your dict: " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "List of all keys" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_keys(['list', 'dictionary', 'function', 'something_random', 'not_so_random'])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "python_words.keys()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "List of all values " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_values(['A collection of values that are not connected, but have an order.', 'A collection of key-value pairs.', 'A named set of instructions that defines a set of actions in Python.', 'puppies', 'kittens'])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "python_words.values()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Modifying values in a dictionary\n", + "---\n", + "At some point you may want to modify one of the values in your dictionary. Modifying a value in a dictionary is pretty similar to modifying an element in a list. You give the name of the dictionary and then the key in square brackets, and set that equal to the new value." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A collection of key-value pairs.\n" + ] + } + ], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }\n", + "\n", + "print(python_words['dictionary'])\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A collection of key-value pairs. Each key can be used to access its corresponding value.\n" + ] + } + ], + "source": [ + "# Update/replace one of the meanings.\n", + "python_words['dictionary'] = 'A collection of key-value pairs. Each key can be used to access its corresponding value.'\n", + "\n", + "print(python_words['dictionary'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Removing key-value pairs\n", + "---\n", + "You may want to remove some key-value pairs from one of your dictionaries at some point. You can do this using the same `del` command you learned to use with lists. To remove a key-value pair, you give the `del` command, followed by the name of the dictionary, with the key that you want to delete. This removes the key and the value as a pair." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'dictionary': 'A collection of key-value pairs.', 'function': 'A named set of instructions that defines a set of actions in Python.'}\n" + ] + } + ], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }\n", + "\n", + " \n", + "# Remove the word 'list' and its meaning.\n", + "del python_words['list']\n", + "\n", + "# Show the current set of words and meanings.\n", + "print(python_words)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Modifying keys in a dictionary\n", + "---\n", + "Modifying a value in a dictionary was straightforward, because nothing else depends on the value. Modifying a key is a little harder, because each key is used to unlock a value. We can change a key in two steps:\n", + "\n", + "- Make a new key, and copy the value to the new key.\n", + "- Delete the old key, which also deletes the old value.\n", + "\n", + "Here's what this looks like. We will use a dictionary with just one key-value pair, to keep things simple." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'list': 'A collection of values that are not connected, but have an order.'}\n" + ] + } + ], + "source": [ + "# We have a spelling mistake!\n", + "python_words = {'lisst': 'A collection of values that are not connected, but have an order.'}\n", + "\n", + "# Create a new, correct key, and connect it to the old value.\n", + "# Then delete the old key.\n", + "python_words['list'] = python_words['lisst']\n", + "del python_words['lisst']\n", + "\n", + "# Print the dictionary, to show that the key has changed.\n", + "print(python_words)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Pet Names 2\n", + "- Make a copy of your program from [Pet Names](#exercises_what).\n", + " - Modify one of the values in your dictionary. You could clarify to name a breed, or you could change an animal from a cat to a dog.\n", + " - Add a new key-value pair to your dictionary.\n", + " - Remove one of the key-value pairs from your dictionary.\n", + "\n", + "- Bonus: Use a function to do all of the looping and printing in this problem.\n", + "\n", + "#### Weight Lifting\n", + "- Make a dictionary where the keys are the names of weight lifting exercises, and the values are the number of times you did that exercise.\n", + " - Modify one of the values in your dictionary, to represent doing more of that exercise.\n", + " - Add a new key-value pair to your dictionary.\n", + " \n", + " - Remove one of the key-value pairs from your dictionary.\n", + " \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looping through a dictionary\n", + "===\n", + "Since dictionaries are really about connecting bits of information, you will often use them in the ways described above, where you add key-value pairs whenever you receive some new information, and then you retrieve the key-value pairs that you care about. Sometimes, however, you will want to loop through the entire dictionary. There are several ways to do this:\n", + "\n", + "- You can loop through all key-value pairs;\n", + "- You can loop through the keys, and pull out the values for any keys that you care about;\n", + "- You can loop through the values." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looping through all key-value pairs\n", + "---\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dictionaries have their own for-loop syntax, but since there are two kinds of information in dictionaries, the structure is a bit more complicated than it is for lists. Here is how to use a for loop with a dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "list\n", + "A collection of values that are not connected, but have an order.\n", + "dictionary\n", + "A collection of key-value pairs.\n", + "function\n", + "A named set of instructions that defines a set of actions in Python.\n" + ] + } + ], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }\n", + "\n", + "# Print out the items (key-value pairs, separated by commas) in the dictionary.\n", + "for word, meaning in python_words.items():\n", + " print(word)\n", + " print(meaning)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " If we had 100 terms in our dictionary, we would still be able to print them out with just 3 lines.\n", + "\n", + "The only tricky part about using for loops with dictionaries is figuring out what to call those first two variables. The general syntax for this for loop is:" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "for key_name, value_name in dictionary_name.items():\n", + " print(key_name) # The key is stored in whatever you called the first variable.\n", + " print(value_name) # The value associated with that key is stored in your second variable." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another example:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The key is: key_1 The value is: value_1\n", + "The key is: key_2 The value is: value_2\n", + "The key is: key_3 The value is: value_3\n" + ] + } + ], + "source": [ + "my_dict = {'key_1': 'value_1',\n", + " 'key_2': 'value_2',\n", + " 'key_3': 'value_3',\n", + " }\n", + "\n", + "for key, value in my_dict.items():\n", + " print('The key is:', key, 'The value is:', value)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This works because the method `.items()` pulls all key-value pairs from a dictionary into a list of tuples:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_items([('key_1', 'value_1'), ('key_2', 'value_2'), ('key_3', 'value_3')])\n" + ] + } + ], + "source": [ + "my_dict = {'key_1': 'value_1',\n", + " 'key_2': 'value_2',\n", + " 'key_3': 'value_3',\n", + " }\n", + "\n", + "print(my_dict.items())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The syntax `for key, value in my_dict.items():` does the work of looping through this list of tuples, and pulling the first and second item from each tuple for us.\n", + "\n", + "There is nothing special about any of these variable names, so Python code that uses this syntax becomes really readable. Rather than create a new example of this loop, let's just look at the original example again to see this in a meaningful context:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "list\n", + "A collection of values that are not connected, but have an order.\n", + "dictionary\n", + "A collection of key-value pairs.\n", + "function\n", + "A named set of instructions that defines a set of actions in Python.\n" + ] + } + ], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }\n", + "\n", + "for word, meaning in python_words.items():\n", + " print(word)\n", + " print(meaning)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looping through all keys in a dictionary\n", + "---\n", + "Python provides a clear syntax for looping through just the keys in a dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Key: key_1\n", + "Key: key_2\n", + "Key: key_3\n" + ] + } + ], + "source": [ + "my_dict = {'key_1': 'value_1',\n", + " 'key_2': 'value_2',\n", + " 'key_3': 'value_3',\n", + " }\n", + "\n", + "for key in my_dict.keys():\n", + " print('Key: '+ key)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is actually the default behavior of looping through the dictionary itself. So you can leave out the `.keys()` part, and get the exact same behavior:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Key: key_1\n", + "Key: key_2\n", + "Key: key_3\n" + ] + } + ], + "source": [ + "my_dict = {'key_1': 'value_1',\n", + " 'key_2': 'value_2',\n", + " 'key_3': 'value_3',\n", + " }\n", + "\n", + "for key in my_dict:\n", + " print('Key: '+ key)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The only advantage of using the `.keys()` in the code is a little bit of clarity. But anyone who knows Python reasonably well is going to recognize what the second version does. In the rest of our code, we will leave out the `.keys()` when we want this behavior.\n", + "\n", + "You can pull out the value of any key that you are interested in within your loop, using the standard notation for accessing a dictionary value from a key:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The value for key_1 is value_1\n", + "The value for key_2 is value_2\n", + "The value for key_3 is value_3\n" + ] + } + ], + "source": [ + "my_dict = {'key_1': 'value_1',\n", + " 'key_2': 'value_2',\n", + " 'key_3': 'value_3',\n", + " }\n", + "\n", + "for key in my_dict:\n", + " print(\"The value for\", key, \"is\", my_dict[key])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's show how we might use this in our Python words program. This kind of loop provides a straightforward way to show only the words in the dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The following Python words have been defined:\n", + "- list\n", + "- dictionary\n", + "- function\n" + ] + } + ], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }\n", + "\n", + "# Show the words that are currently in the dictionary.\n", + "print(\"The following Python words have been defined:\")\n", + "for word in python_words:\n", + " print(\"-\", word)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looping through all values in a dictionary\n", + "---\n", + "Python provides a straightforward syntax for looping through all the values in a dictionary, as well:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Value: value_1\n", + "Value: value_2\n", + "Value: value_3\n" + ] + } + ], + "source": [ + "my_dict = {'key_1': 'value_1',\n", + " 'key_2': 'value_2',\n", + " 'key_3': 'value_3',\n", + " }\n", + "\n", + "for value in my_dict.values():\n", + " print('Value:', value)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Meaning: A collection of values that are not connected, but have an order.\n", + "Meaning: A collection of key-value pairs.\n", + "Meaning: A named set of instructions that defines a set of actions in Python.\n" + ] + } + ], + "source": [ + "python_words = {'list': 'A collection of values that are not connected, but have an order.',\n", + " 'dictionary': 'A collection of key-value pairs.',\n", + " 'function': 'A named set of instructions that defines a set of actions in Python.',\n", + " }\n", + "\n", + "for meaning in python_words.values():\n", + " print(\"Meaning: \", meaning)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Mountain Heights\n", + "- Wikipedia has a list of the [tallest mountains in the world](http://en.wikipedia.org/wiki/List_of_mountains_by_elevation), with each mountain's elevation. Pick five mountains from this list.\n", + " - Create a dictionary with the mountain names as keys, and the elevations as values.\n", + " - Print out just the mountains' names, by looping through the keys of your dictionary.\n", + " - Print out just the mountains' elevations, by looping through the values of your dictionary.\n", + " - Print out a series of statements telling how tall each mountain is: \"Everest is 8848 meters tall.\"\n", + "- Revise your output, if necessary.\n", + " - Make sure there is an introductory sentence describing the output for each loop you write.\n", + " - Make sure there is a blank line between each group of statements.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OPTIONAL: Nesting\n", + "===\n", + "Nesting is one of the most powerful concepts we have come to so far. Nesting involves putting a list or dictionary inside another list or dictionary. We will look at two examples here, lists inside of a dictionary and dictionaries inside of a dictionary. With nesting, the kind of information we can model in our programs is expanded greatly." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lists in a dictionary\n", + "---\n", + "A dictionary connects two pieces of information. Those two pieces of information can be any kind of data structure in Python. Let's keep using strings for our keys, but let's try giving a list as a value.\n", + "\n", + "The first example will involve storing a number of people's favorite numbers. The keys consist of people's names, and the values are lists of each person's favorite numbers. In this first example, we will access each person's list one at a time." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Eric's favorite numbers are:\n", + "[3, 11, 19, 23, 42]\n", + "\n", + "Ever's favorite numbers are:\n", + "[2, 4, 5]\n", + "\n", + "Willie's favorite numbers are:\n", + "[5, 35, 120]\n" + ] + } + ], + "source": [ + "# This program stores people's favorite numbers, and displays them.\n", + "favorite_numbers = {'eric': [3, 11, 19, 23, 42],\n", + " 'ever': [2, 4, 5],\n", + " 'willie': [5, 35, 120],\n", + " }\n", + "\n", + "# Display each person's favorite numbers.\n", + "print(\"Eric's favorite numbers are:\")\n", + "print(favorite_numbers['eric'])\n", + "\n", + "print(\"\\nEver's favorite numbers are:\")\n", + "print(favorite_numbers['ever'])\n", + "\n", + "print(\"\\nWillie's favorite numbers are:\")\n", + "print(favorite_numbers['willie'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are really just working our way through each key in the dictionary, so let's use a for loop to go through the keys in the dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "eric's favorite numbers are:\n", + "[3, 11, 19, 23, 42]\n", + "ever's favorite numbers are:\n", + "[2, 4, 5]\n", + "willie's favorite numbers are:\n", + "[5, 35, 120]\n" + ] + } + ], + "source": [ + "\n", + "# This program stores people's favorite numbers, and displays them.\n", + "favorite_numbers = {'eric': [3, 11, 19, 23, 42],\n", + " 'ever': [2, 4, 5],\n", + " 'willie': [5, 35, 120],\n", + " }\n", + "\n", + "# Display each person's favorite numbers.\n", + "for name in favorite_numbers:\n", + " print(name +\"'s favorite numbers are:\" )\n", + " print(favorite_numbers[name]) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This structure is fairly complex, so don't worry if it takes a while for things to sink in. The dictionary itself probably makes sense; each person is connected to a list of their favorite numbers.\n", + "\n", + "This works, but we'd rather not print raw Python in our output. Let's use a for loop to print the favorite numbers individually, rather than in a Python list." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "eric's favorite numbers are:\n", + "3\n", + "11\n", + "19\n", + "23\n", + "42\n", + "ever's favorite numbers are:\n", + "2\n", + "4\n", + "5\n", + "willie's favorite numbers are:\n", + "5\n", + "35\n", + "120\n" + ] + } + ], + "source": [ + "\n", + "# This program stores people's favorite numbers, and displays them.\n", + "favorite_numbers = {'eric': [3, 11, 19, 23, 42],\n", + " 'ever': [2, 4, 5],\n", + " 'willie': [5, 35, 120],\n", + " }\n", + "\n", + "# Display each person's favorite numbers.\n", + "for name in favorite_numbers:\n", + " print(name +\"'s favorite numbers are:\" )\n", + " # Each value is itself a list, so we need another for loop\n", + " # to work with the list.\n", + " for favorite_number in favorite_numbers[name]:\n", + " print(favorite_number) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dictionaries in a dictionary\n", + "---\n", + "The most powerful nesting concept we will cover right now is nesting a dictionary inside of a dictionary.\n", + "\n", + "To demonstrate this, let's make a dictionary of pets, with some information about each pet. The keys for this dictionary will consist of the pet's name. The values will include information such as the kind of animal, the owner, and whether the pet has been vaccinated." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here is what I know about Willie:\n", + "kind: dog\n", + "owner: eric\n", + "vaccinated: True\n", + "\n", + "Here is what I know about Walter:\n", + "kind: cockroach\n", + "owner: eric\n", + "vaccinated: False\n", + "\n", + "Here is what I know about Peso:\n", + "kind: dog\n", + "owner: chloe\n", + "vaccinated: True\n" + ] + } + ], + "source": [ + "# This program stores information about pets. For each pet,\n", + "# we store the kind of animal, the owner's name, and\n", + "# the breed.\n", + "pets = {'willie': {'kind': 'dog', 'owner': 'eric', 'vaccinated': True},\n", + " 'walter': {'kind': 'cockroach', 'owner': 'eric', 'vaccinated': False},\n", + " 'peso': {'kind': 'dog', 'owner': 'chloe', 'vaccinated': True},\n", + " }\n", + "\n", + "# Let's show all the information for each pet.\n", + "print(\"Here is what I know about Willie:\")\n", + "print(\"kind: \" + pets['willie']['kind'])\n", + "print(\"owner: \" + pets['willie']['owner'])\n", + "print(\"vaccinated: \" + str(pets['willie']['vaccinated']))\n", + "\n", + "print(\"\\nHere is what I know about Walter:\")\n", + "print(\"kind: \" + pets['walter']['kind'])\n", + "print(\"owner: \" + pets['walter']['owner'])\n", + "print(\"vaccinated: \" + str(pets['walter']['vaccinated']))\n", + "\n", + "print(\"\\nHere is what I know about Peso:\")\n", + "print(\"kind: \" + pets['peso']['kind'])\n", + "print(\"owner: \" + pets['peso']['owner'])\n", + "print(\"vaccinated: \" + str(pets['peso']['vaccinated']))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Clearly this is some repetitive code, but it shows exactly how we access information in a nested dictionary. In the first set of `print` statements, we use the name 'willie' to unlock the 'kind' of animal he is, the 'owner' he has, and whether or not he is 'vaccinated'. We have to wrap the vaccination value in the `str` function so that Python knows we want the words 'True' and 'False', not the values `True` and `False`. We then do the same thing for each animal.\n", + "\n", + "Let's rewrite this program, using a for loop to go through the dictionary's keys:" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Here is what I know about willie\n", + "kind: dog\n", + "owner: eric\n", + "vaccinated: True\n", + "\n", + "Here is what I know about walter\n", + "kind: cockroach\n", + "owner: eric\n", + "vaccinated: False\n", + "\n", + "Here is what I know about peso\n", + "kind: dog\n", + "owner: chloe\n", + "vaccinated: True\n" + ] + } + ], + "source": [ + "\n", + "# This program stores information about pets. For each pet,\n", + "# we store the kind of animal, the owner's name, and\n", + "# the breed.\n", + "pets = {'willie': {'kind': 'dog', 'owner': 'eric', 'vaccinated': True},\n", + " 'walter': {'kind': 'cockroach', 'owner': 'eric', 'vaccinated': False},\n", + " 'peso': {'kind': 'dog', 'owner': 'chloe', 'vaccinated': True},\n", + " }\n", + "\n", + "# Let's show all the information for each pet.\n", + "for pet_name, pet_information in pets.items():\n", + " print(\"\\nHere is what I know about \" + pet_name)\n", + " print(\"kind: \" + pet_information['kind'])\n", + " print(\"owner: \" + pet_information['owner'])\n", + " print(\"vaccinated: \" + str(pet_information['vaccinated']))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This code is much shorter and easier to maintain. But even this code will not keep up with our dictionary. If we add more information to the dictionary later, we will have to update our print statements. Let's put a second for loop inside the first loop in order to run through all the information about each pet:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Here is what I know about willie\n", + "kind: dog\n", + "owner: eric\n", + "vaccinated: True\n", + "\n", + "Here is what I know about walter\n", + "kind: cockroach\n", + "owner: eric\n", + "vaccinated: False\n", + "\n", + "Here is what I know about peso\n", + "kind: dog\n", + "owner: chloe\n", + "vaccinated: True\n" + ] + } + ], + "source": [ + "\n", + "# This program stores information about pets. For each pet,\n", + "# we store the kind of animal, the owner's name, and\n", + "# the breed.\n", + "pets = {'willie': {'kind': 'dog', 'owner': 'eric', 'vaccinated': True},\n", + " 'walter': {'kind': 'cockroach', 'owner': 'eric', 'vaccinated': False},\n", + " 'peso': {'kind': 'dog', 'owner': 'chloe', 'vaccinated': True},\n", + " }\n", + "\n", + "# Let's show all the information for each pet.\n", + "for pet_name, pet_information in pets.items():\n", + " print(\"\\nHere is what I know about \" + pet_name)\n", + " # Each animal's dictionary is in 'information'\n", + " for key in pet_information:\n", + " print(key + \": \" + str(pet_information[key]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This nested loop can look pretty complicated, so again, don't worry if it doesn't make sense for a while.\n", + "\n", + "- The first loop gives us all the keys in the main dictionary, which consist of the name of each pet.\n", + "- Each of these names can be used to 'unlock' the dictionary of each pet.\n", + "- The inner loop goes through the dictionary for that individual pet, and pulls out all of the keys in that individual pet's dictionary.\n", + "- We print the key, which tells us the kind of information we are about to see, and the value for that key.\n", + "- You can see that we could improve the formatting in the output.\n", + " - We could capitalize the owner's name.\n", + " - We could print 'yes' or 'no', instead of True and False.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An important note about nesting\n", + "---\n", + "While one level of nesting is really useful, nesting much deeper than that gets really complicated, really quickly. There are other structures such as classes which can be even more useful for modeling information. In addition to this, we can use Python to store information in a database, which is the proper tool for storing deeply nested information.\n", + "\n", + "Often times when you are storing information in a database you will pull a small set of that information out and put it into a dictionary, or a slightly nested structure, and then work with it. But you will rarely, if ever, work with Python data structures nested more than one level deep." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Mountain Heights 3\n", + "- This is an extension of [Mountain Heights](#exercise_mountain_heights). Make sure you save this program under a different filename, such as *mountain\\_heights_3.py*, so that you can go back to your original program if you need to.\n", + " - The list of [tallest mountains in the world](http://en.wikipedia.org/wiki/List_of_mountains_by_elevation) provided all elevations in meters. Convert each of these elevations to feet, given that a meter is approximately 3.28 feet. You can do these calculations by hand at this point.\n", + " - Create a new dictionary, where the keys of the dictionary are still the mountains' names. This time however, the values of the dictionary should be a list of each mountain's elevation in meters, and then in feet: {'everest': [8848, 29029]}\n", + " - Print out just the mountains' names, by looping through the keys of your dictionary.\n", + " - Print out just the mountains' elevations in meters, by looping through the values of your dictionary and pulling out the first number from each list.\n", + " - Print out just the mountains' elevations in feet, by looping through the values of your dictionary and pulling out the second number from each list.\n", + " - Print out a series of statements telling how tall each mountain is: \"Everest is 8848 meters tall, or 29029 feet.\"\n", + "- Bonus:\n", + " - Start with your original program from [Mountain Heights](#exercise_mountain_heights). Write a function that reads through the elevations in meters, and returns a list of elevations in feet. Use this list to create the nested dictionary described above.\n", + "\n", + "#### Mountain Heights 4\n", + "- This is one more extension of Mountain Heights.\n", + " - Create a new dictionary, where the keys of the dictionary are once again the mountains' names. This time, the values of the dictionary are another dictionary. This dictionary should contain the elevation in either meters or feet, and the range that contains the mountain. For example: {'everest': {'elevation': 8848, 'range': 'himalaya'}}.\n", + " - Print out just the mountains' names.\n", + " - Print out just the mountains' elevations.\n", + " - Print out just the range for each mountain.\n", + " - Print out a series of statements that say everything you know about each mountain: \"Everest is an 8848-meter tall mountain in the Himalaya range.\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# License\n", + "\n", + "The MIT License (MIT)\n", + "\n", + "Original work Copyright (c) 2013 Eric Matthes \n", + "Modified work Copyright 2017 Fabian Flöck, Florian Lemmerich \n", + "\n", + "Permission is hereby granted, free of charge, to any person obtaining a copy of\n", + "this software and associated documentation files (the \"Software\"), to deal in\n", + "the Software without restriction, including without limitation the rights to\n", + "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n", + "the Software, and to permit persons to whom the Software is furnished to do so,\n", + "subject to the following conditions:\n", + "\n", + "The above copyright notice and this permission notice shall be included in all\n", + "copies or substantial portions of the Software.\n", + "\n", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n", + "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n", + "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n", + "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n", + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "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.3" + }, + "nav_menu": {}, + "toc": { + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": true, + "toc_section_display": "block", + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/04_if_statements.ipynb b/04_if_statements.ipynb new file mode 100644 index 0000000..6cfe690 --- /dev/null +++ b/04_if_statements.ipynb @@ -0,0 +1,825 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If Statements\n", + "===\n", + "By allowing you to respond selectively to different situations and conditions, if statements open up whole new possibilities for your programs. In this section, you will learn how to test for certain conditions, and then respond in appropriate ways to those conditions." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "toc": "true" + }, + "source": [ + "# Table of Contents\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is an *if* statement?\n", + "===\n", + "An *if* statement tests for a condition, and then responds to that condition. If the condition is true, then whatever action is listed next gets carried out. You can test for multiple conditions at the same time, and respond appropriately to each condition.\n", + "\n", + "Example\n", + "---\n", + "Here is an example that shows a number of the desserts I like. It lists those desserts, but lets you know which one is my favorite." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I like ice cream\n", + "I like chocolate\n", + "apple crisp is my favorite dessert!\n", + "I like cookies\n" + ] + } + ], + "source": [ + "# A list of desserts I like.\n", + "desserts = ['ice cream', 'chocolate', 'apple crisp', 'cookies']\n", + "favorite_dessert = 'apple crisp'\n", + "\n", + "# Print the desserts out, but let everyone know my favorite dessert.\n", + "for dessert in desserts:\n", + " if dessert == favorite_dessert:\n", + " # This dessert is my favorite, let's let everyone know!\n", + " print(dessert, \"is my favorite dessert!\")\n", + " \n", + " else:\n", + " # I like these desserts, but they are not my favorite.\n", + " print(\"I like\", dessert)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### What happens in this program?\n", + "\n", + "Visualize it in [Pythontutor](http://pythontutor.com/visualize.html#code=desserts%20%3D%20%5B'ice%20cream',%20'chocolate',%20'apple%20crisp',%20'cookies'%5D%0Afavorite_dessert%20%3D%20'apple%20crisp'%0A%0A%23%20Print%20the%20desserts%20out,%20but%20let%20everyone%20know%20my%20favorite%20dessert.%0Afor%20dessert%20in%20desserts%3A%0A%20%20%20%20if%20dessert%20%3D%3D%20favorite_dessert%3A%0A%20%20%20%20%20%20%20%20%23%20This%20dessert%20is%20my%20favorite,%20let's%20let%20everyone%20know!%0A%20%20%20%20%20%20%20%20print%28dessert,%20%22is%20my%20favorite%20dessert!%22%29%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%23%20I%20like%20these%20desserts,%20but%20they%20are%20not%20my%20favorite.%0A%20%20%20%20%20%20%20%20print%28%22I%20like%22,%20dessert%29&cumulative=false&curInstr=0&heapPrimitives=false&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false)\n", + "\n", + "- The program starts out with a list of desserts, and one dessert is identified as a favorite.\n", + "- The for loop runs through all the desserts.\n", + "- Inside the for loop, each item in the list is tested.\n", + " - If the current value of *dessert* is equal to the value of *favorite_dessert*, a message is printed that this is my favorite.\n", + " - If the current value of *dessert* is not equal to the value of *favorite_dessert*, a message is printed that I just like the dessert.\n", + " \n", + "You can test as many conditions as you want in an if statement, as you will see in a little bit." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The if-elif...else chain\n", + "===\n", + "You can test whatever series of conditions you want to, and you can test your conditions in any combination you want." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Simple if statements\n", + "---\n", + "The simplest test has a single **if** statement, and a single statement to execute if the condition is **True**." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wow, we have a lot of dogs here!\n" + ] + } + ], + "source": [ + "dogs = ['willie', 'hootz', 'peso', 'juno']\n", + "\n", + "if len(dogs) > 3:\n", + " print(\"Wow, we have a lot of dogs here!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this situation, nothing happens if the test does not pass." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "dogs = ['willie', 'hootz']\n", + "\n", + "if len(dogs) > 3:\n", + " print(\"Wow, we have a lot of dogs here!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that there are no errors. The condition `len(dogs) > 3` evaluates to False, and the program moves on to any lines after the **if** block." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "if-else statements\n", + "---\n", + "Many times you will want to respond in two possible ways to a test. If the test evaluates to **True**, you will want to do one thing. If the test evaluates to **False**, you will want to do something else. The **if-else** structure lets you do that easily. Here's what it looks like:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wow, we have a lot of dogs here!\n" + ] + } + ], + "source": [ + "dogs = ['willie', 'hootz', 'peso', 'juno']\n", + "\n", + "if len(dogs) > 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "else:\n", + " print(\"Okay, this is a reasonable number of dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our results have not changed in this case, because if the test evaluates to **True** only the statements under the **if** statement are executed. The statements under **else** area only executed if the test fails:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Okay, this is a reasonable number of dogs.\n" + ] + } + ], + "source": [ + "dogs = ['willie', 'hootz']\n", + "\n", + "if len(dogs) > 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "else:\n", + " print(\"Okay, this is a reasonable number of dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The test evaluated to **False**, so only the statement under `else` is run." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "if-elif...else chains\n", + "---\n", + "Many times, you will want to test a series of conditions, rather than just an either-or situation. You can do this with a series of if-elif-else statements\n", + "\n", + "There is no limit to how many conditions you can test. You always need one if statement to start the chain, and you can never have more than one else statement. But you can have as many elif statements as you want." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Holy mackerel, we might as well start a dog hostel!\n" + ] + } + ], + "source": [ + "dogs = ['willie', 'hootz', 'peso', 'monty', 'juno', 'turkey']\n", + "\n", + "if len(dogs) >= 5:\n", + " print(\"Holy mackerel, we might as well start a dog hostel!\")\n", + "elif len(dogs) >= 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "else:\n", + " print(\"Okay, this is a reasonable number of dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is important to note that in situations like this, only the first test is evaluated. In an if-elif-else chain, once a test passes the rest of the conditions are ignored." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wow, we have a lot of dogs here!\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['willie', 'hootz', 'peso', 'monty']\n", + "\n", + "if len(dogs) >= 5:\n", + " print(\"Holy mackerel, we might as well start a dog hostel!\")\n", + "elif len(dogs) >= 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "else:\n", + " print(\"Okay, this is a reasonable number of dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first test failed, so Python evaluated the second test. That test passed, so the statement corresponding to `len(dogs) >= 3` is executed." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Okay, this is a reasonable number of dogs.\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['willie', 'hootz']\n", + "\n", + "if len(dogs) >= 5:\n", + " print(\"Holy mackerel, we might as well start a dog hostel!\")\n", + "elif len(dogs) >= 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "else:\n", + " print(\"Okay, this is a reasonable number of dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this situation, the first two tests fail, so the statement in the else clause is executed. Note that this statement would be executed even if there are no dogs at all:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Okay, this is a reasonable number of dogs.\n" + ] + } + ], + "source": [ + "\n", + "dogs = []\n", + "\n", + "if len(dogs) >= 5:\n", + " print(\"Holy mackerel, we might as well start a dog hostel!\")\n", + "elif len(dogs) >= 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "else:\n", + " print(\"Okay, this is a reasonable number of dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that you don't have to take any action at all when you start a series of if statements. You could simply do nothing in the situation that there are no dogs by replacing the `else` clause with another `elif` clause:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "dogs = []\n", + "\n", + "if len(dogs) >= 5:\n", + " print(\"Holy mackerel, we might as well start a dog hostel!\")\n", + "elif len(dogs) >= 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "elif len(dogs) >= 1:\n", + " print(\"Okay, this is a reasonable number of dogs.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case, we only print a message if there is at least one dog present. Of course, you could add a new `else` clause to respond to the situation in which there are no dogs at all:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I wish we had a dog here.\n" + ] + } + ], + "source": [ + "dogs = []\n", + "\n", + "if len(dogs) >= 5:\n", + " print(\"Holy mackerel, we might as well start a dog hostel!\")\n", + "elif len(dogs) >= 3:\n", + " print(\"Wow, we have a lot of dogs here!\")\n", + "elif len(dogs) >= 1:\n", + " print(\"Okay, this is a reasonable number of dogs.\")\n", + "else:\n", + " print(\"I wish we had a dog here.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, the if-elif-else chain lets you respond in very specific ways to any given situation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Three is a Crowd\n", + "- Make a list of names that includes at least four people.\n", + "- Write an if test that prints a message about the room being crowded, if there are more than three people in your list.\n", + "- Modify your list so that there are only two people in it. Use one of the methods for removing people from the list, don't just redefine the list.\n", + "- Run your if test again. There should be no output this time, because there are less than three people in the list.\n", + "\n", + "\n", + "#### Three is a Crowd - Part 2\n", + "- Add an `else` statement to your if tests. If the `else` statement is run, have it print a message that the room is not very crowded.\n", + "\n", + "#### Six is a Mob\n", + "- Add some names to your list, so that there are at least six people in the list.\n", + "- Modify your tests so that\n", + " - If there are more than 5 people, a message is printed about there being a mob in the room.\n", + " - If there are 3-5 people, a message is printed about the room being crowded.\n", + " - If there are 1 or 2 people, a message is printed about the room not being crowded.\n", + " - If there are no people in the room, a message is printed abou the room being empty." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "More than one passing test\n", + "===\n", + "In all of the examples we have seen so far, only one test can pass. As soon as the first test passes, the rest of the tests are ignored. This is really good, because it allows our code to run more efficiently. Many times only one condition can be true, so testing every condition after one passes would be meaningless.\n", + "\n", + "There are situations in which you want to run a series of tests, where every single test runs. These are situations where any or all of the tests could pass, and you want to respond to each passing test. Consider the following example, where we want to greet each dog that is present:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, Willie!\n", + "Hello, Hootz!\n" + ] + } + ], + "source": [ + "dogs = ['willie', 'hootz']\n", + "\n", + "if 'willie' in dogs:\n", + " print(\"Hello, Willie!\")\n", + "if 'hootz' in dogs:\n", + " print(\"Hello, Hootz!\")\n", + "if 'peso' in dogs:\n", + " print(\"Hello, Peso!\")\n", + "if 'monty' in dogs:\n", + " print(\"Hello, Monty!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we had done this using an if-elif-else chain, only the first dog that is present would be greeted:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, Willie!\n" + ] + } + ], + "source": [ + "\n", + "dogs = ['willie', 'hootz']\n", + "\n", + "if 'willie' in dogs:\n", + " print(\"Hello, Willie!\")\n", + "elif 'hootz' in dogs:\n", + " print(\"Hello, Hootz!\")\n", + "elif 'peso' in dogs:\n", + " print(\"Hello, Peso!\")\n", + "elif 'monty' in dogs:\n", + " print(\"Hello, Monty!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Of course, this could be written much more cleanly using lists and for loops. See if you can follow this code." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, Willie\n", + "Hello, Hootz\n" + ] + } + ], + "source": [ + "dogs_we_know = ['willie', 'hootz', 'peso', 'monty', 'juno', 'turkey']\n", + "dogs_present = ['willie', 'hootz']\n", + "\n", + "# Go through all the dogs that are present, and greet the dogs we know.\n", + "for dog in dogs_present:\n", + " if dog in dogs_we_know:\n", + " print(\"Hello, \" + dog.title())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is the kind of code you should be aiming to write. It is fine to come up with code that is less efficient at first. When you notice yourself writing the same kind of code repeatedly in one program, look to see if you can use a loop or a function to make your code more efficient." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "True and False values\n", + "===\n", + "Every value can be evaluated as True or False. The general rule is that any non-zero or non-empty value will evaluate to True. If you are ever unsure, you can open a Python terminal and write two lines to find out if the value you are considering is True or False. Take a look at the following examples, keep them in mind, and test any value you are curious about. I am using a slightly longer test just to make sure something gets printed each time." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to False.\n" + ] + } + ], + "source": [ + "if 0:\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to True.\n" + ] + } + ], + "source": [ + "if 1:\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to True.\n" + ] + } + ], + "source": [ + "# Arbitrary non-zero numbers evaluate to True.\n", + "if 1253756:\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to True.\n" + ] + } + ], + "source": [ + "# Negative numbers are not zero, so they evaluate to True.\n", + "if -1:\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to False.\n" + ] + } + ], + "source": [ + "# An empty string evaluates to False.\n", + "if '':\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to True.\n" + ] + } + ], + "source": [ + "# Any other string, including a space, evaluates to True.\n", + "if ' ':\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to True.\n" + ] + } + ], + "source": [ + "# Any other string, including a space, evaluates to True.\n", + "if 'hello':\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This evaluates to False.\n" + ] + } + ], + "source": [ + "# None is a special object in Python. It evaluates to False.\n", + "if None:\n", + " print(\"This evaluates to True.\")\n", + "else:\n", + " print(\"This evaluates to False.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# License\n", + "\n", + "The MIT License (MIT)\n", + "\n", + "Original work Copyright (c) 2013 Eric Matthes \n", + "Modified work Copyright 2017 Fabian Flöck, Florian Lemmerich \n", + "\n", + "Permission is hereby granted, free of charge, to any person obtaining a copy of\n", + "this software and associated documentation files (the \"Software\"), to deal in\n", + "the Software without restriction, including without limitation the rights to\n", + "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n", + "the Software, and to permit persons to whom the Software is furnished to do so,\n", + "subject to the following conditions:\n", + "\n", + "The above copyright notice and this permission notice shall be included in all\n", + "copies or substantial portions of the Software.\n", + "\n", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n", + "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n", + "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n", + "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n", + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This lecture is adapted from the great 'Introduction to Python' course from Eric Matthes (http://introtopython.org/) by Fabian Flöck and Florian Lemmerich and, like the original, is available under a [MIT license](#License). " + ] + } + ], + "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.3" + }, + "nav_menu": {}, + "toc": { + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": true, + "toc_section_display": "block", + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/05_introducing_functions.ipynb b/05_introducing_functions.ipynb new file mode 100644 index 0000000..608ae31 --- /dev/null +++ b/05_introducing_functions.ipynb @@ -0,0 +1,688 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This lecture is adapted from the great 'Introduction to Python' course from Eric Matthes (http://introtopython.org/) by Fabian Flöck and Florian Lemmerich and, like the original, is available under a [MIT license](#License). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Introducing Functions\n", + "===\n", + "One of the core principles of any programming language is, \"Don't Repeat Yourself\". If you have an action that should occur many times, you can define that action once and then call that code whenever you need to carry out that action.\n", + "\n", + "We are already repeating ourselves in our code, so this is a good time to introduce simple functions. Functions mean less work for us as programmers, and effective use of functions results in code that is less error-prone." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What are functions?\n", + "===\n", + "Functions are a set of actions that we group together, and give a name to. You have already used a number of functions from the core Python language, such as *string* and *list.sort()*. We can define our own functions, which allows us to \"teach\" Python new behavior." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "General Syntax\n", + "---\n", + "A general function looks something like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "ename": "IndentationError", + "evalue": "expected an indented block (, line 7)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m7\u001b[0m\n\u001b[0;31m function_name(value_1, value_2)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m expected an indented block\n" + ] + } + ], + "source": [ + "# Let's define a function.\n", + "def function_name(argument_1, argument_2):\n", + "\t# Do whatever we want this function to do,\n", + "\t# using argument_1 and argument_2 that we will have to give to the function in the brackets whenever we run it later on. \n", + "\n", + "# Use function_name to call the function, pass values for the 2 arguments.\n", + "function_name(value_1, value_2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This code will not run, but it shows how functions are used in general.\n", + "\n", + "- **Defining a function**\n", + " - Give the keyword `def`, which tells Python that you are about to *define* a function.\n", + " - Give your function a name. A variable name tells you what kind of value the variable contains; a function name should tell you what the function does.\n", + " - Give names for each value the function needs in order to do its work.\n", + " - These are basically variable names, but they are only used **inside** the function.\n", + " - They can be different names than what you use in the rest of your program.\n", + " - These are called the function's *arguments*.\n", + " - Make sure the function definition line ends with a colon.\n", + " - Inside the function, write whatever code you need to make the function do its work.\n", + "- **Using your function**\n", + " - To *call* your function, write its name followed by parentheses.\n", + " - Inside the parentheses, give the values you want the function to work with.\n", + " - These can be variables such as `current_name` and `current_age`, or they can be actual values such as 'eric' and 5." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Basic Examples\n", + "===\n", + "For a simple first example, we will look at a program that compliments people. Let's look at the example, and then try to understand the code. First we will look at a version of this program as we would have written it earlier, with no functions." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "You are doing good work, Adriana!\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Billy!\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Caroline!\n", + "Thank you very much for your efforts on this project.\n" + ] + } + ], + "source": [ + "print(\"You are doing good work, Adriana!\")\n", + "print(\"Thank you very much for your efforts on this project.\")\n", + "\n", + "print(\"\\nYou are doing good work, Billy!\")\n", + "print(\"Thank you very much for your efforts on this project.\")\n", + "\n", + "print(\"\\nYou are doing good work, Caroline!\")\n", + "print(\"Thank you very much for your efforts on this project.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Functions take repeated code, put it in one place, and then you call that code when you want to use it. Here's what the same program looks like with a function." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "You are doing good work, Adriana !\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Billy !\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Caroline !\n", + "Thank you very much for your efforts on this project.\n" + ] + } + ], + "source": [ + "def thank_you(name):\n", + " # This function prints a two-line personalized thank you message.\n", + " print(\"\\nYou are doing good work, \", name, '!')\n", + " print(\"Thank you very much for your efforts on this project.\")\n", + " \n", + "thank_you('Adriana')\n", + "thank_you('Billy')\n", + "thank_you('Caroline')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In our original code, each pair of print statements was run three times, and the only difference was the name of the person being thanked. When you see repetition like this, you can usually make your program more efficient by defining a function.\n", + "\n", + "The keyword *def* tells Python that we are about to define a function. We give our function a name, *thank\\_you()* in this case. A variable's name should tell us what kind of information it holds; a function's name should tell us what the variable does. We then put parentheses. Inside these parenthese we create variable names for any variable the function will need to be given in order to do its job. In this case the function will need a name to include in the thank you message. The variable `name` will hold the value that is passed into the function *thank\\_you()*.\n", + "\n", + "To use a function we give the function's name, and then put any values the function needs in order to do its work. In this case we call the function three times, each time passing it a different name." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A common error\n", + "A function must be defined before you use it in your program. For example, putting the function at the end of the program would not work." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'thank_u' 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[0mthank_u\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Adriana'\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[0mthank_u\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Billy'\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[0mthank_u\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Caroline'\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;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mthank_u\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\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;31mNameError\u001b[0m: name 'thank_u' is not defined" + ] + } + ], + "source": [ + "thank_u('Adriana')\n", + "thank_u('Billy')\n", + "thank_u('Caroline')\n", + "\n", + "def thank_u(name):\n", + " # This function prints a two-line personalized thank you message.\n", + " print(\"\\nYou are doing good work, \", name, '!')\n", + " print(\"Thank you very much for your efforts on this project.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On the first line we ask Python to run the function *thank\\_u()*, but Python does not yet know how to do this function. We define our functions at the beginning of our programs, and then we can use them when we need to." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A second example\n", + "---\n", + "It takes two lines of code to print a list using a for loop, so these two lines are repeated whenever you want to print out the contents of a list. This is the perfect opportunity to use a function, so let's see how the code looks with a function.\n", + "\n", + "First, let's see the code we had without a function:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Our students are currently in alphabetical order.\n", + "aaron\n", + "bernice\n", + "cody\n", + "\n", + "Our students are now in reverse alphabetical order.\n", + "cody\n", + "bernice\n", + "aaron\n" + ] + } + ], + "source": [ + "students = ['bernice', 'aaron', 'cody']\n", + "\n", + "# Put students in alphabetical order.\n", + "students.sort()\n", + "\n", + "# Display the list in its current order.\n", + "print(\"Our students are currently in alphabetical order.\")\n", + "for student in students:\n", + " print(student)\n", + "\n", + "# Put students in reverse alphabetical order.\n", + "students.sort(reverse=True)\n", + "\n", + "# Display the list in its current order.\n", + "print(\"\\nOur students are now in reverse alphabetical order.\")\n", + "for student in students:\n", + " print(student)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's what the same code looks like, using a function to print out the list:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Our students are currently in alphabetical order.\n", + "aaron\n", + "bernice\n", + "cody\n", + "\n", + "Our students are now in reverse alphabetical order.\n", + "cody\n", + "bernice\n", + "aaron\n" + ] + } + ], + "source": [ + "def show_students(students, message):\n", + " # Print out a message, and then the list of students\n", + " print(message)\n", + " for student in students:\n", + " print(student)\n", + "\n", + "students = ['bernice', 'aaron', 'cody']\n", + "\n", + "# Put students in alphabetical order.\n", + "students.sort()\n", + "show_students(students, \"Our students are currently in alphabetical order.\")\n", + "\n", + "#Put students in reverse alphabetical order.\n", + "students.sort(reverse=True)\n", + "show_students(students, \"\\nOur students are now in reverse alphabetical order.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is much cleaner code. We have an action we want to take, which is to show the students in our list along with a message. We give this action a name, *show\\_students()*. \n", + "\n", + "This function needs two pieces of information to do its work, the list of students and a message to display. Inside the function, the code for printing the message and looping through the list is exactly as it was in the non-function code.\n", + "\n", + "Now the rest of our program is cleaner, because it gets to focus on the things we are changing in the list, rather than having code for printing the list. We define the list, then we sort it and call our function to print the list. We sort it again, and then call the printing function a second time, with a different message. This is much more readable code.\n", + "\n", + "### Advantages of using functions\n", + "You might be able to see some advantages of using functions, through this example:\n", + "\n", + "- We write a set of instructions once. We save some work in this simple example, and we save even more work in larger programs.\n", + "- When our function works, we don't have to worry about that code anymore. Every time you repeat code in your program, you introduce an opportunity to make a mistake. Writing a function means there is one place to fix mistakes, and when those bugs are fixed, we can be confident that this function will continue to work correctly.\n", + "- We can modify our function's behavior, and that change takes effect every time the function is called. This is much better than deciding we need some new behavior, and then having to change code in many different places in our program." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For a quick example, let's say we decide our printed output would look better with some form of a bulleted list. Without functions, we'd have to change each print statement. With a function, we change just the print statement in the function:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Our students are currently in alphabetical order.\n", + "- aaron\n", + "- bernice\n", + "- cody\n", + "\n", + "Our students are now in reverse alphabetical order.\n", + "- cody\n", + "- bernice\n", + "- aaron\n" + ] + } + ], + "source": [ + "def show_students(students, message):\n", + " # Print out a message, and then the list of students\n", + " print(message)\n", + " for student in students:\n", + " print(\"- \" + student)\n", + "\n", + "students = ['bernice', 'aaron', 'cody']\n", + "\n", + "# Put students in alphabetical order.\n", + "students.sort()\n", + "show_students(students, \"Our students are currently in alphabetical order.\")\n", + "\n", + "#Put students in reverse alphabetical order.\n", + "students.sort(reverse=True)\n", + "show_students(students, \"\\nOur students are now in reverse alphabetical order.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can think of functions as a way to \"teach\" Python some new behavior. In this case, we taught Python how to create a list of students using hyphens; now we can tell Python to do this with our students whenever we want to." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Returning a Value\n", + "---\n", + "Each function you create can return a value. This can be in addition to the primary work the function does, or it can be the function's main job. The following function takes in a number, and returns the corresponding word for that number:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 None\n", + "1 one\n", + "2 two\n", + "3 three\n" + ] + } + ], + "source": [ + "def get_number_word(number):\n", + " # Takes in a numerical value, and returns\n", + " # the word corresponding to that number.\n", + " if number == 1:\n", + " return 'one'\n", + " elif number == 2:\n", + " return 'two'\n", + " elif number == 3:\n", + " return 'three'\n", + " # ...\n", + " \n", + "# Let's try out our function.\n", + "for current_number in range(0,4):\n", + " number_word = get_number_word(current_number)\n", + " print(current_number, number_word)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's helpful sometimes to see programs that don't quite work as they are supposed to, and then see how those programs can be improved. In this case, there are no Python errors; all of the code has proper Python syntax. But there is a logical error, in the first line of the output.\n", + "\n", + "We want to either not include 0 in the range we send to the function, or have the function return something other than `None` when it receives a value that it doesn't know. Let's teach our function the word 'zero', but let's also add an `else` clause that returns a more informative message for numbers that are not in the if-chain." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 zero\n", + "1 one\n", + "2 two\n", + "3 three\n", + "4 I'm sorry, I don't know that number.\n", + "5 I'm sorry, I don't know that number.\n" + ] + } + ], + "source": [ + "def get_number_word(number):\n", + " # Takes in a numerical value, and returns\n", + " # the word corresponding to that number.\n", + " if number == 0:\n", + " return 'zero'\n", + " elif number == 1:\n", + " return 'one'\n", + " elif number == 2:\n", + " return 'two'\n", + " elif number == 3:\n", + " return 'three'\n", + " else:\n", + " return \"I'm sorry, I don't know that number.\"\n", + " \n", + "# Let's try out our function.\n", + "for current_number in range(0,6):\n", + " number_word = get_number_word(current_number)\n", + " print(current_number, number_word)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you use a return statement in one of your functions, keep in mind that the function stops executing as soon as it hits a return statement. For example, we can add a line to the *get\\_number\\_word()* function that will never execute, because it comes after the function has returned a value:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 zero\n", + "1 one\n", + "2 two\n", + "3 three\n", + "4 I'm sorry, I don't know that number.\n", + "5 I'm sorry, I don't know that number.\n" + ] + } + ], + "source": [ + "def get_number_word(number):\n", + " # Takes in a numerical value, and returns\n", + " # the word corresponding to that number.\n", + " if number == 0:\n", + " return 'zero'\n", + " elif number == 1:\n", + " return 'one'\n", + " elif number == 2:\n", + " return 'two'\n", + " elif number == 3:\n", + " return 'three'\n", + " else:\n", + " return \"I'm sorry, I don't know that number.\"\n", + " \n", + " # This line will never execute, because the function has already\n", + " # returned a value and stopped executing.\n", + " print(\"This message will never be printed.\")\n", + " \n", + "# Let's try out our function.\n", + "for current_number in range(0,6):\n", + " number_word = get_number_word(current_number)\n", + " print(current_number, number_word)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Exercises\n", + "---\n", + "#### Greeter\n", + "- Write a function that takes in a person's name, and prints out a greeting.\n", + " - The greeting must be at least three lines, and the person's name must be in each line.\n", + "- Use your function to greet at least three different people.\n", + "- **Bonus:** Store your three people in a list, and call your function from a `for` loop.\n", + "\n", + "#### Full Names\n", + "- Write a function that takes in a first name and a last name, and prints out a nicely formatted full name, in a sentence. Your sentence could be as simple as, \"Hello, *full\\_name*.\"\n", + "- Call your function three times, with a different name each time.\n", + "\n", + "#### Addition Calculator\n", + "- Write a function that takes in two numbers, and adds them together. Make your function print out a sentence showing the two numbers, and the result.\n", + "- Call your function with three different sets of numbers.\n", + "\n", + "#### Return Calculator\n", + "- Modify *Addition Calculator* so that your function returns the sum of the two numbers. The printing should happen outside of the function.\n", + "\n", + "#### List Exercises - Functions\n", + "- Go back and solve each of the following exercises from the section on [Lists and Tuples]\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hints\n", + "===\n", + "These are placed at the bottom, so you can have a chance to solve exercises without seeing any hints.\n", + "\n", + "#### Lyrics\n", + "- Define a function that prints out the lyrics of the refrain. Use this function any time the refrain comes up in the song." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# License\n", + "\n", + "The MIT License (MIT)\n", + "\n", + "Original work Copyright (c) 2013 Eric Matthes \n", + "Modified work Copyright 2017 Fabian Flöck, Florian Lemmerich \n", + "\n", + "Permission is hereby granted, free of charge, to any person obtaining a copy of\n", + "this software and associated documentation files (the \"Software\"), to deal in\n", + "the Software without restriction, including without limitation the rights to\n", + "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n", + "the Software, and to permit persons to whom the Software is furnished to do so,\n", + "subject to the following conditions:\n", + "\n", + "The above copyright notice and this permission notice shall be included in all\n", + "copies or substantial portions of the Software.\n", + "\n", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n", + "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n", + "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n", + "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n", + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "hide_input": false, + "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.3" + }, + "nav_menu": {}, + "toc": { + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": true, + "toc_section_display": "block", + "toc_window_display": true + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/06_more_functions.ipynb b/06_more_functions.ipynb new file mode 100644 index 0000000..0364100 --- /dev/null +++ b/06_more_functions.ipynb @@ -0,0 +1,1241 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "toc": "true" + }, + "source": [ + "# Table of Contents\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This lecture is adapted from the great 'Introduction to Python' course from Eric Matthes (http://introtopython.org/) by Fabian Flöck and Florian Lemmerich and, like the original, is available under a [MIT license](#License). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "More Functions\n", + "===\n", + "Earlier we learned the most bare-boned versions of functions. In this section we will learn more general concepts about functions, such as how to use functions to return values, and how to pass different kinds of data structures between functions." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Default argument values\n", + "===\n", + "When we first introduced functions, we started with this example:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "You are doing good work, Adriana\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Billy\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Caroline\n", + "Thank you very much for your efforts on this project.\n" + ] + } + ], + "source": [ + "def thank_you(name):\n", + " # This function prints a two-line personalized thank you message.\n", + " print(\"\\nYou are doing good work, \", name)\n", + " print(\"Thank you very much for your efforts on this project.\")\n", + " \n", + "thank_you('Adriana')\n", + "thank_you('Billy')\n", + "thank_you('Caroline')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This function works fine, but it fails if you don't pass in a value:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "You are doing good work, Adriana\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Billy\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Caroline\n", + "Thank you very much for your efforts on this project.\n" + ] + }, + { + "ename": "TypeError", + "evalue": "thank_you() missing 1 required positional argument: 'name'", + "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 7\u001b[0m \u001b[0mthank_you\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Billy'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mthank_you\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Caroline'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mthank_you\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;31mTypeError\u001b[0m: thank_you() missing 1 required positional argument: 'name'" + ] + } + ], + "source": [ + "def thank_you(name):\n", + " # This function prints a two-line personalized thank you message.\n", + " print(\"\\nYou are doing good work, \", name)\n", + " print(\"Thank you very much for your efforts on this project.\")\n", + " \n", + "thank_you('Adriana')\n", + "thank_you('Billy')\n", + "thank_you('Caroline')\n", + "thank_you()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That makes sense; the function needs to have a name in order to do its work, so without a name it is stuck.\n", + "\n", + "If you want your function to do something by default, even if no information is passed to it, you can do so by giving your arguments default values. You do this by specifying the default values when you define the function:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "You are doing good work, Adriana\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Billy\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, Caroline\n", + "Thank you very much for your efforts on this project.\n", + "\n", + "You are doing good work, everyone\n", + "Thank you very much for your efforts on this project.\n" + ] + } + ], + "source": [ + "\n", + "def thank_you(name='everyone'):\n", + " # This function prints a two-line personalized thank you message.\n", + " # If no name is passed in, it prints a general thank you message\n", + " # to everyone.\n", + " print(\"\\nYou are doing good work, \", name)\n", + " print(\"Thank you very much for your efforts on this project.\")\n", + " \n", + "thank_you('Adriana')\n", + "thank_you('Billy')\n", + "thank_you('Caroline')\n", + "thank_you()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is particularly useful when you have a number of arguments in your function, and some of those arguments almost always have the same value. This allows people who use the function to only specify the values that are unique to their use of the function." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Games\n", + "- Write a function that accepts the name of a game and prints a statement such as, \"I like playing chess!\"\n", + "- Give the argument a default value, such as `chess`.\n", + "- Call your function at least three times. Make sure at least one of the calls includes an argument, and at least one call includes no arguments.\n", + "\n", + "#### Favorite Movie\n", + "- Write a function that accepts the name of a movie, and prints a statement such as, \"My favorite movie is The Princess Bride.\"\n", + "- Give the argument a default value, such as `The Princess Bride`.\n", + "- Call your function at least three times. Make sure at least one of the calls includes an argument, and at least one call includes no arguments." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Positional Arguments\n", + "===\n", + "Much of what you will have to learn about using functions involves how to pass values from your calling statement to the function itself. The example we just looked at is pretty simple, in that the function only needed one argument in order to do its work. Let's take a look at a function that requires two arguments to do its work.\n", + "\n", + "Let's make a simple function that takes in three arguments. Let's make a function that takes in a person's first and last name, and then prints out everything it knows about the person.\n", + "\n", + "Here is a simple implementation of this function:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Last name, first name: kernighan, brian\n", + "Age: 71\n", + "Last name, first name: thompson, ken\n", + "Age: 70\n", + "Last name, first name: goldberg, adele\n", + "Age: 68\n" + ] + } + ], + "source": [ + "def describe_person(first_name, last_name, age):\n", + " # This function takes in a person's first and last name,\n", + " # and their age.\n", + " # It then prints this information out in a simple format.\n", + " print(\"Last name, first name: \", last_name + ',', first_name, )\n", + " print(\"Age: \", age)\n", + "\n", + "describe_person('brian', 'kernighan', 71)\n", + "describe_person('ken', 'thompson', 70)\n", + "describe_person('adele', 'goldberg', 68)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The arguments in this function are `first_name`, `last_name`, and `age`. These are called *positional arguments* because Python knows which value to assign to each by the order in which you give the function values. In the calling line\n", + "\n", + " describe_person('brian', 'kernighan', 71)\n", + "\n", + "we send the values *brian*, *kernighan*, and *71* to the function. Python matches the first value *brian* with the first argument `first_name`. It matches the second value *kernighan* with the second argument `last_name`. Finally it matches the third value *71* with the third argument `age`.\n", + "\n", + "This is pretty straightforward, but it means we have to make sure to get the arguments in the right order. I.e., if we don't stick to the order, our program might not work anymore as intended:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "unsupported operand type(s) for +: 'int' and 'str'", + "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[0mdescribe_person\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'adele'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m68\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'goldberg'\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;36mdescribe_person\u001b[0;34m(first_name, last_name, age)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;31m# and their age.\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;31m# It then prints this information out in a simple format.\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[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Last name, first name: \"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlast_name\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m','\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfirst_name\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[1;32m 6\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Age: \"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mage\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;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'str'" + ] + } + ], + "source": [ + "describe_person('adele', 68, 'goldberg')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This fails as the program expects a string value for the argument in the second position (last_name). Apart from that, the output would also no make much sense of course, as a last name would appear as the age. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Favorite Colors\n", + "- Write a function that takes two arguments, a person's name and their favorite color. The function should print out a statement such as \"Hillary's favorite color is blue.\"\n", + "- Call your function three times, with a different person and color each time.\n", + "\n", + "#### Phones\n", + "- Write a function that takes two arguments, a brand of phone and a model name. The function should print out a phrase such as \"iPhone 6 Plus\".\n", + "- Call your function three times, with a different combination of brand and model each time." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Keyword arguments\n", + "===\n", + "Python allows us to use a syntax called *keyword arguments*. In this case, we can give the arguments in any order when we call the function, as long as we use the name of the arguments in our calling statement. Here is how the previous code can be made to work using keyword arguments:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First name: brian\n", + "Last name: kernighan\n", + "Age: 71\n", + "First name: ken\n", + "Last name: thompson\n", + "Age: 70\n", + "First name: adele\n", + "Last name: goldberg\n", + "Age: 68\n" + ] + } + ], + "source": [ + "def describe_person(first_name, last_name, age):\n", + " # This function takes in a person's first and last name,\n", + " # and their age.\n", + " # It then prints this information out in a simple format.\n", + " print(\"First name: \", first_name)\n", + " print(\"Last name: \", last_name)\n", + " print(\"Age: \", age)\n", + "\n", + "describe_person(age=71, first_name='brian', last_name='kernighan')\n", + "describe_person(age=70, first_name='ken', last_name='thompson')\n", + "describe_person(age=68, first_name='adele', last_name='goldberg')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This works, because Python does not have to match values to arguments by position. It matches the value 71 with the argument `age`, because the value 71 is clearly marked to go with that argument. This syntax is a little more typing, but it makes for very readable code." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Mixing positional and keyword arguments\n", + "---\n", + "It can make good sense sometimes to mix positional and keyword arguments. In our previous example, we can expect this function to always take in a first name and a last name. Before we start mixing positional and keyword arguments, let's add another piece of information to our description of a person. Let's also go back to using just positional arguments for a moment:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First name: brian\n", + "Last name: kernighan\n", + "Age: 71\n", + "Favorite language: C\n", + "First name: ken\n", + "Last name: thompson\n", + "Age: 70\n", + "Favorite language: Go\n", + "First name: adele\n", + "Last name: goldberg\n", + "Age: 68\n", + "Favorite language: Smalltalk\n" + ] + } + ], + "source": [ + "def describe_person(first_name, last_name, age, favorite_language):\n", + " # This function takes in a person's first and last name,\n", + " # their age, and their favorite language.\n", + " # It then prints this information out in a simple format.\n", + " print(\"First name: \", first_name)\n", + " print(\"Last name: \", last_name)\n", + " print(\"Age: \", age)\n", + " print(\"Favorite language: \", favorite_language)\n", + "\n", + "describe_person('brian', 'kernighan', 71, 'C')\n", + "describe_person('ken', 'thompson', 70, 'Go')\n", + "describe_person('adele', 'goldberg', 68, 'Smalltalk')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can expect anyone who uses this function to supply a first name and a last name, in that order. But now we are starting to include some information that might not apply to everyone. We can address this by keeping positional arguments for the first name and last name, but expect keyword arguments for everything else. We can show this works by adding a few more people, and having different information about each person:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First name: brian\n", + "Last name: kernighan\n", + "Favorite language: C\n", + "\n", + "\n", + "First name: ken\n", + "Last name: thompson\n", + "Age: 70\n", + "\n", + "\n", + "First name: adele\n", + "Last name: goldberg\n", + "Age: 68\n", + "Favorite language: Smalltalk\n", + "\n", + "\n", + "First name: dennis\n", + "Last name: ritchie\n", + "Favorite language: C\n", + "Died: 2011\n", + "\n", + "\n", + "First name: guido\n", + "Last name: van rossum\n", + "Favorite language: Python\n", + "\n", + "\n" + ] + } + ], + "source": [ + "\n", + "def describe_person(first_name, last_name, age=None, favorite_language=None, died=None):\n", + " # This function takes in a person's first and last name,\n", + " # their age, and their favorite language.\n", + " # It then prints this information out in a simple format.\n", + " \n", + " # Required information:\n", + " print(\"First name: \", first_name)\n", + " print(\"Last name: \", last_name)\n", + " \n", + " # Optional information:\n", + " if age:\n", + " print(\"Age: \", age)\n", + " if favorite_language:\n", + " print(\"Favorite language: \", favorite_language)\n", + " if died:\n", + " print(\"Died: \", died)\n", + " \n", + " # Blank line at end.\n", + " print(\"\\n\")\n", + "\n", + "describe_person('brian', 'kernighan', favorite_language='C')\n", + "describe_person('ken', 'thompson', age=70)\n", + "describe_person('adele', 'goldberg', age=68, favorite_language='Smalltalk')\n", + "describe_person('dennis', 'ritchie', favorite_language='C', died=2011)\n", + "describe_person('guido', 'van rossum', favorite_language='Python')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Everyone needs a first and last name, but everthing else is optional. This code takes advantage of the Python keyword `None`, which acts as an empty value for a variable. This way, the user is free to supply any of the 'extra' values they care to. Any arguments that don't receive a value are not displayed. Python matches these extra values by name, rather than by position. This is a very common and useful way to define functions." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Exercises\n", + "---\n", + "#### Sports Teams\n", + "- Write a function that takes in two arguments, the name of a city and the name of a sports team from that city.\n", + "- Call your function three times, using a mix of positional and keyword arguments.\n", + "\n", + "#### World Languages\n", + "- Write a function that takes in two arguments, the name of a country and a major language spoken there.\n", + "- Call your function three times, using a mix of positional and keyword arguments." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Anonymous/Lambda functions\n", + "\n", + "An anonymous function is a function that is defined without a name.\n", + "\n", + "While normal functions are defined using the def keyword, in Python anonymous functions are defined using the 'lambda' keyword.\n", + "\n", + "Hence, anonymous functions are also called lambda functions.\n", + "\n", + "Lambda functions are a very concise way to write a function. These will come in handy later especially when working with Pandas. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is a regular function:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def double_func(x):\n", + " return x * 2" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "double_func(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The same as a lambda function:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "double = lambda x: x * 2 # we have to assign the lambda function to a callable" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "double(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We use lambda functions usually when we require a nameless function for a short period of time. We will explain them in context later." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OPTIONAL: Accepting an arbitrary number of arguments\n", + "===\n", + "We have now seen that using keyword arguments can allow for much more flexible calling statements.\n", + "\n", + "- This benefits you in your own programs, because you can write one function that can handle many different situations you might encounter.\n", + "- This benefits you if other programmers use your programs, because your functions can apply to a wide range of situations.\n", + "- This benefits you when you use other programmers' functions, because their functions can apply to many situations you will care about.\n", + "\n", + "There is another issue that we can address, though. Let's consider a function that takes two number in, and prints out the sum of the two numbers:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The sum of your numbers is 3\n", + "The sum of your numbers is 1\n", + "The sum of your numbers is -1\n" + ] + } + ], + "source": [ + "def adder(num_1, num_2):\n", + " # This function adds two numbers together, and prints the sum.\n", + " totalsum = num_1 + num_2\n", + " print(\"The sum of your numbers is \", totalsum)\n", + " \n", + "# Let's add some numbers.\n", + "adder(1, 2)\n", + "adder(-1, 2)\n", + "adder(1, -2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This function appears to work well. But what if we pass it three numbers, which is a perfectly reasonable thing to do mathematically?" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "adder() takes 2 positional arguments but 3 were given", + "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 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;31m# Let's add some numbers.\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[0madder\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: adder() takes 2 positional arguments but 3 were given" + ] + } + ], + "source": [ + "def adder(num_1, num_2):\n", + " # This function adds two numbers together, and prints the sum.\n", + " totalsum = num_1 + num_2\n", + " print(\"The sum of your numbers is \", totalsum)\n", + " \n", + "# Let's add some numbers.\n", + "adder(1, 2, 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This function fails, because no matter what mix of positional and keyword arguments we use, the function is only written two accept two arguments. In fact, a function written in this way will only work with *exactly* two arguments." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Accepting a sequence of arbitrary length\n", + "---\n", + "Python gives us a syntax for letting a function accept an arbitrary number of arguments. If we place an argument at the end of the list of arguments, with an asterisk in front of it, that argument will collect any remaining values from the calling statement into a tuple. Here is an example demonstrating how this works:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "arg_3: ()\n", + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "arg_3: (3,)\n", + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "arg_3: (3, 4)\n", + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "arg_3: (3, 4, 5)\n" + ] + } + ], + "source": [ + "def example_function(arg_1, arg_2, *arg_3):\n", + " # Let's look at the argument values.\n", + " print('\\narg_1:', arg_1)\n", + " print('arg_2:', arg_2)\n", + " print('arg_3:', arg_3)\n", + " \n", + "example_function(1, 2)\n", + "example_function(1, 2, 3)\n", + "example_function(1, 2, 3, 4)\n", + "example_function(1, 2, 3, 4, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can use a for loop to process these other arguments:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "arg_3 value: 3\n", + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "arg_3 value: 3\n", + "arg_3 value: 4\n", + "\n", + "arg_1: 1\n", + "arg_2: 2\n", + "arg_3 value: 3\n", + "arg_3 value: 4\n", + "arg_3 value: 5\n" + ] + } + ], + "source": [ + "\n", + "def example_function(arg_1, arg_2, *arg_3):\n", + " # Let's look at the argument values.\n", + " print('\\narg_1:', arg_1)\n", + " print('arg_2:', arg_2)\n", + " for value in arg_3:\n", + " print('arg_3 value:', value)\n", + "\n", + "example_function(1, 2)\n", + "example_function(1, 2, 3)\n", + "example_function(1, 2, 3, 4)\n", + "example_function(1, 2, 3, 4, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now rewrite the adder() function to accept two or more arguments, and print the sum of those numbers:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The sum of your numbers is 6\n" + ] + } + ], + "source": [ + "def adder(num_1, num_2, *nums):\n", + " # This function adds the given numbers together,\n", + " # and prints the sum.\n", + " \n", + " # Start by adding the first two numbers, which\n", + " # will always be present.\n", + " totalsum = num_1 + num_2\n", + " \n", + " # Then add any other numbers that were sent.\n", + " for num in nums:\n", + " totalsum = totalsum + num\n", + " \n", + " # Print the results.\n", + " print(\"The sum of your numbers is \", totalsum)\n", + " \n", + "# Let's add some numbers.\n", + "adder(1, 2, 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this new version, Python does the following:\n", + "\n", + "- stores the first value in the calling statement in the argument `num_1`;\n", + "- stores the second value in the calling statement in the argument `num_2`;\n", + "- stores all other values in the calling statement as a tuple in the argument `nums`.\n", + "\n", + "We can then \"unpack\" these values, using a for loop. We can demonstrate how flexible this function is by calling it a number of times, with a different number of arguments each time." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The sum of your numbers is 3\n", + "The sum of your numbers is 6\n", + "The sum of your numbers is 10\n", + "The sum of your numbers is 15\n" + ] + } + ], + "source": [ + "\n", + "def adder(num_1, num_2, *nums):\n", + " # This function adds the given numbers together,\n", + " # and prints the sum.\n", + " \n", + " # Start by adding the first two numbers, which\n", + " # will always be present.\n", + " totalsum = num_1 + num_2\n", + " \n", + " # Then add any other numbers that were sent.\n", + " for num in nums:\n", + " totalsum = totalsum + num\n", + " \n", + " # Print the results.\n", + " print(\"The sum of your numbers is \", totalsum)\n", + "\n", + " \n", + "# Let's add some numbers.\n", + "adder(1, 2)\n", + "adder(1, 2, 3)\n", + "adder(1, 2, 3, 4)\n", + "adder(1, 2, 3, 4, 5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[top](#)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Accepting an arbitrary number of keyword arguments\n", + "---\n", + "Python also provides a syntax for accepting an arbitrary number of keyword arguments. The syntax looks like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "arg_1: a\n", + "arg_2: b\n", + "arg_3: {}\n", + "\n", + "arg_1: a\n", + "arg_2: b\n", + "arg_3: {'value_3': 'c'}\n", + "\n", + "arg_1: a\n", + "arg_2: b\n", + "arg_3: {'value_3': 'c', 'value_4': 'd'}\n", + "\n", + "arg_1: a\n", + "arg_2: b\n", + "arg_3: {'value_3': 'c', 'value_4': 'd', 'value_5': 'e'}\n" + ] + } + ], + "source": [ + "def example_function(arg_1, arg_2, **kwargs):\n", + " # Let's look at the argument values.\n", + " print('\\narg_1:', arg_1)\n", + " print('arg_2:', arg_2)\n", + " print('arg_3:', kwargs)\n", + " \n", + "example_function('a', 'b')\n", + "example_function('a', 'b', value_3='c')\n", + "example_function('a', 'b', value_3='c', value_4='d')\n", + "example_function('a', 'b', value_3='c', value_4='d', value_5='e')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The third argument has two asterisks in front of it, which tells Python to collect all remaining key-value arguments in the calling statement. This argument is commonly named *kwargs*. We see in the output that these key-values are stored in a dictionary. We can loop through this dictionary to work with all of the values that are passed into the function:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "arg_1: a\n", + "arg_2: b\n", + "\n", + "arg_1: a\n", + "arg_2: b\n", + "arg_3 value: c\n", + "\n", + "arg_1: a\n", + "arg_2: b\n", + "arg_3 value: c\n", + "arg_3 value: d\n", + "\n", + "arg_1: a\n", + "arg_2: b\n", + "arg_3 value: c\n", + "arg_3 value: d\n", + "arg_3 value: e\n" + ] + } + ], + "source": [ + "\n", + "def example_function(arg_1, arg_2, **kwargs):\n", + " # Let's look at the argument values.\n", + " print('\\narg_1:', arg_1)\n", + " print('arg_2:', arg_2)\n", + " for key, value in kwargs.items():\n", + " print('arg_3 value:', value)\n", + " \n", + "example_function('a', 'b')\n", + "example_function('a', 'b', value_3='c')\n", + "example_function('a', 'b', value_3='c', value_4='d')\n", + "example_function('a', 'b', value_3='c', value_4='d', value_5='e')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Earlier we created a function that let us describe a person, and we had three things we could describe about a person. We could include their age, their favorite language, and the date they passed away. But that was the only information we could include, because it was the only information that the function was prepared to handle:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First name: brian\n", + "Last name: kernighan\n", + "Favorite language: C\n", + "\n", + "\n", + "First name: ken\n", + "Last name: thompson\n", + "Age: 70\n", + "\n", + "\n", + "First name: adele\n", + "Last name: goldberg\n", + "Age: 68\n", + "Favorite language: Smalltalk\n", + "\n", + "\n", + "First name: dennis\n", + "Last name: ritchie\n", + "Favorite language: C\n", + "Died: 2011\n", + "\n", + "\n", + "First name: guido\n", + "Last name: van rossum\n", + "Favorite language: Python\n", + "\n", + "\n" + ] + } + ], + "source": [ + "def describe_person(first_name, last_name, age=None, favorite_language=None, died=None):\n", + " # This function takes in a person's first and last name,\n", + " # their age, and their favorite language.\n", + " # It then prints this information out in a simple format.\n", + " \n", + " # Required information:\n", + " print(\"First name: %s\" % first_name)\n", + " print(\"Last name: %s\" % last_name)\n", + " \n", + " # Optional information:\n", + " if age:\n", + " print(\"Age: %d\" % age)\n", + " if favorite_language:\n", + " print(\"Favorite language: %s\" % favorite_language)\n", + " if died:\n", + " print(\"Died: %d\" % died)\n", + " \n", + " # Blank line at end.\n", + " print(\"\\n\")\n", + "\n", + "describe_person('brian', 'kernighan', favorite_language='C')\n", + "describe_person('ken', 'thompson', age=70)\n", + "describe_person('adele', 'goldberg', age=68, favorite_language='Smalltalk')\n", + "describe_person('dennis', 'ritchie', favorite_language='C', died=2011)\n", + "describe_person('guido', 'van rossum', favorite_language='Python')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can make this function much more flexible by accepting any number of keyword arguments. Here is what the function looks like, using the syntax for accepting as many keyword arguments as the caller wants to provide:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First name: brian\n", + "Last name: kernighan\n", + "favorite_language: C\n", + "\n", + "\n", + "First name: ken\n", + "Last name: thompson\n", + "age: 70\n", + "\n", + "\n", + "First name: adele\n", + "Last name: goldberg\n", + "age: 68\n", + "favorite_language: Smalltalk\n", + "\n", + "\n", + "First name: dennis\n", + "Last name: ritchie\n", + "favorite_language: C\n", + "died: 2011\n", + "\n", + "\n", + "First name: guido\n", + "Last name: van rossum\n", + "favorite_language: Python\n", + "\n", + "\n" + ] + } + ], + "source": [ + "\n", + "def describe_person(first_name, last_name, **kwargs):\n", + " # This function takes in a person's first and last name,\n", + " # and then an arbitrary number of keyword arguments.\n", + " \n", + " # Required information:\n", + " print(\"First name: %s\" % first_name)\n", + " print(\"Last name: %s\" % last_name)\n", + " \n", + " # Optional information:\n", + " for key in kwargs:\n", + " print(\"%s: %s\" % (key, kwargs[key]))\n", + " \n", + " # Blank line at end.\n", + " print(\"\\n\")\n", + "\n", + "describe_person('brian', 'kernighan', favorite_language='C')\n", + "describe_person('ken', 'thompson', age=70)\n", + "describe_person('adele', 'goldberg', age=68, favorite_language='Smalltalk')\n", + "describe_person('dennis', 'ritchie', favorite_language='C', died=2011)\n", + "describe_person('guido', 'van rossum', favorite_language='Python')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# License\n", + "\n", + "The MIT License (MIT)\n", + "\n", + "Original work Copyright (c) 2013 Eric Matthes \n", + "Modified work Copyright 2017 Fabian Flöck, Florian Lemmerich \n", + "\n", + "Permission is hereby granted, free of charge, to any person obtaining a copy of\n", + "this software and associated documentation files (the \"Software\"), to deal in\n", + "the Software without restriction, including without limitation the rights to\n", + "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n", + "the Software, and to permit persons to whom the Software is furnished to do so,\n", + "subject to the following conditions:\n", + "\n", + "The above copyright notice and this permission notice shall be included in all\n", + "copies or substantial portions of the Software.\n", + "\n", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n", + "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n", + "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n", + "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n", + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "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.3" + }, + "nav_menu": {}, + "toc": { + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": true, + "toc_section_display": "block", + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}