{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 1: Control Structures" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#display the python version:\n", "import sys\n", "print(sys.version)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#simple for loop\n", "for i in range (1, 6):\n", " print(i)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# the range is not including the upper bound!\n", "# the \"body\" of the for block is defined by indentation. it can have multiple lines\n", "# building a string from variables is known as \"string interpolation\".\n", "for i in range (1, 7, 2):\n", " squared_i = i**2\n", " print(\"{0} times {0} is {1}\".format(i,squared_i))\n", "print(\"this is outside the loop\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Read some value from the console\n", "# Test conditions, execute code conditionally\n", "# indentation is important\n", "\n", "someInput = input(\"Type a number: \")\n", "#Note: we do not test if the input is a valid number. \n", "#Learn about Exeption Handling:\n", "# https://docs.python.org/2/tutorial/errors.html\n", "someNumber = int(someInput) \n", "\n", "if (someNumber < 10):\n", " print(\"The number {0} is smaller than 10.\".format(someNumber))\n", "elif (someNumber < 20):\n", " print(\"The number {0} is smaller than 20.\".format(someNumber))\n", " print(\"And the number {0} is larger or equal than 10.\".format(someNumber))\n", "else:\n", " print(\"{0} is a big number.\".format(someNumber))\n", "print(\"finished\") " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#let's play a game: the computer generates a random number,\n", "#you have to guess it\n", "\n", "#Use the random number generator defined in the random class\n", "import random as rand\n", "\n", "#specify the game parameters:\n", "lowerBound = 5;\n", "upperBound = 11;\n", "maxNrTrials = 5;\n", "\n", "#here starts the implementation of the game\n", "secretNumber = rand.randint(lowerBound, upperBound)\n", "print(\"The computer has generated a random number in the interval [{0},{1}]\" \\\n", " # \\ is a line break, the code continues here:\n", " .format(lowerBound, upperBound))\n", "\n", "#define a boolean variable, initialize it with False\n", "isSolved = False\n", "nrOfTrials = 0;\n", "\n", "# a while loop is repeating as long as the entry-condition is True.\n", "# note the logical negation operators \"not\" and \"and\":\n", "while ( (not isSolved) and (nrOfTrials < maxNrTrials)):\n", " guess = int(input(\"Enter your guess: \"))\n", " if secretNumber < guess:\n", " print(\"The secret number is smaller\")\n", " elif secretNumber > guess:\n", " print(\"The secret number is larger\")\n", " else:\n", " isSolved = True\n", " #in all cases, increment the counter variable by one\n", " nrOfTrials += 1 \n", "\n", "if isSolved:\n", " print(\"You solved the puzzle in {0} trials\".format(nrOfTrials))\n", "else:\n", " print(\"You lost. The secret number was: {0}. You did not find it in {1} trials. :-(\"\\\n", " .format(secretNumber, nrOfTrials))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "not True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 2: dealing with vectors and arrays: numpy\n", "\n", "read the docs: http://docs.scipy.org/doc/numpy/" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np \n", "\n", "a = np.array([3, 4])\n", "b = np.array([1, 2])\n", "print(np.linalg.norm(a)) # http://docs.scipy.org/doc/numpy/reference/routines.linalg.html\n", "print(np.dot(a,b))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#a convenient constructor:\n", "print(np.zeros( (2, 3) )) \n", "# how many parameters does the zeros method have? and of what type?\n", "# -> get used to read the API: \n", "# http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.ones.html#numpy.ones\n", "\n", "arrayShape = (2,4)\n", "anArray = np.ones(arrayShape)\n", "print(anArray)\n", "print(\"assign a value to an array element. note the zero based indexing!\")\n", "anArray[1, 0] = 10 \n", "print(anArray)\n", "print(\"get the size of an array\")\n", "print(anArray.shape)\n", "print(\"compare the size to that of a vector:\")\n", "a = np.array([3, 4])\n", "print(a.shape)\n", "print(\"reshape\")\n", "oneByNMatrice = np.reshape(a, (1,2))\n", "print(oneByNMatrice)\n", "print(oneByNMatrice.shape)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#indexing 2d arrays\n", "print(\"initialze a 2-dim array with specific values\")\n", "anArray = np.array( [[0, 1, 2], [10, 11, 12], [20, 21, 22]])\n", "print(anArray)\n", "\n", "print(\"access specific rows and columns:\")\n", "print(anArray[0,:])\n", "print(anArray[:, 1])\n", "\n", "print(\"index from the end:\")\n", "print(anArray[:, -1])\n", "\n", "print(\"get all columns from the first and second row\")\n", "b=anArray[0:2 , :]\n", "print(b)\n", "\n", "print(\"get all rows from the first and third column\")\n", "c=anArray[:, [0, 2]]\n", "print(c)\n", "\n", "print(\"get the diagonal elements\")\n", "print(np.diag(anArray))\n", "\n", "print(\"todo: logical indexing\")\n", "\n", "#learn more about indexing, slicing, ...\n", "# https://docs.scipy.org/doc/numpy-dev/user/quickstart.html\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#get ten values in an interval: linspace or logspace\n", "v1 = np.linspace(1, 2, 5)\n", "print(v1)\n", "v2 = np.logspace(1, 2, 5)\n", "print(v2) #did you expect that result? read-the-docs \n", "#ok,taking log, what do you expect now:\n", "print(np.log(v2))\n", "print(np.log10(v2))\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#more about matrices, use of np.random\n", "print(\"compute the determinant of a 3x3 random matrix\")\n", "myRandomMatrix = np.random.rand(3,3)\n", "print(myRandomMatrix)\n", "determinant = np.linalg.det(myRandomMatrix)\n", "print(determinant)\n", "print(\"Note the size of a 3d VECTOR, it's not a 1 by 3 matrix:\")\n", "randVector = np.random.rand(3)\n", "print(randVector)\n", "print(randVector.size)\n", "\n", "print(\"round to 2 decimals\")\n", "#note the \"named\" parameter decimals. This sometimes improves the readability\n", "roundedValues = np.around(randVector, decimals=2) \n", "#roundedValues = np.around(randVector, 2) \n", "print(roundedValues)\n", "\n", "# matrix multiplication\n", "# matrices\n", "print(\"initialze a 2-dim array with specific values\")\n", "A = np.array( [[0, 1, 2], [10, 11, 12]])\n", "print(\"A\")\n", "print(A)\n", "B = np.array([[1], [2]])\n", "print(\"B\")\n", "print(B)\n", "print(\"A transposed times B\")\n", "print(np.dot(A.transpose(),B))\n", "C = np.random.random_sample(A.shape) # random_sample is the same as rand but takes a shape param\n", "print(\"element wise addition and multiplication\")\n", "print(np.add(A,C))\n", "print(A + C)\n", "print(np.multiply(A,C))\n", "print(A * C)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "other datatypes: **Lists**\n", "\n", "Note: vectors and arrays shown above are the Python implementation of the corresponding mathematical objects. \n", "Sometimes they are not the most convenient way to store data. There are many other ways to store and access values. Datastructures are a topic on their own. We only give an example of lists:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(\"initialize an empty list\")\n", "myList = []\n", "print(\"lists are a dynamic datastructure. it grows as we add elements\")\n", "myList.append(\"This\")\n", "myList.append(\"is\")\n", "#append another list:\n", "myList.extend([\"a\", \"list\"])\n", "print(myList)\n", "print(\"pop the last element from the list. \")\n", "print(myList.pop())\n", "print(\"default sorting\")\n", "myList.sort()\n", "print(myList)\n", "print(\"case insensitive sorting\")\n", "myList.sort(key=str.lower)\n", "#iterate over all elements:\n", "for someElement in myList:\n", " print(someElement)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 3: some math and the use of matplotlib\n", "\n", "Here's the doc:\n", "\n", "http://matplotlib.org\n", "\n", "The fastest way to learn matplotlib, is to browse the examples:\n", "http://matplotlib.org/gallery.html\n", "\n", "What is a figure, an axes, a subplot? That can be confusing. Read this:\n", "\n", "http://matplotlib.org/faq/usage_faq.html\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#the following directive needed in notebooks only, not in your files\n", "%matplotlib inline \n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "x= np.arange(-2*np.pi, 2*np.pi, 0.05)\n", "y_sine = np.sin(x)\n", "y_cosine = np.cos(x)\n", "# we use the pyplot class plt to make a plot\n", "plt.plot(x, y_sine)\n", "plt.plot(x, y_cosine, '--r') #set the line style\n", "plt.axes().set_aspect('equal', 'datalim')\n", "plt.grid()\n", "plt.xlabel(\"x\")\n", "plt.ylabel(\"y=f(x)\")\n", "#for some properties we need a reference to the figure:\n", "#f = plt.figure()\n", "plt.title(\"sine and cosine\")\n", "plt.legend((\"sine\", \"cosine\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# a nested loop demo\n", "# array indexing\n", "# compute some values and store them in an array. visualize the values.\n", "# for more advanced plotting: http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html\n", "\n", "products = np.zeros([10, 10])\n", "for i in range(1, 11):\n", " for k in range (1, 11):\n", " i_times_k = i*k \n", " products[i-1, k-1] = i_times_k #note: indexing is zero based\n", "\n", "plt.imshow(products)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Part 4: Copying and slicing lists and numpy arrays\n", "\n", "Certain features of Python might lead to unwanted behaviour and serious mistakes, if one is not aware of them. \n", "\n", "* Assigning a list to a new variable does not create a copy of the list, but creates a variable that points to the list. This means that modifying the second variable, also modifies the original list.\n", "* Assigning a slice of a list to a new variable, creates a copy of the list. Any modification to the sliced list does not modify the original.\n", "\n", "Check the outcome of the following commands:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "*** Copying a list and modifying 1 element ***\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 99, 3, 4, 5, 6]\n", "[1, 99, 3, 4, 5, 6]\n", "\n", "\n", "*** Slicing a list and modifying 1 element ***\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 2, 3, 4]\n", "[1, 99, 3, 4]\n", "[1, 2, 3, 4, 5, 6]\n", "\n", "\n", "*** Copying a list via slicing and modifying 1 element ***\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 99, 3, 4, 5, 6]\n", "[1, 2, 3, 4, 5, 6]\n", "\n", "\n" ] } ], "source": [ "print \"*** Copying a list and modifying 1 element ***\"\n", "a = [1, 2, 3, 4, 5, 6]\n", "print a\n", "b = a\n", "print b\n", "b[1] = 99\n", "print b\n", "print a\n", "print \"\\n\"\n", "\n", "print \"*** Slicing a list and modifying 1 element ***\"\n", "a = [1, 2, 3, 4, 5, 6]\n", "print a\n", "c = a[0:4]\n", "print c\n", "c[1] = 99\n", "print c\n", "print a\n", "print \"\\n\"\n", "\n", "print \"*** Copying a list via slicing and modifying 1 element ***\"\n", "a = [1, 2, 3, 4, 5, 6]\n", "print a\n", "d = a[:]\n", "print d\n", "d[1] = 99\n", "print d\n", "print a\n", "print \"\\n\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now when it comes to numpy arrays\n", "* Assigning a numpy array to a new variable does not create a copy of the array, but creates a variable that points to the array. This means that modifying the second variable, also modifies the original array. (same as above)\n", "* Assigning a slice of a numpy array to a new variable creates a variable that points to the corresponding elements of the original array as well! (contrary to what we saw above!) This means that modifying the second variable, also modifies the original array!\n", "* To copy the original array and ensure that it is not modified by any modification of its copied version, the method copy() should be used.\n", "\n", "Check the outcome of the following commands:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "*** Copying a numpy array and modifying 1 element ***\n", "[1 2 3 4 5 6]\n", "[1 2 3 4 5 6]\n", "[ 1 99 3 4 5 6]\n", "[ 1 99 3 4 5 6]\n", "\n", "\n", "*** Slicing a numpy array and modifying 1 element ***\n", "[1 2 3 4 5 6]\n", "[1 2 3 4]\n", "[ 1 99 3 4]\n", "[ 1 99 3 4 5 6]\n", "\n", "\n", "*** Copying a numpy array via slicing and modifying 1 element ***\n", "[1 2 3 4 5 6]\n", "[1 2 3 4 5 6]\n", "[ 1 99 3 4 5 6]\n", "[ 1 99 3 4 5 6]\n", "\n", "\n", "*** Literally copying a numpy array and modifying 1 element ***\n", "[1 2 3 4 5 6]\n", "[1 2 3 4 5 6]\n", "[ 1 99 3 4 5 6]\n", "[1 2 3 4 5 6]\n", "\n", "\n" ] } ], "source": [ "import numpy as np\n", "print \"*** Copying a numpy array and modifying 1 element ***\"\n", "a = np.array([1, 2, 3, 4, 5, 6])\n", "print a\n", "b = a\n", "print b\n", "b[1] = 99\n", "print b\n", "print a\n", "print \"\\n\"\n", "\n", "print \"*** Slicing a numpy array and modifying 1 element ***\"\n", "a = np.array([1, 2, 3, 4, 5, 6])\n", "print a\n", "c = a[0:4]\n", "print c\n", "c[1] = 99\n", "print c\n", "print a\n", "print \"\\n\"\n", "\n", "print \"*** Copying a numpy array via slicing and modifying 1 element ***\"\n", "a = np.array([1, 2, 3, 4, 5, 6])\n", "print a\n", "d = a[:]\n", "print d\n", "d[1] = 99\n", "print d\n", "print a\n", "print \"\\n\"\n", "\n", "print \"*** Literally copying a numpy array and modifying 1 element ***\"\n", "a = np.array([1, 2, 3, 4, 5, 6])\n", "print a\n", "b = a.copy()\n", "print b\n", "b[1] = 99\n", "print b\n", "print a\n", "print \"\\n\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "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.13" } }, "nbformat": 4, "nbformat_minor": 0 }