Repository: leriomaggio/python-in-a-notebook Branch: master Commit: ac68538f9a25 Files: 34 Total size: 696.2 KB Directory structure: gitextract_p4ilgqem/ ├── .gitignore ├── 00 Programming Environment.ipynb ├── 01 Hello World.ipynb ├── 01 Introducing the IPython Notebook.ipynb ├── 02 Variable Strings and Numbers.ipynb ├── 03 List and Tuples and Sets.ipynb ├── 04 If Statements.ipynb ├── 05 While Loops and User input.ipynb ├── 06 Dictionaries.ipynb ├── 07 Introduction to Functions.ipynb ├── 07 More Functions.ipynb ├── 08 Classes and OOP.ipynb ├── 09 Exceptions.ipynb ├── 10 External files.ipynb ├── 11 Persistence.ipynb ├── Coding Style (PEP8).ipynb ├── Importing Modules.ipynb ├── Index.ipynb ├── LICENSE ├── README.md ├── Resources and References.ipynb ├── The Zen of Python.ipynb ├── data/ │ ├── data.txt │ ├── data2.txt │ ├── dbase1 │ ├── elderlyHeightWeight.csv │ ├── male_data.tsv │ ├── new_data.csv │ ├── test.txt │ └── testdb ├── files/ │ ├── example.css │ └── makedicts.py ├── multiplying.py └── rocket.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ TOC.ipynb __pycache__ data/BODY_COMPOSITION_DATA_4_ASSIGNMENT.csv data/BODY_COMPOSITION_DATA_4_ASSIGNMENT.tsv data/elderly_bmi.csv data/elderlyPhenoData_small.csv data/energy.txt data/energy_intake.txt data/helium.txt data/marathon.csv data/module_grades.tsv data/nhanes.csv data/nhanes_bmi.csv data/obesity_stats.xlsx data/pparg_prot.fa data/run10.txt data/states.csv Untitled.ipynb ================================================ FILE: 00 Programming Environment.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Programming Environment\n", "\n", "Your \"programming environment\" is the computer you do your work on, and all the software that is installed on your computer that helps you write and run programs. Some systems are better for programming than others, but the best system to learn on is probably the one you are using right now. This section will help you get a system set up that will let you start writing programs quickly." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Overview\n", "===\n", "Our goal is to help you get Python up and running on your computer, so that you can write and run your own programs. To do this, we want to:\n", "\n", "- Find out if Python is already installed on your computer.\n", "- Install Python, if it is not already installed.\n", "\n", "----\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Disclaimer\n", "\n", "If you already have a working Python installation, please feel free to skip this notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Anaconda Python Distribution\n", "\n", "We use **Python 3.5** included in the [**Anaconda**](https://store.continuum.io/cshop/anaconda/) distribution by \n", "[**Continuum Analytics**](http://www.continuum.io/).\n", "\n", "Anaconda is a completely free enterprise-ready Python distribution for large-scale data processing, predictive analytics, and scientific computing. \n", "\n", "Apart from that, Anaconda ships with easy-to-use installers for almost every platform, that wuold drastically reduce the \n", "burden of setting up the environment (exp. on [Windows](http://continuum.io/downloads#34))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Quick Start Guide\n", "\n", "If you've installed **Anaconda** but you don't know what do then, please take a look at the [Quick Start Guide](https://store.continuum.io/static/img/Anaconda-Quickstart.pdf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Standard or System Python Distributions\n", "\n", "If you would like to install more \"classical\" Python distributions (e.g., those available on the \n", "[`python.org`](https://www.python.org/downloads/) web site), please take a look at this notebook:\n", "\n", "\n", "[Programming Environment](http://nbviewer.ipython.org/urls/raw.github.com/ehmatthes/intro_programming/master/notebooks/programming_environment.ipynb)" ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 01 Hello World.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# \"Hello world\" in Python!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "When programmers are learning a new language, we tend to write a one-line program that prints some version of the message \"Hello world!\" this is a simple program that shows whether your computer is properly set up to run Python programs." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello Python world!\n" ] } ], "source": [ "print('Hello Python world!')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "If it works, congratulations! You just ran your first Python program." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 01 Introducing the IPython Notebook.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Introducing the IPython Notebook" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### Aron Ahmadia (US Army ERDC) and David Ketcheson (KAUST)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### Teaching Numerical Methods with IPython Notebooks, SciPy 2014" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "\"Creative
This lecture by Aron Ahmadia and David Ketcheson is licensed under a Creative Commons Attribution 4.0 International License. All code examples are also licensed under the [MIT license](http://opensource.org/licenses/MIT).\n", "\n", "**NOTE**: Some changes have been applied to make this notebook compliant with **Python 3**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## What is this?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is a gentle introduction to the IPython Notebook aimed at lecturers who wish to incorporate it in their teaching, written in an IPython Notebook. This presentation adapts material from the [IPython official documentation](http://nbviewer.ipython.org/github/ipython/ipython/blob/2.x/examples/Notebook)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## What is an IPython Notebook?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "An IPython Notebook is a:\n", "\n", "**[A]** Interactive environment for writing and running code \n", "**[B]** Weave of code, data, prose, equations, analysis, and visualization \n", "**[C]** Tool for prototyping new code and analysis \n", "**[D]** Reproducible workflow for scientific research \n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**[E]** **All of the above**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Writing and Running Code" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The IPython Notebook consists of an ordered list of cells. \n", "\n", "There are four important cell types:\n", "\n", "* **Code**\n", "* **Markdown**\n", "* **Heading**\n", "* **Raw**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We briefly introduce how Code Cells work here. We will return to the other three cell types later." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Code Cells" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# This is a code cell made up of Python comments\n", "# We can execute it by clicking on it with the mouse\n", "# then clicking the \"Run Cell\" button" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, World\n" ] } ], "source": [ "# A comment is a pretty boring piece of code\n", "# This code cell generates \"Hello, World\" when executed\n", "\n", "print(\"Hello, World\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAEACAYAAABI5zaHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADu1JREFUeJzt3H+s3fVdx/Hni1ZwSlpdzYprR6sIU5ZgxQSKxHCWaUYx\nUv9Y3OYSFP8hyyZEErNJlrR/6h/GDOeCjYysy+bYyLKhA8WF3ZD5RzeBhjrajWULlDKuIaxBfsSU\n+faP86XcXW57zr0993xPP/f5SL7p98f7fr/vnJ7zOp/zOfd7U1VIktpyTt8NSJImz3CXpAYZ7pLU\nIMNdkhpkuEtSgwx3SWrQyHBPcl6SA0keTXIoyZ5T1N2e5IkkB5PsmHyrkqRxrR9VUFX/m+SdVfVy\nknXAfyS5v6q++VpNkl3ARVV1cZIrgTuAnavXtiTpdMaalqmql7vV8xi+ISy+82k3sL+rPQBsTLJ5\nUk1KkpZnrHBPck6SR4FngX+vqm8tKtkCHF2wfazbJ0nqwbgj9/+rqt8AtgJXJrl0dduSJJ2JkXPu\nC1XVC0m+DlwLPL7g0DHgbQu2t3b7fkIS/5CNJK1AVWU59eP8tswvJNnYrb8J+F3gyKKye4Ebupqd\nwPGqmj9Fgy5V7Nmzp/ceXv+jcdXzMgs91Ew8P2fleTELi4/F68tKjDNy/0Xg00nOYfhmcHdV3Zfk\npuFrofZ129cl+R7wEnDjirqRJE3EOL8KeQi4fIn9/7Bo+8MT7EuSdAa8Q7Ung8Gg7xY0g3xevM7H\n4sxkpfM5K7pYUtO8nkZLwhtvW5h6FzPQA0BWPL8praYk1KS/UJUknX0Md0lqkOEuSQ0y3CWpQYa7\nJDXIcJekBhnuktQgw12SGmS4S1KDDHdJapDhLkkNMtwlqUGGuyQ1yHCXpAYZ7pLUIMNdkhpkuEtS\ngwx3SWqQ4S5JDTLcJalBhrskNchwl6QGGe6S1CDDXZIaZLhLUoMMd0lq0MhwT7I1yYNJvp3kUJKb\nl6i5JsnxJI90y8dWp11J0jjWj1HzKnBrVR1Mcj7wcJIHqurIorqHqur6ybcoSVqukSP3qnq2qg52\n6y8Ch4EtS5Rmwr1JklZoWXPuSbYDO4ADSxy+KsnBJF9NcukEepMkrdA40zIAdFMy9wC3dCP4hR4G\nLqyql5PsAr4MXDK5NiVJyzFWuCdZzzDYP1NVX1l8fGHYV9X9ST6Z5M1V9fzi2r17955cHwwGDAaD\nFbQtSe2am5tjbm7ujM6RqhpdlOwHnquqW09xfHNVzXfrVwBfqKrtS9TVONfT9CQB+v4/mYUeAILP\nT82iJFTVsr7XHDlyT3I18AHgUJJHGb4KbwO2AVVV+4D3JPkgcAJ4BXjvcpuXJE3OWCP3iV3MkfvM\nceS+kCN3zaaVjNy9Q1WSGmS4S1KDDHdJapDhLkkNMtwlqUGGuyQ1yHCXpAYZ7pLUIMNdkhpkuEtS\ngwx3SWqQ4S5JDTLcJalBhrskNchwl6QGGe6S1CDDXZIaZLhLUoMMd0lqkOEuSQ0y3CWpQYa7JDXI\ncJekBhnuktQgw12SGmS4S1KDDHdJapDhLkkNMtwlqUEjwz3J1iQPJvl2kkNJbj5F3e1JnkhyMMmO\nybcqSRrX+jFqXgVuraqDSc4HHk7yQFUdea0gyS7goqq6OMmVwB3AztVpWZI0ysiRe1U9W1UHu/UX\ngcPAlkVlu4H9Xc0BYGOSzRPuVZI0pmXNuSfZDuwADiw6tAU4umD7GG98A5AkTck40zIAdFMy9wC3\ndCP4Fdm7d+/J9cFgwGAwWOmpzmoXXLCd+fkn+25D0gyam5tjbm7ujM6RqhpdlKwH/gW4v6o+vsTx\nO4CvV9Xd3fYR4Jqqml9UV+Ncby1IAszCYzELfcxCDwDB56dmURKqKsv5mXGnZT4FPL5UsHfuBW7o\nmtgJHF8c7JKk6Rk5ck9yNfAQcIjh8KqA24BtQFXVvq7uE8C1wEvAjVX1yBLncuTeceQ+az2AI3fN\nqpWM3MealpkUw/11hvus9QCGu2bVak7LSJLOIoa7JDXIcJekBhnuktQgw12SGmS4S1KDDHdJapDh\nLkkNMtwlqUGGuyQ1yHCXpAYZ7pLUIMNdkhpkuEtSgwx3SWqQ4S5JDTLcJalBhrskNchwl6QGGe6S\n1CDDXZIaZLhLUoMMd0lqkOEuSQ0y3CWpQYa7JDXIcJekBhnuktSgkeGe5M4k80keO8Xxa5IcT/JI\nt3xs8m1KkpZj/Rg1dwF/B+w/Tc1DVXX9ZFqSJJ2pkSP3qvoG8KMRZZlMO5KkSZjUnPtVSQ4m+WqS\nSyd0TknSCo0zLTPKw8CFVfVykl3Al4FLTlW8d+/ek+uDwYDBYDCBFiSpHXNzc8zNzZ3ROVJVo4uS\nbcA/V9VlY9T+APjNqnp+iWM1zvXWgiTALDwWs9DHLPQAEHx+ahYloaqWNf097rRMOMW8epLNC9av\nYPiG8YZglyRNz8hpmSSfAwbApiRPAXuAc4Gqqn3Ae5J8EDgBvAK8d/XalSSNY6xpmYldzGmZk5yW\nmbUewGkZzarVnJaRJJ1FDHdJapDhLkkNMtwlqUGGuyQ1yHCXpAYZ7pLUIMNdkhpkuEtSgwx3SWqQ\n4S5JDTLcJalBhrskNchwl6QGGe6S1CDDXZIaZLhLUoMMd0lqkOEuSQ0y3CWpQYa7JDXIcJekBhnu\nktQgw12SGmS4S1KDDHdJapDhLkkNMtwlqUEjwz3JnUnmkzx2mprbkzyR5GCSHZNtUZK0XOOM3O8C\n3n2qg0l2ARdV1cXATcAdE+pNkrRCI8O9qr4B/Og0JbuB/V3tAWBjks2TaU+StBLrJ3COLcDRBdvH\nun3zSxU/88wzE7jkyp133nls2rSp1x4kabVNItyXZdu2t59cX7fuXNatO2+q1z9x4jgbN27iueee\nnup1JZ2dLrhgO/PzT/bdxrJNItyPAW9bsL2127ekV1/9nwXrE7j6Mm3YcBnPPXcIqOlf/Cek5+tL\nGscw2M++vBj3VyFzmrPfC9wAkGQncLyqlpySkSRNx8iRe5LPAQNgU5KngD3AuUBV1b6qui/JdUm+\nB7wE3LiaDUuSRkvV9D5uJKm+P95s2HAZL7wwK9MyffcAs9HHLPQAEKb5etDZIZmF52eoqmXNzXiH\nqiQ1yHCXpAYZ7pLUIMNdkhpkuEtSgwx3SWqQ4S5JDTLcJalBhrskNchwl6QGGe6S1CDDXZIaZLhL\nUoMMd0lqkOEuSQ0y3CWpQYa7JDXIcJekBhnuktQgw12SGmS4S1KDDHdJapDhLkkNMtwlqUGGuyQ1\nyHCXpAYZ7pLUIMNdkho0VrgnuTbJkSTfTfKRJY5fk+R4kke65WOTb1WSNK71owqSnAN8AngX8Azw\nrSRfqaoji0ofqqrrV6FHSdIyjTNyvwJ4oqqerKoTwOeB3UvUZaKdSZJWbJxw3wIcXbD9dLdvsauS\nHEzy1SSXTqQ7SdKKjJyWGdPDwIVV9XKSXcCXgUsmdG5J0jKNE+7HgAsXbG/t9p1UVS8uWL8/ySeT\nvLmqnn/j6fYuWB90iyTpdXPdsnKpqtMXJOuA7zD8QvWHwDeB91fV4QU1m6tqvlu/AvhCVW1f4lwF\np7/eatuw4TJeeOEQffcx/Iqi7x5gNvqYhR4AwqjXg9aeZBaen6GqlvW95siRe1X9OMmHgQcYztHf\nWVWHk9w0PFz7gPck+SBwAngFeO/ym5ckTcrIkftEL+bIfYFZGA3AbPQxCz2AI3ct5WwduXuHqiQ1\nyHCXpAYZ7pLUIMNdkhpkuEtSgwx3SWqQ4S5JDTLcJalBhrskNchwl6QGGe6S1CDDXZIaZLhLUoMM\nd0lqkOEuSQ0y3CWpQYa7JDXIcJekBhnuktQgw12SGmS4S1KDDHdJapDhLkkNMtwlqUGGuyQ1yHCX\npAYZ7pLUIMNdkho0VrgnuTbJkSTfTfKRU9TcnuSJJAeT7Jhsm5Kk5RgZ7knOAT4BvBt4B/D+JL+6\nqGYXcFFVXQzcBNyxCr1KzZubm+u7hZnhY3Fmxhm5XwE8UVVPVtUJ4PPA7kU1u4H9AFV1ANiYZPNE\nO5XWAAPtdT4WZ2accN8CHF2w/XS373Q1x5aokSRNyfppX3DDht+f9iV/wiuv/KDX60vSNKSqTl+Q\n7AT2VtW13fZHgaqqv15Qcwfw9aq6u9s+AlxTVfOLznX6i0mSllRVWU79OCP3bwG/kmQb8EPgfcD7\nF9XcC3wIuLt7Mzi+ONhX0pwkaWVGhntV/TjJh4EHGM7R31lVh5PcNDxc+6rqviTXJfke8BJw4+q2\nLUk6nZHTMpKks8/U7lAd50aotSDJ1iQPJvl2kkNJbu67pz4lOSfJI0nu7buXviXZmOSLSQ53z48r\n++6pD0n+PMl/JXksyWeTnNt3T9OU5M4k80keW7Dv55M8kOQ7Sf4tycZR55lKuI9zI9Qa8ipwa1W9\nA7gK+NAafiwAbgEe77uJGfFx4L6q+jXg14HDPfczdUneCvwZcHlVXcZw6vh9/XY1dXcxzMqFPgp8\nrareDjwI/OWok0xr5D7OjVBrQlU9W1UHu/UXGb6A1+Q9AUm2AtcB/9h3L31LsgH47aq6C6CqXq2q\nF3puqy/rgJ9Nsh74GeCZnvuZqqr6BvCjRbt3A5/u1j8N/MGo80wr3Me5EWrNSbId2AEc6LeT3vwt\n8BeAX/zALwHPJbmrm6bal+RNfTc1bVX1DPA3wFMMb4Y8XlVf67ermfCW134DsaqeBd4y6gf8q5A9\nSXI+cA9wSzeCX1OS/B4w332KSbesZeuBy4G/r6rLgZcZfhRfU5L8HMNR6jbgrcD5Sf6o365m0sgB\n0bTC/Rhw4YLtrd2+Nan7uHkP8Jmq+krf/fTkauD6JN8H/gl4Z5L9PffUp6eBo1X1n932PQzDfq35\nHeD7VfV8Vf0Y+BLwWz33NAvmX/t7XUkuAP571A9MK9xP3gjVffP9PoY3Pq1VnwIer6qP991IX6rq\ntqq6sKp+meHz4cGquqHvvvrSfeQ+muSSbte7WJtfND8F7Ezy00nC8HFYc18s88ZPs/cCf9Kt/zEw\nclA4lb8tc6oboaZx7VmT5GrgA8ChJI8y/Hh1W1X9a7+daQbcDHw2yU8B32cN3gxYVd9Mcg/wKHCi\n+3dfv11NV5LPAQNgU5KngD3AXwFfTPKnwJPAH448jzcxSVJ7/EJVkhpkuEtSgwx3SWqQ4S5JDTLc\nJalBhrskNchwl6QGGe6S1KD/B19YUsQgbm54AAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Code cells can also generate graphical output\n", "%matplotlib inline\n", "import matplotlib\n", "matplotlib.pyplot.hist([0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 10]);" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Modal editor" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Starting with IPython 2.0, the IPython Notebook has a modal user interface. This means that the keyboard does different things depending on which mode the Notebook is in. There are two modes: edit mode and command mode." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Edit mode" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Edit mode is indicated by a green cell border and a prompt showing in the editor area:\n", "\n", "\n", "\n", "When a cell is in edit mode, you can type into the cell, like a normal text editor." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
\n", "Enter edit mode by pressing `enter` or using the mouse to click on a cell's editor area.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
\n", "While in edit mode, tab-completion works for variables the kernel knows about from executing previous cells.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Command mode" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Command mode is indicated by a grey cell border:\n", "\n", "\n", "\n", "When you are in command mode, you are able to edit the notebook as a whole, but not type into individual cells. Most importantly, in command mode, the keyboard is mapped to a set of shortcuts that let you perform notebook and cell actions efficiently. For example, if you are in command mode and you press `c`, you will copy the current cell - no modifier is needed." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
\n", "Don't try to type into a cell in command mode; unexpected things will happen!\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
\n", "Enter command mode by pressing `esc` or using the mouse to click *outside* a cell's editor area.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Mouse navigation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All navigation and actions in the Notebook are available using the mouse through the menubar and toolbar, which are both above the main Notebook area:\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "The first idea of mouse based navigation is that **cells can be selected by clicking on them.** The currently selected cell gets a grey or green border depending on whether the notebook is in edit or command mode. If you click inside a cell's editor area, you will enter edit mode. If you click on the prompt or output area of a cell you will enter command mode.\n", "\n", "If you are running this notebook in a live session (not on http://nbviewer.ipython.org) try selecting different cells and going between edit and command mode. Try typing into a cell." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "The second idea of mouse based navigation is that **cell actions usually apply to the currently selected cell**. Thus if you want to run the code in a cell, you would select it and click the \"Play\" button in the toolbar or the \"Cell:Run\" menu item. Similarly, to copy a cell you would select it and click the \"Copy\" button in the toolbar or the \"Edit:Copy\" menu item. With this simple pattern, you should be able to do most everything you need with the mouse.\n", "\n", "Markdown and heading cells have one other state that can be modified with the mouse. These cells can either be rendered or unrendered. When they are rendered, you will see a nice formatted representation of the cell's contents. When they are unrendered, you will see the raw text source of the cell. To render the selected cell with the mouse, click the \"Play\" button in the toolbar or the \"Cell:Run\" menu item. To unrender the selected cell, double click on the cell." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Keyboard Navigation" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The modal user interface of the IPython Notebook has been optimized for efficient keyboard usage. This is made possible by having two different sets of keyboard shortcuts: one set that is active in edit mode and another in command mode." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The most important keyboard shortcuts are `enter`, which enters edit mode, and `esc`, which enters command mode.\n", "\n", "In edit mode, most of the keyboard is dedicated to typing into the cell's editor. Thus, in edit mode there are relatively few shortcuts:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In command mode, the entire keyboard is available for shortcuts:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Here the rough order in which the IPython Developers recommend learning the command mode **shortcuts**:\n", "\n", "1. Basic navigation: `enter`, `shift-enter`, `up/k`, `down/j`\n", "2. Saving the notebook: `s`\n", "2. Cell types: `y`, `m`, `1-6`, `t`\n", "3. Cell creation and movement: `a`, `b`, `ctrl+k`, `ctrl+j`\n", "4. Cell editing: `x`, `c`, `v`, `d`, `z`, `shift+=`\n", "5. Kernel operations: `i`, `0`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "I personally (& humbly) suggest learning `h` first!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## The IPython Notebook Architecture" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "So far, we have learned the basics of using IPython Notebooks.\n", "\n", "For simple demonstrations, the typical user doesn't need to understand how the computations are being handled, but to successfully write and present computational notebooks, **you** will need to understand how the notebook architecture works." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "A *live* notebook is composed of an interactive web page (the front end), a running IPython session (the kernel or back end), and a web server responsible for handling communication between the two (the, err..., middle-end)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "A *static* notebook, as for example seen on NBViewer, is a static view of the notebook's content. The default format is HTML, but a notebook can also be output in PDF or other formats." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The centerpiece of an IPython Notebook is the \"kernel\", the IPython instance responsible for executing all code. Your IPython kernel maintains its state between executed cells." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n" ] } ], "source": [ "x = 0\n", "print(x)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "x += 1\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "There are two important actions for interacting with the kernel. The first is to interrupt it. This is the same as sending a Control-C from the command line. The second is to restart it. This completely terminates the kernel and starts it anew. None of the kernel state is saved across a restart. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Markdown cells" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Text can be added to IPython Notebooks using Markdown cells. Markdown is a popular markup language that is a superset of HTML. Its specification can be found here:\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Markdown basics" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Text formatting" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "You can make text *italic* or **bold** or `monospace`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Itemized Lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* One\n", " - Sublist\n", " - This\n", " - Sublist\n", " - That\n", " - The other thing\n", "* Two\n", " - Sublist\n", "* Three\n", " - Sublist" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Enumerated Lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Here we go\n", " 1. Sublist\n", " 2. Sublist\n", "2. There we go\n", "3. Now this" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Horizontal Rules" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "---\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Blockquotes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> To me programming is more than an important practical art. It is also a gigantic undertaking in the foundations of knowledge. -- Rear Admiral Grace Hopper" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Links" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[IPython's website](http://ipython.org)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Code" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a code snippet: \n", " \n", "```Python\n", "def f(x):\n", " \"\"\"a docstring\"\"\"\n", " return x**2\n", "```\n", " \n", "This is an example of a **Python** function" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "You can also use triple-backticks to denote code blocks.\n", "This also allows you to choose the appropriate syntax highlighter.\n", "\n", "```C\n", "if (i=0; i\n", " " ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo('vW_DRAJ0dtc')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Other HTML" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Be Bold! " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Mathematical Equations" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Courtesy of MathJax, you can beautifully render mathematical expressions, both inline: \n", "$e^{i\\pi} + 1 = 0$, and displayed:\n", "\n", "$$e^x=\\sum_{i=0}^\\infty \\frac{1}{i!}x^i$$" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Equation Environments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also use a number of equation environments, such as `align`:\n", "\n", "\\begin{align}\n", " x &= 4 \\\\\n", "y+z &= x\n", "\\end{align}\n", "\n", "[A full list of available TeX and LaTeX commands is maintained by Dr. Carol Burns.](http://www.onemathematicalcat.org/MathJaxDocumentation/TeXSyntax.htm)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Other Useful MathJax Notes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* inline math is demarcated by `$ $`, or `\\( \\)`\n", "* displayed math is demarcated by `$$ $$` or `\\[ \\]`\n", "* displayed math environments can also be directly demarcated by `\\begin` and `\\end`\n", "* `\\newcommand` and `\\def` are supported, *within* areas MathJax processes (such as in a `\\[ \\]` block)\n", "* equation numbering is not officially supported, but it can be indirectly enabled" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## A Note about Notebook Security" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, a notebook downloaded to a new computer is *untrusted*\n", "\n", "* HTML and Javascript in Markdown cells is now *never* executed\n", "* HTML and Javascript code outputs must be explicitly *re-executed*\n", "* Some of these restrictions can be mitigrated through shared accounts (Sage MathCloud) and secrets" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "notes" } }, "source": [ "More information on notebook security is in the [IPython Notebook documentation](http://ipython.org/ipython-doc/stable/notebook/security.html)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Magics" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "IPython kernels execute a superset of the Python language. The extension functions, commonly referred to as *magics*, come in two variants. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Line Magics" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "* A *line magic* looks like a command line call. The most important of these is `%matplotlib inline`, which embeds all matplotlib plot output as images in the notebook itself." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Variable Type Data/Info\n", "----------------------------------\n", "YouTubeVideo type \n", "matplotlib module /matplotlib/__init__.py'>\n", "x int 1\n" ] } ], "source": [ "%whos" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Cell Magics" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "* A *cell magic* takes its entire cell as an argument. Although there are a number of useful cell magics, you may find `%%timeit` to be useful for exploring code performance." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 7.40 times longer than the fastest. This could mean that an intermediate result is being cached \n", "10000 loops, best of 3: 30.7 µs per loop\n" ] } ], "source": [ "%%timeit\n", "\n", "import numpy as np\n", "np.sum(np.random.rand(1000))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Execute Code as Python 2" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "%%python2\n", "\n", "i = 10**60\n", "print type(i)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Interacting with the Command Line" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "IPython supports one final trick, the ability to interact directly with your shell by using the `!` operator." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "00 Programming Environment.ipynb\r\n", "01 Hello World.ipynb\r\n", "01 Introducing the IPython Notebook.ipynb\r\n", "02 Variable Strings and Numbers.ipynb\r\n", "03 List and Tuples.ipynb\r\n", "04 If Statements.ipynb\r\n", "05 While Loops and User input.ipynb\r\n", "06 Dictionaries.ipynb\r\n", "Index.ipynb\r\n", "LICENSE\r\n", "README.md\r\n", "Resources and References.ipynb\r\n", "TOC.ipynb\r\n", "\u001b[34mfiles\u001b[m\u001b[m\r\n" ] } ], "source": [ "!ls" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "x = !ls" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['00 Programming Environment.ipynb', '01 Hello World.ipynb', '01 Introducing the IPython Notebook.ipynb', '02 Variable Strings and Numbers.ipynb', '03 List and Tuples.ipynb', '04 If Statements.ipynb', '05 While Loops and User input.ipynb', '06 Dictionaries.ipynb', 'Index.ipynb', 'LICENSE', 'README.md', 'Resources and References.ipynb', 'TOC.ipynb', 'files']\n" ] } ], "source": [ "print(x)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## A Note about Notebook Version Control" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "The IPython Notebook is stored using canonicalized JSON for ease of use with version control systems.\n", "\n", "There are two things to be aware of:\n", "\n", "* By default, IPython embeds all content and saves kernel execution numbers. You may want to get in the habit of clearing all cells before committing.\n", "\n", "* As of IPython 2.0, all notebooks are signed on save. This increases the chances of a commit collision during merge, forcing a manual resolution. Either signature can be safely deleted in this situation." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 02 Variable Strings and Numbers.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Variables, Strings, and Numbers" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In this section, you will learn to store information in variables. \n", "\n", "You will learn about two types of data: strings, which are sets of characters, and numerical data types." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "## Contents\n", "---\n", "- [Variables](#variables)\n", " - [Example](#example)\n", " - [Naming rules](#naming_rules)\n", " - [NameError](#name_error)\n", " - [Exercises](#exercises_variables)\n", "- [Strings](#strings)\n", " - [Single and double quotes](#single_double_quotes)\n", " - [Changing case](#changing_case)\n", " - [Combining strings (concatenation)](#concatenation)\n", " - [Whitespace](#whitespace)\n", " - [Exercises](#exercises_strings)\n", "- [Numbers](#numbers)\n", " - [Integer operations](#integer_operations)\n", " - [Floating-point numbers](#floats)\n", " - [Exercises](#exercises_numbers)\n", " - [Challenges](#challenges_numbers)\n", "- [Comments](#comments)\n", " - [What makes a good comment?](#good_comments)\n", " - [When should you write comments?](#when_comments)\n", " - [Exercises](#exercises_comments)\n", "- [Overall Challenges](#challenges_overall)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Variables\n", "===\n", "A variable holds a value." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Example\n", "---" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello Python world!\n" ] } ], "source": [ "message = \"Hello Python world!\"\n", "print(message)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A variable holds a value. You can change the value of a variable at any point." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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[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[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": { "slideshow": { "slide_type": "fragment" } }, "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\"." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can fix **NameErrors** by making sure all of our variable names are spelled consistently." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.1 : Hello World - Variable\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.2 : One Variable, Two Messages\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Introduction to Strings\n", "===\n", "Strings are sets of characters. Strings are easier to understand by looking at some examples." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Single and double quotes\n", "---\n", "Strings are contained by either single or double quotes." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "my_string = \"This is a double-quoted string.\"\n", "my_string = 'This is a single-quoted string.'" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This lets us make strings that contain quotations." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "quote = \"Linus Torvalds once said, \\\n", " 'Any program is only as good as it is useful.'\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Multiline Strings\n", "\n", "In case we need to create a multiline string, there is the **triple-quote** to the rescue:\n", "`'''`" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is a string where I \n", "can confortably write on multiple lines\n", "without worrynng about to use the escape character \"\\\" as in\n", "the previsou example. \n", "As you'll see, the original string formatting is preserved.\n", "\n" ] } ], "source": [ "multiline_string = '''This is a string where I \n", "can confortably write on multiple lines\n", "without worring about to use the escape character \"\\\\\" as in\n", "the previsou example. \n", "As you'll see, the original string formatting is preserved.\n", "'''\n", "\n", "print(multiline_string)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 16, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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_titled = 'Eric'\n", "print(first_name_titled.lower())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note**: Please notice that the original strings remain **always** unchanged" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "eric\n", "Eric\n" ] } ], "source": [ "print(first_name)\n", "print(first_name_titled)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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**. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "A method is something that can be done to a variable." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The methods `lower`, `title`, and `upper` are all functions that have been written into the Python language, which do something to **strings**. \n", "\n", "Later on, you will learn to write your own methods." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 19, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The plus sign combines two strings into one, which is called **concatenation**. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ada Lovelace was considered the world's first computer programmer.\n" ] } ], "source": [ "first_name = 'ada'\n", "last_name = 'lovelace'\n", "full_name = first_name + ' ' + last_name\n", "\n", "message = full_name.title() + ' ' + \\\n", " \"was considered the world's first computer programmer.\"\n", "\n", "print(message)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "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": [ "### Brief introduction to string formatting" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "String Template: The result of the calculation of {calc} is {res}\n", "The result of the calculation of (3*4)+2 is 14\n" ] } ], "source": [ "string_template = 'The result of the calculation of {calc} is {res}'\n", "print(\"String Template: \", string_template)\n", "\n", "print(string_template.format(calc='(3*4)+2', res=(3*4)+2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### There's much more than that!\n", "\n", "For further information about *String formatting*, see the official online documentation about the [`string`](https://docs.python.org/3/library/string.html) module." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 21, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello everyone!\n" ] } ], "source": [ "print(\"Hello everyone!\")" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\tHello everyone!\n" ] } ], "source": [ "print(\"\\tHello everyone!\")" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello \teveryone!\n" ] } ], "source": [ "print(\"Hello \\teveryone!\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello everyone!\n" ] } ], "source": [ "print(\"Hello everyone!\")" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Hello everyone!\n" ] } ], "source": [ "print(\"\\nHello everyone!\")" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello \n", "everyone!\n" ] } ], "source": [ "print(\"Hello \\neveryone!\")" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "\n", "Hello everyone!\n" ] } ], "source": [ "print(\"\\n\\n\\nHello everyone!\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can strip whitespace from the left side, the right side, or both sides of a string." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 29, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": 30, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.3 : Someone Said\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.4 : First Name Cases\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.5 : Full Name\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.6 : About This Person\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.7 : Name Strip\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Numbers\n", "===\n", "Dealing with simple numerical data is fairly straightforward in Python, but there are a few things you should know about." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 35, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n" ] } ], "source": [ "print(3+2)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "print(3-2)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6\n" ] } ], "source": [ "print(3*2)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.5\n" ] } ], "source": [ "print(3/2)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9\n" ] } ], "source": [ "print(3**2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can use parenthesis to modify the standard order of operations." ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "14\n" ] } ], "source": [ "standard_order = 2+3*4\n", "print(standard_order)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "20\n" ] } ], "source": [ "my_order = (2+3)*4\n", "print(my_order)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 42, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.2\n" ] } ], "source": [ "print(0.1+0.1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "However, sometimes you will get an answer with an unexpectly long decimal part:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.30000000000000004\n" ] } ], "source": [ "print(0.1+0.2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can also get the same kind of result with other operations." ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.30000000000000004\n" ] } ], "source": [ "print(3*0.1)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Test\n", "3 * 0.1 == 0.3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The `decimal` to the rescue\n", "\n", "The `decimal` module provides support for fast correctly-rounded decimal floating point arithmetic. It offers several advantages over the float datatype.\n", "For Example:\n", "\n", "* Decimal “is based on a floating-point model which was designed with people in mind, and necessarily has a paramount guiding principle – computers must provide an arithmetic that works in the same way as the arithmetic that people learn at school.” – excerpt from the decimal arithmetic specification.\n", "\n", "\n", "* Decimal numbers can be represented exactly. In contrast, numbers like 1.1 and 2.2 do not have exact representations in binary floating point. End users typically would not expect 1.1 + 2.2 to display as 3.3000000000000003 as it does with binary floating point.\n", "\n", "\n", "* The exactness carries over into arithmetic. In decimal floating point, 0.1 + 0.1 + 0.1 - 0.3 is exactly equal to zero. In binary floating point, the result is 5.5511151231257827e-017. While near to zero, the differences prevent reliable equality testing and differences can accumulate. For this reason, decimal is preferred in accounting applications which have strict equality invariants.\n", "\n", "\n", "* Unlike hardware based binary floating point, the decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for a given problem\n", "\n", "\n", "* The module design is centered around three concepts: the decimal number, the context for arithmetic, and signals.\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### See Also\n", "\n", "* [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)\n", "* [`decimal` module](https://docs.python.org/3/library/decimal.html)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example using decimal" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "0.30000000000000002\n", "0.30000000000000004\n" ] } ], "source": [ "from decimal import Decimal, getcontext\n", "getcontext().prec = 17\n", "result = 3 * Decimal(0.1)\n", "print(type(result))\n", "print(3 * Decimal(0.1))\n", "print(3 * 0.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Note\n", "\n", "The first instruction of the previous cell is an exmaple of **selective module import**.\n", "\n", "So far, just note that the syntax pattern of the selective import is:\n", " \n", " from module import something[,something else comma separated]\n", " \n", "See more about this in the notebook specifically devoted to this!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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." ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a + b = 11\n" ] } ], "source": [ "# Ex 2.8 : Arithmetic\n", "a = 6\n", "b = 5\n", "print(\"a + b = \", end='')\n", "o = a+b\n", "print(o)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The result of the calculation of (3*4)+2 = 14\n" ] } ], "source": [ "# Ex 2.9 : Order of Operations\n", "result = (3*4)+2\n", "print('The result of the calculation of (3*4)+2', result, sep=' = ')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.10 : Long Decimals\n", "print(3.125 / 0.2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Challenges\n", "---\n", "#### Neat Arithmetic\n", "\n", "- Store the results of at least 5 different calculations in separate variables. Make sure you use each operation at least once.\n", "- Print a series of informative statements, such as \"The result of the calculation 5+7 is 12.\"\n", "\n", "#### Neat Order of Operations\n", "- Take your work for \"Order of Operations\" above.\n", "- Instead of just printing the results, print an informative summary of the results. Show each calculation that is being done and the result of that calculation. Explain how you modified the result using parentheses.\n", "\n", "#### Long Decimals - Pattern\n", "- On paper, 0.1+0.2=0.3. But you have seen that in Python, 0.1+0.2=0.30000000000000004.\n", "- Find a number of other calculations that result in a long decimal like this. Try to find a pattern in what kinds of numbers will result in long decimals." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Neat Arithmetic\n", "\n", "# Put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Neat Order of Operations\n", "\n", "# Put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Long Decimals - Pattern\n", "\n", "# Put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This line is not a comment, it is code.\n" ] } ], "source": [ "# This line is a comment.\n", "#this \n", "#is \n", "#not\n", "\n", "print(\"This line is not a comment, it is code.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "When should you write a comment?\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": { "slideshow": { "slide_type": "slide" } }, "source": [ "Exercises\n", "---\n", "#### First Comments\n", "- Choose the longest, most difficult, or most interesting program you have written so far. Write at least one comment in your program.\n" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 2.10 : First Comments\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Overall Challenges\n", "===\n", "We have learned quite a bit so far about programming, but we haven't learned enough yet for you to go create something. In the next notebook, things will get much more interesting, and there will be a longer list of overall challenges.\n", "\n", "\n", "\n", "#### What I've Learned\n", "- Write a program that uses everything you have learned in this notebook at least once.\n", "- Write comments that label each section of your program.\n", "- For each thing your program does, write at least one line of output that explains what your program did.\n", "- For example, you might have one line that stores your name with some whitespace in a variable, and a second line that strips that whitespace from your name:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Overall Challenge\n", "\n", "# Put your code here" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I can strip tabs from my name: eric\n" ] } ], "source": [ "# I learned how to strip whitespace from strings.\n", "name = '\\t\\teric'\n", "print(\"I can strip tabs from my name: \" + name.strip())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 03 List and Tuples and Sets.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Lists Tuples and Sets" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "In this notebook, you will learn to store more than one valuable in a single variable. \n", "\n", "This by itself is one of the most powerful ideas in programming, and it introduces a number of other central concepts such as loops. \n", "\n", "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": { "slideshow": { "slide_type": "skip" } }, "source": [ " Contents\n", "===\n", "- [Lists](#lists)\n", " - [Introducing Lists](#introducing)\n", " - [Example](#example)\n", " - [Naming and defining a list](#naming)\n", " - [Accessing one item in a list](#accessing_one_item)\n", " - [Exercises](#exercises_list_introduction)\n", " - [Lists and Looping](#looping)\n", " - [Accessing all elements in a list](#accessing_all_elements)\n", " - [Enumerating a list](#enumerating_list)\n", " - [Exercises](#exercises_list_loop)\n", " - [Common List Operations](#common_operations)\n", " - [Modifying elements in a list](#modifying_elements)\n", " - [Finding an element in a list](#finding_elements)\n", " - [Testing whether an element is in a list](#testing_elements)\n", " - [Adding items to a list](#adding_items)\n", " - [Creating an empty list](#empty_list)\n", " - [Sorting a list](#sorting_list)\n", " - [Finding the length of a list](#length)\n", " - [Exercises](#exercises_common_operations)\n", " - [Removing Items from a List](#removing_items)\n", " - [Removing items by position](#removing_by_position)\n", " - [Removing items by value](#removing_by_value)\n", " - [Popping items](#popping)\n", " - [Exercises](#exercises_removing_items)\n", " - [Want to see what functions are?](#functions)\n", " - [Slicing a List](#slicing)\n", " - [Copying a list](#copying)\n", " - [Exercises](#exercises_slicing)\n", " - [Numerical Lists](#numerical_lists)\n", " - [The *range()* function](#range_function)\n", " - [The *min()*, *max()*, *sum()* functions](#min_max_sum)\n", " - [Exercises](#exercises_numerical)\n", " - [List Comprehensions](#comprehensions)\n", " - [Numerical comprehensions](#comprehensions_numerical)\n", " - [Non-numerical comprehensions](#comprehensions_non_numerical)\n", " - [Exercises](#exercises_comprehensions)\n", " - [Strings as Lists](#strings_as_lists)\n", " - [Strings as a list of characters](#list_of_characters)\n", " - [Slicing strings](#slicing_strings)\n", " - [Finding substrings](#finding_substrings)\n", " - [Replacing substrings](#replacing_substrings)\n", " - [Counting substrings](#counting_substrings)\n", " - [Splitting strings](#splitting_strings)\n", " - [Other string methods](#other_string_methods)\n", " - [Exercises](#exercises_strings_as_lists)\n", " - [Challenges](#challenges_strings_as_lists)\n", " - [Tuples](#tuples)\n", " - [Defining tuples, and accessing elements](#defining_tuples)\n", " - [Using tuples to make strings](#tuples_strings)\n", " - [Exercises](#exercises_tuples)\n", " - [Sets](#sets)\n", " - [Basic Operatoins on Sets](#set_operations)\n", " - [Exercises](#exercise_set)\n", " - [Overall Challenges](#challenges_overall)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Lists\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Introducing Lists\n", "===\n", "Example\n", "---\n", "A list is a collection of items, that is stored in a variable. The items should be related in some way, but there are no restrictions on what can be stored in a list. Here is a simple example of a list, and how we can quickly access each item in the list." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Bernice!\n", "Hello, Aaron!\n", "Hello, Cody!\n" ] } ], "source": [ "students = ['bernice', 'aaron', 'cody']\n", "\n", "for student in students:\n", " print(\"Hello, \" + student.title() + \"!\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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')." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "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": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "dogs = ['border collie', \n", " 'australian cattle dog', \n", " 'labrador retriever']" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "To access the first element in a list, you give the name of the list, followed by a zero in parentheses." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Border Collie\n" ] } ], "source": [ "dogs = ['border collie', \n", " 'australian cattle dog', \n", " 'labrador retriever']\n", "\n", "dog = dogs[0]\n", "print(dog.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The number in parentheses is called the **index** of the item. \n", "\n", "Because lists start at zero, the index of an item is always one less than its position in the list. \n", "Because of that, **Python** is said to be a [*zero-indexed*](http://en.wikipedia.org/wiki/Zero-based_numbering) \n", "language (as many others, like `C`, or `Java`)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "So to get the second item in the list, we need to use an index of 1, and so on.." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Australian Cattle Dog\n" ] } ], "source": [ "dog = dogs[1]\n", "print(dog.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Labrador Retriever\n" ] } ], "source": [ "dog = dogs[-1]\n", "print(dog.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This syntax also works for the second to last item, the third to last, and so forth." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Australian Cattle Dog\n" ] } ], "source": [ "dog = dogs[-2]\n", "print(dog.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can't use a negative number larger than the length of the list, however." ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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[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[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[0mtitle\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;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "dog = dogs[-4]\n", "print(dog.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.1 : First List\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.2 : First Neat List\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.3 : Your First List\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Lists and Looping\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": 15, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's say something about each dog in our list." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I like border collies.\n", "I like australian cattle dogs.\n", "I like labrador retrievers.\n" ] } ], "source": [ "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", "\n", "for dog in dogs:\n", " print('I like ' + dog + 's.')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 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": 18, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": [ "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": { "slideshow": { "slide_type": "fragment" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": [ "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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 19, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": [ "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", "\n", "for dog in dogs:\n", " print(dogs)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "TypeError", "evalue": "Can't convert 'list' object to str implicitly", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\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[0m\n\u001b[0;32m----> 4\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[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: Can't convert 'list' object to str implicitly" ] } ], "source": [ "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", "\n", "for dog in dogs:\n", " print('I like ' + dogs + 's.')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## The FOR (iteration) loop\n", "\n", "The `for` loop statement is the most widely used iteration mechanisms in Python.\n", "\n", "* Almost every structure in Python can be iterated (*element by element*) by a `for` loop\n", " - a list, a tuple, a dictionary, $\\ldots$ (more details will follows)\n", "\n", "* In Python, also `while` loops are permitted, but `for` is the one you would see (and use) most of the time!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### FOR Special keywords\n", "\n", "Python allows two **keywords** to be used within a `for` loop: **break** and **continue**.\n", "\n", "The two keywords have two **different** meanings:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* **Break** used to *immediatly break the loop and exit!*\n", "* **Continue** used to *skip to the **next** iteration step!*" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**NOTE**: The two keywords are permitted with `while` loops as well!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Examples" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.4 : First List - Loop\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.5 : First Neat List - Loop\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.6 : Your First List - Loop\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Common List Operations\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This method returns a ValueError if the requested item is not in the list." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "ValueError", "evalue": "'poodle' is not in list", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[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[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\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[0m\n\u001b[0m", "\u001b[0;31mValueError\u001b[0m: 'poodle' is not in list" ] } ], "source": [ "dogs = ['border collie', 'australian cattle dog', 'labrador retriever']\n", "\n", "print(dogs.index('poodle'))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 22, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title() + \"s are cool.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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.title() + '!')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": [ "# 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.title() + '!')\n", "\n", "# Recognize our first user, and welcome our newest user.\n", "print(\"\\nThank you for being our very first user, \" + usernames[0].title() + '!')\n", "print(\"And a warm welcome to our newest user, \" + usernames[-1].title() + '!')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Sorting a List\n", "---\n", "We can sort a list alphabetically, in either order." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())\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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())\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.title())\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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 17, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Sorting a numerical list\n", "All of the sorting functions work for numerical lists as well." ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 38, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 42, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 43, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "TypeError", "evalue": "Can't convert 'int' object to str implicitly", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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: Can't convert 'int' object to str implicitly" ] } ], "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": 44, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This will work: 3\n" ] } ], "source": [ "usernames = ['bernice', 'cody', 'aaron']\n", "user_count = len(usernames)\n", "\n", "print(\"This will work: \" + str(user_count))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.7 : Working List\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.8 : Starting From Empty\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.9 : Ordered Working List\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.10 : Ordered Numbers\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.11 : List Lengths\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 30, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 31, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 32, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is easier to show with an example" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 36, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "border collie\n", "['australian cattle dog', 'labrador retriever']\n" ] } ], "source": [ "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": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['david bowie', 'robert plant', 'obama']\n", "['david bowie', 'robert plant']\n", "david bowie ['robert plant']\n", "there are no more famous people in the list\n", "[]\n" ] } ], "source": [ "# Ex 3.12 : Famous People\n", "fpeople = ['david bowie', 'robert plant', 'obama', 'taylor swift']\n", "#Remove each person from the list, one at a time, using each of the four methods we have just seen\n", "fpeople.remove('taylor swift')\n", "print(fpeople)\n", "del fpeople[2]\n", "print(fpeople)\n", "bowie=fpeople.pop(0)\n", "print(bowie,fpeople)\n", "last=fpeople.pop()\n", "print('there are no more famous people in the list')\n", "print(fpeople)\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['david bowie', 'robert plant', 'obama']\n", "['taylor swift']\n", "['david bowie', 'robert plant']\n" ] } ], "source": [ "#Pop the last item from the list\n", "fpeople = ['david bowie', 'robert plant', 'obama', 'taylor swift']\n", "fpeople.pop()\n", "print(fpeople)\n", "# and pop any item except the last item.\n", "fpeople = ['david bowie', 'robert plant', 'obama', 'taylor swift']\n", "for _ in range(0,len(fpeople)-1):\n", " fpeople.pop(0)\n", "print(fpeople)\n", "\n", "fpeople = ['david bowie', 'robert plant', 'obama', 'taylor swift']\n", "fpeople.remove('obama')\n", "del fpeople[2]\n", "print(fpeople)\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Want to see what functions are?\n", "===\n", "At this point, you might have noticed we have a fair bit of repetetive code in some of our examples. This repetition will disappear once we learn how to use functions. If this repetition is bothering you already, you might want to go look at [Introducing Functions](http://nbviewer.ipython.org/urls/raw.github.com/ehmatthes/intro_programming/master/notebooks/introducing_functions.ipynb) before you do any more exercises in this section. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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*." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "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. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Here is how you get a batch containing the first three items." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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[:3]\n", "\n", "for user in first_batch:\n", " print(user.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "When we grab a slice from a list, the original list is not affected:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bernice\n", "Cody\n", "Aaron\n", "Ever\n", "Dalia\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", "# The original list is unaffected.\n", "for user in usernames:\n", " print(user.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can get any segment of a list we want, using the slice method:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 9, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 15, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "abcdefghijklmnopqrstuvwxyz\n", "abcdefghij\n" ] } ], "source": [ "from string import ascii_lowercase\n", "print(ascii_lowercase)\n", "tenletters=ascii_lowercase[0:10]\n", "print(tenletters)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "abc\n", "ghi\n", "ghij\n" ] } ], "source": [ "# Ex 3.13 : Alphabet Slices\n", "#Store the first ten letters of the alphabet in a list.\n", "alphabet=tenletters[:]\n", "#Use a slice to print out the first three letters of the alphabet.\n", "print(alphabet[:3])\n", "#Use a slice to print out any three letters from the middle of your list.\n", "print(alphabet[6:9])\n", "#Use a slice to print out the letters from any point in the middle of your list, to the end.\n", "print(alphabet[6:])\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is the original list:\n", "Alice\n", "Anna\n", "Ada\n", "This is the copy: \n", "Alice\n", "Anna\n", "Ada\n", "Agata\n", "Aurora\n", "['alice', 'anna', 'ada', 'agata', 'aurora']\n", "['alice', 'anna', 'ada']\n", "['Alice', 'Anna', 'Ada', 'Agata', 'Aurora']\n" ] } ], "source": [ "# Ex 3.14 : 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", "names=['alice','anna','ada']\n", "#Use a slice to make a copy of the entire list.\n", "copied_names=names[:]\n", "#Add at least two new names to the new copy of the list.\n", "copied_names.append('agata')\n", "copied_names.append('aurora')\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", "print('This is the original list:')\n", "for name in names:\n", " print(name.title())\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.\n", "print('This is the copy: ')\n", "for cname in copied_names:\n", " print(cname.title())\n", "print(copied_names)\n", "\n", "#title the names in the original list\n", "print (names)\n", "copied_names = [i.title() for i in copied_names]\n", "print(copied_names)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 23, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 26, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 31, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 39, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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) + \n", " \" years worth of life experience.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": 47, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "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", "11\n", "12\n", "13\n", "14\n", "15\n", "16\n", "17\n", "18\n", "19\n", "20\n" ] } ], "source": [ "# Ex 3.15 : First Twenty\n", "twenties=list(range(1,21))\n", "for n in twenties:\n", " print(n)\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "data": { "text/plain": [ "1000000" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ex 3.16 : Larger Sets\n", "millions=list(range(0,int(1e6)))\n", "len(millions)\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[76, 62, 53], [53, 69, 30, 5, 65, 9, 39, 75], [7, 37, 60, 64, 36, 68, 71, 88, 40], [96, 6, 15, 74, 3, 79, 54, 8, 35, 99], [1, 67, 57, 71]]\n", "[191, 345, 471, 469, 196]\n", "The fattest wallet has 471 in it\n", "All together, these wallets have 1672 value in them\n", "The thinnest wallet has 191 in it\n" ] } ], "source": [ "# Ex 3.17 : Five Wallets\n", "#Imagine five wallets with different amounts of cash in them. Store these five values in a list, \n", "#and print out the following sentences:\n", "#\"The fattest wallet has ∗value∗init.\"−\"Theskinniestwallethas value in it.\"\n", "#\"All together, these wallets have $ value in them.\"\n", "\n", "from random import randint\n", "\n", "wallets = [ [randint(1,100) for _ in range(randint(2,10))] for _ in range(5) ]\n", "print(wallets)\n", "amounts = [ sum(wallet) for wallet in wallets ]\n", "print(amounts)\n", "print('The fattest wallet has {} in it'.format(max(amounts)))\n", "print('All together, these wallets have {} value in them'.format(sum(amounts)))\n", "print('The thinnest wallet has {} in it'.format(min(amounts)))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "List Comprehensions\n", "===\n", "I thought carefully before including this section. 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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": 42, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This should make sense at this point. 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": 43, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 44, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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", "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": { "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 45, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 46, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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 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": { "slideshow": { "slide_type": "subslide" } }, "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": 47, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title() + \" 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": { "slideshow": { "slide_type": "subslide" } }, "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": 48, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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 = [student.title() + \" 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": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.18 : Multiples of Ten\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.19 : Cubes\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.20 : Awesomeness\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.21 : Working Backwards\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Strings as Lists\n", "===\n", "Now that you have some familiarity with lists, we can take a second look at strings. A string is really a list of characters, so many of the concepts from working with lists behave the same with strings." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Strings as a list of characters\n", "---\n", "We can loop through a string using a *for* loop, just like we loop through a list:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "H\n", "e\n", "l\n", "l\n", "o\n", "!\n" ] } ], "source": [ "message = \"Hello!\"\n", "\n", "for letter in message:\n", " print(letter)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can create a list from a string. The list will have one element for each character in the string:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!']\n" ] } ], "source": [ "message = \"Hello world!\"\n", "\n", "message_list = list(message)\n", "print(message_list)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Slicing strings\n", "---\n", "We can access any character in a string by its position, just as we access individual items in a list:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('H', '!')\n" ] } ], "source": [ "message = \"Hello World!\"\n", "first_char = message[0]\n", "last_char = message[-1]\n", "\n", "print(first_char, last_char)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can extend this to take slices of a string:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Hel', 'ld!')\n" ] } ], "source": [ "message = \"Hello World!\"\n", "first_three = message[:3]\n", "last_three = message[-3:]\n", "\n", "print(first_three, last_three)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Finding substrings\n", "---\n", "Now that you have seen what indexes mean for strings, we can search for *substrings*. A substring is a series of characters that appears in a string.\n", "\n", "You can use the *in* keyword to find out whether a particular substring appears in a string:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "message = \"I like cats and dogs.\"\n", "dog_present = 'dog' in message\n", "print(dog_present)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you want to know where a substring appears in a string, you can use the *find()* method. The *find()* method tells you the index at which the substring begins." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "16\n" ] } ], "source": [ "message = \"I like cats and dogs.\"\n", "dog_index = message.find('dog')\n", "print(dog_index)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Note, however, that this function only returns the index of the first appearance of the substring you are looking for. If the substring appears more than once, you will miss the other substrings." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "16\n" ] } ], "source": [ "message = \"I like cats and dogs, but I'd much rather own a dog.\"\n", "dog_index = message.find('dog')\n", "print(dog_index)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you want to find the last appearance of a substring, you can use the *rfind()* function:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "48\n" ] } ], "source": [ "message = \"I like cats and dogs, but I'd much rather own a dog.\"\n", "last_dog_index = message.rfind('dog')\n", "print(last_dog_index)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Replacing substrings\n", "---\n", "You can use the *replace()* function to replace any substring with another substring. To use the *replace()* function, give the substring you want to replace, and then the substring you want to replace it with. You also need to store the new string, either in the same string variable or in a new variable." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I like cats and snakes, but I'd much rather own a snake.\n" ] } ], "source": [ "message = \"I like cats and dogs, but I'd much rather own a dog.\"\n", "message = message.replace('dog', 'snake')\n", "print(message)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Counting substrings\n", "---\n", "If you want to know how many times a substring appears within a string, you can use the *count()* method." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "message = \"I like cats and dogs, but I'd much rather own a dog.\"\n", "number_dogs = message.count('dog')\n", "print(number_dogs)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Splitting strings\n", "---\n", "Strings can be split into a set of substrings when they are separated by a repeated character. If a string consists of a simple sentence, the string can be split based on spaces. The *split()* function returns a list of substrings. The *split()* function takes one argument, the character that separates the parts of the string." ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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(' ')\n", "print(words)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 27, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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", "\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": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Other string methods\n", "---\n", "There are a number of [other string methods](http://docs.python.org/3.3/library/stdtypes.html#string-methods) that we won't go into right here, but you might want to take a look at them. Most of these methods should make sense to you at this point. You might not have use for any of them right now, but it is good to know what you can do with strings. This way you will have a sense of how to solve certain problems, even if it means referring back to the list of methods to remind yourself how to write the correct syntax when you need it." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Exercises\n", "---\n", "#### Listing a Sentence\n", "- Store a single sentence in a variable. Use a for loop to print each character from your sentence on a separate line.\n", "\n", "#### Sentence List\n", "- Store a single sentence in a variable. Create a list from your sentence. Print your raw list (don't use a loop, just print the list).\n", "\n", "#### Sentence Slices\n", "- Store a sentence in a variable. Using slices, print out the first five characters, any five consecutive characters from the middle of the sentence, and the last five characters of the sentence.\n", "\n", "#### Finding Python\n", "- Store a sentence in a variable, making sure you use the word *Python* at least twice in the sentence.\n", "- Use the *in* keyword to prove that the word *Python* is actually in the sentence.\n", "- Use the *find()* function to show where the word *Python* first appears in the sentence.\n", "- Use the *rfind()* function to show the last place *Python* appears in the sentence.\n", "- Use the *count()* function to show how many times the word *Python* appears in your sentence.\n", "- Use the *split()* function to break your sentence into a list of words. Print the raw list, and use a loop to print each word on its own line.\n", "- Use the *replace()* function to change *Python* to *Ruby* in your sentence." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.22 : Listing a Sentence\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.23 : Sentence List\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.24 : Sentence Slices\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.25 : Finding Python\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Challenges\n", "---\n", "#### Counting DNA Nucleotides\n", "- [Project Rosalind](http://rosalind.info/problems/locations/) is a [problem set](http://rosalind.info/problems/list-view/) based on biotechnology concepts. It is meant to show how programming skills can help solve problems in genetics and biology.\n", "- If you have understood this section on strings, you have enough information to solve the first problem in Project Rosalind, [Counting DNA Nucleotides](http://rosalind.info/problems/dna/). Give the sample problem a try.\n", "- If you get the sample problem correct, log in and try the full version of the problem!\n", "\n", "#### Transcribing DNA into RNA\n", "- You also have enough information to try the second problem, [Transcribing DNA into RNA](http://rosalind.info/problems/rna/). Solve the sample problem.\n", "- If you solved the sample problem, log in and try the full version!\n", "\n", "#### Complementing a Strand of DNA\n", "- You guessed it, you can now try the third problem as well: [Complementing a Strand of DNA](http://rosalind.info/problems/revc/). Try the sample problem, and then try the full version if you are successful." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Counting DNA Nucleotides\n", "\n", "# Put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Transcribing DNA into RNA\n", "\n", "# Put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Complementing a Strand of DNA\n", "\n", "# Put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": 36, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you try to add something to a tuple, you will get an error:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "AttributeError", "evalue": "'tuple' object has no attribute 'append'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Using tuples to make strings\n", "---\n", "We have seen that it is pretty useful to be able to mix raw English strings with values that are stored in variables, as in the following:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I have a dog.\n" ] } ], "source": [ "animal = 'dog'\n", "print(\"I have a \" + animal + \".\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This was especially useful when we had a series of similar statements to make:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I have a dog.\n", "I have a cat.\n", "I have a bear.\n" ] } ], "source": [ "animals = ['dog', 'cat', 'bear']\n", "for animal in animals:\n", " print(\"I have a \" + animal + \".\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "I like this approach of using the plus sign to build strings because it is fairly intuitive. We can see that we are adding several smaller strings together to make one longer string. This is intuitive, but it is a lot of typing. There is a shorter way to do this, using *placeholders*.\n", "\n", "Python ignores most of the characters we put inside of strings. There are a few characters that Python pays attention to, as we saw with strings such as \"\\t\" and \"\\n\". Python also pays attention to \"%s\" and \"%d\". These are placeholders. When Python sees the \"%s\" placeholder, it looks ahead and pulls in the first argument after the % sign:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I have a dog.\n" ] } ], "source": [ "animal = 'dog'\n", "print(\"I have a %s.\" % animal)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is a much cleaner way of generating strings that include values. We compose our sentence all in one string, and then tell Python what values to pull into the string, in the appropriate places.\n", "\n", "This is called *string formatting*, and it looks the same when you use a list:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I have a dog.\n", "I have a cat.\n", "I have a bear.\n" ] } ], "source": [ "animals = ['dog', 'cat', 'bear']\n", "for animal in animals:\n", " print(\"I have a %s.\" % animal)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you have more than one value to put into the string you are composing, you have to pack the values into a tuple:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I have a dog, a cat, and a bear.\n" ] } ], "source": [ "animals = ['dog', 'cat', 'bear']\n", "print(\"I have a %s, a %s, and a %s.\" % (animals[0], animals[1], animals[2]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### String formatting with numbers\n", "\n", "If you recall, printing a number with a string can cause an error:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "TypeError", "evalue": "cannot concatenate 'str' and 'int' objects", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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[0mnumber\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m23\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"My favorite number is \"\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mnumber\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: cannot concatenate 'str' and 'int' objects" ] } ], "source": [ "number = 23\n", "print(\"My favorite number is \" + number + \".\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Python knows that you could be talking about the value 23, or the characters '23'. So it throws an error, forcing us to clarify that we want Python to treat the number as a string. We do this by *casting* the number into a string using the *str()* function:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My favorite number is 23.\n" ] } ], "source": [ "number = 23\n", "print(\"My favorite number is \" + str(number) + \".\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The format string \"%d\" takes care of this for us. Watch how clean this code is:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My favorite number is 23.\n" ] } ], "source": [ "number = 23\n", "print(\"My favorite number is %d.\" % number)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you want to use a series of numbers, you pack them into a tuple just like we saw with strings:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My favorite numbers are 7, 23, and 42.\n" ] } ], "source": [ "numbers = [7, 23, 42]\n", "print(\"My favorite numbers are %d, %d, and %d.\" % (numbers[0], numbers[1], numbers[2]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Just for clarification, look at how much longer the code is if you use concatenation instead of string formatting:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My favorite numbers are 7, 23, and 42.\n" ] } ], "source": [ "numbers = [7, 23, 42]\n", "print(\"My favorite numbers are \" + str(numbers[0]) + \", \" + str(numbers[1]) + \", and \" + str(numbers[2]) + \".\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can mix string and numerical placeholders in any order you want." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Eric's favorite number is 23, and Ever's favorite number is 2.\n" ] } ], "source": [ "names = ['eric', 'ever']\n", "numbers = [23, 2]\n", "print(\"%s's favorite number is %d, and %s's favorite number is %d.\" % (names[0].title(), numbers[0], names[1].title(), numbers[1]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "There are more sophisticated ways to do string formatting in Python 3, but we will save that for later because it's a bit less intuitive than this approach. For now, you can use whichever approach consistently gets you the output that you want to see." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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", "\n", "#### Revision with Tuples\n", "- Choose a program you have already written that uses string concatenation.\n", "- Save the program with the same filename, but add *\\_tuple.py* to the end. For example, *gymnast\\_scores.py* becomes *gymnast\\_scores_tuple.py*.\n", "- Rewrite your string sections using *%s* and *%d* instead of concatenation.\n", "- Repeat this with two other programs you have already written." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.26 : Gymnast Scores\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.27 : Revision with Tuples\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sets\n", "===\n", "\n", "A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'circle', 'square', 'triangle'}" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "shapes = ['circle','square','triangle','circle']\n", "set_of_shapes = set(shapes)\n", "set_of_shapes" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "circle\n", "square\n", "polygon\n", "triangle\n" ] } ], "source": [ "shapes = {'circle','square','triangle','circle'}\n", "for shape in set_of_shapes:\n", " print(shape)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'circle', 'square', 'polygon', 'triangle'}\n" ] } ], "source": [ "set_of_shapes.add('polygon') \n", "print(set_of_shapes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exists (Check)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Circle is in the set: True\n", "Rhombus is in the set: False\n" ] } ], "source": [ "# Test if circle is IN the set (i.e. exist)\n", "print('Circle is in the set: ', ('circle' in set_of_shapes))\n", "print('Rhombus is in the set:', ('rhombus' in set_of_shapes))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Operations" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'circle', 'triangle'}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "favourites_shapes = set(['circle','triangle','hexagon'])\n", "\n", "# Intersection\n", "set_of_shapes.intersection(favourites_shapes)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'circle', 'hexagon', 'square', 'triangle'}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Union\n", "set_of_shapes.union(favourites_shapes)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'square'}" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Difference\n", "set_of_shapes.difference(favourites_shapes)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Overall Challenges\n", "===\n", "#### Programming Words\n", "- Make a list of the most important words you have learned in programming so far. You should have terms such as list,\n", "- Make a corresponding list of definitions. Fill your list with 'definition'.\n", "- Use a for loop to print out each word and its corresponding definition.\n", "- Maintain this program until you get to the section on Python's Dictionaries." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Overall Challenges: Programming Words\n", "\n", "# Put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "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." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 04 If Statements.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# If Statements" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "# Contents\n", "\n", "- [What is an *if* statement?](#what)\n", " - [Example](#example)\n", "- [Logical tests](#logical_tests)\n", " - [Equality](#equality)\n", " - [Inequality](#inequality)\n", " - [Other inequalities](#other_inequalities)\n", " - [Checking if an item is in a list](#in_list)\n", " - [Exercises](#exercises_logical_tests)\n", "- [The if-elif...else chain](#if-elif-else)\n", " - [Simple if statements](#simple_if)\n", " - [if-else statements](#if-else)\n", " - [if-elif...else chains](#if-elif-else_chains)\n", " - [Exercises](#exercises_if-elif-else)\n", "- [More than one passing test](#more_than_one)\n", "- [True and False values](#true_false)\n", "- [Overall Challenges](#overall_challenges)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "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(\"%s is my favorite dessert!\" % dessert.title())\n", " else:\n", " # I like these desserts, but they are not my favorite.\n", " print(\"I like %s.\" % dessert)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### What happens in this program?\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": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Logical Tests\n", "===\n", "Every if statement evaluates to *True* or *False*. *True* and *False* are Python keywords, which have special meanings attached to them. You can test for the following conditions in your if statements:\n", "\n", "- [equality](#equality) (==)\n", "- [inequality](#inequality) (!=)\n", "- [other inequalities](#other_inequalities)\n", " - greater than (>)\n", " - greater than or equal to (>=)\n", " - less than (<)\n", " - less than or equal to (<=)\n", "- [You can test if an item is **in** a list.](#in_list)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Whitespace\n", "Remember [learning about](04_lists_tuples.html#pep8) PEP 8? There is a [section of PEP 8](http://www.python.org/dev/peps/pep-0008/#other-recommendations) that tells us it's a good idea to put a single space on either side of all of these comparison operators. If you're not sure what this means, just follow the style of the examples you see below." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Equality\n", "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Two items are *equal* if they have the same value. You can test for equality between numbers, strings, and a number of other objects which you will learn about later. Some of these results may be surprising, so take a careful look at the examples below." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In Python, as in many programming languages, two equals signs tests for equality." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Watch out!** Be careful of accidentally using one equals sign, which can really throw things off because that one equals sign actually sets your item to the value you are testing for!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Examples" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 == 5" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3 == 5 " ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 == 5.0" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'eric' == 'eric'" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'Eric' == 'eric'" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'Eric'.lower() == 'eric'.lower()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'5' == 5" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'5' == str(5)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Inequality\n", "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Two items are *inequal* if they do not have the same value. In Python, we test for inequality using the exclamation point and one equals sign.\n", "\n", "Sometimes you want to test for equality and if that fails, assume inequality. Sometimes it makes more sense to test for inequality directly." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3 != 5" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 != 5" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'Eric' != 'eric'" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Other Inequalities\n", "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### greater than" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 > 3" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### greater than or equal to" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 >= 3" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3 >= 3" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### less than" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3 < 5" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### less than or equal to" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3 <= 5" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3 <= 3" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Checking if an item is **in** a list\n", "---\n", "You can check if an item is in a list using the **in** keyword." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vowels = ['a', 'e', 'i', 'o', 'u']\n", "'a' in vowels" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vowels = ['a', 'e', 'i', 'o', 'u']\n", "'b' in vowels" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### True and False\n", "- Write a program that consists of at least ten lines, each of which has a logical statement on it. The output of your program should be 5 **True**s and 5 **False**s.\n", "- Note: You will probably need to write `print(5 > 3)`, not just `5 > 3`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 5.1 : True and False\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 27, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "In this situation, nothing happens if the test does not pass." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 30, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 31, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The test evaluated to **False**, so only the statement under `else` is run." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 32, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 33, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Wow, we have a lot of dogs here!\n" ] } ], "source": [ "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": { "slideshow": { "slide_type": "subslide" } }, "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": 34, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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) >= 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": { "slideshow": { "slide_type": "subslide" } }, "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": 35, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Okay, this is a reasonable number of dogs.\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", "else:\n", " print(\"Okay, this is a reasonable number of dogs.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 36, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "###highlight=[8]\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", "elif len(dogs) >= 1:\n", " print(\"Okay, this is a reasonable number of dogs.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 37, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I wish we had a dog here.\n" ] } ], "source": [ "###highlight=[10,11]\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", "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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "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", "- **Bonus:** Store your if test in a function called something like `crowd_test`.\n", "\n", "#### Three is a Crowd - Part 2\n", "- Save your program from *Three is a Crowd* under a new name.\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", "- Save your program from *Three is a Crowd - Part 2* under a new name.\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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 5.2 : Three is a Crowd\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 5.3 : Three is a Crowd - Part 2\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 5.4 : Six is a Mob\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": 38, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 41, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Willie!\n" ] } ], "source": [ "###highlight=[6,7,8,9,10,11]\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": { "slideshow": { "slide_type": "subslide" } }, "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": 43, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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, %s!\" % dog.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "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": [ "# ADD LOGICAL OPERATORS" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Take a look at the following examples, keep them in mind, and test any value you are curious about." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "I am using a slightly longer test just to make sure something gets printed each time." ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": 61, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": 62, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": 63, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": 64, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": 66, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": 67, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": 68, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Overall Challenges\n", "===\n", "#### Alien Points\n", "- Make a list of ten aliens, each of which is one color: 'red', 'green', or 'blue'.\n", " - You can shorten this to 'r', 'g', and 'b' if you want, but if you choose this option you have to include a comment explaining what r, g, and b stand for.\n", "- Red aliens are worth 5 points, green aliens are worth 10 points, and blue aliens are worth 20 points.\n", "- Use a for loop to determine the number of points a player would earn for destroying all of the aliens in your list.\n", "- [hint](#hint_alien_points)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Overall Challenge: Alien Points\n", "\n", "# Put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "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", "#### Alien Invaders\n", "- After you define your list of aliens, set a variable called `current_score` or `current_points` equal to 0.\n", "- Inside your for loop, write a series of if tests to determine how many points to add to the current score.\n", "- To keep a running total, use the syntax `current_score = current_score + points`, where *points* is the number of points for the current alien." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 05 While Loops and User input.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Loops, Iteration Schemas and Input\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "While loops are really useful because they let your program run until a user decides to quit the program. They set up an infinite loop that runs until the user does something to end the loop. This section also introduces the first way to get input from your program's users." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Contents\n", "===\n", "- [What is a `while` loop?](#what)\n", " - [General syntax](#general_syntax)\n", " - [Example](#example)\n", " - [Exercises](#exercises_while)\n", "- [Accepting user input](#input)\n", " - [General syntax](#general_user_input)\n", " - [Example](#example_user_input)\n", " - [Exercises](#exercises_input)\n", "- [Using while loops to keep your programs running](#keep_running)\n", " - [Exercises](#exercises_running_input)\n", "- [Using while loops to make menus](#menus)\n", "- [Using while loops to process items in a list](#process_list)\n", "- [Accidental Infinite loops](#infinite_loops)\n", " - [Exercises](#exercises_infinite_loops)\n", "- [Overall Challenges](#overall_challenges)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## The FOR (iteration) loop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The `for` loop statement is the most widely used iteration mechanisms in Python.\n", "\n", "* Almost every structure in Python can be iterated (*element by element*) by a `for` loop\n", " - a list, a tuple, a dictionary, $\\ldots$ (more details will follows)\n", "\n", "* In Python, also `while` loops are permitted, but `for` is the one you would see (and use) most of the time!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "What is a while loop?\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "A while loop tests an initial condition. If that condition is true, the loop starts executing. Every time the loop finishes, the condition is reevaluated. As long as the condition remains true, the loop keeps executing. As soon as the condition becomes false, the loop stops executing." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "General syntax\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Set an initial condition.\n", "game_active = True\n", "\n", "# Set up the while loop.\n", "while game_active:\n", " # Run the game.\n", " # At some point, the game ends and game_active will be set to False.\n", " # When that happens, the loop will stop executing.\n", " \n", "# Do anything else you want done after the loop runs." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Every while loop needs an initial condition that starts out true.\n", "- The `while` statement includes a condition to test.\n", "- All of the code in the loop will run as long as the condition remains true.\n", "- As soon as something in the loop changes the condition such that the test no longer passes, the loop stops executing.\n", "- Any code that is defined after the loop will run at this point." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Example\n", "---\n", "Here is a simple example, showing how a game will stay active as long as the player has enough power." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "You are still playing, because your power is 5.\n", "You are still playing, because your power is 4.\n", "You are still playing, because your power is 3.\n", "You are still playing, because your power is 2.\n", "You are still playing, because your power is 1.\n", "\n", "Oh no, your power dropped to 0! Game Over.\n" ] } ], "source": [ "# The player's power starts out at 5.\n", "power = 5\n", "\n", "# The player is allowed to keep playing as long as their power is over 0.\n", "while power > 0:\n", " print(\"You are still playing, because your power is %d.\" % power)\n", " # Your game code would go here, which includes challenges that make it\n", " # possible to lose power.\n", " # We can represent that by just taking away from the power.\n", " power = power - 1\n", " \n", "print(\"\\nOh no, your power dropped to 0! Game Over.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Growing Strength\n", "- Make a variable called strength, and set its initial value to 5.\n", "- Print a message reporting the player's strength.\n", "- Set up a while loop that runs until the player's strength increases to a value such as 10.\n", "- Inside the while loop, print a message that reports the player's current strength.\n", "- Inside the while loop, write a statement that increases the player's strength.\n", "- Outside the while loop, print a message reporting that the player has grown too strong, and that they have moved up to a new level of the game.\n", "- Bonus: Play around with different cutoff levels for the value of *strength*, and play around with different ways to increase the strength value within the while loop." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 6.1 : Growing Strength\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Accepting user input\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Almost all interesting programs accept input from the user at some point. You can start accepting user input in your programs by using the `input()` function. The input function displays a messaget to the user describing the kind of input you are looking for, and then it waits for the user to enter a value. When the user presses Enter, the value is passed to your variable." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "General syntax\n", "---\n", "The general case for accepting input looks something like this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Get some input from the user.\n", "variable = input('Please enter a value: ')\n", "# Do something with the value that was entered." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "You need a variable that will hold whatever value the user enters, and you need a message that will be displayed to the user." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Example\n", "---\n", "In the following example, we have a list of names. We ask the user for a name, and we add it to our list of names." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Please tell me someone I should know: jessica\n", "['guido', 'tim', 'jesse', 'jessica']\n" ] } ], "source": [ "# Start with a list containing several names.\n", "names = ['guido', 'tim', 'jesse']\n", "\n", "# Ask the user for a name.\n", "new_name = input(\"Please tell me someone I should know: \")\n", "\n", "# Add the new name to our list.\n", "names.append(new_name)\n", "\n", "# Show that the name has been added to the list.\n", "print(names)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Game Preferences\n", "- Make a list that includes 3 or 4 games that you like to play.\n", "- Print a statement that tells the user what games you like.\n", "- Ask the user to tell you a game they like, and store the game in a variable such as `new_game`.\n", "- Add the user's game to your list.\n", "- Print a new statement that lists all of the games that we like to play (*we* means you and your user)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 6.2 : Game Preferences\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Using while loops to keep your programs running\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Most of the programs we use every day run until we tell them to quit, and in the background this is often done with a while loop." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Here is an example of how to let the user enter an arbitrary number of names." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Please tell me someone I should know, or enter 'quit': guido\n", "Please tell me someone I should know, or enter 'quit': jesse\n", "Please tell me someone I should know, or enter 'quit': jessica\n", "Please tell me someone I should know, or enter 'quit': tim\n", "Please tell me someone I should know, or enter 'quit': quit\n", "['guido', 'jesse', 'jessica', 'tim', 'quit']\n" ] } ], "source": [ "# Start with an empty list. You can 'seed' the list with\n", "# some predefined values if you like.\n", "names = []\n", "\n", "# Set new_name to something other than 'quit'.\n", "new_name = ''\n", "\n", "# Start a loop that will run until the user enters 'quit'.\n", "while new_name != 'quit':\n", " # Ask the user for a name.\n", " new_name = input(\"Please tell me someone I should know, or enter 'quit': \")\n", "\n", " # Add the new name to our list.\n", " names.append(new_name)\n", "\n", "# Show that the name has been added to the list.\n", "print(names)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "That worked, except we ended up with the name 'quit' in our list. We can use a simple `if` test to eliminate this bug:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Please tell me someone I should know, or enter 'quit': guido\n", "Please tell me someone I should know, or enter 'quit': jesse\n", "Please tell me someone I should know, or enter 'quit': jessica\n", "Please tell me someone I should know, or enter 'quit': tim\n", "Please tell me someone I should know, or enter 'quit': quit\n", "['guido', 'jesse', 'jessica', 'tim']\n" ] } ], "source": [ "# Start with an empty list. You can 'seed' the list with\n", "# some predefined values if you like.\n", "names = []\n", "\n", "# Set new_name to something other than 'quit'.\n", "new_name = ''\n", "\n", "# Start a loop that will run until the user enters 'quit'.\n", "while new_name != 'quit':\n", " # Ask the user for a name.\n", " new_name = input(\"Please tell me someone I should know, or enter 'quit': \")\n", "\n", " # Add the new name to our list.\n", " if new_name != 'quit':\n", " names.append(new_name)\n", "\n", "# Show that the name has been added to the list.\n", "print(names)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is pretty cool! We now have a way to accept input from users while our programs run, and we have a way to let our programs run until our users are finished working." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Many Games\n", "- Modify *[Game Preferences](#exercises_input)* so your user can add as many games as they like." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 6.3 : Many Games\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Using while loops to make menus\n", "===\n", "You now have enough Python under your belt to offer users a set of choices, and then respond to those choices until they choose to quit." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Let's look at a simple example, and then analyze the code:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Welcome to the nature center. What would you like to do?\n", "\n", "[1] Enter 1 to take a bicycle ride.\n", "[2] Enter 2 to go for a run.\n", "[3] Enter 3 to climb a mountain.\n", "[q] Enter q to quit.\n", "\n", "What would you like to do? 1\n", "\n", "Here's a bicycle. Have fun!\n", "\n", "\n", "[1] Enter 1 to take a bicycle ride.\n", "[2] Enter 2 to go for a run.\n", "[3] Enter 3 to climb a mountain.\n", "[q] Enter q to quit.\n", "\n", "What would you like to do? 3\n", "\n", "Here's a map. Can you leave a trip plan for us?\n", "\n", "\n", "[1] Enter 1 to take a bicycle ride.\n", "[2] Enter 2 to go for a run.\n", "[3] Enter 3 to climb a mountain.\n", "[q] Enter q to quit.\n", "\n", "What would you like to do? q\n", "\n", "Thanks for playing. See you later.\n", "\n", "Thanks again, bye now.\n" ] } ], "source": [ "# Give the user some context.\n", "print(\"\\nWelcome to the nature center. What would you like to do?\")\n", "\n", "# Set an initial value for choice other than the value for 'quit'.\n", "choice = ''\n", "\n", "# Start a loop that runs until the user enters the value for 'quit'.\n", "while choice != 'q':\n", " # Give all the choices in a series of print statements.\n", " print(\"\\n[1] Enter 1 to take a bicycle ride.\")\n", " print(\"[2] Enter 2 to go for a run.\")\n", " print(\"[3] Enter 3 to climb a mountain.\")\n", " print(\"[q] Enter q to quit.\")\n", " \n", " # Ask for the user's choice.\n", " choice = input(\"\\nWhat would you like to do? \")\n", " \n", " # Respond to the user's choice.\n", " if choice == '1':\n", " print(\"\\nHere's a bicycle. Have fun!\\n\")\n", " elif choice == '2':\n", " print(\"\\nHere are some running shoes. Run fast!\\n\")\n", " elif choice == '3':\n", " print(\"\\nHere's a map. Can you leave a trip plan for us?\\n\")\n", " elif choice == 'q':\n", " print(\"\\nThanks for playing. See you later.\\n\")\n", " else:\n", " print(\"\\nI don't understand that choice, please try again.\\n\")\n", " \n", "# Print a message that we are all finished.\n", "print(\"Thanks again, bye now.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Our programs are getting rich enough now, that we could do many different things with them. Let's clean this up in one really useful way. There are three main choices here, so let's define a function for each of those items. This way, our menu code remains really simple even as we add more complicated code to the actions of riding a bicycle, going for a run, or climbing a mountain." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Welcome to the nature center. What would you like to do?\n", "\n", "[1] Enter 1 to take a bicycle ride.\n", "[2] Enter 2 to go for a run.\n", "[3] Enter 3 to climb a mountain.\n", "[q] Enter q to quit.\n", "\n", "What would you like to do? 1\n", "\n", "Here's a bicycle. Have fun!\n", "\n", "\n", "[1] Enter 1 to take a bicycle ride.\n", "[2] Enter 2 to go for a run.\n", "[3] Enter 3 to climb a mountain.\n", "[q] Enter q to quit.\n", "\n", "What would you like to do? 3\n", "\n", "Here's a map. Can you leave a trip plan for us?\n", "\n", "\n", "[1] Enter 1 to take a bicycle ride.\n", "[2] Enter 2 to go for a run.\n", "[3] Enter 3 to climb a mountain.\n", "[q] Enter q to quit.\n", "\n", "What would you like to do? q\n", "\n", "Thanks for playing. See you later.\n", "\n", "Thanks again, bye now.\n" ] } ], "source": [ "# Define the actions for each choice we want to offer.\n", "def ride_bicycle():\n", " print(\"\\nHere's a bicycle. Have fun!\\n\")\n", " \n", "def go_running():\n", " print(\"\\nHere are some running shoes. Run fast!\\n\")\n", " \n", "def climb_mountain():\n", " print(\"\\nHere's a map. Can you leave a trip plan for us?\\n\")\n", "\n", "# Give the user some context.\n", "print(\"\\nWelcome to the nature center. What would you like to do?\")\n", "\n", "# Set an initial value for choice other than the value for 'quit'.\n", "choice = ''\n", "\n", "# Start a loop that runs until the user enters the value for 'quit'.\n", "while choice != 'q':\n", " # Give all the choices in a series of print statements.\n", " print(\"\\n[1] Enter 1 to take a bicycle ride.\")\n", " print(\"[2] Enter 2 to go for a run.\")\n", " print(\"[3] Enter 3 to climb a mountain.\")\n", " print(\"[q] Enter q to quit.\")\n", " \n", " # Ask for the user's choice.\n", " choice = input(\"\\nWhat would you like to do? \")\n", " \n", " # Respond to the user's choice.\n", " if choice == '1':\n", " ride_bicycle()\n", " elif choice == '2':\n", " go_running()\n", " elif choice == '3':\n", " climb_mountain()\n", " elif choice == 'q':\n", " print(\"\\nThanks for playing. See you later.\\n\")\n", " else:\n", " print(\"\\nI don't understand that choice, please try again.\\n\")\n", " \n", "# Print a message that we are all finished.\n", "print(\"Thanks again, bye now.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is much cleaner code, and it gives us space to separate the details of taking an action from the act of choosing that action." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Using while loops to process items in a list\n", "===\n", "In the section on Lists, you saw that we can `pop()` items from a list. You can use a while list to pop items one at a time from one list, and work with them in whatever way you need. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Let's look at an example where we process a list of unconfirmed users." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Confirming user Daria...confirmed!\n", "Confirming user Clarence...confirmed!\n", "Confirming user Billy...confirmed!\n", "Confirming user Ada...confirmed!\n", "\n", "Unconfirmed users:\n", "\n", "Confirmed users:\n", "- Daria\n", "- Clarence\n", "- Billy\n", "- Ada\n" ] } ], "source": [ "# Start with a list of unconfirmed users, and an empty list of confirmed users.\n", "unconfirmed_users = ['ada', 'billy', 'clarence', 'daria']\n", "confirmed_users = []\n", "\n", "# Work through the list, and confirm each user.\n", "while len(unconfirmed_users) > 0:\n", " \n", " # Get the latest unconfirmed user, and process them.\n", " current_user = unconfirmed_users.pop()\n", " print(\"Confirming user %s...confirmed!\" % current_user.title())\n", " \n", " # Move the current user to the list of confirmed users.\n", " confirmed_users.append(current_user)\n", " \n", "# Prove that we have finished confirming all users.\n", "print(\"\\nUnconfirmed users:\")\n", "for user in unconfirmed_users:\n", " print('- ' + user.title())\n", " \n", "print(\"\\nConfirmed users:\")\n", "for user in confirmed_users:\n", " print('- ' + user.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This works, but let's make one small improvement. The current program always works with the most recently added user. If users are joining faster than we can confirm them, we will leave some users behind. If we want to work on a 'first come, first served' model, or a 'first in first out' model, we can pop the first item in the list each time." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Confirming user Ada...confirmed!\n", "Confirming user Billy...confirmed!\n", "Confirming user Clarence...confirmed!\n", "Confirming user Daria...confirmed!\n", "\n", "Unconfirmed users:\n", "\n", "Confirmed users:\n", "- Ada\n", "- Billy\n", "- Clarence\n", "- Daria\n" ] } ], "source": [ "# Start with a list of unconfirmed users, and an empty list of confirmed users.\n", "unconfirmed_users = ['ada', 'billy', 'clarence', 'daria']\n", "confirmed_users = []\n", "\n", "# Work through the list, and confirm each user.\n", "while len(unconfirmed_users) > 0:\n", " \n", " # Get the latest unconfirmed user, and process them.\n", " current_user = unconfirmed_users.pop(0)\n", " print(\"Confirming user %s...confirmed!\" % current_user.title())\n", " \n", " # Move the current user to the list of confirmed users.\n", " confirmed_users.append(current_user)\n", " \n", "# Prove that we have finished confirming all users.\n", "print(\"\\nUnconfirmed users:\")\n", "for user in unconfirmed_users:\n", " print('- ' + user.title())\n", " \n", "print(\"\\nConfirmed users:\")\n", "for user in confirmed_users:\n", " print('- ' + user.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is a little nicer, because we are sure to get to everyone, even when our program is running under a heavy load. We also preserve the order of people as they join our project. Notice that this all came about by adding *one character* to our program!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Accidental Infinite loops\n", "===\n", "Sometimes we want a while loop to run until a defined action is completed, such as emptying out a list. Sometimes we want a loop to run for an unknown period of time, for example when we are allowing users to give as much input as they want. What we rarely want, however, is a true 'runaway' infinite loop." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Take a look at the following example. Can you pick out why this loop will never stop?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "current_number = 1\n", "\n", "# Count up to 5, printing the number each time.\n", "while current_number <= 5:\n", " print(current_number)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "1\n", "1\n", "1\n", "1\n", "1\n", "..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "I faked that output, because if I ran it the output would fill up the browser. You can try to run it on your computer, as long as you know how to interrupt runaway processes:\n", "\n", "- On most systems, Ctrl-C will interrupt the currently running program.\n", "- If you are using Geany, your output is displayed in a popup terminal window. You can either press Ctrl-C, or you can use your pointer to close the terminal window." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The loop runs forever, because there is no way for the test condition to ever fail. The programmer probably meant to add a line that increments current_number by 1 each time through the loop:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "5\n" ] } ], "source": [ "current_number = 1\n", "\n", "# Count up to 5, printing the number each time.\n", "while current_number <= 5:\n", " print(current_number)\n", " current_number = current_number + 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You will certainly make some loops run infintely at some point. When you do, just interrupt the loop and figure out the logical error you made.\n", "\n", "Infinite loops will not be a real problem until you have users who run your programs on their machines. You won't want infinite loops then, because your users would have to shut down your program, and they would consider it buggy and unreliable. Learn to spot infinite loops, and make sure they don't pop up in your polished programs later on.\n", "\n", "Here is one more example of an accidental infinite loop:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "current_number = 1\n", "\n", "# Count up to 5, printing the number each time.\n", "while current_number <= 5:\n", " print(current_number)\n", " current_number = current_number - 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "1\n", "0\n", "-1\n", "-2\n", "-3\n", "..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In this example, we accidentally started counting down. The value of `current_number` will always be less than 5, so the loop will run forever." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Marveling at Infinity\n", "- Use one of the examples of a failed while loop to create an infinite loop.\n", "- Interrupt your output.\n", "- Marvel at the fact that if you had not interrupted your output, your computer would have kept doing what you told it to until it ran out of power, or memory, or until the universe went cold around it." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 6.4 : Marveling at Infinity\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Overall Challenges\n", "===\n", "#### Gaussian Addition\n", "This challenge is inspired by a story about the mathematician Carl Frederich Gauss. [As the story goes](http://mathforum.org/library/drmath/view/57919.html), when young Gauss was in grade school his teacher got mad at his class one day.\n", "\n", "\"I'll keep the lot of you busy for a while\", the teacher said sternly to the group. \"You are to add the numbers from 1 to 100, and you are not to say a word until you are done.\"\n", "\n", "The teacher expected a good period of quiet time, but a moment later our mathematician-to-be raised his hand with the answer. \"It's 5050!\" Gauss had realized that if you list all the numbers from 1 to 100, you can always match the first and last numbers in the list and get a common answer:\n", "\n", " 1, 2, 3, ..., 98, 99, 100\n", " 1 + 100 = 101\n", " 2 + 99 = 101\n", " 3 + 98 = 101\n", "\n", "Gauss realized there were exactly 50 pairs of numbers in the range 1 to 100, so he did a quick calculation: 50 * 101 = 5050.\n", "\n", "- Write a program that passes a list of numbers to a function.\n", " - The function should use a while loop to keep popping the first and last numbers from the list and calculate the sum of those two numbers.\n", " - The function should print out the current numbers that are being added, and print their partial sum.\n", " - The function should keep track of how many partial sums there are.\n", " - The function should then print out how many partial sums there were.\n", " - The function should perform Gauss' multiplication, and report the final answer.\n", "- Prove that your function works, by passing in the range 1-100, and verifying that you get 5050.\n", " - `gauss_addition(list(range(1,101)))`\n", "- Your function should work for any set of consecutive numbers, as long as that set has an even length.\n", " - Bonus: Modify your function so that it works for any set of consecutive numbers, whether that set has an even or odd length." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Overall Challenge: Gaussian Addition\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 06 Dictionaries.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Dictionaries (Data Structure)\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Dictionaries allow us to store connected bits of information. For example, you might store a person's name and age together." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Contents\n", "===\n", "- [What are dictionaries?](#what)\n", " - [General Syntax](#general_syntax)\n", " - [Example](#example)\n", " - [Exercises](#exercises_what)\n", "- [Common operations with dictionaries](#common_operations)\n", " - [Adding new key-value pairs](#adding_pairs)\n", " - [Modifying values in a dictionary](#modifying_values)\n", " - [Removing key-value pairs](#removing_pairs)\n", " - [Modifying keys in a dictionary](#modifying_keys)\n", " - [Exercises](#exercises_common_operations)\n", "- [Looping through a dictionary](#looping)\n", " - [Looping through all key-value pairs](#loop_all_keys_values)\n", " - [Looping through all keys in a dictionary](#loop_all_keys)\n", " - [Looping through all values in a dictionary](#loop_all_values)\n", " - [Looping through a dictionary in order](#looping_in_order)\n", " - [Exercises](#exercises_looping)\n", "- [Nesting](#nesting)\n", " - [Lists in a dictionary](#lists_in_dictionary)\n", " - [Dictionaries in a dictionary](#dictionaries_in_dictionary)\n", " - [An important note about nesting](#important_note)\n", " - [Exercises](#exercises_nesting)\n", "- [Overall Challenges](#overall_challenges)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "What are dictionaries?\n", "===\n", "Dictionaries are a way to store information that is connected in some way. Dictionaries store information in *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", "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "General Syntax\n", "---\n", "A general dictionary in Python looks something like this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "dictionary_name = {key_1: value_1, key_2: value_2, key_3: value_3}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "dictionary_name = {key_1: value_1,\n", " key_2: value_2,\n", " key_3: value_3,\n", " }" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is a bit easier to read, especially if the values are long." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Example\n", "---\n", "A simple example involves modeling an actual dictionary." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": [ "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(\"\\nWord: %s\" % 'list')\n", "print(\"Meaning: %s\" % python_words['list'])\n", " \n", "print(\"\\nWord: %s\" % 'dictionary')\n", "print(\"Meaning: %s\" % python_words['dictionary'])\n", "\n", "print(\"\\nWord: %s\" % 'function')\n", "print(\"Meaning: %s\" % python_words['function'])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This code looks pretty repetitive, and it is. 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": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Word: function\n", "Meaning: A named set of instructions that defines a set of actions in Python.\n", "\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" ] } ], "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 in the dictionary.\n", "for word, meaning in python_words.items():\n", " print(\"\\nWord: %s\" % word)\n", " print(\"Meaning: %s\" % meaning)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The output is identical, but we did it in 3 lines instead of 6. 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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "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", "- Use a for loop to print out a series of statements such as \"Willie is a dog.\"\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", "- Use a for loop to print out a series of statements listing each person's name, and their response." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.1 : Pet Names\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.2 : Polling Friends\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Word: function\n", "Meaning: A named set of instructions that defines a set of actions in Python.\n", "\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" ] } ], "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: %s\" % word)\n", " print(\"Meaning: %s\" % meaning)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "list : 507389742764312598\n", "function : -6418509839493444138\n", "dictionary : -4501548687734576673\n", "function : -6418509839493444138\n", "list : 507389742764312598\n", "dictionary : -4501548687734576673\n" ] } ], "source": [ "# Dealing with Hashing Functions\n", "hashings = {}\n", "hashings['function'] = hash('function')\n", "hashings['list'] = hash('list')\n", "hashings['dictionary'] = hash('dictionary')\n", "\n", "for k, v in hashings.items():\n", " print(k,': ',v)\n", "\n", "\n", "from collections import OrderedDict\n", "hashings = OrderedDict()\n", "hashings['function'] = hash('function')\n", "hashings['list'] = hash('list')\n", "hashings['dictionary'] = hash('dictionary')\n", "\n", "for k, v in hashings.items():\n", " print(k,': ',v)\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 17, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dictionary: A collection of key-value pairs.\n", "\n", "dictionary: A collection of key-value pairs. Each key can be used to access its corresponding value.\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('dictionary: ' + python_words['dictionary'])\n", " \n", "# Clarify one of the meanings.\n", "python_words['dictionary'] = 'A collection of key-value pairs. \\\n", " Each key can be used to access its corresponding value.'\n", "\n", "print('\\ndictionary: ' + python_words['dictionary'])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "These are the Python words I know:\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": [ "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", "# Remove the word 'list' and its meaning.\n", "_ = python_words.pop('list')\n", "\n", "# Show the current set of words and meanings.\n", "print(\"\\n\\nThese are the Python words I know:\")\n", "for word, meaning in python_words.items():\n", " print(\"\\nWord: %s\" % word)\n", " print(\"Meaning: %s\" % meaning)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you were going to work with this code, you would certainly want to put the code for displaying the dictionary into a function. Let's see what this looks like:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "These are the Python words I know:\n", "\n", "Word: function\n", "Meaning: A named set of instructions that defines a set of actions in Python.\n", "\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", "\n", "These are the Python words I know:\n", "\n", "Word: function\n", "Meaning: A named set of instructions that defines a set of actions in Python.\n", "\n", "Word: dictionary\n", "Meaning: A collection of key-value pairs.\n" ] } ], "source": [ "def show_words_meanings(python_words):\n", " # This function takes in a dictionary of python words and meanings,\n", " # and prints out each word with its meaning.\n", " print(\"\\n\\nThese are the Python words I know:\")\n", " for word, meaning in python_words.items():\n", " print(\"\\nWord: %s\" % word)\n", " print(\"Meaning: %s\" % meaning)\n", " \n", "\n", "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_words_meanings(python_words)\n", " \n", "# Remove the word 'list' and its meaning.\n", "del python_words['list']\n", "\n", "show_words_meanings(python_words)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "As long as we have a nice clean function to work with, let's clean up our output a little:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "These are the Python words I know:\n", "\n", "function: A named set of instructions that defines a set of actions in Python.\n", "\n", "dictionary: A collection of key-value pairs.\n", "\n", "list: A collection of values that are not connected, but have an order.\n", "\n", "\n", "These are the Python words I know:\n", "\n", "function: A named set of instructions that defines a set of actions in Python.\n", "\n", "dictionary: A collection of key-value pairs.\n" ] } ], "source": [ "def show_words_meanings(python_words):\n", " # This function takes in a dictionary of python words and meanings,\n", " # and prints out each word with its meaning.\n", " print(\"\\n\\nThese are the Python words I know:\")\n", " for word, meaning in python_words.items():\n", " print(\"\\n%s: %s\" % (word, meaning))\n", " \n", "\n", "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_words_meanings(python_words)\n", " \n", "# Remove the word 'list' and its meaning.\n", "del python_words['list']\n", "\n", "show_words_meanings(python_words)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is much more realistic code." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": 37, "metadata": { "collapsed": false }, "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 = {'list': '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": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Pet Names 2\n", "- Make a copy of your program from [Pet Names](#exercises_what).\n", " - Use a for loop to print out a series of statements such as \"Willie is a dog.\"\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", " - Use a for loop to print out a series of statements such as \"Willie is a dog.\"\n", " - Add a new key-value pair to your dictionary.\n", " - Use a for loop to print out a series of statements such as \"Willie is a dog.\"\n", " - Remove one of the key-value pairs from your dictionary.\n", " - Use a for loop to print out a series of statements such as \"Willie is a dog.\"\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", " - Use a for loop to print out a series of statements such as \"I did 10 bench presses\".\n", " - Modify one of the values in your dictionary, to represent doing more of that exercise.\n", " - Use a for loop to print out a series of statements such as \"I did 10 bench presses\".\n", " - Add a new key-value pair to your dictionary.\n", " - - Use a for loop to print out a series of statements such as \"I did 10 bench presses\".\n", " - Remove one of the key-value pairs from your dictionary.\n", " - - Use a for loop to print out a series of statements such as \"I did 10 bench presses\".\n", "- Bonus: Use a function to do all of the looping and printing in this problem." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.3 : Pet Names 2\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.4 : Weight Lifting\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Looping through a dictionary\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Looping through all key-value pairs\n", "---\n", "This is the kind of loop that was shown in the first example. Here's what this loop looks like, in a general format:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Key: key_1\n", "Value: value_1\n", "\n", "Key: key_3\n", "Value: value_3\n", "\n", "Key: key_2\n", "Value: value_2\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('\\nKey: %s' % key)\n", " print('Value: %s' % value)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 10, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[('key_1', 'value_1'), ('key_3', 'value_3'), ('key_2', 'value_2')]\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": { "slideshow": { "slide_type": "subslide" } }, "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": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Word: function\n", "Meaning: A named set of instructions that defines a set of actions in Python.\n", "\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" ] } ], "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(\"\\nWord: %s\" % word)\n", " print(\"Meaning: %s\" % meaning)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Key: key_1\n", "Key: key_3\n", "Key: key_2\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: %s' % key)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 14, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Key: key_1\n", "Key: key_3\n", "Key: key_2\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: %s' % key)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 17, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Key: key_1\n", "Key: key_3\n", "Key: key_2\n", " The value for key_2 is value_2.\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: %s' % key)\n", " if key == 'key_2':\n", " print(\" The value for key_2 is %s.\" % my_dict[key])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The following Python words have been defined:\n", "- function\n", "- list\n", "- dictionary\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(\"- %s\" % word)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can extend this slightly to make a program that lets you look up words. We first let the user choose a word. When the user has chosen a word, we get the meaning for that word, and display it:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The following Python words have been defined:\n", "- function\n", "- list\n", "- dictionary\n", "\n", "What word would you like to learn about? list\n", "\n", "list: A collection of values that are not connected, but have an order.\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(\"- %s\" % word)\n", " \n", "# Allow the user to choose a word, and then display the meaning for that word.\n", "requested_word = raw_input(\"\\nWhat word would you like to learn about? \")\n", "print(\"\\n%s: %s\" % (requested_word, python_words[requested_word]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This allows the user to select one word that has been defined. If we enclose the input part of the program in a while loop, the user can see as many definitions as they'd like:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The following Python words have been defined:\n", "- function\n", "- list\n", "- dictionary\n", "\n", "What word would you like to learn about? (or 'quit') list\n", "\n", " list: A collection of values that are not connected, but have an order.\n", "\n", "What word would you like to learn about? (or 'quit') dictionary\n", "\n", " dictionary: A collection of key-value pairs.\n", "\n", "What word would you like to learn about? (or 'quit') quit\n", "\n", " Sorry, I don't know that word.\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(\"- %s\" % word)\n", "\n", "requested_word = ''\n", "while requested_word != 'quit':\n", " # Allow the user to choose a word, and then display the meaning for that word.\n", " requested_word = raw_input(\"\\nWhat word would you like to learn about? (or 'quit') \")\n", " if requested_word in python_words.keys():\n", " print(\"\\n %s: %s\" % (requested_word, python_words[requested_word]))\n", " else:\n", " # Handle misspellings, and words not yet stored.\n", " print(\"\\n Sorry, I don't know that word.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This allows the user to ask for as many meanings as they want, but it takes the word \"quit\" as a requested word. Let's add an `elif` clause to clean up this behavior:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The following Python words have been defined:\n", "- function\n", "- list\n", "- dictionary\n", "\n", "What word would you like to learn about? (or 'quit') function\n", "\n", " function: A named set of instructions that defines a set of actions in Python.\n", "\n", "What word would you like to learn about? (or 'quit') dictionary\n", "\n", " dictionary: A collection of key-value pairs.\n", "\n", "What word would you like to learn about? (or 'quit') list\n", "\n", " list: A collection of values that are not connected, but have an order.\n", "\n", "What word would you like to learn about? (or 'quit') class\n", "\n", " Sorry, I don't know that word.\n", "\n", "What word would you like to learn about? (or 'quit') quit\n", "\n", " Bye!\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(\"- %s\" % word)\n", "\n", "requested_word = ''\n", "while requested_word != 'quit':\n", " # Allow the user to choose a word, and then display the meaning for that word.\n", " requested_word = raw_input(\"\\nWhat word would you like to learn about? (or 'quit') \")\n", " if requested_word in python_words.keys():\n", " # This is a word we know, so show the meaning.\n", " print(\"\\n %s: %s\" % (requested_word, python_words[requested_word]))\n", " elif requested_word != 'quit':\n", " # This is not in python_words, and it's not 'quit'.\n", " print(\"\\n Sorry, I don't know that word.\")\n", " else:\n", " # The word is quit.\n", " print \"\\n Bye!\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 15, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Value: value_1\n", "Value: value_3\n", "Value: value_2\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: %s' % value)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can use this loop syntax to have a little fun with the dictionary example, by making a little quiz program. The program will display a meaning, and ask the user to guess the word that matches that meaning. Let's start out by showing all the meanings in the dictionary:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Meaning: A named set of instructions that defines a set of actions in Python.\n", "Meaning: A collection of values that are not connected, but have an order.\n", "Meaning: 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", "for meaning in python_words.values():\n", " print(\"Meaning: %s\" % meaning)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now we can add a prompt after each meaning, asking the user to guess the word:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Meaning: A named set of instructions that defines a set of actions in Python.\n", "What word do you think this is? function\n", "You got it!\n", "\n", "Meaning: A collection of values that are not connected, but have an order.\n", "What word do you think this is? function\n", "Sorry, that's just not the right word.\n", "\n", "Meaning: A collection of key-value pairs.\n", "What word do you think this is? dictionary\n", "You got it!\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 each meaning, one at a time, and ask the user\n", "# what word they think it is.\n", "for meaning in python_words.values():\n", " print(\"\\nMeaning: %s\" % meaning)\n", " \n", " guessed_word = raw_input(\"What word do you think this is? \")\n", " \n", " # The guess is correct if the guessed word's meaning matches the current meaning.\n", " if python_words[guessed_word] == meaning:\n", " print(\"You got it!\")\n", " else:\n", " print(\"Sorry, that's just not the right word.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is starting to work, but we can see from the output that the user does not get the chance to take a second guess if they guess wrong for any meaning. We can use a while loop around the guessing code, to let the user guess until they get it right:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Meaning: A named set of instructions that defines a set of actions in Python.\n", "\n", "What word do you think this is? function\n", "You got it!\n", "\n", "Meaning: A collection of values that are not connected, but have an order.\n", "\n", "What word do you think this is? dictionary\n", "Sorry, that's just not the right word.\n", "\n", "What word do you think this is? list\n", "You got it!\n", "\n", "Meaning: A collection of key-value pairs.\n", "\n", "What word do you think this is? dictionary\n", "You got it!\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 each meaning, one at a time, and ask the user\n", "# what word they think it is.\n", "for meaning in python_words.values():\n", " print(\"\\nMeaning: %s\" % meaning)\n", " \n", " # Assume the guess is not correct; keep guessing until correct.\n", " correct = False\n", " while not correct:\n", " guessed_word = input(\"\\nWhat word do you think this is? \")\n", " \n", " # The guess is correct if the guessed word's meaning matches the current meaning.\n", " if python_words[guessed_word] == meaning:\n", " print(\"You got it!\")\n", " correct = True\n", " else:\n", " print(\"Sorry, that's just not the right word.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is better. Now, if the guess is incorrect, the user is caught in a loop that they can only exit by guessing correctly. The final revision to this code is to show the user a list of words to choose from when they are asked to guess:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "A named set of instructions that defines a set of actions in Python.\n", "\n", "What word do you think this is?\n", "function list dictionary \n", "- function\n", "You got it!\n", "\n", "A collection of values that are not connected, but have an order.\n", "\n", "What word do you think this is?\n", "function list dictionary \n", "- dictionary\n", "Sorry, that's just not the right word.\n", "\n", "What word do you think this is?\n", "function list dictionary \n", "- list\n", "You got it!\n", "\n", "A collection of key-value pairs.\n", "\n", "What word do you think this is?\n", "function list dictionary \n", "- dictionary\n", "You got it!\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", "def show_words(python_words):\n", " # A simple function to show the words in the dictionary.\n", " display_message = \"\"\n", " for word in python_words.keys():\n", " display_message += word + ' '\n", " print display_message\n", "\n", "# Print each meaning, one at a time, and ask the user\n", "# what word they think it is.\n", "for meaning in python_words.values():\n", " print(\"\\n%s\" % meaning)\n", "\n", " # Assume the guess is not correct; keep guessing until correct.\n", " correct = False\n", " while not correct:\n", " \n", " print(\"\\nWhat word do you think this is?\")\n", " show_words(python_words)\n", " guessed_word = raw_input(\"- \") \n", " \n", " # The guess is correct if the guessed word's meaning matches the current meaning.\n", " if python_words[guessed_word] == meaning:\n", " print(\"You got it!\")\n", " correct = True\n", " else:\n", " print(\"Sorry, that's just not the right word.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Looping through a dictionary in order\n", "===\n", "Dictionaries are quite useful because they allow bits of information to be connected. One of the problems with dictionaries, however, is that they are not stored in any particular order. When you retrieve all of the keys or values in your dictionary, you can't be sure what order you will get them back. There is a quick and easy way to do this, however, when you want them in a particular order.\n", "\n", "Let's take a look at the order that results from a simple call to *dictionary.keys()*:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "function\n", "list\n", "dictionary\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 in python_words.keys():\n", " print(word)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The resulting list is not in order. The list of keys can be put in order by passing the list into the *sorted()* function, in the line that initiates the for loop:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dictionary\n", "function\n", "list\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 in sorted(python_words.keys()):\n", " print(word)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This approach can be used to work with the keys and values in order. For example, the words and meanings can be printed in alphabetical order by word:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dictionary: A collection of key-value pairs.\n", "Function: A named set of instructions that defines a set of actions in Python.\n", "List: A collection of values that are not connected, but have an order.\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 in sorted(python_words.keys()):\n", " print(\"%s: %s\" % (word.title(), python_words[word]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In this example, the keys have been put into alphabetical order in the for loop only; Python has not changed the way the dictionary is stored at all. So the next time the dictionary is accessed, the keys could be returned in any order. There is no way to permanently specify an order for the items in an ordinary dictionary, but if you want to do this you can use the [OrderedDict](http://docs.python.org/3.3/library/collections.html#ordereddict-objects) structure." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "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", "#### Mountain Heights 2\n", "- Revise your final output from Mountain Heights, so that the information is listed in alphabetical order by each mountain's name.\n", " - That is, print out a series of statements telling how tall each mountain is: \"Everest is 8848 meters tall.\"\n", " - Make sure your output is in alphabetical order." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.5 : Mountain Heights\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.6 : Mountain Heights 2\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": { "slideshow": { "slide_type": "subslide" } }, "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": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Example for a Sparse Matrix Implementation\n", "\n", "sparse_matrix = {}\n", "sparse_matrix[0] = {1: 12.3, 23: 25.5}\n", "sparse_matrix[1] = {3: 12.0, 15: 25.5}\n", "\n", "sparse_matrix[1][15]\n", "\n", "full_matrix = [[1, 3, 4], \n", " [2, 5, 3]]\n", "\n", "full_matrix[1][2]" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Willie's favorite numbers are:\n", "[5, 35, 120]\n", "\n", "Ever's favorite numbers are:\n", "[2, 4, 5]\n", "\n", "Eric's favorite numbers are:\n", "[3, 11, 19, 23, 42]\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", "for name in favorite_numbers:\n", " print(\"\\n%s's favorite numbers are:\" % name.title())\n", " print(favorite_numbers[name]) " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Willie's favorite numbers are:\n", "5\n", "35\n", "120\n", "\n", "Ever's favorite numbers are:\n", "2\n", "4\n", "5\n", "\n", "Eric's favorite numbers are:\n", "3\n", "11\n", "19\n", "23\n", "42\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", "for name in favorite_numbers:\n", " print(\"\\n%s's favorite numbers are:\" % name.title())\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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Things get a little more complicated inside the for loop. The value is a list of favorite numbers, so the for loop pulls each *favorite\\_number* out of the list one at a time. If it makes more sense to you, you are free to store the list in a new variable, and use that to define your for loop:\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Willie's favorite numbers are:\n", "5\n", "35\n", "120\n", "\n", "Ever's favorite numbers are:\n", "2\n", "4\n", "5\n", "\n", "Eric's favorite numbers are:\n", "3\n", "11\n", "19\n", "23\n", "42\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", "for name in favorite_numbers:\n", " print(\"\\n%s's favorite numbers are:\" % name.title())\n", " \n", " # Each value is itself a list, so let's put that list in a variable.\n", " current_favorite_numbers = favorite_numbers[name]\n", " for favorite_number in current_favorite_numbers:\n", " print(favorite_number) " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Here is what I know about Peso:\n", "kind: dog\n", "owner: chloe\n", "vaccinated: True\n", "\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" ] } ], "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", "for pet_name, pet_information in pets.items():\n", " print(\"\\nHere is what I know about %s:\" % pet_name.title())\n", " print(\"kind: \" + pet_information['kind'])\n", " print(\"owner: \" + pet_information['owner'])\n", " print(\"vaccinated: \" + str(pet_information['vaccinated']))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Here is what I know about Peso:\n", "owner: chloe\n", "kind: dog\n", "vaccinated: True\n", "\n", "Here is what I know about Willie:\n", "owner: eric\n", "kind: dog\n", "vaccinated: True\n", "\n", "Here is what I know about Walter:\n", "owner: eric\n", "kind: cockroach\n", "vaccinated: False\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", "for pet_name, pet_information in pets.items():\n", " print(\"\\nHere is what I know about %s:\" % pet_name.title())\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": { "slideshow": { "slide_type": "subslide" } }, "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", " \n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Let's show one last version that uses some if statements to clean up our data for printing:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Here is what I know about Peso:\n", "kind: dog\n", "vaccinated: yes\n", "owner: Chloe\n", "\n", "Here is what I know about Walter:\n", "kind: cockroach\n", "vaccinated: no\n", "owner: Eric\n", "\n", "Here is what I know about Willie:\n", "kind: dog\n", "vaccinated: yes\n", "owner: Eric\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", "for pet_name, pet_information in pets.items():\n", " print(\"\\nHere is what I know about %s:\" % pet_name.title())\n", " # Each animal's dictionary is in pet_information\n", " for key in pet_information:\n", " if key == 'owner':\n", " # Capitalize the owner's name.\n", " print(key + \": \" + pet_information[key].title())\n", " elif key == 'vaccinated':\n", " # Print 'yes' for True, and 'no' for False.\n", " vaccinated = pet_information['vaccinated']\n", " if vaccinated:\n", " print('vaccinated: yes')\n", " else:\n", " print('vaccinated: no')\n", " else:\n", " # No special formatting needed for this key.\n", " print(key + \": \" + pet_information[key])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This code is a lot longer, and now we have nested if statements as well as nested for loops. But keep in mind, this structure would work if there were 1000 pets in our dictionary, and it would work if we were storing 1000 pieces of information about each pet. One level of nesting lets us model an incredible array of information." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.7 : Mountain Heights 3\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 7.8 : Mountain Heights 4\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Overall Challenges\n", "===\n", "#### Word Wall\n", "- A word wall is a place on your wall where you keep track of the new words and meanings you are learning. Write a terminal app that lets you enter new words, and a meaning for each word.\n", " - Your app should have a title bar that says the name of your program.\n", " - Your program should give users the option to see all words and meanings that have been entered so far.\n", " - Your program should give users the option to enter a new word and meaning.\n", " - Your program must not allow duplicate entries.\n", " - Your program should store existing words and meanings, even after the program closes.\n", " - Your program should give users the option to modify an existing meaning.\n", "- Bonus Features\n", " - Allow users to modify the spelling of words.\n", " - Allow users to categorize words.\n", " - Turn the program into a game that quizzes users on words and meanings.\n", " - (later on) Turn your program into a website that only you can use.\n", " - (later on) Turn your program into a website that anyone can register for, and use.\n", " - Add a visualization feature that reports on some statistics about the words and meanings that have been entered.\n", "\n", "#### Periodic Table App\n", "- The [Periodic Table](http://www.ptable.com/) of the Elements was developed to organize information about the elements that make up the Universe. Write a terminal app that lets you enter information about each element in the periodic table.\n", " - Make sure you include the following information:\n", " - symbol, name, atomic number, row, and column\n", " - Choose at least one other piece of information to include in your app.\n", " - Provide a menu of options for users to:\n", " - See all the information that is stored about any element, by entering that element's symbol.\n", " - Choose a property, and see that property for each element in the table.\n", "- Bonus Features\n", " - Provide an option to view the symbols arranged like the periodic table. ([hint](#hints_periodic_table))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Word Wall\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Periodic Table App\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Hints\n", "===\n", "#### Periodic Table App\n", "- You can use a for loop to loop through each element. Pick out the elements' row numbers and column numbers.\n", "- Use two nested for loops to print either an element's symbol or a series of spaces, depending on how full that row is." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 07 Introduction to Functions.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Introducing Functions\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "Contents\n", "===\n", "- [What are functions?](#what)\n", " - [General Syntax](#general_syntax)\n", "- [Examples](#examples)\n", " - [Returning a Value](#return_value)\n", " - [Exercises](#exercises)\n", "- [Challenges](#challenges)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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.title()* and *list.sort()*. We can define our own functions, which allows us to \"teach\" Python new behavior." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "General Syntax\n", "---\n", "A general function looks something like this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Let's define a function.\n", "def function_name(argument_1, argument_2):\n", " # Do whatever we want this function to do,\n", " # using argument_1 and argument_2\n", "\n", "# Use function_name to call the function.\n", "function_name(value_1, value_2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This code will not run, but it shows how functions are used in general." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **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 in 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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- **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": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "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": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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, %s!\" % 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": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "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()*." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "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": { "slideshow": { "slide_type": "subslide" } }, "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": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'thank_you' is not defined", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mthank_you\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Adriana'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[0mthank_you\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Billy'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mthank_you\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Caroline'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mthank_you\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mNameError\u001b[0m: name 'thank_you' is not defined" ] } ], "source": [ "thank_you('Adriana')\n", "thank_you('Billy')\n", "thank_you('Caroline')\n", "\n", "def thank_you(name):\n", " # This function prints a two-line personalized thank you message.\n", " print(\"\\nYou are doing good work, %s!\" % name)\n", " print(\"Thank you very much for your efforts on this project.\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "On the first line we ask Python to run the function *thank\\_you()*, 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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A second example\n", "---\n", "When we introduced the different methods for [sorting a list](http://nbviewer.ipython.org/urls/raw.github.com/ehmatthes/intro_programming/master/notebooks/lists_tuples.ipynb#sorting_list), our code got very repetitive. 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": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())\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.title())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Here's what the same code looks like, using a function to print out the list:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())\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": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- 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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- 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": { "slideshow": { "slide_type": "subslide" } }, "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": 10, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())\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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "fragment" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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.m" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "More Later\n", "---\n", "There is much more to learn about functions, but we will get to those details later. For now, feel free to use functions whenever you find yourself writing the same code several times in a program. Some of the things you will learn when we focus on functions:\n", "\n", "- How to give the arguments in your function default values.\n", "- How to let your functions accept different numbers of arguments." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "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](http://nbviewer.ipython.org/urls/raw.github.com/ehmatthes/intro_programming/master/notebooks/lists_tuples.ipynb), using functions to avoid repetetive code:\n", " - [Ordered Working List](http://nbviewer.ipython.org/urls/raw.github.com/ehmatthes/intro_programming/master/notebooks/lists_tuples.ipynb#exercises_common_operations)\n", " - [Ordered Numbers](http://nbviewer.ipython.org/urls/raw.github.com/ehmatthes/intro_programming/master/notebooks/lists_tuples.ipynb#exercises_common_operations)\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 4.1 : Greeter\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 4.2 : Full Names\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 4.3 : Addition Calculator\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 4.4 : Return Calculator\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 4.5 : List Exercises - Functions\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Challenges\n", "---\n", "#### Lyrics\n", "- Many songs follow a familiar variation of the pattern of *verse*, *refrain*, *verse*, *refrain*. The verses are the parts of the song that tell a story - they are not repeated in the song. The refrain is the part of the song that is repeated throughout the song.\n", "- Find the lyrics to a [song you like](http://www.metrolyrics.com/dont-stop-believin-lyrics-journey.html) that follows this pattern. Write a program that prints out the lyrics to this song, using as few lines of Python code as possible. [hint](#hint_challenges_lyrics)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Challenge: Lyrics\n", "\n", "# Put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "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." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 07 More Functions.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "More Functions\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "Contents\n", "===\n", "- [Default argument values](#default_values)\n", " - [Exercises](#exercises_default_values)\n", "- [Positional arguments](#positional_arguments)\n", " - [Exercises](#exercises_positional_arguments)\n", "- [Keyword arguments](#keyword_arguments)\n", " - [Mixing positional and keyword arguments](#positional_and_keyword)\n", " - [Exercises](#exercises_keyword_arguments)\n", "- [Accepting an arbitrary number of arguments](#arbitrary_arguments)\n", " - [Accepting a sequence of arbitrary length](#arbitrary_sequence)\n", " - [Accepting an arbitrary number of keyword arguments](#arbitrary_keyword_arguments)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Default argument values\n", "===\n", "When we first introduced functions, we started with this example:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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, %s!\" % 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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This function works fine, but it fails if you don't pass in a value:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\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 6\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[0m\n\u001b[1;32m 7\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[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mthank_you\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, %s!\" % name)\n", " print(\"Thank you very much for your efforts on this project.\")\n", " \n", "thank_you('Billy')\n", "thank_you('Caroline')\n", "thank_you()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\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": [ "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, %s!\" % name)\n", " print(\"Thank you very much for your efforts on this project.\")\n", " \n", "thank_you('Billy')\n", "thank_you('Caroline')\n", "thank_you()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 8.1 : Games\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 8.2 : Favorite Movie\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Positional Arguments\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Here is a simple implementation of this function:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First name: Brian\n", "Last name: Kernighan\n", "Age: 71\n", "\n", "First name: Ken\n", "Last name: Thompson\n", "Age: 70\n", "\n", "First name: Adele\n", "Last name: Goldberg\n", "Age: 68\n", "\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: %s\" % first_name.title())\n", " print(\"Last name: %s\" % last_name.title())\n", " print(\"Age: %d\\n\" % age)\n", "\n", "describe_person('brian', 'kernighan', 71)\n", "describe_person('ken', 'thompson', 70)\n", "describe_person('adele', 'goldberg', 68)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If we mess up the order, we get nonsense results or an error:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "AttributeError", "evalue": "'int' object has no attribute 'title'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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 7\u001b[0m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Age: %d\\n\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mdescribe_person\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m71\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'brian'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'kernighan'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0mdescribe_person\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m70\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'ken'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'thompson'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mdescribe_person\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m68\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'adele'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'goldberg'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\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[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[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"First name: %s\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mfirst_name\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtitle\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[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Last name: %s\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mlast_name\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtitle\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Age: %d\\n\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mAttributeError\u001b[0m: 'int' object has no attribute 'title'" ] } ], "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: %s\" % first_name.title())\n", " print(\"Last name: %s\" % last_name.title())\n", " print(\"Age: %d\\n\" % age)\n", "\n", "describe_person(71, 'brian', 'kernighan')\n", "describe_person(70, 'ken', 'thompson')\n", "describe_person(68, 'adele', 'goldberg')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This fails because Python tries to match the value 71 with the argument `first_name`, the value *brian* with the argument `last_name`, and the value *kernighan* with the argument `age`. Then when it tries to print the value `first_name.title()`, it realizes it can't use the `title()` method on an integer." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "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": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 8.3 : Favorite Colors\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 8.4 : Phones\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First name: Brian\n", "Last name: Kernighan\n", "Age: 71\n", "\n", "First name: Ken\n", "Last name: Thompson\n", "Age: 70\n", "\n", "First name: Adele\n", "Last name: Goldberg\n", "Age: 68\n", "\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: %s\" % first_name.title())\n", " print(\"Last name: %s\" % last_name.title())\n", " print(\"Age: %d\\n\" % 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": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First name: Brian\n", "Last name: Kernighan\n", "Age: 71\n", "Favorite language: C\n", "\n", "First name: Ken\n", "Last name: Thompson\n", "Age: 70\n", "Favorite language: Go\n", "\n", "First name: Adele\n", "Last name: Goldberg\n", "Age: 68\n", "Favorite language: Smalltalk\n", "\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: %s\" % first_name.title())\n", " print(\"Last name: %s\" % last_name.title())\n", " print(\"Age: %d\" % age)\n", " print(\"Favorite language: %s\\n\" % 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": { "slideshow": { "slide_type": "subslide" } }, "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": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First name: Brian\n", "Last name: Kernighan\n", "Favorite language: C\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", " \"\"\" \n", " This function takes in a person's first and last name, their age, \n", " and their favorite language.\n", " It then prints this information out in a simple format.\n", " \"\"\"\n", " \n", " print(\"First name: %s\" % first_name.title())\n", " print(\"Last name: %s\" % last_name.title())\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", " # Blank line at end.\n", " print(\"\\n\")\n", "\n", "describe_person('brian', 'kernighan', favorite_language='C')\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": { "slideshow": { "slide_type": "subslide" } }, "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": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 8.5 : Sports Team\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 8.6 : Word Languages\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "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": 39, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "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", " sum = num_1 + num_2\n", " print(\"The sum of your numbers is %d.\" % sum)\n", " \n", "# Let's add some numbers.\n", "adder(1, 2)\n", "adder(-1, 2)\n", "adder(1, -2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 40, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "TypeError", "evalue": "adder() takes exactly 2 arguments (3 given)", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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[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[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: adder() takes exactly 2 arguments (3 given)" ] } ], "source": [ "def adder(num_1, num_2):\n", " # This function adds two numbers together, and prints the sum.\n", " sum = num_1 + num_2\n", " print(\"The sum of your numbers is %d.\" % sum)\n", " \n", "# Let's add some numbers.\n", "adder(1, 2, 3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "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": 31, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can use a for loop to process these other arguments:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": [ "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": { "slideshow": { "slide_type": "subslide" } }, "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": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The sum of your numbers is 6.\n" ] } ], "source": [ "def adder(*nums):\n", " \"\"\"This function adds the given numbers together and prints the sum.\"\"\"\n", " \n", " s = 0 \n", " for num in nums:\n", " s = s + num\n", " # Print the results.\n", " print(\"The sum of your numbers is %d.\" % s)\n", " \n", "# Let's add some numbers.\n", "adder(1, 2, 3)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The sum of your numbers is 6.\n" ] } ], "source": [ "def adder(*nums):\n", " \"\"\"This function adds the given numbers together and prints the sum.\"\"\"\n", " # Print the results.\n", " print(\"The sum of your numbers is %d.\" % sum(nums))\n", " \n", "# Let's add some numbers.\n", "adder(1, 2, 3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "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": 28, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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": [ "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", " sum = num_1 + num_2\n", " \n", " # Then add any other numbers that were sent.\n", " for num in nums:\n", " sum = sum + num\n", " \n", " # Print the results.\n", " print(\"The sum of your numbers is %d.\" % sum)\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": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 9, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import sys\n", "\n", "f = open('./test.txt', 'w')\n", "\n", "FILE_OUT = f #sys.stdout\n", "\n", "def example_function(*args, **kwargs):\n", " print(*args, sep='++', end=' ', file=FILE_OUT)\n", " for k, v in kwargs.items():\n", " print(k, ': ', v, end=' ', file=FILE_OUT)\n", " \n", "example_function(1, 2, 4, 5)\n", "example_function(1, 3, value=1, name=5)\n", "example_function(store='ff', quote='Do. Or do not. There is no try.')\n", "\n", "f.close()" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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_4': 'd', 'value_3': 'c'}\n", "\n", "arg_1: a\n", "arg_2: b\n", "arg_3: {'value_5': 'e', 'value_4': 'd', 'value_3': 'c'}\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": { "slideshow": { "slide_type": "subslide" } }, "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": 36, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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: d\n", "arg_3 value: c\n", "\n", "arg_1: a\n", "arg_2: b\n", "arg_3 value: e\n", "arg_3 value: d\n", "arg_3 value: c\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", " 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": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "second:2\n", "third:3\n", "first:1\n", "\n", "second:2\n", "fourth:4\n", "third:3\n", "first:1\n", "\n", "name:Valerio\n", "surname:Maggio\n" ] } ], "source": [ "def example_function(**kwargs):\n", " print(type(kwargs))\n", " for key, value in kwargs.items():\n", " print('{}:{}'.format(key, value))\n", " \n", "example_function(first=1, second=2, third=3)\n", "example_function(first=1, second=2, third=3, fourth=4)\n", "example_function(name='Valerio', surname='Maggio')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "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": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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.title())\n", " print(\"Last name: %s\" % last_name.title())\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": { "slideshow": { "slide_type": "subslide" } }, "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": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "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, **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.title())\n", " print(\"Last name: %s\" % last_name.title())\n", " \n", " # Optional information:\n", " for key in kwargs:\n", " print(\"%s: %s\" % (key.title(), 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": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is pretty neat. We get the same output, and we don't have to include a bunch of if tests to see what kind of information was passed into the function. We always require a first name and a last name, but beyond that the caller is free to provide any keyword-value pair to describe a person. Let's show that any kind of information can be provided to this function. We also clean up the output by replacing any underscores in the keys with a space." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First name: Brian\n", "Last name: Kernighan\n", "Famous Book: The C Programming Language\n", "Favorite Language: C\n", "\n", "\n", "First name: Ken\n", "Last name: Thompson\n", "Alma Mater: UC Berkeley\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", "Famous Book: The C Programming Language\n", "Favorite Language: C\n", "Died: 2011\n", "\n", "\n", "First name: Guido\n", "Last name: Van Rossum\n", "Company: Dropbox\n", "Favorite Language: Python\n", "\n", "\n" ] } ], "source": [ "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.title())\n", " print(\"Last name: %s\" % last_name.title())\n", " \n", " # Optional information:\n", " for key in kwargs:\n", " print(\"%s: %s\" % (key.title().replace('_', ' '), kwargs[key]))\n", " \n", " # Blank line at end.\n", " print(\"\\n\")\n", "\n", "describe_person('brian', 'kernighan', favorite_language='C', famous_book='The C Programming Language')\n", "describe_person('ken', 'thompson', age=70, alma_mater='UC Berkeley')\n", "describe_person('adele', 'goldberg', age=68, favorite_language='Smalltalk')\n", "describe_person('dennis', 'ritchie', favorite_language='C', died=2011, famous_book='The C Programming Language')\n", "describe_person('guido', 'van rossum', favorite_language='Python', company='Dropbox')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "There is plenty more to learn about using functions, but with all of this flexibility in terms of how to accept arguments for your functions you should be able to write simple, clean functions that do exactly what you need them to do." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 08 Classes and OOP.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Classes\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "So far you have learned about Python's core data types: strings, numbers, lists, tuples, and dictionaries. In this section you will learn about the last major data structure, classes. Classes are quite unlike the other data types, in that they are much more flexible. Classes allow you to define the information and behavior that characterize anything you want to model in your program. Classes are a rich topic, so you will learn just enough here to dive into the projects you'd like to get started on." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "There is a lot of new language that comes into play when you start learning about classes. If you are familiar with object-oriented programming from your work in another language, this will be a quick read about how Python approaches OOP. If you are new to programming in general, there will be a lot of new ideas here. Just start reading, try out the examples on your own machine, and trust that it will start to make sense as you work your way through the examples and exercises." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Contents\n", "===\n", "- [What are classes?](#what)\n", "- [Object-Oriented Terminology](#oop_terminology)\n", " - [General terminology](#general_terminology)\n", " - [A closer look at the Rocket class](#closer_look)\n", " - [The \\_\\_init()\\_\\_ method](#init_method)\n", " - [A simple method](#simple_method)\n", " - [Making multiple objects from a class](#multiple_objects)\n", " - [A quick check-in](#check_in)\n", " - [Exercises](#exercises_closer_look)\n", "- [Refining the Rocket class](#refining_rocket)\n", " - [Accepting parameters for the \\_\\_init\\_\\_() method](#init_parameters)\n", " - [Accepting parameters in a method](#method_parameters)\n", " - [Adding a new method](#adding_method)\n", " - [Exercises](#exercises_refining_rocket)\n", "- [Inheritance](#inheritance)\n", " - [The Shuttle class](#shuttle)\n", " - [Exercises](#exercises_inheritance)\n", "- [Modules and classes](#modules_classes)\n", " - [Storing a single class in a module](#single_class_module)\n", " - [Storing multiple classes in a module](#multiple_classes_module)\n", " - [A number of ways to import modules and classes](#multiple_ways_import)\n", " - [A module of functions](#module_functions)\n", " - [Exercises](#exercises_importing)\n", "- [Method Resolution Order (example)](#mro)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "What are classes?\n", "===\n", "Classes are a way of combining information and behavior. For example, let's consider what you'd need to do if you were creating a rocket ship in a game, or in a physics simulation. One of the first things you'd want to track are the x and y coordinates of the rocket. Here is what a simple rocket ship class looks like in code:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "One of the first things you do with a class is to define the **\\__init\\__()** method. The \\_\\_init\\_\\_() method sets the values for any parameters that need to be defined when an object is first created. The *self* part will be explained later; basically, it's a syntax that allows you to access a variable from anywhere else in the class.\n", "\n", "The Rocket class stores two pieces of information so far, but it can't do anything. The first behavior to define is a core behavior of a rocket: moving up. Here is what that might look like in code:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The Rocket class can now store some information, and it can do something. But this code has not actually created a rocket yet. Here is how you actually make a rocket:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<__main__.Rocket object at 0x7f6f50c39190>\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", "\n", "# Create a Rocket object.\n", "my_rocket = Rocket()\n", "print(my_rocket)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "To actually use a class, you create a variable such as *my\\_rocket*. Then you set that equal to the name of the class, with an empty set of parentheses. Python creates an **object** from the class. An object is a single instance of the Rocket class; it has a copy of each of the class's variables, and it can do any action that is defined for the class. In this case, you can see that the variable my\\_rocket is a Rocket object from the \\_\\_main\\_\\_ program file, which is stored at a particular location in memory." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Once you have a class, you can define an object and use its methods. Here is how you might define a rocket and have it start to move up:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rocket altitude: 0\n", "Rocket altitude: 1\n", "Rocket altitude: 2\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", "\n", "# Create a Rocket object, and have it start to move up.\n", "my_rocket = Rocket()\n", "print(\"Rocket altitude:\", my_rocket.y)\n", "\n", "my_rocket.move_up()\n", "print(\"Rocket altitude:\", my_rocket.y)\n", "\n", "my_rocket.move_up()\n", "print(\"Rocket altitude:\", my_rocket.y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "To access an object's variables or methods, you give the name of the object and then use *dot notation* to access the variables and methods. So to get the y-value of *my\\_rocket*, you use *my\\_rocket.y*. To use the move_up() method on my_rocket, you write *my\\_rocket.move\\_up()*." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Once you have a class defined, you can create as many objects from that class as you want. Each object is its own instance of that class, with its own separate variables. All of the objects are capable of the same behavior, but each object's particular actions do not affect any of the other objects." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Once you have a class, you can define an object and use its methods. Here is how you might define a rocket and have it start to move up:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<__main__.Rocket object at 0x7f6f5073cd10>\n", "<__main__.Rocket object at 0x7f6f5073cc90>\n", "<__main__.Rocket object at 0x7f6f5073cbd0>\n", "<__main__.Rocket object at 0x7f6f5077e410>\n", "<__main__.Rocket object at 0x7f6f5077ead0>\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", " \n", "# Create a fleet of 5 rockets, and store them in a list.\n", "my_rockets = []\n", "for x in range(0,5):\n", " new_rocket = Rocket()\n", " my_rockets.append(new_rocket)\n", "\n", "# Show that each rocket is a separate object.\n", "for rocket in my_rockets:\n", " print(rocket)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can see that each rocket is at a separate place in memory. By the way, if you understand [list comprehensions](03_lists_tuples.html#comprehensions), you can make the fleet of rockets in one line:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<__main__.Rocket object at 0x7f6f50789190>\n", "<__main__.Rocket object at 0x7f6f50763450>\n", "<__main__.Rocket object at 0x7f6f507634d0>\n", "<__main__.Rocket object at 0x7f6f50763510>\n", "<__main__.Rocket object at 0x7f6f50763550>\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", " \n", "# Create a fleet of 5 rockets, and store them in a list.\n", "my_rockets = [Rocket() for x in range(0,5)]\n", "\n", "# Show that each rocket is a separate object.\n", "for rocket in my_rockets:\n", " print(rocket)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can prove that each rocket has its own x and y values by moving just one of the rockets:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rocket altitude: 1\n", "Rocket altitude: 0\n", "Rocket altitude: 0\n", "Rocket altitude: 0\n", "Rocket altitude: 0\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", " \n", "# Create a fleet of 5 rockets, and store them in a list.\n", "my_rockets = [Rocket() for x in range(0,5)]\n", "\n", "# Move the first rocket up.\n", "my_rockets[0].move_up()\n", "\n", "# Show that only the first rocket has moved.\n", "for rocket in my_rockets:\n", " print(\"Rocket altitude:\", rocket.y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The syntax for classes may not be very clear at this point, but consider for a moment how you might create a rocket without using classes. You might store the x and y values in a dictionary, but you would have to write a lot of ugly, hard-to-maintain code to manage even a small set of rockets. As more features become incorporated into the Rocket class, you will see how much more efficiently real-world objects can be modeled with classes than they could be using just lists and dictionaries." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "\n", "#### Rocket With No Class\n", "- Using just what you already know, try to write a program that simulates the [above example](#what) about rockets.\n", " - Store an x and y value for a rocket.\n", " - Store an x and y value for each rocket in a set of 5 rockets. Store these 5 rockets in a list.\n", "- Don't take this exercise too far; it's really just a quick exercise to help you understand how useful the class structure is, especially as you start to see more capability added to the Rocket class." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.0 : Rocket with no Class\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Object-Oriented terminology\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Classes are part of a programming paradigm called **object-oriented programming**. Object-oriented programming, or OOP for short, focuses on building reusable blocks of code called classes. When you want to use a class in one of your programs, you make an **object** from that class, which is where the phrase \"object-oriented\" comes from. Python itself is not tied to object-oriented programming, but you will be using objects in most or all of your Python projects. In order to understand classes, you have to understand some of the language that is used in OOP." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "General terminology\n", "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "A **class** is a body of code that defines the **attributes** and **behaviors** required to accurately model something you need for your program. You can model something from the real world, such as a rocket ship or a guitar string, or you can model something from a virtual world such as a rocket in a game, or a set of physical laws for a game engine." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "An **attribute** is a piece of information. In code, an attribute is just a variable that is part of a class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "A **behavior** is an action that is defined within a class. These are made up of **methods**, which are just functions that are defined for the class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "An **object** is a particular instance of a class. An object has a certain set of values for all of the attributes (variables) in the class. You can have as many objects as you want for any one class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "There is much more to know, but these words will help you get started. They will make more sense as you see more examples, and start to use classes on your own." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "A closer look at the Rocket class\n", "---\n", "Now that you have seen a simple example of a class, and have learned some basic OOP terminology, it will be helpful to take a closer look at the Rocket class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The \\_\\_init()\\_\\_ method\n", "---\n", "Here is the initial code block that defined the Rocket class:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The first line shows how a class is created in Python. The keyword **class** tells Python that you are about to define a class. The rules for naming a class are the same rules you learned about [naming variables](var_string_num.html#naming_rules), but there is a strong convention among Python programmers that classes should be named using CamelCase. If you are unfamiliar with CamelCase, it is a convention where each letter that starts a word is capitalized, with no underscores in the name. The name of the class is followed by a set of parentheses. These parentheses will be empty for now, but later they may contain a class upon which the new class is based." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "It is good practice to write a comment at the beginning of your class, describing the class. There is a [more formal syntax](http://www.python.org/dev/peps/pep-0257/) for documenting your classes, but you can wait a little bit to get that formal. For now, just write a comment at the beginning of your class summarizing what you intend the class to do. Writing more formal documentation for your classes will be easy later if you start by writing simple comments now." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Function names that start and end with two underscores are special built-in functions that Python uses in certain ways. The \\_\\_init()\\_\\_ method is one of these special functions. It is called automatically when you create an object from your class. The \\_\\_init()\\_\\_ method lets you make sure that all relevant attributes are set to their proper values when an object is created from the class, before the object is used. In this case, The \\_\\_init\\_\\_() method initializes the x and y values of the Rocket to 0." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The **self** keyword often takes people a little while to understand. The word \"self\" refers to the current object that you are working with. When you are writing a class, it lets you refer to certain attributes from any other part of the class. Basically, all methods in a class need the *self* object as their first argument, so they can access any attribute that is part of the class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Now let's take a closer look at a **method**." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A simple method\n", "---\n", "Here is the method that was defined for the Rocket class:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A method is just a function that is part of a class. Since it is just a function, you can do anything with a method that you learned about with functions. You can accept [positional](08_more_functions.html#positional_arguments) arguments, [keyword](08_more_functions.html#keyword_arguments) arguments, an arbitrary [list of argument values](08_more_functions.html#arbitrary_sequence), an arbitrary [dictionary of arguments](08_more_functions.html#arbitrary_keyword_arguments), or any combination of these. Your arguments can return a value or a set of values if you want, or they can just do some work without returning any values." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Each method has to accept one argument by default, the value **self**. This is a reference to the particular object that is calling the method. This *self* argument gives you access to the calling object's attributes. In this example, the self argument is used to access a Rocket object's y-value. That value is increased by 1, every time the method move_up() is called by a particular Rocket object. This is probably still somewhat confusing, but it should start to make sense as you work through your own examples." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you take a second look at what happens when a method is called, things might make a little more sense:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rocket altitude: 0\n", "Rocket altitude: 1\n", "Rocket altitude: 2\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", "\n", "# Create a Rocket object, and have it start to move up.\n", "my_rocket = Rocket()\n", "print(\"Rocket altitude:\", my_rocket.y)\n", "\n", "my_rocket.move_up()\n", "print(\"Rocket altitude:\", my_rocket.y)\n", "\n", "my_rocket.move_up()\n", "print(\"Rocket altitude:\", my_rocket.y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "In this example, a Rocket object is created and stored in the variable my_rocket. After this object is created, its y value is printed. The value of the attribute *y* is accessed using dot notation. The phrase *my\\_rocket.y* asks Python to return \"the value of the variable y attached to the object my_rocket\".\n", "\n", "After the object my_rocket is created and its initial y-value is printed, the method move_up() is called. This tells Python to apply the method move_up() to the object my_rocket. Python finds the y-value associated with my_rocket and adds 1 to that value. This process is repeated several times, and you can see from the output that the y-value is in fact increasing." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Making multiple objects from a class\n", "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "One of the goals of object-oriented programming is to create reusable code. Once you have written the code for a class, you can create as many objects from that class as you need. It is worth mentioning at this point that classes are usually saved in a separate file, and then imported into the program you are working on. So you can build a library of classes, and use those classes over and over again in different programs. Once you know a class works well, you can leave it alone and know that the objects you create in a new program are going to work as they always have." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can see this \"code reusability\" already when the Rocket class is used to make more than one Rocket object. Here is the code that made a fleet of Rocket objects:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<__main__.Rocket object at 0x7f6f50763090>\n", "<__main__.Rocket object at 0x7f6f5077ead0>\n", "<__main__.Rocket object at 0x7f6f50763990>\n", "<__main__.Rocket object at 0x7f6f50763a10>\n", "<__main__.Rocket object at 0x7f6f50763a50>\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", " \n", "# Create a fleet of 5 rockets, and store them in a list.\n", "my_rockets = []\n", "for x in range(0,5):\n", " new_rocket = Rocket()\n", " my_rockets.append(new_rocket)\n", "\n", "# Show that each rocket is a separate object.\n", "for rocket in my_rockets:\n", " print(rocket)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you are comfortable using list comprehensions, go ahead and use those as much as you can. I'd rather not assume at this point that everyone is comfortable with comprehensions, so I will use the slightly longer approach of declaring an empty list, and then using a for loop to fill that list. That can be done slightly more efficiently than the previous example, by eliminating the temporary variable *new\\_rocket*:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<__main__.Rocket object at 0x7f6f50763990>\n", "<__main__.Rocket object at 0x7f6f50763a10>\n", "<__main__.Rocket object at 0x7f6f50763750>\n", "<__main__.Rocket object at 0x7f6f506fd8d0>\n", "<__main__.Rocket object at 0x7f6f506fd6d0>\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", " \n", "# Create a fleet of 5 rockets, and store them in a list.\n", "my_rockets = []\n", "for x in range(0,5):\n", " my_rockets.append(Rocket())\n", "\n", "# Show that each rocket is a separate object.\n", "for rocket in my_rockets:\n", " print(rocket)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "What exactly happens in this for loop? The line *my\\_rockets.append(Rocket())* is executed 5 times. Each time, a new Rocket object is created and then added to the list my\\_rockets. The \\_\\_init\\_\\_() method is executed once for each of these objects, so each object gets its own x and y value. When a method is called on one of these objects, the *self* variable allows access to just that object's attributes, and ensures that modifying one object does not affect any of the other objecs that have been created from the class.\n", "\n", "Each of these objects can be worked with individually. At this point we are ready to move on and see how to add more functionality to the Rocket class. We will work slowly, and give you the chance to start writing your own simple classes." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A quick check-in\n", "---\n", "If all of this makes sense, then the rest of your work with classes will involve learning a lot of details about how classes can be used in more flexible and powerful ways. If this does not make any sense, you could try a few different things:\n", "\n", "- Reread the previous sections, and see if things start to make any more sense.\n", "- Type out these examples in your own editor, and run them. Try making some changes, and see what happens.\n", "- Try the next exercise, and see if it helps solidify some of the concepts you have been reading about.\n", "- Read on. The next sections are going to add more functionality to the Rocket class. These steps will involve rehashing some of what has already been covered, in a slightly different way.\n", "\n", "Classes are a huge topic, and once you understand them you will probably use them for the rest of your life as a programmer. If you are brand new to this, be patient and trust that things will start to sink in." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Your Own Rocket\n", "- Without looking back at the previous examples, try to recreate the [Rocket class](#multiple_objects) as it has been shown so far.\n", " - Define the Rocket() class.\n", " - Define the \\_\\_init\\_\\_() method, which sets an x and a y value for each Rocket object.\n", " - Define the move_up() method.\n", " - Create a Rocket object.\n", " - Print the object.\n", " - Print the object's y-value.\n", " - Move the rocket up, and print its y-value again.\n", " - Create a fleet of rockets, and prove that they are indeed separate Rocket objects." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.1 : Your Own Rocket\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Refining the Rocket class\n", "===\n", "The Rocket class so far is very simple. It can be made a little more interesting with some refinements to the \\_\\_init\\_\\_() method, and by the addition of some methods." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Accepting paremeters for the \\_\\_init\\_\\_() method\n", "---\n", "The \\_\\_init\\_\\_() method is run automatically one time when you create a new object from a class. The \\_\\_init\\_\\_() method for the Rocket class so far is pretty simple:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self):\n", " # Each rocket has an (x,y) position.\n", " self.x = 0\n", " self.y = 0\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "All the \\_\\_init\\_\\_() method does so far is set the x and y values for the rocket to 0. We can easily add a couple keyword arguments so that new rockets can be initialized at any position:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now when you create a new Rocket object you have the choice of passing in arbitrary initial values for x and y:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rocket 0 is at (0, 0).\n", "Rocket 1 is at (0, 10).\n", "Rocket 2 is at (100, 0).\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_up(self):\n", " # Increment the y-position of the rocket.\n", " self.y += 1\n", " \n", "# Make a series of rockets at different starting places.\n", "rockets = []\n", "rockets.append(Rocket())\n", "rockets.append(Rocket(0,10))\n", "rockets.append(Rocket(100,0))\n", "\n", "# Show where each rocket is.\n", "for index, rocket in enumerate(rockets):\n", " print(\"Rocket %d is at (%d, %d).\" % (index, rocket.x, rocket.y))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Accepting paremeters in a method\n", "---\n", "The \\_\\_init\\_\\_ method is just a special method that serves a particular purpose, which is to help create new objects from a class. Any method in a class can accept parameters of any kind. With this in mind, the move_up() method can be made much more flexible. By accepting keyword arguments, the move_up() method can be rewritten as a more general move_rocket() method." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This new method will allow the rocket to be moved any amount, in any direction:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_rocket(self, x_increment=0, y_increment=1):\n", " # Move the rocket according to the paremeters given.\n", " # Default behavior is to move the rocket up one unit.\n", " self.x += x_increment\n", " self.y += y_increment" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The paremeters for the move() method are named x_increment and y_increment rather than x and y. It's good to emphasize that these are changes in the x and y position, not new values for the actual position of the rocket. By carefully choosing the right default values, we can define a meaningful default behavior. If someone calls the method move_rocket() with no parameters, the rocket will simply move up one unit in the y-direciton. Note that this method can be given negative values to move the rocket left or right:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rocket 0 is at (0, 1).\n", "Rocket 1 is at (10, 10).\n", "Rocket 2 is at (-10, 0).\n" ] } ], "source": [ "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_rocket(self, x_increment=0, y_increment=1):\n", " # Move the rocket according to the paremeters given.\n", " # Default behavior is to move the rocket up one unit.\n", " self.x += x_increment\n", " self.y += y_increment\n", " \n", "# Create three rockets.\n", "rockets = [Rocket() for x in range(0,3)]\n", "\n", "# Move each rocket a different amount.\n", "rockets[0].move_rocket()\n", "rockets[1].move_rocket(10,10)\n", "rockets[2].move_rocket(-10,0)\n", " \n", "# Show where each rocket is.\n", "for index, rocket in enumerate(rockets):\n", " print(\"Rocket %d is at (%d, %d).\" % (index, rocket.x, rocket.y))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Adding a new method\n", "---\n", "One of the strengths of object-oriented programming is the ability to closely model real-world phenomena by adding appropriate attributes and behaviors to classes. One of the jobs of a team piloting a rocket is to make sure the rocket does not get too close to any other rockets. Let's add a method that will report the distance from one rocket to any other rocket.\n", "\n", "If you are not familiar with distance calculations, there is a fairly simple formula to tell the distance between two points if you know the x and y values of each point." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This new method performs that calculation, and then returns the resulting distance." ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The rockets are 11.180340 units apart.\n" ] } ], "source": [ "from math import sqrt\n", "\n", "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_rocket(self, x_increment=0, y_increment=1):\n", " # Move the rocket according to the paremeters given.\n", " # Default behavior is to move the rocket up one unit.\n", " self.x += x_increment\n", " self.y += y_increment\n", " \n", " def get_distance(self, other_rocket):\n", " # Calculates the distance from this rocket to another rocket,\n", " # and returns that value.\n", " distance = sqrt((self.x-other_rocket.x)**2+(self.y-other_rocket.y)**2)\n", " return distance\n", " \n", "# Make two rockets, at different places.\n", "rocket_0 = Rocket()\n", "rocket_1 = Rocket(10,5)\n", "\n", "# Show the distance between them.\n", "distance = rocket_0.get_distance(rocket_1)\n", "print(\"The rockets are %f units apart.\" % distance)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Hopefully these short refinements show that you can extend a class' attributes and behavior to model the phenomena you are interested in as closely as you want. The rocket could have a name, a crew capacity, a payload, a certain amount of fuel, and any number of other attributes. You could define any behavior you want for the rocket, including interactions with other rockets and launch facilities, gravitational fields, and whatever you need it to! There are techniques for managing these more complex interactions, but what you have just seen is the core of object-oriented programming.\n", "\n", "At this point you should try your hand at writing some classes of your own. After trying some exercises, we will look at object inheritance, and then you will be ready to move on for now." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Your Own Rocket 2\n", "- There are enough new concepts here that you might want to try re-creating the [Rocket class](#adding_method) as it has been developed so far, looking at the examples as little as possible. Once you have your own version, regardless of how much you needed to look at the example, you can modify the class and explore the possibilities of what you have already learned.\n", " - Re-create the Rocket class as it has been developed so far:\n", " - Define the Rocket() class.\n", " - Define the \\_\\_init\\_\\_() method. Let your \\_\\_init\\_\\_() method accept x and y values for the initial position of the rocket. Make sure the default behavior is to position the rocket at (0,0).\n", " - Define the move_rocket() method. The method should accept an amount to move left or right, and an amount to move up or down.\n", " - Create a Rocket object. Move the rocket around, printing its position after each move.\n", " - Create a small fleet of rockets. Move several of them around, and print their final positions to prove that each rocket can move independently of the other rockets.\n", " - Define the get_distance() method. The method should accept a Rocket object, and calculate the distance between the current rocket and the rocket that is passed into the method.\n", " - Use the get_distance() method to print the distances between several of the rockets in your fleet.\n", "\n", "#### Rocket Attributes\n", "- Start with a copy of the Rocket class, either one you made from a previous exercise or the latest version from the [last section](#adding_method).\n", "- Add several of your own attributes to the \\_\\_init\\_\\_() function. The values of your attributes can be set automatically by the \\_\\_init\\_\\_ function, or they can be set by paremeters passed into \\_\\_init\\_\\_().\n", "- Create a rocket and print the values for the attributes you have created, to show they have been set correctly.\n", "- Create a small fleet of rockets, and set different values for one of the attributes you have created. Print the values of these attributes for each rocket in your fleet, to show that they have been set properly for each rocket.\n", "- If you are not sure what kind of attributes to add, you could consider storing the height of the rocket, the crew size, the name of the rocket, the speed of the rocket, or many other possible characteristics of a rocket.\n", "\n", "#### Rocket Methods\n", "- Start with a copy of the Rocket class, either one you made from a previous exercise or the latest version from the [last section](#adding_method).\n", "- Add a new method to the class. This is probably a little more challenging than adding attributes, but give it a try.\n", " - Think of what rockets do, and make a very simple version of that behavior using print statements. For example, rockets lift off when they are launched. You could make a method called *launch()*, and all it would do is print a statement such as \"The rocket has lifted off!\" If your rocket has a name, this sentence could be more descriptive.\n", " - You could make a very simple *land_rocket()* method that simply sets the x and y values of the rocket back to 0. Print the position before and after calling the *land_rocket()* method to make sure your method is doing what it's supposed to.\n", " - If you enjoy working with math, you could implement a *safety_check()* method. This method would take in another rocket object, and call the get_distance() method on that rocket. Then it would check if that rocket is too close, and print a warning message if the rocket is too close. If there is zero distance between the two rockets, your method could print a message such as, \"The rockets have crashed!\" (Be careful; getting a zero distance could mean that you accidentally found the distance between a rocket and itself, rather than a second rocket.)\n", " \n", "#### Person Class\n", "- Modeling a person is a classic exercise for people who are trying to learn how to write classes. We are all familiar with characteristics and behaviors of people, so it is a good exercise to try.\n", " - Define a Person() class.\n", " - In the \\_\\_init()\\_\\_ function, define several attributes of a person. Good attributes to consider are name, age, place of birth, and anything else you like to know about the people in your life.\n", " - Write one method. This could be as simple as *introduce_yourself()*. This method would print out a statement such as, \"Hello, my name is Eric.\"\n", " - You could also make a method such as *age_person()*. A simple version of this method would just add 1 to the person's age.\n", " - A more complicated version of this method would involve storing the person's birthdate rather than their age, and then calculating the age whenever the age is requested. But dealing with dates and times is not particularly easy if you've never done it in any other programming language before.\n", " - Create a person, set the attribute values appropriately, and print out information about the person.\n", " - Call your method on the person you created. Make sure your method executed properly; if the method does not print anything out directly, print something before and after calling the method to make sure it did what it was supposed to.\n", " \n", "#### Car Class\n", "- Modeling a car is another classic exercise.\n", " - Define a Car() class.\n", " - In the \\_\\_init\\_\\_() function, define several attributes of a car. Some good attributes to consider are make (Subaru, Audi, Volvo...), model (Outback, allroad, C30), year, num_doors, owner, or any other aspect of a car you care to include in your class.\n", " - Write one method. This could be something such as *describe_car()*. This method could print a series of statements that describe the car, using the information that is stored in the attributes. You could also write a method that adjusts the mileage of the car or tracks its position.\n", " - Create a car object, and use your method.\n", " - Create several car objects with different values for the attributes. Use your method on several of your cars." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.2 : Your Own Rocket 2\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.3 : Rocket Attributes\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.4 : Rocket Methods\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.5 : Person Class\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.6 : Car Class\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Inheritance\n", "===" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "One of the most important goals of the object-oriented approach to programming is the creation of stable, reliable, reusable code. If you had to create a new class for every kind of object you wanted to model, you would hardly have any reusable code. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In Python and any other language that supports OOP, one class can **inherit** from another class. This means you can base a new class on an existing class; the new class *inherits* all of the attributes and behavior of the class it is based on. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "A new class can override any undesirable attributes or behavior of the class it inherits from, and it can add any new attributes or behavior that are appropriate. The original class is called the **parent** class, and the new class is a **child** of the parent class. The parent class is also called a **superclass**, and the child class is also called a **subclass**." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The child class inherits all attributes and behavior from the parent class, but any attributes that are defined in the child class are not available to the parent class. This may be obvious to many people, but it is worth stating. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This also means a child class can override behavior of the parent class. If a child class defines a method that also appears in the parent class, objects of the child class will use the new method rather than the parent class method.\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "To better understand inheritance, let's look at an example of a class that can be based on the Rocket class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The SpaceShuttle class\n", "---\n", "If you wanted to model a space shuttle, you could write an entirely new class. But a space shuttle is just a special kind of rocket. Instead of writing an entirely new class, you can inherit all of the attributes and behavior of a Rocket, and then add a few appropriate attributes and behavior for a Shuttle.\n", "\n", "One of the most significant characteristics of a space shuttle is that it can be reused. So the only difference we will add at this point is to record the number of flights the shutttle has completed. Everything else you need to know about a shuttle has already been coded into the Rocket class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Here is what the Shuttle class looks like:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<__main__.Shuttle object at 0x7f1e62ba6cd0>\n" ] } ], "source": [ "from math import sqrt\n", "\n", "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_rocket(self, x_increment=0, y_increment=1):\n", " # Move the rocket according to the paremeters given.\n", " # Default behavior is to move the rocket up one unit.\n", " self.x += x_increment\n", " self.y += y_increment\n", " \n", " def get_distance(self, other_rocket):\n", " # Calculates the distance from this rocket to another rocket,\n", " # and returns that value.\n", " distance = sqrt((self.x-other_rocket.x)**2+(self.y-other_rocket.y)**2)\n", " return distance\n", " \n", "class Shuttle(Rocket):\n", " # Shuttle simulates a space shuttle, which is really\n", " # just a reusable rocket.\n", " \n", " def __init__(self, x=0, y=0, flights_completed=0):\n", " super().__init__(x, y)\n", " self.flights_completed = flights_completed\n", " \n", "shuttle = Shuttle(10,0,3)\n", "print(shuttle)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "When a new class is based on an existing class, you write the name of the parent class in parentheses when you define the new class:\n", "\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class NewClass(ParentClass):" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The \\_\\_init\\_\\_() function of the new class needs to call the \\_\\_init\\_\\_() function of the parent class. The \\_\\_init\\_\\_() function of the new class needs to accept all of the parameters required to build an object from the parent class, and these parameters need to be passed to the \\_\\_init\\_\\_() function of the parent class. The *super().\\_\\_init\\_\\_()* function takes care of this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class NewClass(ParentClass):\n", " \n", " def __init__(self, arguments_new_class, arguments_parent_class):\n", " super().__init__(arguments_parent_class)\n", " # Code for initializing an object of the new class." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The *super()* function passes the *self* argument to the parent class automatically. You could also do this by explicitly naming the parent class when you call the \\_\\_init\\_\\_() function, but you then have to include the *self* argument manually:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class Shuttle(Rocket):\n", " # Shuttle simulates a space shuttle, which is really\n", " # just a reusable rocket.\n", " \n", " def __init__(self, x=0, y=0, flights_completed=0):\n", " Rocket.__init__(self, x, y)\n", " self.flights_completed = flights_completed" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This might seem a little easier to read, but it is preferable to use the *super()* syntax. When you use *super()*, you don't need to explicitly name the parent class, so your code is more resilient to later changes. As you learn more about classes, you will be able to write child classes that inherit from multiple parent classes, and the *super()* function will call the parent classes' \\_\\_init\\_\\_() functions for you, in one line. This explicit approach to calling the parent class' \\_\\_init\\_\\_() function is included so that you will be less confused if you see it in someone else's code." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The output above shows that a new Shuttle object was created. This new Shuttle object can store the number of flights completed, but it also has all of the functionality of the Rocket class: it has a position that can be changed, and it can calculate the distance between itself and other rockets or shuttles. This can be demonstrated by creating several rockets and shuttles, and then finding the distance between one shuttle and all the other shuttles and rockets." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This example uses a simple function called [randint](https://docs.python.org/3/library/random.html#random.randint), which generates a random integer between a lower and upper bound, to determine the position of each rocket and shuttle:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from math import sqrt\n", "from random import randint\n", "\n", "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_rocket(self, x_increment=0, y_increment=1):\n", " # Move the rocket according to the paremeters given.\n", " # Default behavior is to move the rocket up one unit.\n", " self.x += x_increment\n", " self.y += y_increment\n", " \n", " def get_distance(self, other_rocket):\n", " # Calculates the distance from this rocket to another rocket,\n", " # and returns that value.\n", " distance = sqrt((self.x-other_rocket.x)**2+(self.y-other_rocket.y)**2)\n", " return distance" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "class Shuttle(Rocket):\n", " # Shuttle simulates a space shuttle, which is really\n", " # just a reusable rocket.\n", " \n", " def __init__(self, x=0, y=0, flights_completed=0):\n", " super().__init__(x, y)\n", " self.flights_completed = flights_completed" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Create several shuttles and rockets, with random positions.\n", "# Shuttles have a random number of flights completed.\n", "shuttles = []\n", "for x in range(0,3):\n", " x = randint(0,100)\n", " y = randint(1,100)\n", " flights_completed = randint(0,10)\n", " shuttles.append(Shuttle(x, y, flights_completed))\n", "\n", "rockets = []\n", "for x in range(0,3):\n", " x = randint(0,100)\n", " y = randint(1,100)\n", " rockets.append(Rocket(x, y))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shuttle 0 has completed 8 flights.\n", "Shuttle 1 has completed 6 flights.\n", "Shuttle 2 has completed 9 flights.\n", "\n", "\n", "The first shuttle is 0.000000 units away from shuttle 0.\n", "The first shuttle is 40.199502 units away from shuttle 1.\n", "The first shuttle is 30.886890 units away from shuttle 2.\n" ] } ], "source": [ "# Show the number of flights completed for each shuttle.\n", "for index, shuttle in enumerate(shuttles):\n", " print(\"Shuttle %d has completed %d flights.\" % (index, shuttle.flights_completed))\n", " \n", "print(\"\\n\") \n", "# Show the distance from the first shuttle to all other shuttles.\n", "first_shuttle = shuttles[0]\n", "for index, shuttle in enumerate(shuttles):\n", " distance = first_shuttle.get_distance(shuttle)\n", " print(\"The first shuttle is %f units away from shuttle %d.\" % (distance, index))\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "The first shuttle is 40.311289 units away from rocket 0.\n", "The first shuttle is 15.556349 units away from rocket 1.\n", "The first shuttle is 76.694198 units away from rocket 2.\n" ] } ], "source": [ "print(\"\\n\")\n", "# Show the distance from the first shuttle to all other rockets.\n", "for index, rocket in enumerate(rockets):\n", " distance = first_shuttle.get_distance(rocket)\n", " print(\"The first shuttle is %f units away from rocket %d.\" % (distance, index))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Inheritance is a powerful feature of object-oriented programming. Using just what you have seen so far about classes, you can model an incredible variety of real-world and virtual phenomena with a high degree of accuracy. The code you write has the potential to be stable and reusable in a variety of applications." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Student Class\n", "- Start with your program from [Person Class](#exercise_person_class).\n", "- Make a new class called Student that inherits from Person.\n", "- Define some attributes that a student has, which other people don't have.\n", " - A student has a school they are associated with, a graduation year, a gpa, and other particular attributes.\n", "- Create a Student object, and prove that you have used inheritance correctly.\n", " - Set some attribute values for the student, that are only coded in the Person class.\n", " - Set some attribute values for the student, that are only coded in the Student class.\n", " - Print the values for all of these attributes.\n", "\n", "#### Refining Shuttle\n", "- Take the latest version of the [Shuttle class](#shuttle). Extend it.\n", " - Add more attributes that are particular to shuttles such as maximum number of flights, capability of supporting spacewalks, and capability of docking with the ISS.\n", " - Add one more method to the class, that relates to shuttle behavior. This method could simply print a statement, such as \"Docking with the ISS,\" for a dock_ISS() method.\n", " - Prove that your refinements work by creating a Shuttle object with these attributes, and then call your new method." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.7 : Student Class\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.8 : Refining Shuttle\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Modules and classes\n", "===\n", "Now that you are starting to work with classes, your files are going to grow longer. This is good, because it means your programs are probably doing more interesting things. But it is bad, because longer files can be more difficult to work with. Python allows you to save your classes in another file and then import them into the program you are working on. This has the added advantage of isolating your classes into files that can be used in any number of different programs. As you use your classes repeatedly, the classes become more reliable and complete overall." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Storing a single class in a module\n", "---\n", "\n", "When you save a class into a separate file, that file is called a **module**. You can have any number of classes in a single module. There are a number of ways you can then import the class you are interested in.\n", "\n", "Start out by saving just the Rocket class into a file called *rocket.py*. Notice the naming convention being used here: the module is saved with a lowercase name, and the class starts with an uppercase letter." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This convention is pretty important for a number of reasons, and it is a really good idea to follow the convention." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Save as rocket.py\n", "from math import sqrt\n", "\n", "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_rocket(self, x_increment=0, y_increment=1):\n", " # Move the rocket according to the paremeters given.\n", " # Default behavior is to move the rocket up one unit.\n", " self.x += x_increment\n", " self.y += y_increment\n", " \n", " def get_distance(self, other_rocket):\n", " # Calculates the distance from this rocket to another rocket,\n", " # and returns that value.\n", " distance = sqrt((self.x-other_rocket.x)**2+(self.y-other_rocket.y)**2)\n", " return distance" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Make a separate file called *rocket_game.py*. If you are more interested in science than games, feel free to call this file something like *rocket_simulation.py*. Again, to use standard naming conventions, make sure you are using a lowercase_underscore name for this file." ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The rocket is at (0, 0).\n" ] } ], "source": [ "# Save as rocket_game.py\n", "from rocket import Rocket\n", "\n", "rocket = Rocket()\n", "print(\"The rocket is at (%d, %d).\" % (rocket.x, rocket.y))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is a really clean and uncluttered file. A rocket is now something you can define in your programs, without the details of the rocket's implementation cluttering up your file. You don't have to include all the class code for a rocket in each of your files that deals with rockets; the code defining rocket attributes and behavior lives in one file, and can be used anywhere." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The first line tells Python to look for a file called *rocket.py*. It looks for that file in the same directory as your current program. You can put your classes in other directories, but we will get to that convention a bit later. Notice that you do not." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "When Python finds the file *rocket.py*, it looks for a class called *Rocket*. When it finds that class, it imports that code into the current file, without you ever seeing that code. You are then free to use the class Rocket as you have seen it used in previous examples." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Storing multiple classes in a module\n", "---\n", "\n", "A module is simply a file that contains one or more classes or functions, so the Shuttle class actually belongs in the rocket module as well:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# Save as rocket.py\n", "from math import sqrt\n", "\n", "class Rocket():\n", " # Rocket simulates a rocket ship for a game,\n", " # or a physics simulation.\n", " \n", " def __init__(self, x=0, y=0):\n", " # Each rocket has an (x,y) position.\n", " self.x = x\n", " self.y = y\n", " \n", " def move_rocket(self, x_increment=0, y_increment=1):\n", " # Move the rocket according to the paremeters given.\n", " # Default behavior is to move the rocket up one unit.\n", " self.x += x_increment\n", " self.y += y_increment\n", " \n", " def get_distance(self, other_rocket):\n", " # Calculates the distance from this rocket to another rocket,\n", " # and returns that value.\n", " distance = sqrt((self.x-other_rocket.x)**2+(self.y-other_rocket.y)**2)\n", " return distance\n", " \n", "\n", "class Shuttle(Rocket):\n", " # Shuttle simulates a space shuttle, which is really\n", " # just a reusable rocket.\n", " \n", " def __init__(self, x=0, y=0, flights_completed=0):\n", " super().__init__(x, y)\n", " self.flights_completed = flights_completed" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now you can import the Rocket and the Shuttle class, and use them both in a clean uncluttered program file:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The rocket is at (0, 0).\n", "\n", "The shuttle is at (0, 0).\n", "The shuttle has completed 0 flights.\n" ] } ], "source": [ "# Save as rocket_game.py\n", "from rocket import Rocket, Shuttle\n", "\n", "rocket = Rocket()\n", "print(\"The rocket is at (%d, %d).\" % (rocket.x, rocket.y))\n", "\n", "shuttle = Shuttle()\n", "print(\"\\nThe shuttle is at (%d, %d).\" % (shuttle.x, shuttle.y))\n", "print(\"The shuttle has completed %d flights.\" % shuttle.flights_completed)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The first line tells Python to import both the *Rocket* and the *Shuttle* classes from the *rocket* module. You don't have to import every class in a module; you can pick and choose the classes you care to use, and Python will only spend time processing those particular classes." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A number of ways to import modules and classes\n", "---\n", "There are several ways to import modules and classes, and each has its own merits." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### import *module_name*\n", "\n", "The syntax for importing classes that was just shown:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from module_name import ClassName" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "is straightforward, and is used quite commonly. It allows you to use the class names directly in your program, so you have very clean and readable code. This can be a problem, however, if the names of the classes you are importing conflict with names that have already been used in the program you are working on. This is unlikely to happen in the short programs you have been seeing here, but if you were working on a larger program it is quite possible that the class you want to import from someone else's work would happen to have a name you have already used in your program." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "In this case, you can use simply import the module itself:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The rocket is at (0, 0).\n", "\n", "The shuttle is at (0, 0).\n", "The shuttle has completed 0 flights.\n" ] } ], "source": [ "# Save as rocket_game.py\n", "import rocket\n", "\n", "rocket_0 = rocket.Rocket()\n", "print(\"The rocket is at (%d, %d).\" % (rocket_0.x, rocket_0.y))\n", "\n", "shuttle_0 = rocket.Shuttle()\n", "print(\"\\nThe shuttle is at (%d, %d).\" % (shuttle_0.x, shuttle_0.y))\n", "print(\"The shuttle has completed %d flights.\" % shuttle_0.flights_completed)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The general syntax for this kind of import is:\n", "\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import module_name" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "After this, classes are accessed using dot notation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "module_name.ClassName" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This prevents some name conflicts. If you were reading carefully however, you might have noticed that the variable name *rocket* in the previous example had to be changed because it has the same name as the module itself. This is not good, because in a longer program that could mean a lot of renaming." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### import *module_name* as *local_module_name*\n", "\n", "There is another syntax for imports that is quite useful:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import module_name as local_module_name" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "When you are importing a module into one of your projects, you are free to choose any name you want for the module in your project. So the last example could be rewritten in a way that the variable name *rocket* would not need to be changed:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The rocket is at (0, 0).\n", "\n", "The shuttle is at (0, 0).\n", "The shuttle has completed 0 flights.\n" ] } ], "source": [ "# Save as rocket_game.py\n", "import rocket as rocket_module\n", "\n", "rocket = rocket_module.Rocket()\n", "print(\"The rocket is at (%d, %d).\" % (rocket.x, rocket.y))\n", "\n", "shuttle = rocket_module.Shuttle()\n", "print(\"\\nThe shuttle is at (%d, %d).\" % (shuttle.x, shuttle.y))\n", "print(\"The shuttle has completed %d flights.\" % shuttle.flights_completed)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This approach is often used to shorten the name of the module, so you don't have to type a long module name before each class name that you want to use. But it is easy to shorten a name so much that you force people reading your code to scroll to the top of your file and see what the shortened name stands for. In this example," ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import rocket as rocket_module" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "leads to much more readable code than something like:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import rocket as r" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### from *module_name* import *\n", "There is one more import syntax that you should be aware of, but you should probably avoid using. This syntax imports all of the available classes and functions in a module:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from module_name import *" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is not recommended, for a couple reasons. First of all, you may have no idea what all the names of the classes and functions in a module are. If you accidentally give one of your variables the same name as a name from the module, you will have naming conflicts. Also, you may be importing way more code into your program than you need.\n", "\n", "If you really need all the functions and classes from a module, just import the module and use the `module_name.ClassName` syntax in your program." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "You will get a sense of how to write your imports as you read more Python code, and as you write and share some of your own code." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A module of functions\n", "---\n", "You can use modules to store a set of functions you want available in different programs as well, even if those functions are not attached to any one class. To do this, you save the functions into a file, and then import that file just as you saw in the last section. Here is a really simple example; save this is *multiplying.py*:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Save as multiplying.py\n", "def double(x):\n", " return 2*x\n", "\n", "def triple(x):\n", " return 3*x\n", "\n", "def quadruple(x):\n", " return 4*x" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now you can import the file *multiplying.py*, and use these functions. Using the `from module_name import function_name` syntax:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n", "15\n", "20\n" ] } ], "source": [ "from multiplying import double, triple, quadruple\n", "\n", "print(double(5))\n", "print(triple(5))\n", "print(quadruple(5))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Using the `import module_name` syntax:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n", "15\n", "20\n" ] } ], "source": [ "import multiplying\n", "\n", "print(multiplying.double(5))\n", "print(multiplying.triple(5))\n", "print(multiplying.quadruple(5))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Using the `import module_name as local_module_name` syntax:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n", "15\n", "20\n" ] } ], "source": [ "import multiplying as m\n", "\n", "print(m.double(5))\n", "print(m.triple(5))\n", "print(m.quadruple(5))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Using the `from module_name import *` syntax:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n", "15\n", "20\n" ] } ], "source": [ "from multiplying import *\n", "\n", "print(double(5))\n", "print(triple(5))\n", "print(quadruple(5))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Exercises\n", "---\n", "#### Importing Student\n", "- Take your program from [Student Class](#exercise_student_class)\n", " - Save your Person and Student classes in a separate file called *person.py*.\n", " - Save the code that uses these classes in four separate files.\n", " - In the first file, use the `from module_name import ClassName` syntax to make your program run.\n", " - In the second file, use the `import module_name` syntax.\n", " - In the third file, use the `import module_name as different_local_module_name` syntax.\n", " - In the fourth file, use the `import *` syntax.\n", " \n", "#### Importing Car\n", "- Take your program from [Car Class](#exercise_car_class)\n", " - Save your Car class in a separate file called *car.py*.\n", " - Save the code that uses the car class into four separate files.\n", " - In the first file, use the `from module_name import ClassName` syntax to make your program run.\n", " - In the second file, use the `import module_name` syntax.\n", " - In the third file, use the `import module_name as different_local_module_name` syntax.\n", " - In the fourth file, use the `import *` syntax." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.9 : Importing Student\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 9.10 : Importing Car\n", "\n", "# put your code here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "[top](#top)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Method Resolution Order (`mro`)\n", "---" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MRO: [, , , , ]\n", "c.a: A\n", "c.b: B\n", "Greetings from Type: \n", "Greetings from Type: \n", "Greetings from Type: \n" ] } ], "source": [ "class A:\n", " def __init__(self, a):\n", " self.a = a\n", " \n", "\n", "class GreatB:\n", " \n", " def greetings(self):\n", " print('Greetings from Type: ', self.__class__)\n", " \n", "class B(GreatB):\n", " def __init__(self, b):\n", " self.b = b\n", " \n", " \n", "class C(A,B):\n", " def __init__(self, a, b):\n", " A.__init__(self, a)\n", " B.__init__(self, b)\n", " \n", "print('MRO: ', C.mro()) \n", "c = C('A', 'B')\n", "print('c.a: ', c.a)\n", "print('c.b: ', c.b)\n", "\n", "c.greetings()\n", "super(C, c).greetings()\n", "super(B, c).greetings()\n", "\n" ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 09 Exceptions.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Exceptions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exceptions which are events that can modify the *flow* of control through a program. \n", "\n", "In Python, exceptions are triggered automatically on errors, and they can be triggered and intercepted by your code.\n", "\n", "They are processed by **four** statements we’ll study in this notebook, the first of which has two variations (listed separately here) and the last of which was an optional extension until Python 2.6 and 3.0:\n", "\n", "* `try/except`:\n", " * Catch and recover from exceptions raised by Python, or by you\n", " \n", "* `try/finally`:\n", " * Perform cleanup actions, whether exceptions occur or not.\n", "\n", "* `raise`:\n", " * Trigger an exception manually in your code.\n", " \n", "* `assert`:\n", " * Conditionally trigger an exception in your code.\n", " \n", "* `with/as`:\n", " * Implement context managers in Python 2.6, 3.0, and later (optional in 2.5)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `try/except` Statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", "try:\n", " statements # Run this main action first\n", "except name1: \n", " # Run if name1 is raised during try block\n", " statements\n", "except (name2, name3): \n", " # Run if any of these exceptions occur\n", " statements \n", "except name4 as var: \n", " # Run if name4 is raised, assign instance raised to var \n", " statements\n", "except: # Run for all other exceptions raised\n", " statements\n", "else:\n", " statements # Run if no exception was raised during try block\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]\n" ] } ], "source": [ "list_of_numbers = [number for number in range(1, 100)]\n", "print(list_of_numbers)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Getting number at position 1 : 1\n", "Cleaning UP\n" ] } ], "source": [ "dictionary_of_numbers = {}\n", "for number in list_of_numbers:\n", " dictionary_of_numbers[number**2] = number\n", " \n", "try:\n", " index = list_of_numbers.index(2)\n", " value = dictionary_of_numbers[index]\n", "except (ValueError, KeyError):\n", " print('Error Raised, but Controlled! ')\n", "else: \n", " # This executes ONLY if no exception is raised\n", " print('Getting number at position %d : %d' % (index, value))\n", "finally:\n", " # Do cleanup operations\n", " print('Cleaning UP')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `try/finally` Statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The other flavor of the try statement is a specialization that has to do with finalization (a.k.a. termination) actions. If a finally clause is included in a try, Python will always run its block of statements “on the way out” of the try statement, whether an exception occurred while the try block was running or not. \n", "\n", "In it's general form, it is:\n", "\n", "```\n", "try:\n", " statements # Run this action first \n", "finally:\n", " statements # Always run this code on the way out\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `with/as` Context Managers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python 2.6 and 3.0 introduced a new exception-related statement—the with, and its optional as clause. This statement is designed to work with context manager objects, which support a new method-based protocol, similar in spirit to the way that iteration tools work with methods of the iteration protocol. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Context Manager Intro" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Basic Usage:\n", "\n", "```\n", "with expression [as variable]: \n", " with-block\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Classical Usage\n", "\n", "```python\n", "\n", "with open(r'C:\\misc\\data') as myfile: \n", " for line in myfile:\n", " print(line)\n", " # ...more code here...\n", "```\n", "\n", "... even using multiple context managers:\n", "\n", "```python\n", "with open('script1.py') as f1, open('script2.py') as f2: \n", " for (linenum, (line1, line2)) in enumerate(zip(f1, f2)):\n", " if line1 != line2:\n", " print('%s\\n%r\\n%r' % (linenum, line1, line2))\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### How it works\n", "\n", "1. The expression is evaluated,resulting in an object known as a **context manager** that must have `__enter__` and `__exit__` methods\n", "\n", "2. The context manager’s `__enter__` method is called. The value it returns is assigned to the variable in the as clause if present, or simply discarded otherwise\n", "\n", "3. The code in the nested with block is executed.\n", "\n", "4. If the with block raises an exception, the `__exit__(type,value,traceback)` method is called with the exception details. These are the same three values returned by `sys.exc_info` (Python function). If this method returns a `false` value, the exception is **re-raised**; otherwise, the exception is terminated. The exception should normally be reraised so that it is propagated outside the with statement.\n", "\n", "5. If the with block does not raise an exception, the `__exit__` method is still called, but its type, value, and traceback arguments are all passed in as `None`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Usage with Exceptions" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class TraceBlock:\n", " def message(self, arg):\n", " print('running ' + arg) \n", " \n", " def __enter__(self):\n", " print('starting with block')\n", " return self\n", " \n", " def __exit__(self, exc_type, exc_value, exc_tb):\n", " if exc_type is None: \n", " print('exited normally\\n')\n", " else:\n", " print('raise an exception! ' + str(exc_type)) \n", " return False # Propagate" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "starting with block\n", "running test 1\n", "reached\n", "exited normally\n", "\n" ] } ], "source": [ "with TraceBlock() as action: \n", " action.message('test 1')\n", " print('reached')" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "starting with block\n", "running test 2\n", "raise an exception! \n" ] }, { "ename": "TypeError", "evalue": "", "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[0;32mwith\u001b[0m \u001b[0mTraceBlock\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0maction\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0maction\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmessage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'test 2'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\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[0;34m'not reached'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: " ] } ], "source": [ "with TraceBlock() as action: \n", " action.message('test 2') \n", " raise TypeError()\n", " print('not reached')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## User Defined Exceptions" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class AlreadyGotOne(Exception): \n", " pass\n", "\n", "def gail():\n", " raise AlreadyGotOne()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "got exception\n" ] } ], "source": [ "try:\n", " gail()\n", "except AlreadyGotOne:\n", " print('got exception')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "ename": "Career", "evalue": "So I became a waiter of Engineer", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mCareer\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 8\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34m'So I became a waiter of {}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_job\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mCareer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Engineer'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mCareer\u001b[0m: So I became a waiter of Engineer" ] } ], "source": [ "class Career(Exception):\n", " \n", " def __init__(self, job, *args, **kwargs):\n", " super(Career, self).__init__(*args, **kwargs)\n", " self._job = job\n", " \n", " def __str__(self): \n", " return 'So I became a waiter of {}'.format(self._job)\n", " \n", "raise Career('Engineer')" ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 10 External files.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Text Files\n", "\n", "Data is often stored in formats that are not easy to read unless you have some specialised software. Excel spreadsheets are one example; how do you read an Excel spreadsheet if you don't have Excel? This reliance on particular software is not very useful for programmatic analysis of data. Instead if we're going to use a programming language to analyse or process our data we would prefer some \"easy to deal with\" format. Text files or [flatfiles](http://en.wikipedia.org/wiki/Text_file) provide just the sort of format we need (there are other choices). You can think of these as a single sheet from a spreadsheet with the data arranged in rows (separated by our old friend the ```\\n``` character) and columns (separated by some other character)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "There are two common characters used to separate the data in text files into columns. The ```\\t```, or tab stop character and the humble comma (,). In both cases fields in our input file are separated by a single tab stop or a single comma. \n", "\n", "This gives rise to two commonly used file extensions (the bit after the dot in file names e.g. in ```myfile.docx``` the 'docx' is the file extension.). These file extensions are ```.tsv``` for 'tab separated file' and ```.csv``` for 'comma separated file'. Other separators in text files of data may be little used characters such as '|', ':' or spaces. As a quick aside separating fields in data files by spaces is tricky because an individual value might also contain spaces and therefore be inappropriately divided over more than one column.\n", "\n", "As an illustration if you were to print a couple of lines from a ```.tsv``` file out it would look something like this:" ] }, { "cell_type": "raw", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "data_field1\\tdata_field2\\tdata_field3\\n \n", "data_field1\\tdata_field2\\tdata_field3\\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Each field is separated by a tab stop ```\\t``` and the end of a line is indicated by the ```\\n``` combination.\n", "\n", "In a ```.csv``` file you would see:" ] }, { "cell_type": "raw", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "data_field1,data_field2,data_field3\\n\n", "data_field1,data_field2,data_field3\\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Note:\n", "\n", "It's important to note that there is NO STANDARD for either the layout OR naming of text files. In the exercises that follow the text file we will be working with has the extension ```.csv``` which should mean comma separated but in fact the data is separated by tabs - because that's what I'm in the habit of doing. Please ignore my bad habits!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Opening (and Reading) Files\n", "\n", "When you open a file in a programme such as Word or Excel you have to select the file you want from a 'File -> Open' dialogue of some kind. In other words you have to point the programme at the specific file you want which is stored at some specific location on your computer. This is also true when you open a file in Python. \n", "The difference is that when you open a file in python you have to specify the file location in words (as a **filepath**) rather then selecting from a dialogue. So the first thing we have to do is assign the file location to a variable. This textual representation of the file location is called the filepath. \n", "\n", "Once we have the filepath we can use the python function ```open()``` to 'get a handle' on the file. This **file handle** should also be assigned to a variable. We can then operate on that variable. Let's see an example." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<_io.TextIOWrapper name='data/elderlyHeightWeight.csv' mode='r' encoding='UTF-8'>\n" ] } ], "source": [ "file_loc = 'data/elderlyHeightWeight.csv'\n", "f_hand = open(file_loc, 'r')\n", "print(f_hand)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In the example above we have opened a small file containing height and weight information on a group of elderly men and women from a body composition study." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "In the first line we assign the file path to the variable ```file_loc```. We then use that variable to open a file handle (```f_hand```) using the ```open()``` function. The file location is the first argument to the ```open()``` function and the second argument ```'r'``` indicates that we want to *read* from the file i.e. we want access to the data in the file but we don't want to change the file itself. Finally we use a ```print``` statement to print the file handle. \n", "\n", "The results of the ```print``` statement might surprise you. Rather than printing the contents of the file what we get is a representation of the location in the computer memory of where the file is i.e. at memory location 0x7... etc in the example above.\n", "\n", "Whilst we can also open Excel or Word files in python this requires the use of special software libraries. We'll see some of those later in the course. Mostly when we are analysing data in files we open simple text files. Both Excel and Word can save files out as simple text files. \n", "\n", "The first few lines of the file we will work with are shown below." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\r\n", "F\t77\t63.8\t155.5\r\n", "F\t80\t56.4\t160.5\r\n", "F\t76\t55.2\t159.5\r\n" ] } ], "source": [ "!head -n 4 data/elderlyHeightWeight.csv" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "While the file handle does not contain the data from the file (it only points at it) it is easy to construct a ```for``` loop to cycle through the lines of the file and carry out some computation. For example we can easily count the number of lines in the file." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "There are 19 lines in the file.\n" ] } ], "source": [ "count = 0 # initialise\n", "\n", "for line in f_hand: # iterate\n", " count = count + 1\n", " \n", "print('There are %d lines in the file.' % count )" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Why doesn't `open()` open the file directly?\n", "\n", "It might seem stupid that after using ```open()``` a file handle is created but the file contents aren't directly available. The reason the ```open()``` function does not read the whole file immediately but just points to it is to do with file size. If you do not know in advance the size of the files you are dealing with (often the case - how often do you check the size of files you open on your computer?) automatically opening *very* large files could:\n", "\n", "* Take a long time\n", "* Crash the whole computer system - essentially you'd run out of memory" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "For some biological applications the data files (which may well be text files e.g. in RNA Seq data - see comment [here](http://seqanswers.com/forums/showthread.php?t=10787)) can be very large. So it's safer to point to the file rather than automatically open it. This is also true of other data or informatics applications.\n", "\n", "In the ```for``` loop above python splits the file into lines based on the newline character (```\\n``` - the split is implicit), increments the ```count``` variable by 1 for every line and then discards that line. So there is only ever one line from the file in the computer memory at any given time.\n", "\n", "If you know that your file is likely to be small you can read the whole file into memory with the ```read()``` method (remember the dot notation!). \n", "\n", "This reads the entire contents of the file, newlines and all, into one large string." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "F\t77\t63.8\t155.5\n", "F\t80\t56.4\t160.5\n", "F\t76\t55.2\t159.5\n", "F\t77\t58.5\t151\n", "F\t82\t64\t165.5\n", "F\t78\t51.6\t167\n", "F\t85\t54.6\t154\n", "F\t83\t71\t153\n", "M\t79\t75.5\t171\n", "M\t75\t83.9\t178.5\n", "M\t79\t75.7\t167\n", "M\t84\t72.5\t171.5\n", "M\t76\t56.2\t167\n", "M\t80\t73.4\t168.5\n", "M\t75\t67.7\t174.5\n", "M\t75\t93\t168\n", "M\t78\t95.6\t168\n", "M\t80\t75.6\t183.5\n", "\n" ] } ], "source": [ "file_loc = 'data/elderlyHeightWeight.csv'\n", "f_hand = open(file_loc, 'r')\n", "f_data = f_hand.read()\n", "print(f_data)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "F\t77\t63.8\t155.5\n", "\n" ] } ], "source": [ "f_hand.close()\n", "f_hand = open(file_loc)\n", "print(f_hand.readline(), end = '')\n", "print(f_hand.readline(), end = '')\n", "f_hand.close()\n", "f_hand = open(file_loc)\n", "lines = f_hand.readlines()\n", "print(type(lines))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "286\n", "Gender\tAge\n" ] }, { "data": { "text/plain": [ "'Gender\\tAge\\tbody wt\\tht\\n'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "file_loc = 'data/elderlyHeightWeight.csv'\n", "f_hand = open(file_loc, 'r')\n", "f_data = f_hand.read()\n", "f_data[:22]\n", "print(len(f_data))\n", "print( f_data[:10])\n", "r'{}'.format(f_data[:22]) # note the tab stop in the output" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "In the above example we first create the file handle and then ```read``` the entire contents of the file into one string. We check the length of that string (286 characters including whitespace characters like ```\\n```) and we print the first 10 characters (refer back to the material on slicing if you're unsure how the ```[:10]``` slice works). The ```print``` statement interprets the tab stop properly but if we just ask for the first 22 characters to be returned (i.e. we do not use ```print```) we can see the tab stop and the ```\\n```. Compare this to the illustration of a .tsv file shown above.\n", "\n", "Using the ```print``` statement and subsetting is fine but not convenient. You might want to print the whole of the first line. The ```readline()``` method will read one line at a time and you can use this to e.g. just display the header line (if you know or suspect that your file has a header line)." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "\n", "F\t77\t63.8\t155.5\n", "\n" ] } ], "source": [ "f_hand = open(file_loc, 'r')\n", "line = f_hand.readline() # reads first line\n", "print(line)\n", "# next line \n", "line=f_hand.readline()\n", "print(line)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "After reading in the current line ```readline()``` then moves on to the next line. So calling ```readline()``` again uses the next line in the file. One other thing to bear in mind is that ```readline()``` leaves whitespace and in particular the ```\\n``` character at the end of the line. You can see that above (there's a blank line between the printed lines) in the following example." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "data": { "text/plain": [ "'F\\t80\\t56.4\\t160.5\\n'" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "line = f_hand.readline() # note next line has been read\n", "line # compare to print above" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you're using python to join lines together in some new format that might not be what you want. There is a method, ```strip()```(see [here](https://docs.python.org/3/library/string.html)) that removes whitespace at the end of lines and can be used to remove this potentially extraneous ```\\n``` character. Note also that methods can be **chained** together so you can use ```readline()``` and ```strip()``` sequentially using the following syntax. " ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "data": { "text/plain": [ "'Gender\\tAge\\tbody wt\\tht'" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f_hand = open(file_loc, 'r') # read in in file again to get header line\n", "line = f_hand.readline().strip() # read the line then strip the whitespace at the end of the line\n", "line # no \\n!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Use of ```strip()``` has removed the ```\\n``` from our selected line. There are also ```lstrip()``` and ```rstrip()``` methods that strip whitespace from only the left or right sides of a string respectively.\n", "\n", "Just to confuse you further there's also a ```readlines()``` method that reads all the lines in the file into a ```list```. Again the lines are separated on the invisible ```\\n``` character. This can be handy because you can assign the ```list``` to a variable and then loop through the list to print file lines or simply extract the lines you want using slice notation." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Gender\\tAge\\tbody wt\\tht\\n', 'F\\t77\\t63.8\\t155.5\\n']\n", "19\n" ] } ], "source": [ "f_hand = open(file_loc, 'r')\n", "lines = f_hand.readlines()\n", "print(lines[0:2]) # check we have a list\n", "print(len(lines))" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "F\t77\t63.8\t155.5\n", "F\t80\t56.4\t160.5\n", "F\t76\t55.2\t159.5\n" ] } ], "source": [ "for i in range(4):\n", " print (lines[i].strip())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "---\n", "\n", "### Alternative Implementations (just for fun)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### no. 1" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "F\t77\t63.8\t155.5\n", "F\t80\t56.4\t160.5\n", "F\t76\t55.2\t159.5\n" ] } ], "source": [ "for line in lines[:4]:\n", " print(line.strip())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### no. 2" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "F\t77\t63.8\t155.5\n", "F\t80\t56.4\t160.5\n", "F\t76\t55.2\t159.5\n" ] } ], "source": [ "for i, line in enumerate(lines):\n", " if i == 4:\n", " break\n", " print(line.strip())" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Just like ```readline()``` the ```readlines()``` method leaves the trailing \\n at the end of the line but you can use ```strip()``` to remove it if you have to as we did above. We had to use the ```strip()``` method on the individual line rather than on the list of lines as lists ```strip()``` does not operate on lists. Try moving the ```strip()``` to the end of ```lines = f_hand.readlines()``` and see what kind if error you get.\n", "\n", "Finally (and perhaps most usefully) there is the ```splitlines()``` method that does the same as ```readlines()``` but drops the trailing ```\\n``` automatically." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "F\t77\t63.8\t155.5\n", "F\t80\t56.4\t160.5\n", "F\t76\t55.2\t159.5\n" ] } ], "source": [ "f_hand = open(file_loc, 'r')\n", "lines = f_hand.read().splitlines() # read file, then split lines to lists, drops trailing \\n\n", "for i in range(4):\n", " print (lines[i])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Notice we didn't have to use ```strip()```.\n", "\n", "One final thing to note is that whenever we finish with a file we should close it. Leaving files 'open' after data has been read from them can lead to increasing amounts of memory being used and also corruption of the file. Closing files is accomplished by using the ```close()``` method on the file handle. Also illustrated is a simple filter to print out only the male data using the string method ```startswith()``` - which returns a boolean value depending on whether the line begins with the given argument (M in this case) or not." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "M\t79\t75.5\t171\n", "M\t75\t83.9\t178.5\n", "M\t79\t75.7\t167\n", "M\t84\t72.5\t171.5\n", "M\t76\t56.2\t167\n", "M\t80\t73.4\t168.5\n", "M\t75\t67.7\t174.5\n", "M\t75\t93\t168\n", "M\t78\t95.6\t168\n", "M\t80\t75.6\t183.5\n" ] } ], "source": [ "file_loc = 'data/elderlyHeightWeight.csv' # relative path\n", "f_hand = open(file_loc, 'r')\n", "lines = f_hand.read().splitlines() # lines to a list\n", "print (lines[0]) # header\n", "\n", "for line in lines: # loop to filter\n", " if line.startswith('M'):\n", " print (line)\n", " \n", "f_hand.close() " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "## `filter` alternative" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "def filter_function(line):\n", " return line.startswith('M')" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\n", "M\t79\t75.5\t171\n", "M\t75\t83.9\t178.5\n", "M\t79\t75.7\t167\n", "M\t84\t72.5\t171.5\n", "M\t76\t56.2\t167\n", "M\t80\t73.4\t168.5\n", "M\t75\t67.7\t174.5\n", "M\t75\t93\t168\n", "M\t78\t95.6\t168\n", "M\t80\t75.6\t183.5\n" ] } ], "source": [ "f_hand = open(file_loc)\n", "lines = f_hand.readlines()\n", "male_gender = filter(filter_function, lines)\n", "print(lines[0].strip())\n", "for ml in male_gender:\n", " print(ml.strip())\n", "f_hand.close()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "#### Using `lambda` expressions" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "M\t79\t75.5\t171\n", "M\t75\t83.9\t178.5\n", "M\t79\t75.7\t167\n", "M\t84\t72.5\t171.5\n", "M\t76\t56.2\t167\n", "M\t80\t73.4\t168.5\n", "M\t75\t67.7\t174.5\n", "M\t75\t93\t168\n", "M\t78\t95.6\t168\n", "M\t80\t75.6\t183.5\n" ] } ], "source": [ "f_hand = open(file_loc)\n", "male_gender = filter(lambda l: l.startswith('M'), f_hand)\n", "for ml in male_gender:\n", " print(ml.strip())\n", "f_hand.close()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "## Exercises " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### Show the content of the file using a Shell command\n", "\n", "#### Tip 1: The shell command to be used could be `cat`\n", "#### Tip 2: Remember the `!` (esclamation mark)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender\tAge\tbody wt\tht\r\n", "F\t77\t63.8\t155.5\r\n", "F\t80\t56.4\t160.5\r\n", "F\t76\t55.2\t159.5\r\n", "F\t77\t58.5\t151\r\n", "F\t82\t64\t165.5\r\n", "F\t78\t51.6\t167\r\n", "F\t85\t54.6\t154\r\n", "F\t83\t71\t153\r\n", "M\t79\t75.5\t171\r\n", "M\t75\t83.9\t178.5\r\n", "M\t79\t75.7\t167\r\n", "M\t84\t72.5\t171.5\r\n", "M\t76\t56.2\t167\r\n", "M\t80\t73.4\t168.5\r\n", "M\t75\t67.7\t174.5\r\n", "M\t75\t93\t168\r\n", "M\t78\t95.6\t168\r\n", "M\t80\t75.6\t183.5\r\n" ] } ], "source": [ "!cat data/elderlyHeightWeight.csv" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### Ex. no 2\n", "\n", "Print all the lines in the file where the `Age` value is in the range `[70, 80)`" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "F\t77\t63.8\t155.5\n", "F\t76\t55.2\t159.5\n", "F\t77\t58.5\t151\n", "F\t78\t51.6\t167\n", "M\t79\t75.5\t171\n", "M\t75\t83.9\t178.5\n", "M\t79\t75.7\t167\n", "M\t76\t56.2\t167\n", "M\t75\t67.7\t174.5\n", "M\t75\t93\t168\n", "M\t78\t95.6\t168\n" ] } ], "source": [ "f_hand = open(file_loc)\n", "for i, line in enumerate(f_hand):\n", " if i == 0:\n", " continue\n", " line = line.strip()\n", " _, age, *_ = line.split('\\t')\n", " if 70 <= int(age) < 80:\n", " print(line)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### Ex. no 3 \n", "\n", "Print the two lines in the files for each `gender` corresponding to the two entries with the (relative) maximum value of *body weight* (`body wt`) plus *height* (`ht`)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### Sol `#1`: Using a Dictionary" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "info = {} # Dictonary holding per-sex lines info\n", "f_hand = open(file_loc)\n", "lines = f_hand.read().splitlines()\n", "for l in lines[1:]:\n", " l = l.strip()\n", " key = l[0]\n", " info.setdefault(key, [])\n", " info[key].append(tuple(l.split('\\t')))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'F': [('F', '77', '63.8', '155.5'),\n", " ('F', '80', '56.4', '160.5'),\n", " ('F', '76', '55.2', '159.5'),\n", " ('F', '77', '58.5', '151'),\n", " ('F', '82', '64', '165.5'),\n", " ('F', '78', '51.6', '167'),\n", " ('F', '85', '54.6', '154'),\n", " ('F', '83', '71', '153')],\n", " 'M': [('M', '79', '75.5', '171'),\n", " ('M', '75', '83.9', '178.5'),\n", " ('M', '79', '75.7', '167'),\n", " ('M', '84', '72.5', '171.5'),\n", " ('M', '76', '56.2', '167'),\n", " ('M', '80', '73.4', '168.5'),\n", " ('M', '75', '67.7', '174.5'),\n", " ('M', '75', '93', '168'),\n", " ('M', '78', '95.6', '168'),\n", " ('M', '80', '75.6', '183.5')]}\n" ] } ], "source": [ "from pprint import pprint # pprint is for **pretty printing** structures\n", "pprint(info)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('M', '78', '95.6', '168')\n" ] } ], "source": [ "max_male = max(info['M'], key=lambda e: float(e[2]) + float(e[3]))\n", "print(max_male)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### Sol. `#2`: Using a list comprehension " ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "## Creating Partial Lists using **List Comprehension**\n", "males = [l.strip().split('\\t') for l in lines[1:] \n", " if l.startswith('M')]\n", "females = [l.strip().split('\\t') for l in lines[1:] \n", " if l.startswith('F')] " ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "data": { "text/plain": [ "[['M', '79', '75.5', '171'],\n", " ['M', '75', '83.9', '178.5'],\n", " ['M', '79', '75.7', '167'],\n", " ['M', '84', '72.5', '171.5'],\n", " ['M', '76', '56.2', '167'],\n", " ['M', '80', '73.4', '168.5'],\n", " ['M', '75', '67.7', '174.5'],\n", " ['M', '75', '93', '168'],\n", " ['M', '78', '95.6', '168'],\n", " ['M', '80', '75.6', '183.5']]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "males" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['M', '78', '95.6', '168']\n" ] } ], "source": [ "max_male = max(males, key=lambda e: float(e[2]) + float(e[3]))\n", "print(max_male)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "# The ```csv``` module\n", "\n", "Getting the data from a file and doing something with it is all well and good. However once we've done our analysis we usually want to save the results to another file. We can do this using base python but it's easier if we use a python **library**, in this case the [```csv```](http://www.pythonforbeginners.com/systems-programming/using-the-csv-module-in-python/) library. We'll learn more about libraries in the next unit but for now just consider libraries as extra python code that you can get access to if you need it. In fact that's exactly what many libraries are. So the quesion arises 'how do we get access to a library?'. We have to tell python we want to use the library up front. To do this we use the ```import``` statement." ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "import csv" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "It's that simple! Now python makes available to us all the useful code in the ```csv``` library. The ```csv``` library, unsurprisingly, contains python functions and methods to make dealing with csv (and other) text files easier. Let's first see how to open a text file using the ```csv``` library and printing out the first few lines.\n", "\n", "To read data from a csv file, we use the ```reader()``` function. The ```reader()``` function takes each line of the file and makes a ```reader``` object containing lists made up of each row in the input data. Objects in programming are containers for both data and methods that act on that data (a bit esoteric so don't worry if you don't quite get that). One method the ```reader``` object supports is the ```.next()``` method. We can use this to access each row at a time. Notably once we have processed the line it's gone from the ```reader``` object." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Note:\n", "\n", "From **here on**, we are going to keep using the `with/as` statement to handle I/O operations, namely **Context Manager** objects.\n", "\n", "For more information, see this [notebook](09 Exceptions.ipynb#ctx).\n", "\n" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Gender', 'Age', 'body wt', 'ht']\n", "\n", "['F', '77', '63.8', '155.5']\n", "['F', '80', '56.4', '160.5']\n", "['F', '76', '55.2', '159.5']\n", "['F', '77', '58.5', '151']\n" ] } ], "source": [ "# import csv - already done\n", "with open('data/elderlyHeightWeight.csv', 'r') as csvfile:\n", " reader = csv.reader(csvfile, delimiter='\\t') # define the field delimiter\n", " header = next(reader)\n", " print (header)\n", " print () # blank line\n", "\n", " for i in range(4):\n", " print (next(reader)) # print the first 4 lines after the header" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can see that the ```reader()``` function has processed each line into a single list element based on the field delimiter we supplied. Importantly also note that all the values are now of type ```str``` in each list (everything is in quotes). This is important if you want to do calculations on these values. \n", "\n", "Using the ```csv``` module makes it easy to select whole columns by selecting the data we want from the ```reader```. We'll use the ```.next()``` method to find the column order and then iterate over the rows with a ```for``` loop to pull out height and weight." ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Gender', 'Age', 'body wt', 'ht']\n", "['Weight', '63.8', '56.4', '55.2', '58.5', '64', '51.6', '54.6', '71', '75.5', '83.9', '75.7', '72.5', '56.2', '73.4', '67.7', '93', '95.6', '75.6']\n", "['Height', '155.5', '160.5', '159.5', '151', '165.5', '167', '154', '153', '171', '178.5', '167', '171.5', '167', '168.5', '174.5', '168', '168', '183.5']\n" ] } ], "source": [ "\n", "with open('data/elderlyHeightWeight.csv', 'r') as csvfile:\n", " reader = csv.reader(csvfile, delimiter='\\t') # define the field delimiter\n", "\n", " # use next() method on reader object to id the headers\n", " headers = next(reader)\n", " print(headers)\n", " \n", " # we now know weight index is 2, height index is 3\n", " \n", " weight = ['Weight'] # list to hold data, put in header \n", " height = ['Height']\n", "\n", " for row in reader:\n", " weight.append(row[2])\n", " height.append(row[3])\n", " \n", " print (weight)\n", " print (height)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "The ```iterable``` in the \n", "\n", "```\n", "for...\n", "``` \n", "\n", "loop above is each row of the input file. From each row we simply capture the two values we want and add these to lists. We could then further process the data in these two lists." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Writing files" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "In order to open a file for writing we use the ```'w'``` parameter in our ```open()``` statement. Rather obviously ```'w'``` stands for write. If the file doesn't exist a new file is created with the given name and extension.\n", "\n", "Note that if the file exists then opening it with the ```'w'``` argument removes any data that was in the file and overwrites it with what you put in. This may not be what you wanted to do. We'll cover how you append data to a file without overwriting the contents shortly. \n", "\n", "Once we have an open file we can write data to it with the ```write()``` method applied to the file handle.\n", "\n", "Let's open a file and write some data to it." ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "with open('data/test.txt', 'w') as f_out:\n", " for i in range(10):\n", " line = 'Line ' + str(i) + '\\n'\n", " f_out.write(line)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If you run the above code a new file should appear in your data directory (notice we opened the writeable file in the ```/data``` directory) called ```test.txt```. That file should have 10 lines in it with the word 'Line' and a number from 0-9. \n", "\n", "In the above code we first opened (created) the file ```test.txt``` and then ran through a range of numbers (from 0 to 9) using a ```for``` loop. At each iteration of the loop we concatenated (joined) the word 'Line' to the string representation of the number (note the use of ```str```) and a newline character. Finally we wrote each of the resulting strings to our new file. In the last line we closed the file." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Putting it together!\n", "\n", "Write a script that uses the ```csv``` module to open a file after getting a filepath from the user. Use the script to open the ```elderlyHeightWeight.csv``` file. Write out a new file containing only male data. Remember to close all the files once your done. In addition include a ```try\\except``` clause to handle the situation where the requested file doesn't exist.\n", "\n", "Hint: ```csv.reader``` objects are lists. Recall how you ```.join()``` lists elements into a string." ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "source": [ "## Adding data to an existing file\n", "\n", "As noted above if you open an existing file and write data to it all that pre-existing data gets over written. That's not usually what you want to do. In fact in general you probably never want to write to any file that has raw data you are going to analyse in it - because you might lose or screw-up your original data. Sometimes however you might want to add new measurements (perhaps taken over time) to an existing file. For these cases there's the ```'a'``` argument to the ```open()``` function. The ```a``` stands for append. Let's take the file containing only the male data we wrote in the last exercise, open it in append mode and write the female data to that file." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "import csv\n", "\n", "# assumes your file was called male_data.tsv\n", "try:\n", " with open('data/male_data.tsv', 'a') as new_file, open('data/elderlyHeightWeight.csv', 'r') as f_hand: \n", " reader = csv.reader(f_hand, delimiter='\\t') # define the field delimiter\n", " male_data = [line for line in reader if line[0] == 'M']\n", " for line in male_data:\n", " new_file.write('\\t'.join(line)+'\\n')\n", "except FileNotFoundError:\n", " print('The file does not exist.')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Processing and writing file data\n", "\n", "Let's do something a bit more useful than just copying data around from one file to another. Often when we have demographic data like this one of the things we want to do is create new variables from that data. The ```elderlyHeightWeight.csv``` file contains... eh, well... height and weight data from a sample of elderly study participants. One obvious new variable we could create from this is BMI. However we'll save that for the exercise!\n", "\n", "Instead we'll demonstrate the process by converting the height from cm to m - a simple division by 100. We can write this data to a new column. The strategy we'll use is to read each field of the data into a separate list. We will process the appropriate list and then use the the [```writer()```](https://docs.python.org/2/library/csv.html) method of the ```csv``` module to write our new file including processed height data.\n", "\n", "We'll use a slightly different approach here from that demonstrated above (previous height & weight example). Instead of iterating over the rows we'll use iterator variables in our ```for``` loop. " ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gender: \n", "\t ['F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M']\n", "Age: \n", "\t ['77', '80', '76', '77', '82', '78', '85', '83', '79', '75', '79', '84', '76', '80', '75', '75', '78', '80']\n", "body wt: \n", "\t ['63.8', '56.4', '55.2', '58.5', '64', '51.6', '54.6', '71', '75.5', '83.9', '75.7', '72.5', '56.2', '73.4', '67.7', '93', '95.6', '75.6']\n", "ht: \n", "\t ['155.5', '160.5', '159.5', '151', '165.5', '167', '154', '153', '171', '178.5', '167', '171.5', '167', '168.5', '174.5', '168', '168', '183.5']\n" ] } ], "source": [ "# import csv - done above\n", "\n", "from collections import defaultdict\n", "with open('data/elderlyHeightWeight.csv', 'r') as f_hand:\n", " csv_info = dict()\n", " reader = csv.DictReader(f_hand, delimiter='\\t') # define the field delimiter\n", " for entry in reader:\n", " for key, value in entry.items():\n", " if key not in csv_info:\n", " csv_info[key] = [] # initialise as an Empty list\n", " csv_info[key].append(value)\n", " \n", "for key, value in csv_info.items():\n", " print('{}: \\n\\t {}'.format(key, value))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "In this code snippet we first initialised four lists - one to hold each column of our data. We then iterated over the columns of the data and assigned each value to its relevant list variable.\n", "\n", "If you examine these lists you'll see that the first entry is the column header (which is handy for tracking data) and the other entries are the actual data for that column in the original file." ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['ht', '155.5', '160.5', '159.5', '151', '165.5', '167', '154', '153', '171', '178.5', '167', '171.5', '167', '168.5', '174.5', '168', '168', '183.5']\n" ] } ], "source": [ "print (height)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Now we have the data separated out it's a trivial effort to calculate the height in meters (from the given height in cm). In the code below we use the ```range()``` function to get the positions of the actual heights (i.e. we skip the column header), we convert those heights from ```str``` to ```float``` and we calculate the height in meters and append this to a new list." ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['ht_m', 1.555, 1.605, 1.595, 1.51, 1.655, 1.67, 1.54, 1.53, 1.71, 1.785, 1.67, 1.715, 1.67, 1.685, 1.745, 1.68, 1.68, 1.835]\n" ] } ], "source": [ "height_m = []\n", "height_m.append('ht_m') # a new header\n", "\n", "# use range(1,len(height)) so we don't get the header again\n", "for ht in height[1:]:\n", " height_m.append(float(ht)/100) # note the conversion to a float here\n", "\n", "print (height_m)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Now we have all the data we need to write the new file. First we'll capture each line of our new file to a list (the ```zip()``` function) and then write each line to the new file. The ```csv``` library extends the ```.write()``` method with a ```writer``` object. One method of ```writer``` objects is ```.writerow()``` the use of which is demonstrated below." ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "with open('data/new_data.csv', 'w') as newdata_file:\n", " writer = csv.writer(newdata_file, delimiter='\\t') # define a writer object\n", " \n", " # iterate over data and write to file\n", " # use zip to create list of tuples for writing\n", " for row in zip(gender, age, weight, height, height_m):\n", " writer.writerow(row)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "Remember that the [```zip()```](https://docs.python.org/3/library/functions.html#zip) function will create an **iterator** (i.e. `zip object`) made up of ```tuples```. In the example above the use of ```zip()``` creates a sequence the first element of which is all the first elements of our data lists, the second list element is all the second elements etc. It's easier to see this than explain it." ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "zip_sequence = zip(gender, age, weight, height, height_m)\n", "print(type(zip_sequence))" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Gender', 'F', 'F', 'F']\n", "['Age', '77', '80', '76']\n", "['body wt', '63.8', '56.4', '55.2']\n", "['ht', '155.5', '160.5', '159.5']\n", "['ht_m', 1.555, 1.605, 1.595]\n", "[('Gender', 'Age', 'body wt', 'ht', 'ht_m'), ('F', '77', '63.8', '155.5', 1.555), ('F', '80', '56.4', '160.5', 1.605), ('F', '76', '55.2', '159.5', 1.595)]\n" ] } ], "source": [ "print (gender[:4])\n", "print (age[:4])\n", "print (weight[:4])\n", "print (height[:4])\n", "print (height_m[:4])\n", "print # just a blank line\n", "print (list(zip_sequence)[:4])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "The first element in each of our data lists is the column header. The ```zip()``` function captures these first elements into a tuple - ```('Gender', 'Age', 'body wt', 'ht', 'ht_m')``` - and this, in turn, becomes the first element of a new list, ```data_out```. The ```zip()``` function then captures all the second elements from each data list and these become part of a ```tuple``` which is the second element of ```data_out```. In this way each data list is 'zipped up' with the other lists. \n", "\n", "To output the rows we simply iterate over the ```data_out``` list and send each element to our output file as a row using the ```.writerow()``` method." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "## Putting it together 1\n", "\n", "Open the ```elderlyHeightWeight.csv``` using the functions in the ```csv``` module and extract each column to a separate list. Use the height and weight data to calculate the BMI for each subject. Use ```zip()``` to create a list of data to write out and write all the phenotype data including BMI back to a new file.\n", "\n", "Hint - if you use the ```csv.reader()``` remember the issues with the ```str``` type in lists." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "## Putting it together 2\n", "\n", "Read the file you just created back in and select only those trial participants who are obese. Print the sex, age and BMI of these people. Obese means a BMI of 30 or more." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "## Homework\n", "\n", "The ```nhanes.tsv``` file in the ```data``` directory contains data on 4581 Americans aged from 20 to 70 from the 2011-2012 [NHANES](http://wwwn.cdc.gov/Nchs/Nhanes/Search/DataPage.aspx?Component=Demographics&CycleBeginYear=2011) survey. The data included are \n", "\n", "* individual number (unique ID for each individual in NHANES)\n", "* age (years) \n", "* sex (1 = M, 2 = F)\n", "* weight (kg)\n", "* height (cm). \n", "\n", "Write a script that will read this data and count the number of NA values in height and /or weight and count the number of males and females.\n", "\n", "Calculate the BMI for each individual, add this to the original file and write out a new file indluding BMI data.\n", "\n", "Finally calculate the mean BMI for males and females and write these out as well (to 2 decimal places).\n", "\n", "Hint: In this exercise you should use the techniques you have learned to loop over the lines of a file and extract each variable into its' own list. You can then calculate the BMI values easily. However you won't be able to calculate a BMI for individuals with 'NA' in either weight or height columns. How can you use the ```continue``` keyword when you loop over your data to avoid collecting values for these individuals?" ] } ], "metadata": { "celltoolbar": "Slideshow", "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: 11 Persistence.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Persistence" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this notebook, our focus is on **persistent data** — the kind that outlives a program that creates it. \n", "\n", "That’s not true by default for objects a script constructs, of course; things like lists, dictionaries, and even class instance objects live in your computer’s memory and are lost as soon as the script ends. \n", "\n", "To make data live longer, we need to do something special. \n", "\n", "In Python there are (at least) five *traditional* ways to save information in between program executions:\n", "\n", "* *Flat files*\n", " * Text and bytes stored directly on your computer\n", " \n", "* *DBM keyed files*\n", " * Keyed access to strings stored in dictionary-like files\n", " \n", "* *Pickled objects*\n", " * Pickled objects \n", " \n", "* *Shelve files*\n", " * Pickled Python objects saved in DBM keyed files\n", "\n", "* *SQL relational databases (RDBMSs)*\n", " * Table-based storage that supports SQL queries (SQLite, MySQL, PostGreSQL, etc.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# SQL Database Interface" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For programs that can benefit from the power of SQL, Python also broadly supports relational database management systems (**RDBMSs**).\n", "\n", "The databases we’ll meet in this notebook, though, are structured and processed in very different ways:\n", "\n", "* They store data in related tables of columns (rather than in persistent dictionaries of arbitrarily structured persistent Python objects).\n", "\n", "* They support the SQL query language for accessing data and exploiting relation- ships among it (instead of Python object traversals).\n", "\n", "For some applications, the end result can be a potent combination. Moreover, some SQL-based database systems provide industrial-strength persistence support for enterprise-level data." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python Modules" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Today, there are freely available interfaces that let Python scripts utilize all common relational database systems, both free and commercial: MySQL, Oracle, Sybase, Informix, InterBase, PostgreSQL (Postgres), SQLite, ODBC, and more.\n", "\n", "In addition, the Python community has defined a **database API** (*aka* `DB API`) specification that works portably with a variety of underlying database packages. \n", "\n", "Scripts written for this API can be migrated to different database vendor packages, with minimal or no source code changes.\n", "\n", "As of Python 2.5, Python itself includes built-in support for the SQLite relational database system as part of its standard library. \n", "\n", "Because this system supports the portable database API, it serves as a tool for both program storage and prototyping—systems developed with SQLite work largely unchanged when a more feature-rich database such as MySQL or Oracle is deployed.\n", "\n", "Moreover, the popular `SQLObject` and `SQLAlchemy` third-party systems both provide an **Object Relational Mapper (ORM)**, which grafts an object interface onto your database, in which tables are modeled by as Python classes, rows by instances of those classes, and columns by instance attributes. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python SQL Interface" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The **Python Database API** (DB API) specification defines an interface for communicating with underlying database systems from Python scripts. \n", "\n", "Vendor-specific database interfaces for Python may or may not conform to this API completely, but all database extensions for Python in common use are minor variations on a theme. \n", "\n", "Under the database API, SQL databases in Python are grounded on three core concepts:\n", "\n", "* **Connection Objects**:\n", " > Represent a connection to a database, are the interface to rollback and commit operations, provide package implementation details, and generate cursor objects.\n", " \n", "* **Cursor Objects**:\n", " > Represent an SQL statement submitted as a string and can be used to access and step through SQL statement results.\n", " \n", "* **Query results of SQL select statements**:\n", " > Are returned to scripts as Python sequences of sequences (e.g., a *list of tuples*), representing database tables of rows. Within these row sequences, column field values are normal Python objects such as strings, integers, and floats (e.g., `[('bob', 48), ('emily',47)]`). Column values may also be special types that encapsulate things such as date and time, and database `NULL` values are returned as the Python `None` object." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Connection Objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beyond this, the API defines a standard set of database exception types, special database type object constructors, and informational top-level calls including thread safety and replacement style checks.\n", "\n", "For instance, to establish a database connection under the Python API-compliant **Oracle** interface, install the commonly used Python Oracle extension module (i.e. `pip install cx_oracle`) as well as Oracle itself, and then run a statement of this form:\n", "\n", "```python\n", " connobj = connect(\"user/password@system\")\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This call’s arguments may vary per database and vendor (e.g., some may require network details or a local file’s name), but they generally contain what you provide to log in to your database system. \n", "\n", "Once you have a connection object, there a variety of things you can do with it, including:\n", "\n", "```python\n", " connobj.close() # close connection now (not at object __del__ time)\n", " connobj.commit() # commit any pending transactions to the database \n", " connobj.rollback() # roll database back to start of pending transactions\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Cursor Objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But one of the most useful things to do with a connection object is to generate a cursor object:\n", "\n", "```python\n", " cursobj = connobj.cursor() # return a new cursor object for running SQL\n", "```\n", "\n", "Cursor objects have a set of methods, too (e.g., close to close the cursor before its destructor runs, and callproc to call a stored procedure), but the most important may be this one:\n", "\n", "```python\n", " cursobj.execute(sqlstring [, parameters]) # run SQL query or command string\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parameters are passed in as a sequence or mapping of values, and are substituted into the `SQL` statement string according to the interface module’s replacement target conventions. \n", "\n", "The execute method can be used to run a variety of `SQL` statement strings:\n", "\n", "* DDL definition statements (e.g., `CREATE TABLE`);\n", "* DML modification statements (e.g., `UPDATE` or `INSERT`);\n", "* DQL query statements (e.g., `SELECT`)\n", "\n", "After running an SQL statement, the cursor’s `rowcount` attribute gives the number of rows *changed* (for **DML** changes) or *fetched* (for **DQL** queries), and the cursor’s `description` attribute gives column names and types after a query; \n", "`execute` also returns the number of rows affected or fetched in the most vendor interfaces. \n", "\n", "For **DQL** query statements, you must call one of the `fetch` methods to complete the operation:\n", "\n", "```python\n", " single_tuple = cursobj.fetchone() # fetch next row of a query result \n", " list_of_tuple = cursobj.fetchmany([size]) # fetch next set of rows of query result\n", " list_of_tuple = cursobj.fetchall() # fetch all remaining rows of the result\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And once you’ve received fetch method results, table information is processed using normal Python sequence operations; for example, you can step through the tuples in a `fetchall` result list with a simple for loop or comprehension expression. \n", "\n", "Most Python database interfaces also allow you to provide values to be passed to `SQL` statement strings, by providing targets and a tuple of parameters. For instance:\n", "\n", "```python\n", "\n", "query = 'SELECT name, shoesize FROM spam WHERE job = ? AND age = ?' \n", "cursobj.execute(query, (value1, value2))\n", "results = cursobj.fetchall()\n", "for row in results: \n", " pass # do something\n", " \n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this event, the database interface utilizes *prepared statements* (an optimization and convenience) and correctly passes the parameters to the database regardless of their Python types. \n", "\n", "The notation used to code targets in the query string may vary in some database interfaces (e.g., `:p1` and `:p2` or two `%s`, rather than the two `?s` used by the **Oracle interface**); in any event, this is not the same as Python’s \n", "`%` string formatting operator, as it sidesteps security issues along the way.\n", "\n", "Finally, if your database supports stored procedures, you can call them with the `callproc` method or by passing an `SQL CALL` or `EXEC` statement string to the execute method. \n", "\n", "`callproc` may generate a result table retrieved with a `fetch` variant, and returns a modified copy of the input sequence — input parameters are left untouched, and output and input/output parameters are replaced with possibly new values. \n", "\n", "Additional API features, including support for database `blobs` (roughly, with sized results), is described in the API’s documentation. \n", "\n", "For now, let’s move on to do some real SQL processing in Python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## An SQL Database API Tutorial with SQLite" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We don’t have space to provide an exhaustive reference for the database API in this notebook. \n", "\n", "To sample the flavor of the interface, though, let’s step through a few simple examples. \n", "\n", "We’ll use the **SQLite** database system for this tutorial. \n", "\n", "SQLite is a standard part of Python itself, which you can reasonably expect to be available in all Python installations. Although SQLite implements a complete relational database system, it takes the form of an in-process library instead of a server. \n", "\n", "This generally makes it better suited for program storage than for enterprise-level data needs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Note:\n", "\n", "Thanks to Python’s portable DB API, though, other popular database packages such as **PostgreSQL, MySQL, and Oracle** are used almost identically; the initial call to log in to the database will be all that normally requires different argument values for scripts that use standard SQL code. \n", "\n", "Because of this, we can use the SQLite system both as a prototyping tool in applications development and as an easy way to get started with the Python SQL database API in this book.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Getting Started" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Regardless of which database system your scripts talk to, the basic SQL interface in Python is very simple. \n", "\n", "In fact, it’s hardly object-oriented at all queries and other database commands are sent as strings of SQL. \n", "\n", "Whether large or small, though, the Python code needed to process your database turns out to be surprisingly straightforward. \n", "\n", "To get started, the first thing we need to do is open a connection to the database and create a table for storing records:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import sqlite3\n", "conn = sqlite3.connect('data/dbase1')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start out by importing the Python SQLite interface here— it’s a standard library module called `sqlite3` to our scripts. \n", "\n", "Next we create a **connection** object, passing in the items our database requires at start-up time—here, the name of the local file where our databases will be stored. \n", "\n", "This file is what you’ll want to back up to save your database. It will create the file if needed, or open its current content; SQLite also accepts that special string `:memory:` to create a temporary database in memory instead." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As long as a script sticks to using standard SQL code, the connect call’s arguments are usually the only thing that can vary across different database systems. \n", "\n", "For example, in the MySQL interface this call accepts a network host’s domain name, user name, and password, passed as keyword arguments instead, and the **Oracle example** sketched earlier expects a more specific sting syntax. \n", "\n", "Once we’ve gotten past this platform-specific call, though, the rest of the API is largely database **neutral**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Making Database and Tables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, let’s make a cursor for submitting SQL statements to the database server, and submit one to create a first table:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curs = conn.cursor()\n", "try:\n", " curs.execute('drop table people')\n", "except:\n", " pass # did not exist\n", "curs.execute('create table people (name char(30), job char(10), pay int(4))')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The last command here creates the table called “people” within the database; the name, job, and pay information specifies the columns in this table, as well as their datatypes, using a “type(size)” syntax — two strings and an integer. \n", "\n", "Datatypes can be more sophisticated than ours, but we’ll ignore such details here. \n", "\n", "In SQLite, the file is the database, so there’s no notion of creating or using a specific database within it, as there is in some systems." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Adding Records" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are three basic statement-based approaches we can use here: \n", "\n", "* inserting one row at a time; \n", "* inserting multiple rows with a single call statement;\n", "* using a Python loop.\n", "\n", "Here is the simple case" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curs.execute('insert into people values (?, ?, ?)', ('Bob', 'dev', 50000))\n", "curs.rowcount" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'qmark'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sqlite3.paramstyle" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, `qmark` means this module accepts `?` for replacement targets. \n", "\n", "Other database modules might use styles such as format (meaning a `%s` target), or numeric indexes or mapping keys; see the **DB API** for more details." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To insert multiple rows with a single statement, use the `executemany` method and a sequence of row sequences (e.g., a list of lists). This call is like calling `execute` once for each row sequence in the argument, and in fact may be implemented as such; database interfaces may also use database-specific techniques to make this run quicker, though:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curs.executemany('insert into people values (?, ?, ?)', \n", " [ ('Sue', 'mus', '70000'),\n", " ('Ann', 'mus', '60000')])\n", "curs.rowcount" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We inserted two rows at once in the last statement. \n", "\n", "It’s hardly any more work to achieve the same result by inserting one row at a time with a Python loop:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "rows = [['Tom', 'mgr', 100000], ['Kim', 'adm', 30000], ['pat', 'dev', 90000]]\n", "for row in rows:\n", " curs.execute('insert into people values (? , ?, ?)', row)\n", "conn.commit()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Blending Python and SQL like this starts to open up all sorts of interesting possibilities. \n", "\n", "Notice the last command; we always need to call the connection’s `commit` method to write our changes out to the database. Otherwise, when the connection is closed, our changes may be lost. \n", "\n", "In fact, until we call the `commit` method, none of our inserts may be visible from other database connections." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Side note:\n", "\n", "Technically, the API suggests that a connection object should automatically call its `rollback` method to back out changes that have not yet been committed, when it is closed (which happens manually when its close method is called, or automatically when the connection object is about to be garbage collected). \n", "\n", "For database systems that don’t support transaction commit and rollback operations, these calls may do nothing. SQLite implements both the commit and rollback methods; the latter rolls back any changes made since the last commit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Running Queries" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Bob', 'dev', 50000)\n", "('Sue', 'mus', 70000)\n", "('Ann', 'mus', 60000)\n", "('Tom', 'mgr', 100000)\n", "('Kim', 'adm', 30000)\n", "('pat', 'dev', 90000)\n" ] } ], "source": [ "curs.execute('select * from people')\n", "for row in curs.fetchall():\n", " print(row)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Tuple unpacking** comes in handy in loops here, too, to pick out column values as we go. \n", "\n", "Here’s a simple formatted display of two of the columns’ values:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bob : 50000\n", "Sue : 70000\n", "Ann : 60000\n", "Tom : 100000\n", "Kim : 30000\n", "pat : 90000\n" ] } ], "source": [ "curs.execute('select * from people')\n", "for (name, job, pay) in curs.fetchall():\n", " print(name, ':', pay)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because the query result is a sequence, we can use Python’s powerful sequence and iteration tools to process it. \n", "\n", "For instance, to select just the name column values, we can run a more specific SQL query and get a list of tuples" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[('Bob',), ('Sue',), ('Ann',), ('Tom',), ('Kim',), ('pat',)]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curs.execute('select name from people')\n", "names = curs.fetchall()\n", "names" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### `fetchall` vs `fetchone`\n", "\n", "The `fetchall` call we’ve used so far fetches the entire query result table all at once, as a single sequence (an empty sequence comes back, if the result is empty). \n", "\n", "That’s convenient, but it may be slow enough to block the caller temporarily for large result tables or generate substantial network traffic if the server is running remotely (something could easily require a parallel thread in GUI). \n", "\n", "To avoid such a bottleneck, we can also grab just one row, or a bunch of rows, at a time with `fetchone` and `fetchmany`. \n", "\n", "The `fetchone` call returns the next result row or a `None` false value at the end of the table:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Bob', 'dev', 50000)\n", "('Sue', 'mus', 70000)\n", "('Ann', 'mus', 60000)\n", "('Tom', 'mgr', 100000)\n", "('Kim', 'adm', 30000)\n", "('pat', 'dev', 90000)\n" ] } ], "source": [ "curs.execute('select * from people')\n", "while True:\n", " row = curs.fetchone() \n", " if not row: \n", " break \n", " print(row)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Bob', 'dev', 50000)\n", "('Sue', 'mus', 70000)\n", "('Ann', 'mus', 60000)\n", "('Tom', 'mgr', 100000)\n", "('Kim', 'adm', 30000)\n", "('pat', 'dev', 90000)\n" ] } ], "source": [ "curs.execute('select * from people')\n", "for row in curs:\n", " print(row)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `fetchmany` call returns a sequence of rows from the result, but not the entire table; you can specify how many rows to grab each time with a parameter or rely on the default as given by the cursor’s `arraysize` attribute. \n", "\n", "Each call gets at most that many more rows from the result or an empty sequence at the end of the table:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Bob', 'dev', 50000)\n", "('Sue', 'mus', 70000)\n", "('Ann', 'mus', 60000)\n", "('Tom', 'mgr', 100000)\n", "('Kim', 'adm', 30000)\n", "('pat', 'dev', 90000)\n" ] } ], "source": [ "curs.execute('select * from people')\n", "while True:\n", " rows = curs.fetchmany() # size=N optional argument\n", " if not rows: \n", " break\n", " for row in rows:\n", " print(row)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### More sophisticated Example" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(('name', None, None, None, None, None, None),\n", " ('job', None, None, None, None, None, None),\n", " ('pay', None, None, None, None, None, None))" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "curs.description" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "------------------------------\n", "name => Bob\n", "job => dev\n", "pay => 50000\n", "------------------------------\n", "name => Sue\n", "job => mus\n", "pay => 70000\n", "------------------------------\n", "name => Ann\n", "job => mus\n", "pay => 60000\n", "------------------------------\n", "name => Tom\n", "job => mgr\n", "pay => 100000\n", "------------------------------\n", "name => Kim\n", "job => adm\n", "pay => 30000\n", "------------------------------\n", "name => pat\n", "job => dev\n", "pay => 90000\n" ] } ], "source": [ "curs.execute('select * from people')\n", "colnames = [desc[0] for desc in curs.description]\n", "for row in curs:\n", " print('-' * 30)\n", " for (name, value) in zip(colnames, row):\n", " print('%s => %s' % (name, value))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercise:\n", "\n", "Convert list of row tuples to list of row dicts with field name keys." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# %load files/makedicts.py\n", "\"\"\"\n", "convert list of row tuples to list of row dicts with field name keys\n", "\"\"\"\n", "import sqlite3\n", "\n", "def makedicts(cursor, query, params=()):\n", " cursor.execute(query, params)\n", " colnames = [desc[0] for desc in cursor.description]\n", " rowdicts = [dict(zip(colnames, row)) for row in cursor]\n", " return rowdicts\n", "\n", "conn = sqlite3.connect('data/dbase1')\n", "cursor = conn.cursor()\n", "query = 'select name, pay from people where pay < ?'\n", "lowpay = makedicts(cursor, query, [70000])\n", "for rec in lowpay: \n", " print(rec)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercise no. 2\n", "\n", "Load Data from Text files: load table from comma-delimited text file." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "bob,devel,50000\r", "\r\n", "sue,music,60000\r", "\r\n", "ann,devel,40000\r", "\r\n", "tim,admin,30000\r", "\r\n", "kim,devel,60000" ] } ], "source": [ "!cat data/data.txt" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "bob,developer,80000\r", "\r\n", "sue,music,90000\r", "\r\n", "ann,manager,80000" ] } ], "source": [ "!cat data/data2.txt" ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: Coding Style (PEP8).ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Coding Style: PEP 8\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "You are now starting to write Python programs that have a little substance. Your programs are growing a little longer, and there is a little more structure to your programs. This is a really good time to consider your overall style in writing code." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Why do we need style conventions?\n", "---\n", "\n", "The people who originally developed Python made some of their decisions based on the realization that code is read much more often than it is written. The original developers paid as much attention to making the language easy to read, as well as easy to write. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Python has gained a lot of respect as a programming language because of how readable the code is. You have seen that Python uses indentation to show which lines in a program are grouped together. This makes the structure of your code visible to anyone who reads it." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "There are, however, some styling decisions we get to make as programmers that can make our programs more readable for ourselves, and for others." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "There are several audiences to consider when you think about how readable your code is." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Yourself, 6 months from now\n", "\n", "- You know what you are thinking when you write code for the first time. But how easily will you recall what you were thinking when you come back to that code tomorrow, next week, or six months from now? We want our code to be as easy to read as possible six months from now, so we can jump back into our projects when we want to." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### Other programmers you might want to collaborate with\n", "\n", "- Every significant project is the result of collaboration these days. If you stay in programming, you will work with others in jobs and in open source projects. If you write readable code with good commments, people will be happy to work with you in any setting." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### Potential employers\n", "\n", "- Most people who hire programmers will ask to see some code you have written, and they will probably ask you to write some code during your interview. If you are in the habit of writing code that is easy to read, you will do well in these situations." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "What is a PEP?\n", "---\n", "\n", "A PEP is a *Python Enhancement Proposal*. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "One of the earliest PEPs was a collection of guidelines for writing code that is easy to read. It was PEP 8, the [Style Guide for Python Code](http://www.python.org/dev/peps/pep-0008/). " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "When people want to suggest changes to the actual Python language, someone drafts a Python Enhancement Proposal. \n", "\n", "There is a lot in there that won't make sense to you for some time yet, but there are some suggestions that you should be aware of from the beginning. Starting with good style habits now will help you write clean code from the beginning, which will help you make sense of your code as well." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Basic Python style guidelines\n", "---\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### Indentation\n", "- Use 4 spaces for indentation. This is enough space to give your code some visual structure, while leaving room for multiple indentation levels. There are configuration settings in most editors to automatically convert tabs to 4 spaces, and it is a good idea to check this setting. On Geany, this is under Edit>Preferences>Editor>Indentation; set Width to 4, and Type to *Spaces*." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### Line Length\n", "- Use up to 79 characters per line of code, and 72 characters for comments. This is a style guideline that some people adhere to and others completely ignore. This used to relate to a limit on the display size of most monitors. Now almost every monitor is capable of showing much more than 80 characters per line. But we often work in terminals, which are not always high-resolution. We also like to have multiple code files open, next to each other. It turns out this is still a useful guideline to follow in most cases. There is a secondary guideline of sticking to 99 characters per line, if you want longer lines." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Many editors have a setting that shows a vertical line that helps you keep your lines to a certain length. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Blank Lines\n", "- Use single blank lines to break up your code into meaningful blocks. You have seen this in many examples so far. You can use two blank lines in longer programs, but don't get excessive with blank lines." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### Comments\n", "- Use a single space after the pound sign at the beginning of a line. If you are writing more than one paragraph, use an empty line with a pound sign between paragraphs." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### Naming Variables\n", "- Name variables and program files using only lowercase letters, underscores, and numbers. Python won't complain or throw errors if you use capitalization, but you will mislead other programmers if you use capital letters in variables at this point." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "That's all for now. We will go over more style guidelines as we introduce more complicated programming structures. If you follow these guidelines for now, you will be well on your way to writing readable code that professionals will respect." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Import statements\n", "---\n", "PEP8 provides clear guidelines about [where](http://www.python.org/dev/peps/pep-0008/#imports) import statements should appear in a file. The names of modules should be on separate lines:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# this\n", "import sys\n", "import os\n", "\n", "# not this\n", "import sys, os" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The names of classes can be on the same line:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from rocket import Rocket, Shuttle" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Imports should always be placed at the top of the file. When you are working on a longer program, you might have an idea that requires an import statement. You might write the import statement in the code block you are working on to see if your idea works. If you end up keeping the import, make sure you move the import statement to the top of the file. This lets anyone who works with your program see what modules are required for the program to work.\n", "\n", "Your import statements should be in a predictable order:\n", "\n", "- The first imports should be standard Python modules such as *sys*, *os*, and *math*.\n", "- The second set of imports should be \"third-party\" libraries. These are libraries that are written and maintained by independent programmers, which are not part of the official Python language." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Module and class names\n", "---\n", "Modules should have [short, lowercase names](http://www.python.org/dev/peps/pep-0008/#package-and-module-names). If you want to have a space in the module name, use an underscore.\n", "\n", "[Class names](http://www.python.org/dev/peps/pep-0008/#class-names) should be written in *CamelCase*, with an initial capital letter and any new word capitalized. There should be no underscores in your class names.\n", "\n", "This convention helps distinguish modules from classes, for example when you are writing import statements." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Exercises\n", "---\n", "#### Skim PEP 8\n", "- If you haven't done so already, skim [PEP 8 - Style Guide for Python Code](http://www.python.org/dev/peps/pep-0008/#block-comments). As you continue to learn Python, go back and look at this every once in a while. I can't stress enough that many good programmers will take you much more seriously from the start if you are following community-wide conventions as you write your code.\n", "\n", "#### Implement PEP 8\n", "- Take three of your longest programs, and add the extension *\\_pep8.py* to the filename of each program. Revise your code so that it meets the styling conventions listed above." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.28 : Skim PEP 8\n", "\n", "# put your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Ex 3.29 : Implement PEP 8\n", "\n", "# put your code here" ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: Importing Modules.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Modules" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Most of the functionality in Python is provided by *modules*. The Python Standard Library is a large collection of modules that provides *cross-platform* implementations of common facilities such as access to the operating system, file I/O, string management, network communication, and much more." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## References" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * The Python Language Reference: http://docs.python.org/3/reference/index.html\n", " * The Python Standard Library: http://docs.python.org/3/library/" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "To use a module in a Python program it first has to be imported. A module can be imported using the `import` statement." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "For example, to import the module `math`, which contains many standard mathematical functions, we can do:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import math" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This includes the whole module and makes it available for use later in the program. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "For example, we can do:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "import math\n", "\n", "x = math.cos(2 * math.pi)\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Alternatively, we can chose to import all symbols (functions and variables) in a module to the current namespace (so that we don't need to use the prefix \"`math.`\" every time we use something from the `math` module:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "from math import cos, pi\n", "\n", "x = cos(2 * pi)\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is called **selective Import**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This pattern can be very convenient, but in large programs that include many modules it is often a good idea to keep the symbols from each module in their own namespaces, by using the `import math` pattern. This would elminate potentially confusing problems with name space collisions." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Btw, in case of `namespace collisions` (or to avoid `namespace pollution`) we may use the `as` **keyword**" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from math import cos as cosine # Now the `cos` function can be referenced as `cosine`" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "6.123233995736766e-17" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cosine(pi/2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Finally, if we want to import **everything** from a module, we may the `*` character:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from math import *" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cosine Function: -1.0\n", "Sin Function: 1.2246467991473532e-16\n", "Logarithm: 1.0\n", "Power function: 27.0\n" ] } ], "source": [ "print(\"Cosine Function: \", cos(pi))\n", "print(\"Sin Function: \", sin(pi))\n", "print(\"Logarithm: \", log(e))\n", "print(\"Power function: \", pow(3, 3))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Looking at what a module contains, and its documentation" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Once a module is imported, we can list the symbols it provides using the `dir` function:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']\n" ] } ], "source": [ "import math\n", "\n", "print(dir(math))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "And using the function `help` we can get a description of each function (almost .. not all functions have docstrings, as they are technically called, but the vast majority of functions are documented this way). " ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function log in module math:\n", "\n", "log(...)\n", " log(x[, base])\n", " \n", " Return the logarithm of x to the given base.\n", " If the base not specified, returns the natural logarithm (base e) of x.\n", "\n" ] } ], "source": [ "help(math.log)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can also use the `help` function directly on modules: Try\n", "\n", " help(math) \n", "\n", "Some very useful modules form the Python standard library are `os`, `sys`, `math`, `shutil`, `re`, `subprocess`, `multiprocessing`, `threading`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## How Import Works" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because imports are at the heart of program structure in **Python**, this section goes into more formal detail on the import operation to make this process less abstract.\n", "\n", "In more details, this is particularly important as in Python, the import process is **not** just a textual insertions of one file into another. \n", "\n", "It really consists of a set of runtime operations that perform three distinct steps the first time a program imports a given file:\n", "\n", "1. *Find* the module file\n", "2. *Compile* it to byte code\n", "3. *Run* the module's code to build the objects it defines\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Find It" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, Python must locate the (module) file the code is trying to `import` (omitting extension and directory paths).\n", "\n", "To do so, Python applies a proper *module search path* algorithm. In particular, Python looks for the module to import in the following directories, and in the following order:\n", "\n", "1. The Home Directory of the program\n", "2. `PYTHONPATH` directories\n", "3. Standard library directories\n", "4. The contents of any `.pth` file (if present)\n", "5. The `site-packages` home of third-party extensions (e.g., `/usr/lib/python3/site-packages/`)\n", "\n", "(**More on this, later**)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Compile it" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After finding a source code file that matches an import statement by traversing the module search path, Python next compiles it to byte code, if necessary.\n", "\n", "In particular, in this step, the two choices are:\n", "\n", "* **Compile**: \n", "\n", "If the byte code file is older than the source file (i.e., if you’ve changed the source) or was created by a different Python version, Python automatically regenerates the byte code when the program is run.\n", "\n", "This model is modified somewhat in Python 3.2+ where byte code files are segregated in a `__pycache__` subdirectory and named with their Python version to avoid contention and recompiles when multiple Pythons are installed. \n", "\n", "This obviates the need to check version numbers in the byte code, but the timestamp check is still used to detect changes in the source.\n", "\n", "* **Don't Compile**:\n", "\n", "If, on the other hand, Python finds a `.pyc` byte code file that is not older than the corresponding `.py` source file and was created by the same Python version, it skips the source-to-byte-code compile step.\n", "\n", "In addition, if Python finds only a byte code file on the search path and no source, **it simply loads the byte code directly**.\n", "\n", "This means you can ship a program **as just byte code files** and avoid sending source. \n", "\n", "In other words, the compile step is *by-passed* if possible to speed program startup." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. Run it" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The final step of an import operation executes the byte code of the module.\n", "\n", "All statements in the file are run in turn, from top to bottom, and any assignments made to names during this step generate attributes of the resulting module object. \n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Modules & Packages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Modules** are probably best understood as simply packages of names - i.e., *places to define names you want to make visible to the rest of a system*. \n", "\n", "Technically, modules usually correspond to **files**, and Python creates a **module object** to contain all the names assigned in a module file. \n", "\n", "But in simple terms, modules are just namespaces (places where names are created), and the names that live in a module are called its *attributes*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In addition to a module name, an import can name a *directory path*. \n", "\n", "A directory of Python code is said to be a **package**, so such imports are known as package imports. \n", "\n", "In effect, a package import turns a directory on your computer into another Python namespace, with *attributes* corresponding to the *subdirectories* and *module files* that the directory contains." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Package Relative Imports" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The coverage of package imports so far has focused mostly on importing package files from *outside* the package.\n", "\n", "Within the package itself, imports of same-package files can use the same full path syntax as imports from outside the package. However, package files can also make use of special *intrapackage* search rules to simplify import statements. \n", "\n", "That is, rather than listing package import paths, imports within the package can be **relative** to the package." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The way this works is version-dependent: \n", "\n", "**Python 2.X** implicitly searches package directories first on imports, while **Python 3.X** requires explicit relative import syntax in order to import from the package directory. \n", "\n", "This 3.X change can enhance code readability by making same-package imports more obvious, but it’s also incompatible with 2.X and may break some programs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Python 3.3 changes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For imports in packages, though, Python 3.X introduces two changes:\n", "\n", "* It modifies the module import search path semantics to skip the package’s own directory by default. Imports check only paths on the sys.path search path. These are known as **absolute imports**.\n", "\n", "* It extends the syntax of `from` statements to allow them to explicitly request that imports search the package’s directory only, with leading dots. This is known as **relative import** syntax." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Examples:\n", "\n", "```python\n", "\n", "from . import spam\n", "\n", "from .spam import name\n", "\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Why Relative Imports?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consider the following package directory:\n", "\n", "```\n", " mypkg\\ \n", " __init__.py\n", " main.py \n", " string.py\n", "```\n", "\n", "This defines a package named `mypkg` containing modules named `mypkg.main` and `mypkg.string`. \n", "\n", "Now, suppose that the main module tries to import a module named `string`. \n", "\n", "In **Python 2.X** and earlier, Python will first look in the mypkg directory to perform a relative import. \n", "\n", "It will find and import the `string.py` file located there, assigning it to the name string in the `mypkg.main`\n", "module’s namespace.\n", "It could be, though, that the intent of this import was to load the Python standard library’s **string module** instead.\n", "\n", "Unfortunately, in these versions of Python, there’s **no straightforward** way to ignore `mypkg.string` and look for the standard library’s string module located on the module search path.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On the other hand, in Python 3.3+, you could:\n", "\n", "```python\n", "\n", "from string import punctuations # standard library module\n", "from .string import * # relative import (intrapackage)\n", "\n", "```" ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: Index.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Introduction to Python\n", "===\n", "Introduction to Python is a resource for students who want to learn Python as their first language, and for teachers who want a free and open curriculum to use with their students." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set Up Your Programming Environment\n", "\n", "If your computer is not yet set up to run Python programs, you may consider to take a look at the \n", "[Programming Environment](00 Programming Environment.ipynb) notebook.\n", "\n", "Otherwise, feel free to skip ahead!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Start Learning Python\n", "\n", "If your computer is already set up to run Python programs, you can get started with [Hello World](01 Hello World.ipynb), to test that everything works properly and fine." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Contents\n", "\n", "Please take a look at the [Table of Contents](toc.ipynb) to see a list of the topics covered throughout the notebooks, along with a brief description of each part." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Feedback\n", "\n", "If you have any questions or comments, feel free to get in touch:\n", "\n", "- **Twitter**: [@leriomaggio](https://twitter.com/leriomaggio)\n", "- **Email**: `valeriomaggio at gmail dot com`\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Contribute\n", "\n", "If you already know Python and would like to help contribute to the project, please see the project's [GitHub page](https://github.com/leriomaggio/python-in-a-notebook)." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Valerio Maggio Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Python in a Notebook # This repository contains a curated collection of Jupyter/IPython Notebooks of introductory materials about programming in Python. ## Goals ## Available notebooks are intended to aid both students and teachers in learning and teaching Python programming, respectively. In more details, the goals of this project are: - Introduce students as quickly as possible to the basics of Python programming; - Introduce best practice as early as possible, while remaining accessible to students with no background in programming at all; - Provide teachers an easy-to-use material about programming in Python to be used in their lectures ## Running Notebooks ## All you need to do to play notebooks is to open a Terminal, and type the following command: jupyter notebook **That's it!** :) ## Programming Environment These notebooks are written primarily in **Python 3**. If the default Python on your system is Python 3, then you will have a simpler time contributing to the project. If you only have Python 2, you might want to consider adding Python 3 to your system. In this regards, you may find useful to take a look at the *Programming Environment* [notebook]() where you could find links and details on how to set up your environment depending on your platform. ### Requirements ### * Python 3.x (2.x would work as well) * IPython 4.x (with **notebook support**) or Jupyter: * `pip install ipython[notebook]` (OR) * `pip install jupyter` ## License and Sharing Material Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. ================================================ FILE: Resources and References.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# References" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some of the notebooks included in this collection have been borrowed or adapted from the ones available in the [**Introduction to Python**](https://github.com/ehmatthes/intro_programming) project by [Eric Matthes](mailto:ehmatthes@gmail.com)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Documentation\n", "---\n", "\n", "For information related to Python programming, always refer to the [official Python documentation](https://docs.python.org/3/) (v3.5.1)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "#### Exploring the Python Community\n", "\n", "As I have said earlier, 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", "- [PyCon Italia](http://pycon.it)\n", "\n", " PyCon Italia is the Italian Python conference where professionals, researchers and lovers of the most beautiful programming language, gather together.\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": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Resources\n", "===\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A preliminary list of tutorials, talks, and challenges is provided below. This page will be updated frequently.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tutorials\n", "--\n", "\n", "- Google Python class - YouTube videos\n", "\n", " [Part 1(1)](https://www.youtube.com/watch?v=tKTZoB2Vjuk) - Introduction to Python and strings\n", " \n", " [Part 1(2)](https://www.youtube.com/watch?v=EPYupizJYQI) - Working with lists, tuples and sorting\n", " \n", " [Part 1(3)](https://www.youtube.com/watch?v=haycL41dAhg) - Working with dictionaries and files\n", " \n", " [Part 2(1)](https://www.youtube.com/watch?v=kWyoYtvJpe4) - Regular expressions\n", " \n", " [Part 2(2)](https://www.youtube.com/watch?v=uKZ8GBKmeDM) - Using modules, system commands\n", " \n", " [Part 2(3)](https://www.youtube.com/watch?v=Nn2KQmVF5Og) - Exceptions, parsing URLs\n", " \n", " [Part 2(4)](https://www.youtube.com/watch?v=IcteAbMC1Ok) - List comprehensions\n", "\n", "\n", "- [Guide for beginners who are non-programmers](https://wiki.python.org/moin/BeginnersGuide/NonProgrammers)\n", "\n", " Python's wiki page lists several resources for beginners.\n", "\n", "\n", "- [Python Tutor](http://pythontutor.com/)\n", "\n", " Python Tutor visually helps understand how code executes on a computer." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Talks\n", "--\n", "\n", "Pyvideos - Videos related to Python programming in different events including [Pycon](http://www.pycon.org/), [Scipy](https://conference.scipy.org/).\n", "\n", "Example: [Fast Python, Slow Python at Pycon 2014](http://pyvideo.org/video/2627/fast-python-slow-python)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Challenges\n", "--\n", "\n", "If you are equipped with basics of Python, taking up challenges is a great way to implement the skills.\n", "\n", "- [Google Python class exercises](https://developers.google.com/edu/python/exercises/basic)\n", "\n", " Four exercises are provided as part of the Python class by Google. \n", " \n", " Level - Basic/intermediate\n", " \n", "\n", "- [Project Euler](https://projecteuler.net/)\n", "\n", " Project Euler is a project of mathematical/programming challenges aimed at designing efficient solutions. Project Euler is a good place to challenge your mathematical and programming skills. Most of the problems can be solved within few seconds provided you have an efficient solution.\n", "\n", " Level - Advanced | Requires knowledge of mathematics.\n", "\n", "\n", "- [Python Challenge](http://www.pythonchallenge.com/)\n", "\n", " Level - Intermediate/Advanced\n", "\n", "\n", "\n" ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: The Zen of Python.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Zen of Python\n", "===\n", "The Python community is incredibly large and diverse. People are using Python in science, in medicine, in robotics, on the internet, and in any other field you can imagine. This diverse group of thinkers has developed a collective mindset about how programs should be written. If you want to understand Python and the community of Python programmers, it is a good idea to learn the ways Python programmers think.\n", "\n", "You can easily see a set of guiding principles that is written right into the language:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The Zen of Python, by Tim Peters\n", "\n", "Beautiful is better than ugly.\n", "Explicit is better than implicit.\n", "Simple is better than complex.\n", "Complex is better than complicated.\n", "Flat is better than nested.\n", "Sparse is better than dense.\n", "Readability counts.\n", "Special cases aren't special enough to break the rules.\n", "Although practicality beats purity.\n", "Errors should never pass silently.\n", "Unless explicitly silenced.\n", "In the face of ambiguity, refuse the temptation to guess.\n", "There should be one-- and preferably only one --obvious way to do it.\n", "Although that way may not be obvious at first unless you're Dutch.\n", "Now is better than never.\n", "Although never is often better than *right* now.\n", "If the implementation is hard to explain, it's a bad idea.\n", "If the implementation is easy to explain, it may be a good idea.\n", "Namespaces are one honking great idea -- let's do more of those!\n" ] } ], "source": [ "import this" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "There is a lot here. Let's just take a few lines, and see what they mean for you as a new programmer." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Beautiful is better than ugly.**\n", "\n", "Python programmers recognize that good code can actually be beautiful. If you come up with a particularly elegant or efficient way to solve a problem, especially a difficult problem, other Python programmers will respect your work and may even call it beautiful. There is beauty in high-level technical work." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Explicit is better than implicit.**\n", "\n", "It is better to be clear about what you are doing, than come up with some shorter way to do something that is difficult to understand." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Simple is better than complex.**\n", "**Complex is better than complicated.**\n", "\n", "Keep your code simple whenever possible, but recognize that we sometimes take on really difficult problems for which there are no easy solutions. In those cases, accept the complexity but avoid complication." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Readability counts.**\n", "\n", "There are very few interesting and useful programs these days that are written and maintained entirely by one person. Write your code in a way that others can read it as easily as possible, and in a way that you will be able to read and understand it 6 months from now. This includes writing good comments in your code." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**There should be one-- and preferably only one --obvious way to do it.**\n", "\n", "There are many ways to solve most problems that come up in programming. However, most problems have a standard, well-established approach. Save complexity for when it is needed, and solve problems in the most straightforward way possible." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Now is better than never.**\n", "\n", "No one ever writes perfect code. If you have an idea you want to implement it, write some code that works. Release it, let it be used by others, and then steadily improve it." ] } ], "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 } ================================================ FILE: data/data.txt ================================================ bob,devel,50000 sue,music,60000 ann,devel,40000 tim,admin,30000 kim,devel,60000 ================================================ FILE: data/data2.txt ================================================ bob,developer,80000 sue,music,90000 ann,manager,80000 ================================================ FILE: data/elderlyHeightWeight.csv ================================================ Gender Age body wt ht F 77 63.8 155.5 F 80 56.4 160.5 F 76 55.2 159.5 F 77 58.5 151 F 82 64 165.5 F 78 51.6 167 F 85 54.6 154 F 83 71 153 M 79 75.5 171 M 75 83.9 178.5 M 79 75.7 167 M 84 72.5 171.5 M 76 56.2 167 M 80 73.4 168.5 M 75 67.7 174.5 M 75 93 168 M 78 95.6 168 M 80 75.6 183.5 ================================================ FILE: data/male_data.tsv ================================================ M 79 75.5 171 M 75 83.9 178.5 M 79 75.7 167 M 84 72.5 171.5 M 76 56.2 167 M 80 73.4 168.5 M 75 67.7 174.5 M 75 93 168 M 78 95.6 168 M 80 75.6 183.5 ================================================ FILE: data/new_data.csv ================================================ Gender Age body wt ht ht_m F 77 63.8 155.5 1.555 F 80 56.4 160.5 1.605 F 76 55.2 159.5 1.595 F 77 58.5 151 1.51 F 82 64 165.5 1.655 F 78 51.6 167 1.67 F 85 54.6 154 1.54 F 83 71 153 1.53 M 79 75.5 171 1.71 M 75 83.9 178.5 1.785 M 79 75.7 167 1.67 M 84 72.5 171.5 1.715 M 76 56.2 167 1.67 M 80 73.4 168.5 1.685 M 75 67.7 174.5 1.745 M 75 93 168 1.68 M 78 95.6 168 1.68 M 80 75.6 183.5 1.835 ================================================ FILE: data/test.txt ================================================ Line 0 Line 1 Line 2 Line 3 Line 4 Line 5 Line 6 Line 7 Line 8 Line 9 ================================================ FILE: files/example.css ================================================ ================================================ FILE: files/makedicts.py ================================================ """ convert list of row tuples to list of row dicts with field name keys """ import sqlite3 def makedicts(cursor, query, params=()): cursor.execute(query, params) colnames = [desc[0] for desc in cursor.description] rowdicts = [dict(zip(colnames, row)) for row in cursor.fetchall()] return rowdicts conn = sqlite3.connect('data/dbase1') cursor = conn.cursor() query = 'select name, pay from people where pay < ?' lowpay = makedicts(cursor, query, [70000]) for rec in lowpay: print(rec) ================================================ FILE: multiplying.py ================================================ # Save as multiplying.py def double(x): return 2*x def triple(x): return 3*x def quadruple(x): return 4*x ================================================ FILE: rocket.py ================================================ from math import sqrt class Rocket(): # Rocket simulates a rocket ship for a game, # or a physics simulation. def __init__(self, x=0, y=0): # Each rocket has an (x,y) position. self.x = x self.y = y def move_rocket(self, x_increment=0, y_increment=1): # Move the rocket according to the paremeters given. # Default behavior is to move the rocket up one unit. self.x += x_increment self.y += y_increment def get_distance(self, other_rocket): # Calculates the distance from this rocket to another rocket, # and returns that value. distance = sqrt((self.x-other_rocket.x)**2+(self.y-other_rocket.y)**2) return distance class Shuttle(Rocket): # Shuttle simulates a space shuttle, which is really # just a reusable rocket. def __init__(self, x=0, y=0, flights_completed=0): super().__init__(x, y) self.flights_completed = flights_completed