{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Notebook-7: Lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Notebook Content \n", "\n", "In previous code camp notebooks we looked at numeric (**integers** and **floats**) and textual (**strings**) data, but it's probably been quite difficult to imagine how you'd assemble these simple data into something useful. The new data types (**lists** and **dictionaries**) will _begin_ to show you how that can happen, and they will allow you to 'express' much more complex concepts with ease." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What's the Difference?\n", "\n", "Up until now, our variables have only held _one_ things: a number, or a string. \n", "\n", "In other words, we've had things like, `myNumber = 5` or `myString = \"Hello world!\"`. And that's it. \n", "\n", "Now, with **lists** and **dictionaries** we can store _multiple_ things: several numbers, several strings, or some mish-mash of both. That is, lists and dictionaries are data _structures_ that can contain multiple data _types_. \n", "\n", "Here's a brief summary of these data structures, highlighting their main difference:\n", "- A **list** is an *ordered* collection of 'items' (numbers, strings, etc.). You can ask for the first item in a list, the 3rd, or the 1,000th, it doesn't really matter because your list has an order and it keeps that order.\n", "- A **dictionary** is an *unordered* collection of 'items' (numbers, strings, etc.). You access items in a dictionary in a similar way to how you access a real dictionary: you have a 'key' (i.e. the word for which you want the definition) and you use this to look up the 'value' (i.e. the definition of the word).\n", "\n", "There's obviously a lot more to lists and dictionaries than this, but it's a good starting point.\n", "\n", "Let's start with **lists** in this notebook and we'll continue with **dictionaries** in the following.\n", "\n", "You can go back to our short video that talks about lists:\n", "\n", "[![The Basics](http://img.youtube.com/vi/UDNtW3sy-og/0.jpg)](https://youtu.be/UDNtW3sy-og?t=452)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### In this Notebook\n", "\n", "- Indexing & Slicing\n", "- List operations\n", " - Addition and Mulitplication\n", " - You're (not) in the list!\n", "- List functions\n", " - insert\n", " - append\n", " - index\n", " - len" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----\n", "# Lists\n", "\n", "So a **list** is an ordered collection of items that we access by position (what Python calls the **index**) within that collection. So the first item in a list is always the first item in the list. End of (well, sort of... more on this later). \n", "\n", "Because lists contain multiple data items, we create and use them differently from the simple (single item) variables we've seen so far. You can always spot a list because it is a series of items separated by commas and grouped together between a pair of square brackets ( *[A, B, C, ..., n]* ).\n", "\n", "Here is a list of 4 items assigned to a variable called `myList`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myList = [1,2,4,5]\n", "print(myList)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists are pretty versatile: they don't really care what kind of items you ask them to store. So you can use a list to hold items of all the other data types that we have seen so far! \n", "\n", "Below we assign a new list to a variable called `myList` and then print it out so that you can see that it 'holds' all of these different types of data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myList = ['hi I am', 2312, 'mixing', 6.6, 90, 'strings, integers and floats']\n", "print(myList)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We don't want to get too technical here, but it's important to note one thing: `myList` is still just **one** thing – a list – and not six things (`'hi I am', 2312, 'mixing', 6.6, 90, 'strings, integers and floats'`). So we can only assign one list to a variable called `myList`. It's like the difference between a person and a crowd: a crowd is one thing that holds many people inside it...\n", "\n", "## Indexing\n", "\n", "To access an item in a list you use an **index**. This is a new and important concept and it's a term that we're going to use a _lot_ in the future, so try to really get this term into your head before moving forward in the notebook.\n", "\n", "### Accessing Elements in a List using Indexes\n", "\n", "The index is just the location of the item in the list that you want to access. So let's say that we want to fetch the second item, we access it via the *index notation* like so:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myList = ['hi', 2312, 'mixing', 6.6, 90, 'strings, integers and floats' ]\n", "print(myList[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See what has happened there? We have:\n", "\n", "1. Assigned a list with 6 elements to the variable `myList`.\n", "2. Accessed the second element in the list using that element's _index_ between a pair of square brackets (next to the list's name).\n", "\n", "Wait a sec – didn't we say *second* element? Why then is the index `1`???\n", "\n", "### Zero-Indexing\n", "\n", "Good catch! That's because list indexes are *zero-based*: this is a fancy way to say that the count starts from 0 instead of that from 1. So the first element has index 0, and the last element has index _n-1_ (i.e. the count of the number of items in the list [_n_] minus one). Zero indexing is a bit how like the ground floor in the UK is often shown as floor 0 in a lift. \n", "\n", "To recap:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myNewList = ['first', 'second', 'third']\n", "print(\"The first element is: \" + myNewList[0])\n", "print(\"The third element is: \" + myNewList[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Negative Indexing\n", "\n", "Since programmers are lazy, they also have a short-cut for accessing the _end_ of a list. Since positive numbers count from the start of a list, negative numbers count from the end:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(myNewList[-1])\n", "print(myNewList[-2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The _last_ element has index `-1`. So you count forwards from `0`, but backwards from `-1`.\n", "\n", "You can remember it this way: the last item in the list is at _n-1_ (where _n_ is the number of items in the list), so `...[-1]` is a sensible way to access the last item." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "\n", "Edit the code so that it prints the 'second' element in the list" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "print(\"The second element is :\" + myNewList[???])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "print(\"The second element is :\" + myNewList[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Index Out of Range\n", "\n", "What happens when you try to access an element that doesn't exist? \n", "\n", "We know that `myList` has 3 elements, so what if we try to access the 200th element in the list? In that case Python, as usual, will inform us of the problem using an *error message* pointing to the problem:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(myNewList[200])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!" ] }, { "cell_type": "markdown", "metadata": { "solution2": "hidden", "solution2_first": true }, "source": [ "Do you remember the past lesson on *syntax errors* and *exceptions*? What is the error message displayed in the code above? Is it an *exception* or a *syntax error*? Can you find the explanation for what's going in the [Official Documentation](https://www.google.ie/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0ahUKEwiN3s-0qr7OAhVGIcAKHYBLAE4QFggoMAI&url=https%3A%2F%2Fdocs.python.org%2F2%2Ftutorial%2Ferrors.html&usg=AFQjCNG6q1juN8ZVXOEqOYWxE18Cv5X_qw&sig2=o92WLjkV1PNNfgpW1w9n0g&cad=rja)? " ] }, { "cell_type": "markdown", "metadata": { "solution2": "hidden" }, "source": [ "Even if a statement or expression is syntactically correct, it may cause an error when an attempt is made to execute it. Errors detected during execution are called ***exceptions*** and are not unconditionally fatal. The last line of the error message indicates what happened.\n", "\n", "You can see from the last line to you have an error related to your index - where your list index is out of range." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A String is a List?\n", "\n", "Even if you didn't realise it, you have already been working with lists in a _sense_ because *strings* are _basically_ lists! Think about it this way: strings are an ordered sequence of characters because 'hello' and 'olhel' are very different words! It turns out that characters in a string can be accessed the same way we'd access a generic list." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myString = \"ABCDEF\"\n", "print(myString[0])\n", "print(myString[-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Slicing\n", "\n", "If you want to access more than one item at a time, then you can specify a _range_ using two index values instead of just one. \n", "\n", "If you provide two numbers, Python will assume you are indicating the start and end of a _group_ of items. This operation is called *list slicing*, but keep in mind that indexes start from 0!\n", "\n", "_Note_: remember too that the error above when we tried to get the 200th element was _index out of range_. So 'range' is how Python talks about more than one list element." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "shortSentence = \"Now I'll just print THIS word, between the 20th and the 25th character: \"\n", "print(shortSentence[20:25])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "\n", "Using the previous code as a guide, edit the code below so that it prints from the second to the fourth (inclusive) characters from the string:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "shown", "solution2_first": true }, "outputs": [], "source": [ "shortSentence2 = \"A12B34c7.0\"\n", "print(shortSentence2[???:???])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "shown" }, "outputs": [], "source": [ "shortSentence2 = \"A12B34c7.0\"\n", "print(shortSentence2[1:4]) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To print the entirety of a list from any starting position onwards, just drop the second index value while leaving the `:` in your code:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stringToPrint = \"I will print from HERE onwards\"\n", "print(\"Starting from the 17th position: \" + stringToPrint[17:])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that there are _two_ spaces between \"position:\" and \"HERE\" in the printout above? That's because the 17th character is a space. Let's make it a little more obvious:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Starting from the 17th position: '\" + stringToPrint[17:] + \"'\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Got it?\n", "\n", "#### A challenge for you!\n", "\n", "Now, combining what we've seen above, how do you think you would print everything _up to the eighth character from the end_ (which is the space between \"HERE\" and \"onwards\")?\n", "\n", "You'll need to combine:\n", "1. Negative indexing\n", "2. List slicing\n", "\n", "There are two ways to do it, one way uses only one number, the other uses two. Both are correct. Why don't you try to figure them both out? For 'Way 2' below the `???` is a placeholder for a full slicing operation since if we gave you more of a hint it would make it too obvious." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "print(\"Up to the 18th position (Way 1): '\" + stringToPrint[???:???] + \"'\")\n", "print(\"Up to the 18th position (Way 2): '\" + ??? + \"'\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "print(\"Up to the 18th position (Way 1): '\" + stringToPrint[-8:] + \"'\")\n", "print(\"Up to the 18th position (Way 2): '\" + stringToPrint[22:30] + \"'\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Strings have also plenty of methods that might prove to be quite useful in the future; for a fuller overview check out [this reference](https://en.wikibooks.org/wiki/Python_Programming/Variables_and_Strings).\n", "\n", "## List operations\n", "\n", "So far, we've only created a list, but just like a real to-do list, most lists don't usually stay the same throughout the day (or the execution of your application). Their _real_ value comes when we start to change them: adding and removing items, updating an existing item, concatenating several lists (i.e. sticking them together), etc.\n", "\n", "### Replacing an item\n", "\n", "Here's how we replace an item in a list:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myNewList = ['first', 'second', 'third']\n", "print(myNewList)\n", "\n", "# This replaces the item in the 2nd position\n", "myNewList[1] = 'new element'\n", "\n", "print(myNewList)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This shouldn't surprise you too much: it's just an assignment (via \"=\") after all! \n", "\n", "So if you see `list[1]` on the right side of the assignment (the \"=\") then we are _reading from_ a list, but if you see `list[1]` on the left side of the assignment then we are _writing to_ a list.\n", "\n", "Here's an example for a (small) party at a friend's place:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "theParty = ['Bob','Doug','Louise','Nancy','Sarah','Jane']\n", "print(theParty)\n", "\n", "theParty[1] = 'Phil' # Doug is replaced at the party by Phil\n", "print(theParty)\n", "\n", "theParty[0] = theParty[1]\n", "print(theParty) # Phil is an evil genius and manages to also replace Doug with a Phil clone" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Got it?\n", "\n", "### Addition and Multiplication\n", "\n", "You can also operate on entire lists at one time, rather than just on their elements individually. For instance, given two lists you might want to add them together like so:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "britishProgrammers = [\"Babbage\", \"Lovelace\"]\n", "nonBritishProgrammers = [\"Torvald\", \"Knuth\"]\n", "\n", "famousProgrammers = britishProgrammers + nonBritishProgrammers\n", "print(famousProgrammers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can even multiply them, although in this particular instance it is kind of pointless:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(britishProgrammers * 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "\n", "Correct the syntax in the following code to properly define a new list: " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "otherNonBritishProgrammers = [\"Wozniak\" ??? \"Van Rossum\"]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "otherNonBritishProgrammers = [\"Wozniak\",\"Van Rossum\"]\n", "otherNonBritishProgrammers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Edit the following code to print out all the non british programmers:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "print nonBritishProgrammers ??? otherNonBritishProgrammers" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "print(nonBritishProgrammers + otherNonBritishProgrammers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### You're (not) in the list!\n", "\n", "Ever stood outside a club or event and been told: \"You're not on/in the list\"? Well, Python is like that too. In fact, Python tries as hard as possible to be _like_ English – this isn't by accident, it's by design – and once you've done a _bit_ of programming in Python you can start to guess how to do something by thinking about how you might say it in English. \n", "\n", "So if you want to check if an item exists in a list you can use the **in** operator:\n", "\n", "```python\n", "element in list\n", "```\n", "\n", "The **in** operator will return `True` if the item is present, and `False` otherwise. This is a new data type (called a Boolean) that we'll see a lot more of in two notebooks' time. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print ('Lovelace' in britishProgrammers)\n", "print ('Lovelace' in nonBritishProgrammers)\n", "\n", "letters = ['a','b','c','d','e','f','g','h','i']\n", "print ('e' in letters)\n", "print ('z' in letters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Note:_ You might also have spotted that this time there are parentheses (\"(...)\") after `print`. In general, as you become more experienced you'll _always_ want to put parentheses after a `print` statement (because that's how Python3 works) but the intricacies of _why_ this is the case are a bit out of the scope of an introductory set of lessons.\n", "\n", "Anyway, if you want to check if an item does not exist in a list then you can use the **not in ** operator. Let's go back to our party:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(theParty)\n", "print('Bob' not in theParty)\n", "print('Jane' not in theParty)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So here, that 'Boolean' gives us `True` on the first `not in` because it's \"true that Bob isn't at the party\" and `False` on the second one because it's \"not true that Jane isn't at the party\"! Double-negatives aren't supposed to exist in English, but they certainly do in programming!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "\n", "Complete the missing bits of the following code so that we print out Ada Lovelace, her full name:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "firstProgrammerSurnames = [\"Babbage\", \"Lovelace\"]\n", "firstProgrammerNames = [\"Charles\", \"Ada\"]\n", "\n", "firstProgrammerSurnames[1] = firstProgrammerNames[1] + \" \" + firstProgrammerSurnames[1]\n", "\n", "print(\"Lady \"+ ???[1] +\" is considered to be the first programmer.\") " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "firstProgrammerSurnames = [\"Babbage\", \"Lovelace\"]\n", "firstProgrammerNames = [\"Charles\", \"Ada\"]\n", "\n", "firstProgrammerSurnames[1] = firstProgrammerNames[1] + \" \" + firstProgrammerSurnames[1]\n", "\n", "print(\"Lady \"+ firstProgrammerSurnames[1] +\" is considered to be the first programmer.\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Note_ : Actually, Lady Ada Lovelace is a [fascinating person](https://en.wikipedia.org/wiki/Ada_Lovelace): she isn't just the first female programmer, she was the first programmer full-stop. For many years Charles Babbage got all the credit for inventing computers simply because he was a guy and designed the clever mechanical adding machine. However, lately, we've realised that Ada was the one who actually saw that Babbage hadn't just invented a better abacus, he'd invented a general-purpose computing device! \n", "\n", "She was so far ahead of her time that the code she wrote down couldn't even run on Babbage's 'simple' (i.e. remarkably complex for the time) computer, but it is now recognised as the first computer algorithm. As a result, there is now a day in her honour every year that is celebrated around the world at places like Google and Facebook, as well as at King's and MIT, because we want to recognise the fundamental contribution to computing made by women programmers. \n", "\n", "This contribution was long overlooked by the men who thought that the hard part was the machine, not the programming. Rather entertainingly (given the kudos attached to the people who created applications like Google and Facebook), most men thought that programming was just like typing and was, therefore 'women's work'. So why not take a few minutes to [recognise the important contributions of women to the history of computing](http://www.npr.org/blogs/alltechconsidered/2014/10/06/345799830/the-forgotten-female-programmers-who-created-modern-tech).\n", "\n", "![Margaret Hamilton, _lead_ software engineer at MIT, next to the code that she and her colleagues created, taking Apollo 11 to the moon.](http://static1.squarespace.com/static/54537cf7e4b046486283233c/t/56b892ae044262401f580f68/1454936876985/margaret+hamilton+meme.jpg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extending Lists\n", "\n", "We've already seen that we can combine two lists using the `+` operator, but if you wanted to constantly add new items to your list then having to do something like this would be annoying:\n", "```python\n", "myList = [] # An empty list\n", "\n", "myList = myList + ['New item']\n", "myList = myList + ['Another new item']\n", "myList = myList + ['And another one!']\n", "\n", "print(myList)\n", "```\n", "Not just annoying, but also hard to read! As with most things, because programmers are lazy there's an easier way to write this in Python:\n", "```python\n", "myList = [] # An empty list\n", "\n", "myList.append('New item')\n", "myList.append('Another new item')\n", "myList.append('And another one!')\n", "\n", "print(myList)\n", "```\n", "\n", "Why don't you try typing it all in the coding area below? You'll get the same answer either way, but one is faster to write and easier to read!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Appending to a list using `append(...)` is actually using something called a _function_. We've not really seen this concept before and we're not going to go into it in enormous detail here (there's a whole other notebook to introduce you to functions). The things that you need to notice at _this_ point in time are:\n", "\n", "1. That square brackets ('[' and ']') are used for list indexing.\n", "2. That parentheses ('(' and ')') are (normally) used for function calls.\n", "\n", "The best thing about functions is that they are like little packages of code that can do a whole bunch of things at once (e.g. add an item to a list by modifying the list directly), but you only need to remember to write `append(...)`. \n", "\n", "What did I mean just now by 'modifying the list directly'? \n", "\n", "Notice that in the first example above we had to write:\n", "```python\n", "myList = myList + ['New item']\n", "``` \n", "because we had to write the result of concatenating the two lists together back to the variable. The list isn't really growing, we're just overwriting what was _already_ in `myList` with the results of the list addition operation. What do you think you would get if you wrote the following code:\n", "```python\n", "myList = [] # An empty list\n", "\n", "myList + ['New item']\n", "myList + ['Another new item']\n", "myList + ['And another one!']\n", "\n", "print(myList)\n", "``` \n", "If you aren't sure, why don't you try typing this into the coding area above and try to figure out why the answer is: ''.\n", "\n", "Meanwhile, in the second example we could just write: \n", "```python \n", "myList.append('New item')\n", "```\n", "and the change was made to `myList` directly! So this is easier to read _and_ it is more like what we'd expect to happen: the list grows without us having to overwrite the old variable." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Other List Functions\n", "\n", "`append()` is a function, and there are many other functions that can be applied to lists such as: `len`, `insert` and `index`. You tell Python to *execute a function* (sometimes also termed *calling a function*) by writing the function's name, followed by a set of parentheses. The parentheses will contain any optional inputs necessary for the function to do its job. Appending to a list wouldn't be very useful if you couldn't tell Python _what_ to append in the first place!\n", "\n", "The `len` function is also a good example of this:\n", "```python\n", "len(theParty)\n", "```\n", "Here, the function `len` (lazy short-hand for _length_ ) is _passed_ `theParty` list as an input in order to do its magic.\n", "\n", "The functions `append`, `insert` and `index` work a _little_ bit differently. They have to be _called_ using `theParty` list. We're at risk of joining Alice down the rabbit-hole here, so let's just leave it at: the second set of functions are of a particular _type_ known as *methods* of the *list class*. We'll stop there. \n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to use a _list method_ you always need to 'prepend' (i.e. lead with) the name of list you want to work with, like so:\n", "\n", "```python\n", "theParty.append(\"New Guest\")\n", "theParty.insert(2, \"Anastasia\")\n", "theParty.index(\"Sarah\")\n", "```\n", "\n", "The idea here is that methods are associated with specific types of things such as lists, whereas generic functions are kind of free-floating. Think about it this way: you can't append something to a number, because that _makes no sense_. Appending is something that only makes sense in the context of a list. In contrast, something like `len` works on several different types of variables: lists and string both!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Append\n", "\n", "Reminder: here's appending..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "britishProgrammers = ['Lovelace']\n", "britishProgrammers.append(\"Turing\")\n", "print(britishProgrammers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Insert\n", "\n", "That's cool, but as you noticed `append` only ever inserts the new item as the last element in the list. What if you want it to go somewhere else?\n", "\n", "With `insert` you can also specify a position" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(nonBritishProgrammers)\n", "nonBritishProgrammers.insert(1, \"Swartz\")\n", "print(nonBritishProgrammers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Index\n", "\n", "Lastly, with the `index` method you can easily ask Python to find the position (index) of a given item:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Say you want to know in where \"Knuth\" is \n", "# in the list of non-British programmers...\n", "print(nonBritishProgrammers.index(\"Knuth\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add the famous [Grace Hopper](https://en.wikipedia.org/wiki/Grace_Hopper) (inventress of the first compiler!) to the list of British programmers, and then print her index position:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "nonBritishProgrammers.???(\"Hopper\") \n", "print(nonBritishProgrammers.???(\"Hopper\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "nonBritishProgrammers.append(\"Hopper\") \n", "# let's check\n", "print(nonBritishProgrammers)\n", "print(nonBritishProgrammers.index(\"Hopper\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Length\n", "\n", "Cool, so those were some of the *methods you can invoke on* a list. Let's focus now on some *functions* that take lists as an _input_.\n", "\n", "With the function `len` you can immediately know the `len`-gth of a given list:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print( len(britishProgrammers) )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "length_of_list = len(nonBritishProgrammers)\n", "print(\"There are \" + str(length_of_list) + \" elements in the list of non-British Programmers\")" ] }, { "cell_type": "markdown", "metadata": { "solution2": "hidden", "solution2_first": true }, "source": [ "Did you see the `str(length_of_list)`? There's another function! We didn't draw attention to it before, we just told you to use `str(5.0)` to convert the float `5.0` to the string `\"5.0\"`. We can tell it's a function because it uses the format `functionName(...some input...)`. So the function name is `str` (as in _convert to string_) and the input is a number (in this case it's the length of the list `nonBritishProgrammers`). So now we can easily convert between different types of data: we took an integer (you can check this by adding the following line to the code above: \n", "```python\n", "print length_of_list + 1\n", "```\n", "And then print it out as a string. So `length_of_list` is a number, and by calling `str(length_of_list)` we changed it to a string that we could print out. Given that programmers are lazy, can you guess how you'd convert the string \"3\" to the _integer_ 3?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "print(int(length_of_list) + 1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "three = \"3\"\n", "# Let's check the data type\n", "type(three)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "# Change to Integer\n", "three = int(three)\n", "type(three)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "\n", "Complete the missing bits of the following code:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "length_of_brits = ???(britishProgrammers)\n", "print \"There are \" ??? \" British programmers.\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "length_of_brits = len(britishProgrammers)\n", "print(\"There are \" + str(length_of_brits) + \" British programmers.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To check if the output of `range()` is a list we can use the `type()` function:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Code (Applied Geo-example)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's have a little play with some geographical coordinates. Based on what we've just done in this notebook, what do you think would be a good data type for storing lat/long coordinates?\n", "\n", "Go on, I'll bet you can't guess!\n", "\n", "Let's use what we know to jump to a particular point on the planet..." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# We'll see more of this package import\n", "# later... for now, just know that it \n", "# provides access to a function called IFrame\n", "from IPython.display import IFrame\n", "\n", "# We want to view an OpenStreetMap map\n", "siteName = \"http://www.openlinkmap.org/small.php\"\n", "\n", "# Specify the location and zoom level\n", "latitude = 63.6314\n", "longitude = -19.6083\n", "zoomLevel = 10\n", "mapURL = ['?lat=', str(latitude), '&lon=', str(longitude), '&zoom=', str(zoomLevel)]\n", "\n", "# Show the ULR\n", "print(siteName + ''.join(mapURL))\n", "\n", "# And now show us an inline map!\n", "IFrame(siteName + ''.join(mapURL), width='100%', height=400)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now let's try somewhere closer to home. Try using the `KCLMapCoordinates` list below (which tells you the x/y and zoom-level) in combination with the code above. I'd suggest copying what you need from above, pasting it into the code below, and then using what you know about accessing list information so that the map shows the location of King's College London..." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "shown", "solution2_first": true }, "outputs": [], "source": [ "# King's College coordinates\n", "# What format are they in? Does it seem appropriate?\n", "KCLMapCoordinates = [51.51130657591914, -0.11596798896789551, 15]\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "shown" }, "outputs": [], "source": [ "# We want to view an OpenStreetMap map\n", "siteName = \"http://www.openlinkmap.org/small.php\"\n", "\n", "# Specify the location and zoom level\n", "latitude = KCLMapCoordinates[0]\n", "longitude = KCLMapCoordinates[1]\n", "zoomLevel = 15\n", "mapURL = ['?lat=', str(latitude), '&lon=', str(longitude), '&zoom=', str(zoomLevel)]\n", "\n", "# Show the ULR\n", "print(siteName + ''.join(mapURL))\n", "\n", "# And now show us an inline map!\n", "IFrame(siteName + ''.join(mapURL), width='100%', height=400)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Further references:\n", "\n", "General list or resources\n", "- [Awesome list of resources](https://github.com/vinta/awesome-python)\n", "- [Python Docs](https://docs.python.org/2.7/tutorial/introduction.html)\n", "- [HitchHiker's guide to Python](http://docs.python-guide.org/en/latest/intro/learning/)\n", "- [Python for Informatics](http://www.pythonlearn.com/book_007.pdf)\n", "- [Learn Python the Hard Way - Lists](http://learnpythonthehardway.org/book/ex32.html)\n", "- [Learn Python the Hard Way - Dictionaries](http://learnpythonthehardway.org/book/ex39.html)\n", "- [CodeAcademy](https://www.codecademy.com/courses/python-beginner-en-pwmb1/0/1)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Credits!\n", "\n", "#### Contributors:\n", "The following individuals have contributed to these teaching materials: \n", "- [James Millington](https://github.com/jamesdamillington)\n", "- [Jon Reades](https://github.com/jreades)\n", "- [Michele Ferretti](https://github.com/miccferr)\n", "- [Zahratu Shabrina](https://github.com/zarashabrina)\n", "\n", "#### License\n", "The content and structure of this teaching project itself is licensed under the [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 license](https://creativecommons.org/licenses/by-nc-sa/4.0/), and the contributing source code is licensed under [The MIT License](https://opensource.org/licenses/mit-license.php).\n", "\n", "#### Acknowledgements:\n", "Supported by the [Royal Geographical Society](https://www.rgs.org/HomePage.htm) (with the Institute of British Geographers) with a Ray Y Gildea Jr Award.\n", "\n", "#### Potential Dependencies:\n", "This notebook may depend on the following libraries: None" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" } }, "nbformat": 4, "nbformat_minor": 1 }