{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "These notes follow the official python tutorial pretty closely: http://docs.python.org/3/tutorial/" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "from __future__ import print_function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists group together data. Many languages have arrays (we'll look at those in a bit in python). But unlike arrays in most languages, lists can hold data of all different types -- they don't need to be homogeneos. The data can be a mix of integers, floating point or complex #s, strings, or other objects (including other lists).\n", "\n", "A list is defined using square brackets:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "a = [1, 2.0, \"my list\", 4]" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2.0, 'my list', 4]\n", "\n" ] } ], "source": [ "print(a)\n", "print(type(a[0]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can index a list to get a single element -- remember that python starts counting at 0:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "my list\n" ] } ], "source": [ "print(a[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Like with strings, mathematical operators are defined on lists:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2.0, 'my list', 4, 1, 2.0, 'my list', 4]\n" ] } ], "source": [ "print(a*2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `len()` function returns the length of a list" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n" ] } ], "source": [ "print(len(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Unlike strings, lists are _mutable_ -- you can change elements in a list easily" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['l', 'o', 'r', 'e', 'm', ' ', 'i', 'p', 's', 'u', 'm']\n" ] } ], "source": [ "b = \"lorem ipsum\"\n", "a[1] = -2.0\n", "my_list=list(b)\n", "print(my_list)\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "a[0:1] = [-1, -2.1] # this will put two items in the spot where 1 existed before" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that lists can even contain other lists:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, ['other list', 3], 'my list', 4]\n" ] } ], "source": [ "a[1] = [\"other list\", 3]\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just like everything else in python, a list is an object that is the instance of a class. Classes have methods (functions) that know how to operate on an object of that class.\n", "\n", "There are lots of methods that work on lists. Two of the most useful are append, to add to the end of a list, and pop, to remove the last element:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.append(6)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0]\n", "[0, 1]\n", "[0, 1, 2]\n", "[0, 1, 2, 3]\n", "[0, 1, 2, 3, 4]\n", "[0, 1, 2, 3, 4, 5]\n", "[0, 1, 2, 3, 4, 5, 6]\n", "[0, 1, 2, 3, 4, 5, 6, 7]\n", "[0, 1, 2, 3, 4, 5, 6, 7, 8]\n", "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "a = []\n", "for i in range(10):\n", " a.append(i)\n", "print(a)\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Quick Exercise:

\n", "\n", "An operation we'll see a lot is to begin with an empty list and add elements to it. An empty list is created as:\n", "```\n", "a = []\n", "```\n", "\n", " * Create an empty list\n", " * Append the integers 1 through 10 to it. \n", " * Now pop them out of the list one by one.\n", " \n", "
" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]\n", "[1, 2]\n", "[1, 2, 3]\n", "[1, 2, 3, 4]\n", "[1, 2, 3, 4, 5]\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 2, 3, 4, 5, 6, 7]\n", "[1, 2, 3, 4, 5, 6, 7, 8]\n", "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n", "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n", "[1, 2, 3, 4, 5, 6, 7, 8]\n", "[1, 2, 3, 4, 5, 6, 7]\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 2, 3, 4, 5]\n", "[1, 2, 3, 4]\n", "[1, 2, 3]\n", "[1, 2]\n", "[1]\n", "[]\n" ] } ], "source": [ "a=[]\n", "for i in range(1,11):\n", " a.append(i)\n", " print(a)\n", "for i in range(1,11):\n", " a.pop()\n", " print(a) \n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### copying lists\n", "\n", "copying may seem a little counterintuitive at first. The best way to think about this is that your list lives in memory somewhere and when you do \n", "\n", "```\n", "a = [1, 2, 3, 4]\n", "```\n", "\n", "then the variable `a` is set to point to that location in memory, so it refers to the list.\n", "\n", "If we then do\n", "```\n", "b = a\n", "```\n", "then `b` will also point to that same location in memory -- the exact same list object.\n", "\n", "Since these are both pointing to the same location in memory, if we change the list through `a`, the change is reflected in `b` as well:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4]\n", "['changed', 2, 3, 4]\n" ] } ], "source": [ "a = [1, 2, 3, 4]\n", "b = a # both a and b refer to the same list object in memory\n", "print(a)\n", "a[0] = \"changed\"\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "if you want to create a new object in memory that is a copy of another, then you can either index the list, using `:` to get all the elements, or use the `list()` function:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['changed', 'two', 3, 4]\n", "['changed', 2, 3, 4]\n" ] } ], "source": [ "c = list(a) # you can also do c = a[:], which basically slices the entire list\n", "\n", "\n", "a[1] = \"two\"\n", "print(a)\n", "print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Things get a little complicated when a list contains another mutable object, like another list. Then the copy we looked at above is only a _shallow copy_. Look at this example—the list within the list here is still the same object in memory for our two copies:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, [2, 3], 4]\n" ] } ], "source": [ "f = [1, [2, 3], 4]\n", "print(f)\n" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, [2, 3], 4]\n" ] } ], "source": [ "g = list(f)\n", "print(g)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we are going to change an element of that list `[2, 3]` inside of our main list. We need to index `f` once to get that list, and then a second time to index that list:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, ['a', 3], 4]\n", "[1, ['a', 3], 4]\n" ] } ], "source": [ "f[1][0] = \"a\"\n", "print(f)\n", "print(g)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the change occured in both—since that inner list is shared in memory between the two. Note that we can still change one of the other values without it being reflected in the other list—this was made distinct by our shallow copy:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, ['a', 3], 4]\n", "[-1, ['a', 3], 4]\n" ] } ], "source": [ "f[0] = -1\n", "print(g)\n", "print(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again, this is what is referred to as a shallow copy. If the original list had any special objects in it (like another list), then the new copy and the old copy will still point to that same object. There is a deep copy method when you really want everything to be unique in memory.\n", "\n", "When in doubt, use the `id()` function to figure out where in memory an object lies (you shouldn't worry about the what value of the numbers you get from `id` mean, but just whether they are the same as those for another object)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4564568584 4564568584 4564940616\n" ] } ], "source": [ "print(id(a), id(b), id(c))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are lots of other methods that work on lists (remember, ask for help)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-1, 2, 5, 9, 10, 24]\n" ] } ], "source": [ "my_list = [10, -1, 5, 24, 2, 9]\n", "my_list.sort()\n", "print(my_list)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "Help on class list in module builtins:\n", "\n", "class list(object)\n", " | list(iterable=(), /)\n", " | \n", " | Built-in mutable sequence.\n", " | \n", " | If no argument is given, the constructor creates a new empty list.\n", " | The argument must be an iterable if specified.\n", " | \n", " | Methods defined here:\n", " | \n", " | __add__(self, value, /)\n", " | Return self+value.\n", " | \n", " | __contains__(self, key, /)\n", " | Return key in self.\n", " | \n", " | __delitem__(self, key, /)\n", " | Delete self[key].\n", " | \n", " | __eq__(self, value, /)\n", " | Return self==value.\n", " | \n", " | __ge__(self, value, /)\n", " | Return self>=value.\n", " | \n", " | __getattribute__(self, name, /)\n", " | Return getattr(self, name).\n", " | \n", " | __getitem__(...)\n", " | x.__getitem__(y) <==> x[y]\n", " | \n", " | __gt__(self, value, /)\n", " | Return self>value.\n", " | \n", " | __iadd__(self, value, /)\n", " | Implement self+=value.\n", " | \n", " | __imul__(self, value, /)\n", " | Implement self*=value.\n", " | \n", " | __init__(self, /, *args, **kwargs)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __iter__(self, /)\n", " | Implement iter(self).\n", " | \n", " | __le__(self, value, /)\n", " | Return self<=value.\n", " | \n", " | __len__(self, /)\n", " | Return len(self).\n", " | \n", " | __lt__(self, value, /)\n", " | Return self

Quick Exercise:

\n", "\n", "Create a dictionary where the keys are the string names of the numbers zero to nine and the values are their numeric representation (0, 1, ... , 9)\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7, 'eight': 8, 'nine': 9}\n", "{'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seveneight': 7, 'nine': 8}\n" ] } ], "source": [ "mydict = {\"zero\": 0, \"one\": 1, \"two\":2, \"three\":3, \"four\": 4,\\\n", " \"five\":5, \"six\":6, \"seven\":7, \"eight\": 8, \"nine\": 9 }\n", "print(mydict)\n", "keyNum=['zero','one','two','three','four','five','six','seven'\\\n", " 'eight','nine']\n", "dic={}\n", "i=0\n", "for key in keyNum:\n", " dic[key] = i\n", " i+=1\n", "print (dic) \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# List Comprehensions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "list comprehensions provide a compact way to initialize lists. Some examples from the tutorial" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n", "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n", "[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]\n" ] } ], "source": [ "squares = []\n", "squares = [x**2 for x in range(10)]\n", "print(squares)\n", "squares2 = []\n", "for i in range(10):\n", " squares2.append(i**2)\n", "print(squares2) \n", "\n", "for i in range(len(squares)):\n", " squares2[i] = i**3\n", "print(squares2) " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "here we use another python type, the tuple, to combine numbers from two lists into a pair" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]\n" ] } ], "source": [ "t_list=[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]\n", "print(t_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Quick Exercise:

\n", "\n", "Use a list comprehension to create a new list from `squares` containing only the even numbers. It might be helpful to use the modulus operator, `%`\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 4, 16, 36, 64, 100, 144, 196, 256, 324]\n", "[0, 4, 16, 36, 64]\n" ] } ], "source": [ "even_squares = [(2*x)**2 for x in range(10)]\n", "print(even_squares)\n", "even_squares =[x for x in squares if x%2 == 0]\n", "print(even_squares)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Tuples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "tuples are immutable -- they cannot be changed, but they are useful for organizing data in some situations. We use () to indicate a tuple:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [], "source": [ "a = ()\n", "a = (1, 2, 3, 4)\n", "b = []\n", "b = [1, 2, 3, 4]\n" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 2, 3, 4)\n", "[1, 2, 3, 4]\n" ] } ], "source": [ "print(a)\n", "print(b)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can unpack a tuple:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "w, x, y, z = a" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "print(w)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 2 3 4\n" ] } ], "source": [ "print(w, x, y, z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since a tuple is immutable, we cannot change an element:" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "b[0] = 2\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But we can turn it into a list, and then we can change it" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [], "source": [ "z = list(a)" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "z[0] = \"new\"" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['new', 2, 3, 4]\n" ] } ], "source": [ "print(z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is often not clear how tuples differ from lists. The most obvious way is that they are immutable. Often we'll see tuples used to store related data that should all be interpreted together. A good example is a Cartesian point, (x, y). Here is a list of points:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[(1, 2), (2, 3), (3, 4)]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "points = []\n", "points.append((1,2))\n", "points.append((2,3))\n", "points.append((3,4))\n", "points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "we can even generate these for a curve using a list comprehension:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[(0, 5),\n", " (1, 7),\n", " (2, 9),\n", " (3, 11),\n", " (4, 13),\n", " (5, 15),\n", " (6, 17),\n", " (7, 19),\n", " (8, 21),\n", " (9, 23)]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "points = [(x, 2*x + 5) for x in range(10)]\n", "points" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 1 }