{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 00: Introduction to python for hydrologists\n", "\n", "In this background introduction, we will review concepts introduced in the \n", "[University of Waterloo Python Background Tutorial](https://cscircles.cemc.uwaterloo.ca/)\n", "\n", "This notebook is a general overview of Python. We will cover many of the basic aspects of Python that are distinct (and sometimes confusing) relative to other programming and scripting languages. \n", "\n", "First let's consider three ways that we can interact with Python:\n", "\n", "1. Through a command-line session\n", "2. Using iPython\n", "3. Using a Jupyter notebook like this one\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('hello world')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using Python as a Calculator\n", "Python can be used to simple perform arithmetic operations.\n", "(note: in an iPython notebook like this one, shift-ENTER evaluates the code)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Spaces are fine" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "6*9" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "6 + (99.98 * 5.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exponents use `**` rather than `^` in some other languages." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print (5**9.1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What if you want to do more than basic arithmetic?\n", "There are a couple ways to access more mathematical functions: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import math\n", "np.sqrt(9)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "? np" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "math.sqrt(9.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of these two options, we typically use `np` because, as we will cover in detail later, `numpy` provides many other features important to the kind of scientific work we perform." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Structures and a few definitions \n", "**data structure** -- A way to store and organize data in a computer. \n", "In Python, there are a variety of data structures -- some mutable, and others immutable\n", "\n", "**mutability** -- An _immutable_ object is one whose property or state cannot be changed, whereas, _mutable_ objects can change state \n", "\n", "The most basic data types are numbers, including: \n", "`integer (int)` \n", "`float/double precision (float)` \n", "`long ingteger (long)` \n", "`complex (complex)`\n", "There are also groups of characters:\n", "`string (str)`\n", "\n", "Variables can be of any type and the results can be assigned to symbols without predefining type (like `DIMENSION` in FORTRAN). `print` statements display values to standard output, and the `type` function tells you which number type a variable (or number) is.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 5.9\n", "print (a)\n", "aa = 5.91\n", "print (a)\n", "print (aa)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a2 = 5.\n", "print (a2)\n", "type(a2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Variables and types\n", "\n", "### Symbol names \n", "\n", "Variable names in Python can contain alphanumerical characters `a-z`, `A-Z`, `0-9` and some special characters such as `_`. Normal variable names must start with a letter. \n", "\n", "By convention, variable names start with a lower-case letter, and Class names start with a capital letter. \n", "\n", "In addition, there are a number of Python keywords that cannot be used as variable names. These keywords are:\n", "\n", "> `and, as, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, while, with, yield`\n", "\n", "Note: Be aware of the keyword `lambda`, which could easily be a natural variable name in a scientific program. But being a keyword, it cannot be used as a variable name.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import keyword\n", "keyword.kwlist" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are also built-in objects that should not be used as variable names." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import builtins\n", "dir(builtins)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Assignment\n", "\n", "The assignment operator in Python is `=`. Python is a dynamically typed language, so we do not need to specify the type of a variable when we create one.\n", "\n", "Assigning a value to a new variable creates the variable:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b=99.1\n", "# variable names can practically as long as you like\n", "this_reallyDESCRIPTIVE_crazyvariableNAME_is_maybe_a_bit_long = 7\n", "print(this_reallyDESCRIPTIVE_crazyvariableNAME_is_maybe_a_bit_long)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In general, appropriate type conversion is possible:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 8.9\n", "b = int(a)\n", "print (b)\n", "c = str(a)\n", "b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Strings\n", "Grouping characters together creates strings." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "avar = \"this is a string (Includes 'spaces' and punctuation)\"\n", "print(avar)\n", "len(avar)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using square brackets (`[]`) we can dereference values as if the string were an array or a list (as we will discuss next)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(avar[0])\n", "print(avar[1])\n", "# negative indices count from the end of the string\n", "print(avar[-1])\n", "print(avar[-2])\n", "# we can even print every nth character\n", "print(avar[::3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since strings are just sequences of characters, they can be operated on using addition and multiplication." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d = 'a' + 'b' + ' c '\n", "print (d)\n", "print (d*5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For comparisons, it can be important to match case, so we can cast to upper or lower or a couple other options" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "avar.upper()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "avar.lower()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "avar.capitalize()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "avar.swapcase()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also replace text using `replace()`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "avar.replace('and','&')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Lists ###\n", "There are a few ways to group values in Python. The most basic way is a list, defined by square brackets(`[ ]`) and comma-delimited \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [2.3, 3.4, 5.5, 12.4, 33]\n", "print(type(a))\n", "print(type(a[1]))\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Important Note!!! -->\n", "Python uses zero-referencing (like C, but unlike MATLAB and FORTRAN). Using square brackets, look at the various values of `a` (e.g. `a[0]`, `a[2]`). Also, see what you get with `a[-1]` and `a[-2]`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Lists of Lists\n", "You can make lists made up of anything (e.g. numbers, other lists, etc.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b=5\n", "c=[3,'4stuff',5.9]\n", "d = [a,b,c]\n", "print (d)\n", "print (d[0])\n", "print (d[1])\n", "print (d[2])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "aaaa = [1,2,3]\n", "aaaa + [5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `append` versus `extend`\n", "You can add to a list in two ways -- using the `extend` or `append` methods. Let's look at `append` first:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a=[1,2,3]\n", "print (a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.append(4)\n", "a.append(5)\n", "print (a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.append([6,7,8])\n", "print (a)\n", "a[-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This did exactly what it should, but looks strange at first. We `appended` on the data we wanted to, but since we passed a list, we just took the list `[6,7,8]` on to the end of `a`. What if we wanted to continue our sequence? Then we could use `extend`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a=[1,2,3,4,5]\n", "a.extend([6,7,8])\n", "print (a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The same behavior will happen even if the list as it is is already made up of multiple types." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print (d)\n", "d.append([5,6,7,8,9])\n", "print (d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can create an empty list two ways" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = list()\n", "print (type(a), a)\n", "b = []\n", "print (type(b), b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.append('stuff')\n", "a.append(99)\n", "print (a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "aaa = [0]\n", "aaa.append(8)\n", "aaa" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also add and remove elements from lists in a couple ways:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [ 2,99,2,99, 'stuff']\n", "print (a.index(99))\n", "a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# index tells us where in a list a specific value resides\n", "print (a.index(99))\n", "print (a.index('stuff'))\n", "# insert can add a value -- note that this shifts the list over\n", "a.insert(0, 'newstuff')\n", "print (a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a[0] = 99999\n", "print (a)\n", "b = a.pop(4) #remove item in position 4 and assign to b\n", "print (b)\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tuples\n", "A similar construction to a `list` is a `tuple`. A `tuple` is defined using regular parentheses (`()`). The key differences is tuples are *immutable*.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# we can make a list\n", "a = [3,4,5]\n", "print (type(a))\n", "print (a)\n", "# it's mutable meaning we can change it in place\n", "a[0] = 999\n", "print (a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# a tuple is similar\n", "a = (3,4,5)\n", "print(type(a))\n", "print (a)\n", "# we can dereference values from it in the same way as we would a list\n", "print (a[0])\n", "# but we cannot change values in place\n", "a[0] = 999" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a=(1,'howdy')\n", "b=list(a)\n", "print (type(a))\n", "print (type(b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We won't talk very much about `tuples` except to say that they are sometimes required as input to functions, sometimes functions return them, and they can be useful for other reasons. Also, they can be constructed using `zip` to pull together a couple `lists`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = zip([1,2],[11,22],[111,222])\n", "print (a)\n", "print(type(a))\n", "for b in a:\n", " print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also assign tuples without using parentheses, although it's kind of sloppy. We can unpack a tuple into multiple variables." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 5,6,7\n", "val1, val2, val3 = a\n", "print (a)\n", "print (val1)\n", "print (val2)\n", "print (val3)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This can be done all at once as well!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "val1, val2, val3 = 5,6,7\n", "print (val1)\n", "print (val2)\n", "print (val3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dictionaries\n", "\n", "Dictionaries are also like lists, except that each element is a key-value pair. The syntax for dictionaries is `{key1 : value1, ...}`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "params = {\"parameter1\" : 1.0,\n", " \"parameter2\" : 2.0,\n", " \"parameter3\" : 3.0,}\n", "\n", "print(type(params))\n", "print(params)\n", "\n", "parlist = [ 1.0, 2.0, 3.0]\n", "print (params)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "params.items()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The keys can be obtained separate from their values as a list." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in params.keys():\n", " print (i)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ckeys = [i for i in params.keys()]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "params[ckeys[1]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"parameter1 = \" + str(params[\"parameter1\"]))\n", "print(\"parameter2 = \" + str(params[\"parameter2\"]))\n", "print(\"parameter3 = \" + str(params[\"parameter3\"]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Can also get just the values" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "params.values()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or everyone's favorite....`tuples`! `.items()` returns tuples of the key, values pairs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "params.items()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "params[\"parameter1\"] = \"A\"\n", "params[\"parameter2\"] = \"B\"\n", "\n", "# add a new entry\n", "params[\"parameter4\"] = \"D\"\n", "\n", "print(\"parameter1 = \" + str(params[\"parameter1\"]))\n", "print(\"parameter2 = \" + str(params[\"parameter2\"]))\n", "print(\"parameter3 = \" + str(params[\"parameter3\"]))\n", "print(\"parameter4 = \" + str(params[\"parameter4\"]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A trick using `zip` and `dict` ####\n", "Say we have two lists -- one of which is a set of keys and another is accompanying values (like we read them in from two columns in a spreadsheet)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "keys = ['HK','VKA','RCH','COND']\n", "vals = [1.2e-6, 0.001, 1.9e-9, 4.0]\n", "MFdict = dict(zip(keys,vals))\n", "MFdict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Process Flow\n", "We will cover conditional statements and a variety of loop types.\n", "### Conditional statements: if, elif, else\n", "\n", "The Python syntax for conditional execution of code use the keywords `if`, `elif` (else if), `else`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "statement1 = True\n", "statement2 = True\n", "\n", "if statement1==True:\n", " print(\"statement1 is True\")\n", " \n", "elif statement2==True:\n", " print(\"statement2 is True\")\n", " \n", "else:\n", " print(\"statement1 and statement2 are False\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are a couple critical things to see here. \n", "\n", "1. There is no `end if ` or other closing of the statement. This is all controlled by indentation.\n", "2. Each statement ends in a `':'`\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "statement1 or statement2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "not statement2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rather than just `True` or `False`, we can check for equivalence to other values.\n", "\n", "1. '`==`' indicates test for equality\n", "2. '`!=`' indicates test for nonequality" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 5\n", "print (a)\n", "a!=5.01" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "statement1 = 5.2\n", "\n", "if statement1 == 'junk':\n", " print ('junky')\n", " \n", "elif statement1 != 5:\n", " print ('neither \"junky\" nor 5')\n", "else:\n", " print ('must be 5 eh?')\n", "print ('wow - it worked?')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### An aside on indentation\n", "Technically, tabs or any *consistent* number of spaces can be used to control indentation. A casual standard is using 4 spaces. Many editors replace tabs with spaces to be safe. \n", "\n", "The level of indentation defines blocks without requiring a symbol or word to close a block or loop." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### few examples of indentation behavior:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "statement1 = True\n", "statement2 = True\n", "\n", "if statement1==True:\n", " if statement2==True:\n", " print(\"both statement1 and statement2 are True\")\n", "print( statement2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Bad indentation!\n", "if statement1==True:\n", " if statement2==True:\n", " print(\"both statement1 and statement2 are True\") # this line is not properly indented" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "statement1 = True \n", "\n", "if statement1==True:\n", " print(\"printed if statement1 is True\")\n", " \n", " print(\"Trying to say False but still inside the if block\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if statement1:\n", " print(\"printed if statement1 is True\")\n", " \n", "print(\"Statement 1 is false --- printed now outside the if block\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loops\n", "\n", "In Python, loops can be programmed in a number of different ways. The most common is the `for` loop, which is used together with iterable objects, such as lists. The basic syntax is:\n", "\n", "\n", "**`for` loops**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in [1,2,[9,8,0],4]:\n", " print (i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `for` loop iterates over the elements of the supplied list, and executes the containing block once for each element. Note the same indentation rules as for `if` statements. \n", "\n", "Any kind of list can be used in the `for` loop. For example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "range(4)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for x in range(4): # by default range start at 0\n", " print(x)\n", "print ('-'*12)\n", "print ('4 is missing but the length is {0}'.format(len(range(4))))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uh oh! Where is 4? `range` constructions do not include the final value. This takes some getting used to! \n", "\n", "There is a long discussion here: http://stackoverflow.com/questions/4504662/why-does-rangestart-end-not-include-end\n", "\n", "Suffice it to say that the length of a range is the number stated and this is all related to zero indexing.\n", "\n", "Ranges can also start at values other than 0, but still never include the final value." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for x in range(-3,3):\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that we aren't using an index like `i` to dereference items from the list. Rather, we are just iterating over those items. They need not be numbers." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = ['This', 'is', 'different', 'than', 'F77']\n", "for word in a:\n", " print (word)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We could do this like in other languages, but quickly it becomes clear that it would be contrived." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in range(len(a)):\n", " print (a[i])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sometimes we also need an index for some reason. We can get both using `enumerate`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i, word in enumerate(a):\n", " print ('word number {0} is \"{1}\"'.format(i, word))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also iterate over the keys of a dictionary in a couple ways. First, just iterating over the keys:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for key in params.keys():\n", " print (key + \" = \" + str(params[key]))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# the following shorthand is now preferred\n", "for key in params:\n", " print (key + \" = \" + str(params[key]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Second we can iterate over the items and unpack them." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for key, val in params.items():\n", " print (key + \" = \" + str(val))\n", " #print (poo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### List Comprehension\n", "\n", "A very Pythonic and compact way to build a list using a `for` loop is using a `list comprehension`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [x**3 for x in range(10)]\n", "print (a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can get conditional statements into a list comprehension -- but, once it get too complicated, it gets to be \"clever\" and it's better to be more explicit" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b = [x**3 if x>0 else x for x in range(-5,5)]\n", "print (b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "adict = dict(zip(range(10),a))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for key, value in adict.items():\n", " print (str(key) + \"^3 = \" + str(value))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also do a \"dictionary comprehension\" \n", "http://stackoverflow.com/questions/1747817/python-create-a-dictionary-with-list-comprehension" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d = {str(a) + \"^3\": a**3 for a in range(10)}\n", "print (d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`while` loops**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = 0\n", "while i<4:\n", " print(i)\n", " i += 1 # shorthand for i = i + 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = 5\n", "while i: # shorthand for while i != 0\n", " print('howdy again')\n", " i -= 1 # shorthand for i = i - 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = 0\n", "while 3:\n", " print(i)\n", " i += 2\n", " if i > 10:\n", " break" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## HEEEEEELP!\n", "\n", "You will always need help with Python. There are so many packages, modules, functions, datatypes, and everything else it takes a while to keep it all straight, and you will always need to update \n", "\n", "1. Stackoverflow is amazing--it can be toxic at times, but the community often converges on useful answers. Here's an [example](http://stackoverflow.com/questions/5505380/most-efficient-way-to-pull-specified-rows-from-a-2-d-array).\n", "2. Official documentation is good, but can overwhelm.\n", " \n", " * Python in general: https://docs.python.org/3/contents.html\n", " * numpy and scipy: http://docs.scipy.org/doc/\n", " * matplotlib: https://matplotlib.org/stable/users/index.html and especially https://matplotlib.org/stable/gallery/index.html\n", "3. Of course, Google is good _Google your error message text!_\n", "4. If you like books, consider [O'Reilly](http://shop.oreilly.com/product/0636920028154.do)\n", "5. While in iPython (or a notebook) try `help(os)` or `? os` for example.\n", "\n", " * `help(os)` brings up docstrings in the output window\n", " * `?os` opens a separate pane below (that you can kick out to another tab using a button next to the X) \n", " \n", "6. what about chatGPT? For sure, you can try to get chatGPT to write your code. It's pretty effective, but definitely you need to verify what it suggests!\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.11.10" } }, "nbformat": 4, "nbformat_minor": 4 }