{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Introduction to Jupyter and Python\n", "This is a [Jupyter](https://jupyter.org/) notebook.\n", "[Here is a Jupyter tutorial](https://youtu.be/Rc4JQWowG5I).\n", "\n", "This _cell_ is a [Markdown](http://daringfireball.net/projects/markdown/syntax) cell: it contains text with markup commands rather than executable computer code.\n", "\n", "You can also style text in a Markdown cell using html tags.\n", "\n", "Markdown cells in Jupyter support [MathJax](https://www.mathjax.org/), so you can write lovely typeset mathematics, e.g., $ e^{i\\pi} = -1$.\n", "\n", "$$\n", " e^x \\equiv \\sum_{j=1}^\\infty \\frac{x^j}{j!}.\n", "$$\n", "\n", "Here is a [demo of Markdown and MathJax in Jupyter](https://youtu.be/-F4WS8o-G2A)\n", "\n", "This particular Jupyter notebook is a Python notebook (there are also R and Julia notebooks, among other programming languages).\n", "This notebook is communicating with a Python kernel and can execute Python commands.\n", "\n", "[Here is an introduction to Python](https://www.python.org/about/gettingstarted/). \n", "\n", "For a more thorough introduction to Python for Science, see https://scipy-lectures.github.io/\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Jupyter\n", "\n", "Most of Jupyter's functionality is clear from its drop-down menus: commands to insert or delete cells, to execute cells, to clear output, etc.\n", "\n", "One of the most useful features of Jupyter is its help functions and tab completion.\n", "\n", "For instance, typing \"tab\" while you are typing the name of a function will give you a list of functions that start with the letters you have typed so far.\n", "\n", "Please click \"help\" and take the User Interface Tour.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python\n", "\n", "The rest of this notebook is a brief introduction to Python (within Jupyter). \n", "We will see more of Python in later sections of the course, as we encounter particular topics linear algebra, least squares, optimization, random number generation, the Bootstrap, etc." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello world! I'm so happy to be in Tokyo!\n" ] } ], "source": [ "# This is a code cell (but this line is a comment, because it starts with '#')\n", "# This is a Python notebook, so you can type Python commands into this cell, for example:\n", "print('Hello world! I\\'m so happy to be in Tokyo!')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "7\n", "7\n", "25\n", "2\n", "2.5\n" ] } ], "source": [ "# more Python\n", "\n", "# arithmetic\n", "print 5+2 \n", "print 5^2\n", "print 5**2\n", "print 5/2 # by default, division of integers is truncated.\n", "print 5/2.0" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.5\n" ] } ], "source": [ "# You will use many Python packages to get higher-level data constructs, functions, etc.\n", "# __future__ arithmetic doesn't truncate integer division\n", "from __future__ import division\n", "print 5/2" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "ename": "NameError", "evalue": "name 'sqrt' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msqrt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# sqrt is not in the core language. It's in the math package.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'sqrt' is not defined" ] } ], "source": [ "sqrt(4) # sqrt is not in the core language. It's in the math package." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.0\n" ] }, { "ename": "ValueError", "evalue": "math domain error", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msqrt\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[0;32m----> 3\u001b[0;31m \u001b[0;32mprint\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msqrt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# no complex arithmetic in the basic math package\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mValueError\u001b[0m: math domain error" ] } ], "source": [ "import math\n", "print math.sqrt(4)\n", "print math.sqrt(-1) # no complex arithmetic in the basic math package" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1j\n", "2.0\n", "(2+0j)\n" ] } ], "source": [ "import numpy as np # numeric Python. Lots of goodies.\n", "import scipy as sp # scientific Python. More goodies.\n", "\n", "print np.sqrt(-1+0j) # Python uses j to denote sqrt(-1). Numpy can take the square root of complex numbers\n", "print np.sqrt(4)\n", "print np.sqrt(4+0j)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "25\n", "5\n" ] } ], "source": [ "# variables\n", "x = 5\n", "print x\n", "print x**2\n", "y = x\n", "print y" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.14159265359\n", "2.71828182846\n" ] } ], "source": [ "# Python has some pre-defined values\n", "print math.pi\n", "print math.e" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "nan\n", "nan\n", "True\n", "False\n" ] } ], "source": [ "# not a number\n", "x = float('nan')\n", "print x\n", "print x + 1 # arithmetic with \"NA\" gives \"NA\"\n", "\n", "print math.isnan(x)\n", "print math.isnan(math.pi)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4]\n", "[1, 2, 3, 4]\n", "[1, 3, 5, 7, 9]\n", "[10, 9, 8, 7, 6]\n" ] } ], "source": [ "# ranges\n", "print range(5) # by default, ranges start at 0\n", "print range(1,5) # includes lower endpoint but not upper endpoint\n", "print range(1,10,2) # step size\n", "print range(10,5,-1) # negative steps are OK " ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 1. 1.5 2. 2.5 3. ]\n", "[ 3. 2.5 2. 1.5 1. ]\n", "[ 1. 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9]\n", "[ 3. 2.5 2. 1.5]\n" ] } ], "source": [ "# non-integer spaced ranges\n", "print np.linspace(1, 3, num=5) # 5 equispaced points between 1 and 3\n", "print np.linspace(3, 1, num=5) # 5 equispaced points between 3 and 1\n", "\n", "print np.arange(1, 2, step = 0.1) # go from 1 to 2 in steps of 0.1\n", "print np.arange(3, 1, step = -0.5) # from 3 to 1 in steps of -0.5\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "0\n", "4\n" ] }, { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m# Python uses 0-based indexing\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mprint\u001b[0m \u001b[0my\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[0;32m----> 8\u001b[0;31m \u001b[0;32mprint\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m# nothing there!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "# how long is a list?\n", "y = range(5)\n", "print len(y) \n", "\n", "# indexing a list\n", "print y[0] # Python uses 0-based indexing\n", "print y[4]\n", "print y[6] # nothing there!" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4, 2]\n", "6\n" ] } ], "source": [ "# you can append to lists\n", "y.append(2)\n", "print y\n", "print len(y)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4]\n", "4\n", "[0, 1, 2, 3]\n", "[0, 1, 2, 3, 4]\n", "1\n", "[0, 2, 3, 4]\n" ] } ], "source": [ "# you can pop elements from lists\n", "y = range(5)\n", "print y\n", "print y.pop() # remove and return the last element of the list\n", "print y # last element is gone now\n", "\n", "y = range(5)\n", "print y\n", "print y.pop(1) # remove and return the element in position 1 (recall Python uses 0-based indices)\n", "print y # element in position 1 is gone now" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 3]\n", "[2, 3, 4]\n", "[3, 4]\n", "[3 4]\n" ] } ], "source": [ "# slightly more advanced indexing\n", "#\n", "y = range(5)\n", "print y[2:4] # 3rd and 4th elements of y--remember, last element isn't included\n", "print y[2:5] # 3rd through 5th\n", "\n", "# logical indexing: easy to use list comprehensions. List comprehensions are a great Python language feature!\n", "ygt2 = [v for v in y if v > 2]\n", "print ygt2\n", "\n", "# alternatively, use a numpy array\n", "y = np.array(range(5))\n", "print y[np.where(y > 2)]" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0 1]\n", " [0 2]\n", " [1 3]]\n", "[[0 0 1]\n", " [1 2 3]]\n" ] } ], "source": [ "# build a matrix\n", "x = np.array([[0,1], [0,2], [1,3]])\n", "print x\n", "print x.T" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1 2 3 4 5]\n", " [ 6 7 8 9 10]]\n", "[[ 1 2 3 4 5]\n", " [ 6 7 8 9 10]\n", " [ 1 4 9 16 25]]\n", "[[ 1 6]\n", " [ 2 7]\n", " [ 3 8]\n", " [ 4 9]\n", " [ 5 10]]\n", "[[ 1 6 1]\n", " [ 2 7 4]\n", " [ 3 8 9]\n", " [ 4 9 16]\n", " [ 5 10 25]]\n" ] } ], "source": [ "# building arrays\n", "x = np.array(range(1,6))\n", "y = np.array(range(6, 11))\n", "\n", "# row binding\n", "print np.vstack((x,y)) # glue these together as rows\n", "print np.vstack((x,y,x**2))\n", "\n", "# column binding\n", "print np.vstack((x,y)).T # glue these together as columns\n", "print np.vstack((x,y,x**2)).T" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1. 1. 1. 1.]\n", " [ 1. 1. 1. 1.]\n", " [ 1. 1. 1. 1.]]\n", "[[ 0. 0. 0.]\n", " [ 0. 0. 0.]\n", " [ 0. 0. 0.]\n", " [ 0. 0. 0.]]\n" ] } ], "source": [ "# pre-defined arrays in numpy\n", "print np.ones((3,4))\n", "print np.zeros((4,3))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1. 1. 1. 1.]\n", " [ 1. 1. 1. 1.]\n", " [ 1. 1. 1. 1.]]\n", "[[ 1. 1. 1.]\n", " [ 1. 1. 1.]\n", " [ 1. 1. 1.]\n", " [ 1. 1. 1.]]\n" ] } ], "source": [ "# changing the dimension of an array\n", "x = np.ones((3,4))\n", "print x\n", "x = np.reshape(x, (4,3))\n", "print x" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 2 3 4]\n", "[ 1 4 9 16]\n", "[3 0 1 6]\n", "[ 1. 1.41421356 1.73205081 2. ]\n", "[ 0. 0.69314718 1.09861229 1.38629436]\n" ] } ], "source": [ "# operations on numpy arrays\n", "y = np.array(range(1,5))\n", "print y\n", "print y**2\n", "print y^2 # careful: the caret operator is bitwise XOR, not exponentiation!\n", "print np.sqrt(y)\n", "print np.log(y)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0 1]\n", " [0 2]\n", " [1 3]]\n", "[[ 1 3]\n", " [ 3 14]]\n", "[[ 2.8 -0.6]\n", " [-0.6 0.2]]\n", "[[ 1.00000000e+00 -1.11022302e-16]\n", " [ 0.00000000e+00 1.00000000e+00]]\n" ] } ], "source": [ "# linear algebra: linalg package in scipy\n", "x = np.array([[0,1], [0,2], [1,3]])\n", "print x\n", "xtx = np.dot(x.T, x) # matrix multiplication\n", "print xtx\n", "\n", "from scipy import linalg\n", "\n", "xtxInv = sp.linalg.inv(xtx) # matrix inversion is in the linalg part of scipy. \n", " # NOTE: generally should avoid inverting matrices\n", " # there are much better ways to solve linear systems\n", "\n", "print xtxInv\n", "\n", "print np.dot(xtx, xtxInv) # was that really the inverse?" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-0.6 0.2] [ 0. 0.]\n" ] } ], "source": [ "# solving linear systems: the linalg package in scipy\n", "\n", "b = np.array([0, 1])\n", "y = linalg.solve(xtx,b) \n", "print y, np.dot(xtx,y) -b" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0.49868413 0.47601081 0.55385093 0. ] [ 0.46695487 3.08249731 -7.61942371 4.67542972]\n", "difference: [-0.03172925 2.6064865 -8.17327463 4.67542972]\n" ] } ], "source": [ "# least squares: linalg package in scipy\n", "\n", "# build a quadratic with noise; fit a cubic\n", "\n", "import numpy.random\n", "\n", "n = 25\n", "\n", "x = np.linspace(0,1,n) # grid of x values\n", "A = np.vstack((np.ones(n), x, x**2, x**3)).T # Design matrix. The column of ones gives the constant term.\n", "\n", "# generate fake data\n", "coeffs = np.random.rand(3) # three independent uniform[0,1] variables\n", "coeffs = np.append(coeffs,0)\n", "y = np.dot(A, coeffs) + np.random.randn(n) # data are quadratic plus independent standard Gaussian noise\n", "\n", "fitc, err, rank, sigma = linalg.lstsq(A, y)\n", "\n", "print coeffs, fitc\n", "print 'difference:', fitc-coeffs" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nRK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# a little plotting\n", "# the %matplotlib inline call is a bit of \"magic\" so that plots display in the browser.\n", "%matplotlib inline \n", "import matplotlib.pyplot as plt # amazing matplotlib plotting library. See http://matplotlib.org/gallery.html\n", "\n", "preds = np.dot(A, fitc)\n", "\n", "# blue stars for data, red dashes for fitted function, green solid line for true function\n", "plt.plot(x,y,'b*',x,preds,'r--',x,np.dot(A,coeffs),'g-', linewidth=2) \n", "plt.axis([-0.1,1.1,-3,4]) # axis limits\n", "plt.xlabel('$x$') # axis labels. Can use LaTeX math markup\n", "plt.ylabel('$y$, predictions, truth')\n", "plt.title('Fit of cubic function to quadratic data with $N(0,1)$ errors')\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "False\n", "True\n", "False\n", "False\n", "False\n", "True\n" ] } ], "source": [ "# logical (Boolean) variables\n", "print True\n", "print False\n", "x = True\n", "print x\n", "print 1 == 2\n", "print 1 > 2\n", "print 1 >= 2\n", "print 1 != 2" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "True\n", "True\n", "False\n", "True\n", "False\n", "True\n" ] } ], "source": [ "# logical operators\n", "print not True\n", "print not False\n", "print True or False # logical \"or\"\n", "print False or False\n", "print True and True # logical \"and\"\n", "print True and False\n", "print not(True and False)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "True\n", "True\n", "True\n", "True\n" ] } ], "source": [ "# most numerical values can be cast as Booleans\n", "import math\n", "print 0 and True\n", "print 0 or True\n", "print 1 and True\n", "print math.pi and True\n", "print \"hello\" and True " ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[10 9 8 7 6]\n", "[ 6 7 8 9 10]\n", "[4 3 2 1 0]\n", "10 6 100 100\n", "40 [10 19 27 34 40]\n", "30240 [ 10 90 720 5040 30240]\n" ] } ], "source": [ "# sorting, max, min\n", "x = np.array(range(10,5,-1))\n", "print x\n", "print np.sort(x)\n", "# what permutation puts the list in sorted order?\n", "print np.argsort(x)\n", "#\n", "print np.max(x), np.min(x), np.max(x**2), np.max(x)**2\n", "print np.sum(x), np.cumsum(x)\n", "print np.prod(x), np.cumprod(x)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 3, 3]\n", "set([1, 2, 3])\n", "3\n", "True\n", "True\n", "False\n", "True\n", "True\n", "False\n", "False\n", "False\n", "False\n", "False\n", "True\n", "True\n", "True\n", "True\n", "set([1, 2, 3, 5, 6, 7, 8, 9])\n", "set([1, 2, 3, 5, 6, 7, 8, 9])\n", "set([1])\n", "set([1])\n", "set([2, 3])\n" ] } ], "source": [ "# Set operations\n", "x = [1, 2, 3, 3, 3]\n", "print x\n", "s = set(x)\n", "print s\n", "print len(s) # cardinality of s\n", "\n", "print 1 in s # is 1 an element of s?\n", "print 0 not in s #\n", "\n", "print s.isdisjoint([1, 2])\n", "print s.isdisjoint([0, 10])\n", "\n", "print s.issubset(range(1,5))\n", "print s <= range(1,5)\n", "print s.issubset(range(2))\n", "print s <= range(2)\n", "\n", "print s < range(1,5) # proper subset?\n", "print s < range(1,4)\n", "\n", "print s.issuperset(range(1,3))\n", "print s >= range(1,3)\n", "print s > range(1,4)\n", "print s > range(1,3)\n", "\n", "print s.union(range(5,10))\n", "print s | set(range(5,10))\n", "\n", "print s.intersection(range(2))\n", "print s & set(range(2))\n", "\n", "print s.difference(range(2))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "ename": "IndentationError", "evalue": "unindent does not match any outer indentation level (, line 10)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m10\u001b[0m\n\u001b[0;31m i =i+1 # indentation matters in Python! if this were indented more or less, it would complain\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m unindent does not match any outer indentation level\n" ] } ], "source": [ "# printing and flow control\n", "x = 3\n", "\n", "for i in range(x): # first flow control\n", " print x**i \n", "\n", "i =1\n", "while i <= 5: # second flow control\n", " print x**i\n", " i =i+1 # indentation matters in Python! if this were indented more or less, it would complain\n", " \n", "\n", "\n", "if 1 < 2: # third flow control\n", " print '1 is less than 2'\n", "\n", "\n", "if 2 < 1:\n", " print '2 is less than 1'\n", "else:\n", " print '2 is not less than 1'\n", "\n", "if 2 < 0:\n", " print '2 is less than 0'\n", "elif 2 < 1:\n", " print '2 is less than 1'\n", "else:\n", " print '2 is neither less than 1 nor less than zero'" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Next chapter: [Sets, Combinatorics, & Probability](prob.ipynb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%run talkTools.py" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }