{ "metadata": { "name": "", "signature": "sha256:ee82a62a6e2d275936b4aaf4c0d99ca35f33a2f43d7c8859c8d089f2b1824d8c" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Introduction to programming 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Clyde Fare and Jo\u00e3o Pedro Malhado, Imperial College London (contact: [python@imperial.ac.uk](mailto:python@imperial.ac.uk))\n", "\n", "\n", "This notebook is licensed under a [Creative Commons Attribution 4.0 (CC-by) license](http://creativecommons.org/licenses/by/4.0)" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Overview" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You are by now familiar with the basic \"pieces\" that form a program is the form of variables of different types. We have also introduced *if* statements as a mechanism to introduce \"adaptability\" into the code according to circumstances.\n", "\n", "In this workshop we will introduce another data type, lists, as collections of data, and loops, which are the major work horse in many programming languages." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Grouping data together" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the previous workshop we have looked at three basic data types used in programming: numbers, strings and booleans. All programs can in principle be written using just these data types, but to solve many problems it is often useful to use more sophisticated data types, provided by the programming language (or some extension).\n", "\n", "A useful and versatyle data structure provided by Python are *lists*, and we will be making use of these during this course." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "List" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists provide a way of keeping and treating data together. We can create a list by putting its elements in a comma separated list enclosed in square brackets.\n", "\n", " days_of_the_week = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that we have created an object with a different type\n", "\n", " type(days_of_the_week)" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access the members of a list using the *index* of that item:\n", "\n", " days_of_the_week[2]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The index is an integer which specifies the element we want. A little confusingly Python uses 0 as the index of the first element of a list. Thus, in this example, the 0 element is \"Sunday\", 1 is \"Monday\", and so on. \n", "\n", "If we want to count back from the last element of a list we use a negative index. An index of -1 corresponds to the last element of the list, whilst an index of -2 corresponds to the second to last element, -3 the third last, etc.\n", "\n", " days_of_the_week[-1]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we try and provide an index that goes beyond the last element of a list Python will throw an IndexError (this is a common error in programming)\n", "\n", " days_of_the_week[8]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As an excercise, retrieve \"Thursday\" from the list days_of_the_week." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Besides selecting individual elements, we can also select ranges within the list using two integer numbers separated by a colon ':'. The sublist starts with the element defined by the starting index and include all elements upto **but not including** the element defined by the ending index. This process is called *slicing*\n", "\n", " working_days=days_of_the_week[1:6]\n", " working_days" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This behaviour of indexes can seem strange at first. It is perhaps helpful to think of the indexes when slicing as pointing *between* list elements, to the comma.\n", "\n", " [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\n", " | | | | | | | |\n", " 0 1 2 3 4 5 6 7\n", " \n", "When slicing between 1 and 6, we are including the elements between the commas so numbered. This is a picture that can help you visualize what is going on and it should not be taken too literally." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we ommit the ending index, the sublist will include all elements until the end of the list\n", "\n", " catholic_working_days=days_of_the_week[1:]\n", " catholic_working_days" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Conversely, if we ommit the starting index, the elements will be taken from the beginning of the list.\n", "\n", "Define a variable jewish_working_days, including all the elements of days_of_the_week, except \"Saturday\"." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Besides extracting elements of the list, indexes can also be used to modify parts of the list\n", "\n", " days_of_the_week[1]=\"Bank holiday\"\n", " days_of_the_week" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also specify a range in doing this\n", "\n", " days_of_the_week[1:3]=[\"Hard work\",\"Hard work\"]\n", " days_of_the_week" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We may specify discontinuous ranges on the list, by indicating a third number after another colon. This is a step index, specifying the increment to the list index.\n", "\n", " sport_days=days_of_the_week[1:6:2]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This slicing mechanism can also be used to insert elements in the list\n", "\n", " days_of_the_week[5:5]=[\"Extra day\"]\n", " days_of_the_week" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once more we can think of the slicing indexes as pointing between list elements. In the \"space between\" list elements, we are assigning a new element, an insertion into the list." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists are very general and its elements do not have to have the same data type. For example, we can have both strings and number is the same list\n", "\n", " [\"Today\", 7, 99.3, \"\", 5**2]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "List elements can even be other lists. Tables of data usually take this form\n", " \n", " outer_list=[[\"dozens\",\"units\"],[0.5,6],[1,12],[2,24]]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just as we can access the members of a list with an index:\n", "\n", " outer_list[2]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So too we can access the members of an inner list by an extra index (do not confuse this notation with the list range we used above)\n", "\n", " outer_list[2][1]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The indices are operating sequencially. We can use round brakets to make this clearer.\n", "\n", " (outer_list[2])[1]\n", " \n", "The first index, is selecting from outer_list the element index 2, which is the list [1,12]. The second index is selecting from this list the elements index 1." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the above looks a bit confusing here's an alternative way of getting the same answer that shows what's happening when this double index is being used:\n", "\n", " inner_list = outer_list[2]\n", " inner_element = inner_list[1]\n", " inner_element" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Operations on lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are many operations involving lists provided by the Python language. We shall not try to be exaustive, we will start with a few simple operations that will allow us to do most of the work, and introduce useful features as we go along.\n", "\n", "First we will note a certain analogy between lists and strings: lists are an ordered collection of elements, while strings are ordered collections of characters. Indeed we can use indexing in strings in a similar way we used them with lists\n", "\n", " analogy=\"A string is an ordered collection of characters\"\n", " analogy[0]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ " analogy[15:33]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We could thus expect that some of the operations on strings could have a similar behaviour on lists. We can thus use the function *len* to determine the lentgh of a list\n", "\n", " len(days_of_the_week)" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Try to predict the result of the following command\n", "\n", " len(days_of_the_week[1:5])" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use the opertor '+' to perform list concatenation, and can be used to build bigger lists\n", "\n", " [1,2,3]+[4,5,6]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ " [1,2,3]+[\"something\"]+[10]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The operator \\* with an integer yields the repetition of the list elemets\n", "\n", " 5*[0,1]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ " 3*[[1,2]]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Extra: Variations of lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Besides lists, Python posesses other similar data structures with somewhat different properties that make them more suited for some applications. We shall not be making use of these during the course as lists are more general, but you may find them when looking at code written by others.\n", "\n", "Below we cover only the simplest properties of these other data structures, but you can [read more](http://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences) about them elsewhere." ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Tuples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tuples are indicated by round brackets\n", "\n", " tup=(1,2,3,4,\"last\")" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access its elements like lists\n", "\n", " tup[1:3]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But we cannot change its content\n", "\n", " tup[0]=20" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sets are indicated by a sequence inside curly brackets (or the *set()* function). While lists can have many repeated elements, sets eliminate the redundancy and only keep one element of each\n", "\n", " set([1,1,1,2,2,2])" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we make a set from a string, the string is \"destroyed\" as we obtain a set with all characters used in the string, but lose the order that potentialy gave meaning to the string\n", "\n", " set(\"The quick brown fox jumps over the lazy dog!\")" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Dictionaries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While list are accessed by a position index, dictionaries are accessed by a label\n", "\n", " atomic_number={\"He\":2,\"Ne\":10,\"Ar\":18,\"Kr\":36,\"Xe\":54,\"Rn\":86}" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ " atomic_number[\"Ar\"]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Arrays" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Arrays are not a part of the standard Python language, but they are part of the module [NumPy](https://docs.scipy.org/doc/numpy/user/quickstart.html) which is very useful in scientific applications. We will be looking in more detail on how to use external modules, here, to use arrays just execute the following line" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from numpy import array" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Although arrays can be formed of different data types, the most useful ones are fomerd with just numbers.\n", " \n", " array([1,2,3])" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the square brackets inside the round brackets.\n", "\n", "As the notation above suggests, lists of numbers (but also tupples) can be transformed into arrays using the *array()* function\n", "\n", " l=[3,2,1]\n", " array(l)" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One of the reasons arrays are so useful is that behave like vectors\n", "\n", " 2*array([1,1.1,2.5,0])" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ " array([-1,0,1])+array([1,2,-20])" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will not be using arrays further in this course, but if you want to investigate further you can look into the [NumPy documentation](http://docs.scipy.org/doc/numpy/user/index.html) or another of the [Imperial College courses](https://github.com/imperialchem/python-data-viz-intro)." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Summary" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "List provide a way to group together and manipulate data. Imagine we were dealing with a dataset with the maximum temperature of every day in the year. It would be unpractical if we had to assign each value to a different variable.\n", "\n", "Lists can contain data of any type at the same time. We can also have lists of lists.\n", "\n", "We learned how to access different elements inside a list.\n", "\n", "We will next be looking at loops, which allow for manipulating lists in a more versatile way." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Revision on data types, lists, an a little more" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the previous workshop of this series we looked at different data types used in programing, and associated operations. Different types of numbers (integers, floating point, complex); strings; booleans; and the data grouping type list. The function *type()* tests for the data type of a given object.\n", "\n", " one=1\n", " type(one==1)" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do you apreciate the difference between '=' and '==' above?\n", "The following expression encapsulates several of the concepts introduced in the previous workshop\n", "\n", " mixtype=[1.0,\"1\",1,2j**2/(-4),[3**0]]" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is the data type of the variable just defined?" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Can you identify the data type of all elements of the mixtype list? Use the cell below to test the different elements of the list." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is the data type of the element inside the last element of mixtype?" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How to proceed to retrieve last three elements of mixtype?" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To achieve these tasks we have retrieved parts of the content of the list by specifying its position on the list, or equivalently its index. We can also test for the presence of a given element inside the list by using the keyword *in*\n", "\n", " 0 in mixtype" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the output of the operation is not the element of the list but a boolean. The construction\n", "\n", " 0 in mixtype\n", "\n", "could be translated into english as the question\n", "\n", " Is 0 inside mixtype?\n", " \n", "This is a \"yes or no\" question, and thus the boolean reply.\n", "\n", "Now pose a \"question\" on mixtype that would be True." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the last workshop we noticed the analogy between lists and strings. The keyword *in* can also be used to test for substrings inside strings\n", "\n", " \"banana\" in \"bananarama\"" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use the boolean result of this operation in an *if* statement\n", "\n", " if \"banana\" in \"bananarama\":\n", " result=\"I love the eighties!\"\n", " else:\n", " result=\"Please choose a more exciting fruit\"\n", " \n", " result" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Repeating instructions: loops" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The main use of machines is to do things people cannot do, or to repeat the same task many times over. Computers are particularly suited to repeat logical tasks, and can do this in a much more efficient way than people. When programming a computer, repeating tasks is achieved via *loops*, which are a corner stone of many programming languages.\n", "\n", "In Python there are two types of loops: *for* loops are used when the number of repetitions is known *a priori*; *while* loops repeat the instruction until a specific test condition fails. We will look at how these two types of loops work in more detail." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "For loops" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before starting looking at *for* loops, it is useful to look at the function *range()*. In doing so, we remind ourselves of how to obtain information about a particular function, or any other defined object. This is done by appending a question mark after the object name\n", "\n", " range?" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On the window that poped up below, we can see the information about what the function *range* does. You should not be shy about using this functionality, use it whenever you have doubts about what a given object is or does.\n", "\n", "As the documentation about the function suggets, the range() function generates a virtual sequence of numbers, a sort of a counter, technically an iterator. If we use the function on its own we don't quite see what is happening\n", "\n", " range(6)" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Things become clearer when we make the result of the function range() explicit by transforming it into a list\n", "\n", " list(range(6))" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When the function range is called with one argument, range() creates a sequence of numbers starting from 0 up to, but not including, the number specified. In this case, a sequence starting from 0 and ending in 5.\n", "\n", "A sequence starting on any other value can be created, by calling range() with 2 arguments\n", "\n", " list(range(2,6))" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The number sequence is incremented by one by default, but we can specify any other increment with a third argument\n", "\n", " list(range(0,10,2))" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A decreasing sequence can be specifies with a negative step value, and in this case the start of the sequence is greater than the end\n", "\n", " list(range(6,0,-1))" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we have a counter at hand, we can use it to guide a for loop. A very simple piece of code involving a for loop, that repeatedly prints a string to the screen, would be:\n", "\n", " for i in range(20):\n", " print(\"All work and no play makes Jack a dull boy.\")\n", " print(\"I had enough!\")" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us analyse in a bit more detail how this code is operating. The first line\n", "\n", " for i in range(20):\n", " \n", "iniciates the loop. In plain english it could read something like:\n", "\n", " For each element we choose to call 'i' in the virtual counter range(20), execute the code that follows.\n", "\n", "Since our virtual counter has 20 elements, the loop will run 20 times.\n", "\n", "As with the *if* statement before, below the initial line and indented, we write the instructions to be executed at each loop cycle: the loop body. In this case, we print a string to the screen.\n", "\n", "The last print statement in our piece of code is not indented, it is **not** part of the loop body, and therefore will be executed after the loop has finished and only once.\n", "\n", "We re-examine the first line of the *for* loop to note that the element *i* is a variable that takes on a different value of range(20) (in this case) for each cycle of the loop. As with any variable, we could have used any name that we see fit, and we could use that variable within the loop body\n", "\n", " for counter_number in range(1,20,2):\n", " print(\"Sheep number \",counter_number)\n", " print(\"The shepherd counted\",counter_number,\"sheep\")" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that after the loop ends the loop variable can still be used and has the last value assigned.\n", "\n", "Instead of range(), we can also use any list in the loop definition. The loop variable will assume each value on the list, and the loop stops when the list reaches the end.\n", "\n", " for item in [0,\"Wittgenstein\",1/137,\"\u5b54\u592b\u5b50\"]:\n", " print(\"List element \",item)" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So far we have looked only at very simple loop bodies with only one print statement. In general, the loop body will contain some more sophisticated operation\n", "\n", " for item in [0,\"Wittgenstein\",1/137,\"\u5b54\u592b\u5b50\"]:\n", " if type(item)==str:\n", " print(item)\n", " else:\n", " print(\"Do not bother\")" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Loops are a fundamental part of programming, it is very important that you understand how they work. If there is anything that is not clear in the examples above, please ask a demonstrator.*" ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Some loops in action" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Loops are the work horse of many programs, and when writing programs in the future more often than not you will be using at least one loop. Now that we have some basic understanding of the *for* loop functionality, we will look at some examples where it is used to perform some meaningful tasks.\n", "\n", "We will now pretend that we don't know about the existence of function *len()* and will want to determine the length of a list *l* using a loop. First it is important to acknowledge that we could determine the length of a list by adding 1 repeatedly for each element of the list. Indeed the simple act of counting consists of successively incrementing our \"counter\" by 1. The recognition of the existence of a repetitive pattern is what indicates that we can use a loop to achieve the task.\n", "\n", "In order to determine the length of a list, we can define a variable *length* which we will update in the loop body as we \"travel\" through the list\n", "\n", " l=[0,\"Wittgenstein\",1/137,\"\u5b54\u592b\u5b50\"]\n", " \n", " length=0\n", " for i in l:\n", " length=length+1\n", " length" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This type of general structure is fairly common when using loops. \n", "\n", "* Define a *result* variable (in this case called *length*)\n", "* Give it an appropriate starting value (in our case, before the loop starts, we have not counted in any elements yet so we set length=0)\n", "* Set up the loop, where it starts and where it ends (in this case we loop over all elements of the list *l*)\n", "* Update the result variable in the loop body (we redefine the length variable at each step by adding 1 to the current value: length=length+1)\n", "* When the loop ends we should have the result variable should have the value we are looking for\n", "\n", "Note that in this case we are not making use of the loop variable *i* which is taking each value in the list, but we need to specify it in defining the loop.\n", "\n", "To make clearer how the loop is operating, we can insert a few print() statements. Note that inside the loop the print() statement comes after the *length* variable changes\n", "\n", " length=0\n", " print(\"Before the loop starts, length=\",length)\n", " \n", " for i in l:\n", " length=length+1\n", " print(\"In this loop cycle, the list element is \",i,\", and length=\",length)\n", " \n", " print(\"At the end of the loop, length=\",length)\n", " length" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Try now to adapt the code above to count the number of elements of the list *l* which are of type string. You can store this value as variable *string_count*." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another example is how to calculate the factorial of a number *n* using a loop (we again pretend that such a function does not exist in the math python module). Once more, it is important to recognise that the calculation of a factorial can be seen as a repetition of multiplications of increasing integer numbers up to *n*.\n", "\n", "Following the same general structure as before: we define the result variable as *factorial*; set up a loop going from 1 to *n*; update *factorial* in the loop body.\n", "\n", " n=99\n", " \n", " factorial=1\n", " for i in range(1,n+1):\n", " factorial=factorial*i\n", " factorial" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That is a big number!\n", "\n", "Note the use of n+1 when using range(). Is it clear why we did it that way?\n", "\n", "If it is not clear how the code above is operating, choose a smaller value of *n* and insert some print() statements to guide you.\n", "If it is still not clear, do ask a demonstrator.\n", "\n", "Loops can be used to build lists by starting with an empty list and repeatedly adding new elements to it. Let us build a list with integer powers of 11 between -5 and 5.\n", "\n", " powers11=[]\n", " for i in range(-5,6):\n", " powers11=powers11+[11**i]\n", " powers11" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The way we are incrementaly building the list is by at each cyle creating a single element list with the element we wish to add (in this case [11\\*\\*i]) and using the list concatenation operator '+' to join it to the existing list.\n", "\n", "The use of loops is very common when dealing with lists and transformations on lists. This is because we often want to apply a given operation or test to all elements of the list. As an example we will look on how to extract all the multiples of 3 from a list.\n", "\n", "We will go through all the elements of the list (here we will take a sequence of numbers between 1 and 20), test if the element is a multiple of 3, and if this is true we add this element to our result variable. The result variable is thus a new list, we will call mult3, that is initially empty and we incremently construct inside the loop.\n", "\n", " sequence=list(range(1,21))\n", " \n", " mult3=[]\n", " for i in sequence:\n", " if i%3 == 0:\n", " mult3=mult3+[i]\n", " mult3" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A given element is only added to the mult3 list if the remainder of its division by 3 is zero." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "While loops" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An alternative form of introducing repetition in a program is by using a *while* loop, which is slightly more general than the *for* loop. Instead of repeating a piece of code a fixed number of times (which can be equal to the length of a list) like a *for* loop, a *while* repeats the action until a given test stops being True (i.e. becomes False).\n", "\n", "The *while* loop can be seen as an hybrid between an *if* statement and a *for* loop: an *if* statement executes a block of code **if** the result of a given test is True; a *while* loop repeatedly executes a block of code **while** the result of the test is True.\n", "\n", "We will look at an example where we are summing powers of 0.5 from 0 to 10 to see how the *while* loop works\n", "\n", " s=0\n", " i=0\n", " while i<=10:\n", " s=s+0.5**i\n", " i=i+1\n", " s" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the first two lines we are setting up variables that will manipulate in the loop. In the line\n", "\n", " while i<=10:\n", "\n", "we are setting up the loop, including the test i<=10. Since the variable *i* has the value 0 when entering the loop, the test is true and the idented loop body below this line will repeatedly execute until the variable *i* is no longer less or equal to 10.\n", "\n", "As with the *for* loop before, we set up a *result* variable, here called *s*, that we initialize to 0 and will increment inside the loop in the line\n", "\n", " s=s+0.5**i\n", " \n", "Unlike the *for* loop, we must initialize and update a loop variable *i*. The update of the loop variable occurs inside the loop body in line\n", "\n", " i=i+1\n", " \n", "The update of the loop variable is a crutial step. Without it, *i* would always keep the value 0, the test i<=10 would always be True and the loop would continue for all eternity (in theory). This type of infinit loop is not an uncommon bug in programming, and is easy to fall into with a *while* loop. You can give it a try by removing the line of code that updates *i* and executing th cell. Your notebook is now locked in an infinite loop. **Do not panic.** Go to the 'Kernel' tab on the notebook menu and 'Interrupt' the kernel execution. *Lesson is: watch out for your test condition and make sure the loop will stop at some point.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A situation where using a *while* loop is advantageous is when performing a search for the first element in a sequence. We don't necessarily want to go through all the elements, we simple want to find the first. For example, the following code counts after how many characters does the first sentence in the text (represented by a string) has. Let us first define the text." ] }, { "cell_type": "code", "collapsed": false, "input": [ "dante='''Nel mezzo del cammin di nostra vita\n", "mi ritrovai in una valle oscura,\n", "ch\u00e9 la diritta via era smarrita.\n", "Ahi quanto a dir qual era \u00e8 cosa dura\n", "esta selva selvaggia e aspra e forte\n", "che nel pensier rinova la paura!\n", "Tant'\u00e8 amara che poco \u00e8 pi\u00fa che morte;\n", "ma per trattar del ben ch'i' vi trovai,\n", "dir\u00f2 de l'altre cose ch'i' v'ho scorte.'''" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The code would look like\n", "\n", " i=0\n", " while dante[i]!= '.':\n", " i=i+1\n", " i" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The loop will stop when pointing to the position *i* of the string with the full stop.\n", "\n", "We have been a bit careless writing this code however, the first sentence could have ended with a question or exclamation mark. Further, we could have a rather poorly written text with no punctuation, in which case our code would yield an infinite loop and block the computer. We should thus add the condition to stop the cycle if *i* reaches or exceeds the length of the string. Such safeguards could look like\n", "\n", " i=0\n", " while i