diff --git a/getting_started/01_basics.ipynb b/getting_started/01_basics.ipynb index 4caa7fb735b09a77b08786f69a0e5757f5ac6fbb..11cc06dce3e1220432f84ca70c8907ecb150d461 100644 --- a/getting_started/01_basics.ipynb +++ b/getting_started/01_basics.ipynb @@ -57,16 +57,24 @@ "* strings\n", "* tuples\n", "* lists\n", - "* dictionary\n", + "* dictionaries\n", "\n", "N-dimensional arrays and other types are supported through common modules (e.g., numpy, scipy, scikit-learn). These will be covered in a subsequent exercise." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 130, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n" + ] + } + ], "source": [ "a = 4\n", "b = 3.6\n", @@ -85,9 +93,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 131, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 20, 30]\n", + "{'b': 20, 'a': 10}\n", + "4 3.6 abc\n" + ] + } + ], "source": [ "print(d)\n", "print(e)\n", @@ -117,9 +135,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 132, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "test string :: another test string\n" + ] + } + ], "source": [ "s1 = \"test string\"\n", "s2 = 'another test string'\n", @@ -135,9 +161,20 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 133, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This is\n", + "a string over\n", + "multiple lines\n", + "\n" + ] + } + ], "source": [ "s3 = '''This is\n", "a string over\n", @@ -158,9 +195,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 134, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The numerical value is 1 and a name is PyTreat\n", + "A name is PyTreat and a number is 1\n" + ] + } + ], "source": [ "x = 1\n", "y = 'PyTreat'\n", @@ -183,9 +229,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 135, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "THIS IS A TEST STRING\n", + "this is a test string\n" + ] + } + ], "source": [ "s = 'This is a Test String'\n", "print(s.upper())\n", @@ -201,9 +256,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 136, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This is a Better String\n" + ] + } + ], "source": [ "s = 'This is a Test String'\n", "s2 = s.replace('Test', 'Better')\n", @@ -219,9 +282,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 137, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This is a Test String :: This is a Better String\n" + ] + } + ], "source": [ "s3 = s + ' :: ' + s2\n", "print(s3)" @@ -236,9 +307,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 138, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This is an example of an example String\n" + ] + } + ], "source": [ "import re\n", "s = 'This is a test of a Test String'\n", @@ -250,7 +329,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "where the `r` before the quote is used to force the regular expression specification to be a `raw string`.\n", + "where the `r` before the quote is used to force the regular expression specification to be a `raw string` (see [here](https://docs.python.org/3.5/library/re.html) for more info).\n", "\n", "For more information on matching and substitutions, look up the regular expression module on the web.\n", "\n", @@ -259,9 +338,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 139, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* A very spacy string *\n", + "*A very spacy string*\n" + ] + } + ], "source": [ "s2 = ' A very spacy string '\n", "print('*' + s2 + '*')\n", @@ -277,9 +365,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 140, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['This', 'is', 'a', 'test', 'of', 'a', 'Test', 'String']\n", + "['A', 'very', 'spacy', 'string']\n" + ] + } + ], "source": [ "print(s.split())\n", "print(s2.split())" @@ -294,9 +391,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 141, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[' This is', ' as you can see ', ' a very weirdly spaced and punctuated string ... ']\n" + ] + } + ], "source": [ "s4 = ' This is, as you can see , a very weirdly spaced and punctuated string ... '\n", "print(s4.split(','))" @@ -315,9 +420,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 142, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "232.03\n", + "25.03\n", + "25.03\n" + ] + } + ], "source": [ "sint='23'\n", "sfp='2.03'\n", @@ -341,14 +456,23 @@ "but for numerical vectors and arrays it is much better to use _numpy_\n", "arrays (or matrices), which are covered in a later tutorial.\n", "\n", - "A tuple is like a list or a vector, but with less flexibility than a full list, however anything can be stored in either a list or tuple, without any consistency being required. For example:" + "A tuple is like a list or a vector, but with less flexibility than a full list (tuples are immutable), however anything can be stored in either a list or tuple, without any consistency being required. Tuples are defined using round brackets and lists are defined using square brackets. For example:" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 143, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3, 7.6, 'str')\n", + "[1, 'mj', -5.4]\n" + ] + } + ], "source": [ "xtuple = (3, 7.6, 'str')\n", "xlist = [1, 'mj', -5.4]\n", @@ -365,9 +489,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 144, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x2 is: ((3, 7.6, 'str'), [1, 'mj', -5.4])\n", + "x3 is: [(3, 7.6, 'str'), [1, 'mj', -5.4]]\n" + ] + } + ], "source": [ "x2 = (xtuple, xlist)\n", "x3 = [xtuple, xlist]\n", @@ -387,9 +520,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 145, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 20, 30, 70, 80]\n" + ] + } + ], "source": [ "a = [10, 20, 30]\n", "a = a + [70]\n", @@ -401,17 +542,27 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "> Similar things can be done for tuples, except for the last one: that is, a += (80) as a tuple is immutable so cannot be changed like this. \n", + "\n", "<a class=\"anchor\" id=\"Indexing\"></a>\n", "### Indexing\n", "\n", - "Square brackets are used to index tuples, lists, dictionaries, etc. For example:" + "Square brackets are used to index tuples, lists, strings, dictionaries, etc. For example:" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 146, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20\n" + ] + } + ], "source": [ "d = [10, 20, 30]\n", "print(d[1])" @@ -427,9 +578,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 147, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10\n", + "30\n" + ] + } + ], "source": [ "a = [10, 20, 30, 40, 50, 60]\n", "print(a[0])\n", @@ -445,9 +605,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 148, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "60\n", + "10\n" + ] + } + ], "source": [ "print(a[-1])\n", "print(a[-6])" @@ -462,18 +631,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 149, + "metadata": {}, + "outputs": [ + { + "ename": "IndexError", + "evalue": "list index out of range", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-149-f4cf4536701c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m7\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m: list index out of range" + ] + } + ], "source": [ "print(a[-7])" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 150, + "metadata": {}, + "outputs": [ + { + "ename": "IndexError", + "evalue": "list index out of range", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-150-52d95fbe5286>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m: list index out of range" + ] + } + ], "source": [ "print(a[6])" ] @@ -487,9 +680,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 151, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n" + ] + } + ], "source": [ "print(len(a))" ] @@ -503,9 +704,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 152, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20\n", + "40\n" + ] + } + ], "source": [ "b = [[10, 20, 30], [40, 50, 60]]\n", "print(b[0][1])\n", @@ -516,7 +726,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "but *not* an index like b[0, 1].\n", + "but *not* an index like `b[0, 1]`. However, numpy arrays (covered in a later practical) can be indexed like `b[0, 1]` and similarly for higher dimensions.\n", "\n", "> Note that `len` will only give the length of the top level.\n", "> In general, numpy arrays should be preferred to nested lists when the contents are numerical.\n", @@ -529,9 +739,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 153, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 20, 30]\n" + ] + } + ], "source": [ "print(a[0:3])" ] @@ -548,9 +766,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 154, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 20, 30]\n", + "[20, 30]\n" + ] + } + ], "source": [ "a = [10, 20, 30, 40, 50, 60]\n", "print(a[0:3]) # same as a(1:3) in MATLAB\n", @@ -569,9 +796,21 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 155, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "list indices must be integers or slices, not list", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-155-aad7915ae3d8>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: list indices must be integers or slices, not list" + ] + } + ], "source": [ "b = [3, 4]\n", "print(a[b])" @@ -581,6 +820,67 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "In python you can leave the start and end values implicit, as it will assume these are the beginning and the end. For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 20, 30]\n", + "[20, 30, 40, 50, 60]\n", + "[10, 20, 30, 40, 50]\n" + ] + } + ], + "source": [ + "print(a[:3])\n", + "print(a[1:])\n", + "print(a[:-1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "in the last example remember that negative indices are subject to wrap around so that `a[:-1]` represents all elements up to the penultimate one.\n", + "\n", + "You can also change the step size, which is specified by the third value (not the second one, as in MATLAB). For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 30]\n", + "[10, 30, 50]\n", + "[60, 50, 40, 30, 20, 10]\n" + ] + } + ], + "source": [ + "print(a[0:4:2])\n", + "print(a[::2])\n", + "print(a[::-1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "the last example is a simple way to reverse a sequence.\n", + "\n", + "\n", "<a class=\"anchor\" id=\"List-operations\"></a>\n", "### List operations\n", "\n", @@ -589,9 +889,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 158, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 20, 30, 10, 20, 30, 10, 20, 30, 10, 20, 30]\n" + ] + } + ], "source": [ "d = [10, 20, 30]\n", "print(d * 4)" @@ -606,12 +914,28 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 159, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10, 20, 30, 40]\n", + "[10, 20, 30, 40, 50, 60]\n", + "[10, 20, 30, 40, 50, 60, 70, 80]\n", + "[10, 30, 40, 50, 60, 70, 80]\n", + "[30, 40, 50, 60, 70, 80]\n" + ] + } + ], "source": [ "d.append(40)\n", "print(d)\n", + "d.extend([50, 60])\n", + "print(d)\n", + "d = d + [70, 80]\n", + "print(d)\n", "d.remove(20)\n", "print(d)\n", "d.pop(0)\n", @@ -622,15 +946,27 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "> Note that `d.append([50,60])` would run but instead of adding two extra elements it only adds a single element, where this element is a list of length two, making a messy list. Try it and see if this is not clear.\n", + "\n", "<a class=\"anchor\" id=\"Looping\"></a>\n", "### Looping over elements in a list (or tuple)" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 160, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10\n", + "20\n", + "30\n" + ] + } + ], "source": [ "d = [10, 20, 30]\n", "for x in d:\n", @@ -641,7 +977,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "> Note that the indentation within the loop is _*crucial*_. All python control blocks are delineated purely by indentation.\n", + "> Note that the indentation within the loop is _*crucial*_. All python control blocks are delineated purely by indentation. We recommend using **four spaces** and no tabs, as this is a standard practice and will help a lot when collaborating with others.\n", "\n", "<a class=\"anchor\" id=\"Getting-help\"></a>\n", "### Getting help\n", @@ -651,9 +987,134 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 161, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on list object:\n", + "\n", + "class list(object)\n", + " | list() -> new empty list\n", + " | list(iterable) -> new list initialized from iterable's items\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<value.\n", + " | \n", + " | __mul__(self, value, /)\n", + " | Return self*value.n\n", + " | \n", + " | __ne__(self, value, /)\n", + " | Return self!=value.\n", + " | \n", + " | __new__(*args, **kwargs) from builtins.type\n", + " | Create and return a new object. See help(type) for accurate signature.\n", + " | \n", + " | __repr__(self, /)\n", + " | Return repr(self).\n", + " | \n", + " | __reversed__(...)\n", + " | L.__reversed__() -- return a reverse iterator over the list\n", + " | \n", + " | __rmul__(self, value, /)\n", + " | Return self*value.\n", + " | \n", + " | __setitem__(self, key, value, /)\n", + " | Set self[key] to value.\n", + " | \n", + " | __sizeof__(...)\n", + " | L.__sizeof__() -- size of L in memory, in bytes\n", + " | \n", + " | append(...)\n", + " | L.append(object) -> None -- append object to end\n", + " | \n", + " | clear(...)\n", + " | L.clear() -> None -- remove all items from L\n", + " | \n", + " | copy(...)\n", + " | L.copy() -> list -- a shallow copy of L\n", + " | \n", + " | count(...)\n", + " | L.count(value) -> integer -- return number of occurrences of value\n", + " | \n", + " | extend(...)\n", + " | L.extend(iterable) -> None -- extend list by appending elements from the iterable\n", + " | \n", + " | index(...)\n", + " | L.index(value, [start, [stop]]) -> integer -- return first index of value.\n", + " | Raises ValueError if the value is not present.\n", + " | \n", + " | insert(...)\n", + " | L.insert(index, object) -- insert object before index\n", + " | \n", + " | pop(...)\n", + " | L.pop([index]) -> item -- remove and return item at index (default last).\n", + " | Raises IndexError if list is empty or index is out of range.\n", + " | \n", + " | remove(...)\n", + " | L.remove(value) -> None -- remove first occurrence of value.\n", + " | Raises ValueError if the value is not present.\n", + " | \n", + " | reverse(...)\n", + " | L.reverse() -- reverse *IN PLACE*\n", + " | \n", + " | sort(...)\n", + " | L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes defined here:\n", + " | \n", + " | __hash__ = None\n", + "\n" + ] + } + ], "source": [ "help(d)" ] @@ -667,9 +1128,64 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 162, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['__add__',\n", + " '__class__',\n", + " '__contains__',\n", + " '__delattr__',\n", + " '__delitem__',\n", + " '__dir__',\n", + " '__doc__',\n", + " '__eq__',\n", + " '__format__',\n", + " '__ge__',\n", + " '__getattribute__',\n", + " '__getitem__',\n", + " '__gt__',\n", + " '__hash__',\n", + " '__iadd__',\n", + " '__imul__',\n", + " '__init__',\n", + " '__iter__',\n", + " '__le__',\n", + " '__len__',\n", + " '__lt__',\n", + " '__mul__',\n", + " '__ne__',\n", + " '__new__',\n", + " '__reduce__',\n", + " '__reduce_ex__',\n", + " '__repr__',\n", + " '__reversed__',\n", + " '__rmul__',\n", + " '__setattr__',\n", + " '__setitem__',\n", + " '__sizeof__',\n", + " '__str__',\n", + " '__subclasshook__',\n", + " 'append',\n", + " 'clear',\n", + " 'copy',\n", + " 'count',\n", + " 'extend',\n", + " 'index',\n", + " 'insert',\n", + " 'pop',\n", + " 'remove',\n", + " 'reverse',\n", + " 'sort']" + ] + }, + "execution_count": 162, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "dir(d)" ] @@ -678,7 +1194,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "> Note that google is often more helpful!\n", + "> Note that google is often more helpful! At least, as long as you find pages relating to the right version of python - we use python 3 for FSL, so check that what you find is appropriate for that.\n", "\n", "---\n", "\n", @@ -690,9 +1206,20 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 163, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "dict_keys(['b', 'a'])\n", + "dict_values([20, 10])\n", + "10\n" + ] + } + ], "source": [ "e = {'a' : 10, 'b': 20}\n", "print(len(e))\n", @@ -707,7 +1234,7 @@ "source": [ "The keys and values can take on almost any type, even dictionaries!\n", "Python is nothing if not flexible. However, each key must be unique\n", - "and the dictionary must be \"hashable\".\n", + "and [hashable](https://docs.python.org/3.5/glossary.html#term-hashable).\n", "\n", "<a class=\"anchor\" id=\"Adding-to-a-dictionary\"></a>\n", "### Adding to a dictionary\n", @@ -717,9 +1244,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 164, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'b': 20, 'a': 10, 'c': 555}\n" + ] + } + ], "source": [ "e['c'] = 555 # just like in Biobank! ;)\n", "print(e)" @@ -737,9 +1272,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 165, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'a': 10, 'c': 555}\n", + "{'a': 10}\n" + ] + } + ], "source": [ "e.pop('b')\n", "print(e)\n", @@ -759,13 +1303,23 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 166, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('b', 20)\n", + "('a', 10)\n", + "('c', 555)\n" + ] + } + ], "source": [ "e = {'a' : 10, 'b': 20, 'c':555}\n", "for k, v in e.items():\n", - " print((k, v))" + " print((k, v))" ] }, { @@ -779,9 +1333,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 167, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('b', 20)\n", + "('a', 10)\n", + "('c', 555)\n" + ] + } + ], "source": [ "for k in e:\n", " print((k, e[k]))" @@ -793,7 +1357,7 @@ "source": [ "> Note that in both cases the order is arbitrary. The `sorted` function can be used if you want keys in a sorted order; e.g. `for k in sorted(e):` ...\n", ">\n", - "> There are also other options if you want a dictionary with ordering.\n", + "> There are also [other options](https://docs.python.org/3.5/library/collections.html#collections.OrderedDict) if you want a dictionary with ordering.\n", "\n", "---\n", "\n", @@ -805,9 +1369,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 168, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "7\n" + ] + } + ], "source": [ "a = 7\n", "b = a\n", @@ -824,9 +1396,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 169, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[8888]\n" + ] + } + ], "source": [ "a = [7]\n", "b = a\n", @@ -843,9 +1423,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 170, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[7, 7]\n" + ] + } + ], "source": [ "a = [7]\n", "b = a * 2\n", @@ -862,9 +1450,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 171, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[7]\n" + ] + } + ], "source": [ "a = [7]\n", "b = list(a)\n", @@ -876,14 +1472,23 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There is a constructor for each type and this con be useful for converting between types:" + "There is a constructor for each type and this can be useful for converting between types:" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 172, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2, 5, 7)\n", + "[2, 5, 7]\n" + ] + } + ], "source": [ "xt = (2, 5, 7)\n", "xl = list(xt)\n", @@ -902,25 +1507,44 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 173, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a: [5]\n", + "x: [5, 10]\n", + "a: [5, 10]\n", + "x: [5, 10, 10]\n", + "a: [5, 10]\n", + "return value: [5, 10, 10]\n", + "a: [5, 10]\n", + "b: [5, 10, 10]\n" + ] + } + ], "source": [ "def foo1(x):\n", - " x.append(10)\n", + " x.append(10)\n", + " print('x: ', x)\n", "def foo2(x):\n", - " x = x + [10]\n", + " x = x + [10]\n", + " print('x: ', x)\n", "def foo3(x):\n", - " return x + [10]\n", + " print('return value: ', x + [10])\n", + " return x + [10]\n", "\n", "a = [5]\n", - "print(a)\n", + "print('a: ', a)\n", "foo1(a)\n", - "print(a)\n", + "print('a: ', a)\n", "foo2(a)\n", - "print(a)\n", - "foo3(a)\n", - "print(a)" + "print('a: ', a)\n", + "b = foo3(a)\n", + "print('a: ', a)\n", + "print('b: ', b)" ] }, { @@ -948,9 +1572,21 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 174, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Not a is: False\n", + "Not 1 is: False\n", + "Not 0 is: True\n", + "Not {} is: True\n", + "{}==0 is: False\n" + ] + } + ], "source": [ "a = True\n", "print('Not a is:', not a)\n", @@ -969,9 +1605,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 175, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n", + "True\n", + "True\n" + ] + } + ], "source": [ "print('the' in 'a number of words')\n", "print('of' in 'a number of words')\n", @@ -982,6 +1628,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "A useful keyword is `None`, which is a bit like \"null\". This can be a default value for a variable and should be tested with the `is` operator rather than `==` (for technical reasons that it isn't worth going into here). For example: `a is None` or `a is not None` are the preferred tests.\n", + "\n", + "\n", "<a class=\"anchor\" id=\"If-statements\"></a>\n", "### If statements\n", "\n", @@ -990,19 +1639,28 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 176, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.5890515724950383\n", + "Positive\n" + ] + } + ], "source": [ "import random\n", "a = random.uniform(-1, 1)\n", "print(a)\n", "if a>0:\n", - " print('Positive')\n", + " print('Positive')\n", "elif a<0:\n", - " print('Negative')\n", + " print('Negative')\n", "else:\n", - " print('Zero')" + " print('Zero')" ] }, { @@ -1014,13 +1672,21 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 177, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Variable is true, or at least not empty\n" + ] + } + ], "source": [ "a = [] # just one of many examples\n", "if not a:\n", - " print('Variable is true, or at least not empty')" + " print('Variable is true, or at least not empty')" ] }, { @@ -1039,12 +1705,24 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 178, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "is\n", + "more\n", + "than\n", + "1\n" + ] + } + ], "source": [ "for x in [2, 'is', 'more', 'than', 1]:\n", - " print(x)" + " print(x)" ] }, { @@ -1058,9 +1736,23 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 179, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n" + ] + } + ], "source": [ "for x in range(2, 9):\n", " print(x)" @@ -1077,9 +1769,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 180, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "7\n" + ] + } + ], "source": [ "x, y = [4, 7]\n", "print(x)\n", @@ -1095,15 +1796,27 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 181, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('Some', 0), ('set', 1), ('of', 2), ('items', 3)]\n", + "0 Some\n", + "1 set\n", + "2 of\n", + "3 items\n" + ] + } + ], "source": [ "alist = ['Some', 'set', 'of', 'items']\n", "blist = list(range(len(alist)))\n", "print(list(zip(alist, blist)))\n", "for x, y in zip(alist, blist):\n", - " print(y, x)" + " print(y, x)" ] }, { @@ -1120,18 +1833,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 182, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "34.995996566662235\n" + ] + } + ], "source": [ "import random\n", "n = 0\n", "x = 0\n", "while n<100:\n", - " x += random.uniform(0, 1)**2 # where ** is a power operation\n", - " if x>50:\n", - " break\n", - " n += 1\n", + " x += random.uniform(0, 1)**2 # where ** is a power operation\n", + " if x>50:\n", + " break\n", + " n += 1\n", "print(x)" ] }, @@ -1141,6 +1862,8 @@ "source": [ "You can also use `continue` as in other languages.\n", "\n", + "> Note that there is no `do ... while` construct.\n", + "\n", "---\n", "\n", "<a class=\"anchor\" id=\"quick-intro\"></a>\n", @@ -1158,9 +1881,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 183, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.33573141209899227 0.11271558106998338\n" + ] + } + ], "source": [ "import random\n", "x = random.uniform(0, 1)\n", @@ -1180,9 +1911,18 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 184, + "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, 64, 81]\n" + ] + } + ], "source": [ "v1 = [ x**2 for x in range(10) ]\n", "print(v1)\n", @@ -1219,14 +1959,24 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 185, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(22.360679774997898, 500)\n", + "37.416573867739416\n", + "37.416573867739416\n" + ] + } + ], "source": [ "def myfunc(x, y, z=0):\n", " r2 = x*x + y*y + z*z\n", " r = r2**0.5\n", - " return (r, r2)\n", + " return r, r2\n", "\n", "rad = myfunc(10, 20)\n", "print(rad)\n", @@ -1242,6 +1992,8 @@ "source": [ "> Note that the `_` is used as shorthand here for a dummy variable\n", "> that you want to throw away.\n", + ">\n", + "> The return statement implicitly creates a tuple to return and is equivalent to `return (r, r2)`\n", "\n", "One nice feature of python functions is that you can name the\n", "arguments when you call them, rather than only doing it by position.\n", @@ -1250,16 +2002,24 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 186, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "22.360679774997898 30 60\n" + ] + } + ], "source": [ "def myfunc(x, y, z=0, flag=''):\n", - " if flag=='L1':\n", - " r = abs(x) + abs(y) + abs(z)\n", - " else:\n", - " r = (x*x + y*y + z*z)**0.5\n", - " return r\n", + " if flag=='L1':\n", + " r = abs(x) + abs(y) + abs(z)\n", + " else:\n", + " r = (x*x + y*y + z*z)**0.5\n", + " return r\n", "\n", "rA = myfunc(10, 20)\n", "rB = myfunc(10, 20, flag='L1')\n", @@ -1271,7 +2031,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You will often see python functions called with these named arguments.\n", + "You will often see python functions called with these named arguments. In fact, for functions with more than 2 or 3 variables this naming of arguments is recommended, because it clarifies what each of the arguments does for anyone reading the code.\n", "\n", "---\n", "\n", @@ -1283,7 +2043,7 @@ "\n", "Write some code to do the following: \n", " * separate out the filenames and ID codes into separate lists (ID's\n", - " should be numerical values, not strings)\n", + " should be numerical values, not strings) - you may need several steps for this\n", " * loop over the two and generate a _string_ that could be used to\n", " rename the directories (e.g., `mv /vols/Data/pytreat/AAC /vols/Data/pytreat/S165873`) - we will cover how to actually execute these in a later practical\n", " * convert your dual lists into a dictionary, with ID as the key\n", @@ -1300,7 +2060,7 @@ "metadata": {}, "outputs": [], "source": [ - "mstr = '/vols/Data/pytreat/AAC, 165873, /vols/Data/pytreat/AAG, 170285, /vols/Data/pytreat/AAH, 196792, /vols/Data/pytreat/AAK, 212577, /vols/Data/pytreat/AAQ, 385376, /vols/Data/pytreat/AB, 444600, /vols/Data/pytreat/AC6, 454578, /vols/Data/pytreat/V8, 501502, /vols/Data/pytreat/2YK, 667688, /vols/Data/pytreat/C3PO, 821971'" + "mstr = '/vols/Data/pytreat/AAC, 165873, /vols/Data/pytreat/AAG, 170285, /vols/Data/pytreat/AAH, 196792, /vols/Data/pytreat/AAK, 212577, /vols/Data/pytreat/AAQ, 385376, /vols/Data/pytreat/AB, 444600, /vols/Data/pytreat/AC6, 454578, /vols/Data/pytreat/V8, 501502, /vols/Data/pytreat/2YK, 667688, /vols/Data/pytreat/C3PO, 821971'\n" ] } ], diff --git a/getting_started/01_basics.md b/getting_started/01_basics.md index 760f2c41de0963f9172f51179a675cd395513b84..9c5928de0ac64d057b56057096881f180d495089 100644 --- a/getting_started/01_basics.md +++ b/getting_started/01_basics.md @@ -51,7 +51,7 @@ Python has many different types and variables are dynamic and can change types ( * strings * tuples * lists -* dictionary +* dictionaries N-dimensional arrays and other types are supported through common modules (e.g., numpy, scipy, scikit-learn). These will be covered in a subsequent exercise. @@ -146,7 +146,7 @@ s = 'This is a test of a Test String' s1 = re.sub(r'a [Tt]est', "an example", s) print(s1) ``` -where the `r` before the quote is used to force the regular expression specification to be a `raw string`. +where the `r` before the quote is used to force the regular expression specification to be a `raw string` (see [here](https://docs.python.org/3.5/library/re.html) for more info). For more information on matching and substitutions, look up the regular expression module on the web. @@ -195,7 +195,7 @@ Both tuples and lists are builtin python types and are like vectors, but for numerical vectors and arrays it is much better to use _numpy_ arrays (or matrices), which are covered in a later tutorial. -A tuple is like a list or a vector, but with less flexibility than a full list, however anything can be stored in either a list or tuple, without any consistency being required. For example: +A tuple is like a list or a vector, but with less flexibility than a full list (tuples are immutable), however anything can be stored in either a list or tuple, without any consistency being required. Tuples are defined using round brackets and lists are defined using square brackets. For example: ``` xtuple = (3, 7.6, 'str') xlist = [1, 'mj', -5.4] @@ -222,10 +222,12 @@ a += [80] print(a) ``` +> Similar things can be done for tuples, except for the last one: that is, a += (80) as a tuple is immutable so cannot be changed like this. + <a class="anchor" id="Indexing"></a> ### Indexing -Square brackets are used to index tuples, lists, dictionaries, etc. For example: +Square brackets are used to index tuples, lists, strings, dictionaries, etc. For example: ``` d = [10, 20, 30] print(d[1]) @@ -265,7 +267,7 @@ b = [[10, 20, 30], [40, 50, 60]] print(b[0][1]) print(b[1][0]) ``` -but *not* an index like b[0, 1]. +but *not* an index like `b[0, 1]`. However, numpy arrays (covered in a later practical) can be indexed like `b[0, 1]` and similarly for higher dimensions. > Note that `len` will only give the length of the top level. > In general, numpy arrays should be preferred to nested lists when the contents are numerical. @@ -299,6 +301,23 @@ b = [3, 4] print(a[b]) ``` +In python you can leave the start and end values implicit, as it will assume these are the beginning and the end. For example: +``` +print(a[:3]) +print(a[1:]) +print(a[:-1]) +``` +in the last example remember that negative indices are subject to wrap around so that `a[:-1]` represents all elements up to the penultimate one. + +You can also change the step size, which is specified by the third value (not the second one, as in MATLAB). For example: +``` +print(a[0:4:2]) +print(a[::2]) +print(a[::-1]) +``` +the last example is a simple way to reverse a sequence. + + <a class="anchor" id="List-operations"></a> ### List operations @@ -313,12 +332,18 @@ There are also other operations such as: ``` d.append(40) print(d) +d.extend([50, 60]) +print(d) +d = d + [70, 80] +print(d) d.remove(20) print(d) d.pop(0) print(d) ``` +> Note that `d.append([50,60])` would run but instead of adding two extra elements it only adds a single element, where this element is a list of length two, making a messy list. Try it and see if this is not clear. + <a class="anchor" id="Looping"></a> ### Looping over elements in a list (or tuple) @@ -328,7 +353,7 @@ for x in d: print(x) ``` -> Note that the indentation within the loop is _*crucial*_. All python control blocks are delineated purely by indentation. +> Note that the indentation within the loop is _*crucial*_. All python control blocks are delineated purely by indentation. We recommend using **four spaces** and no tabs, as this is a standard practice and will help a lot when collaborating with others. <a class="anchor" id="Getting-help"></a> ### Getting help @@ -347,7 +372,7 @@ dir(d) ``` -> Note that google is often more helpful! +> Note that google is often more helpful! At least, as long as you find pages relating to the right version of python - we use python 3 for FSL, so check that what you find is appropriate for that. --- @@ -365,7 +390,7 @@ print(e['a']) The keys and values can take on almost any type, even dictionaries! Python is nothing if not flexible. However, each key must be unique -and the dictionary must be "hashable". +and [hashable](https://docs.python.org/3.5/glossary.html#term-hashable). <a class="anchor" id="Adding-to-a-dictionary"></a> ### Adding to a dictionary @@ -394,7 +419,7 @@ Several variables can jointly work as loop variables in python, which is very co ``` e = {'a' : 10, 'b': 20, 'c':555} for k, v in e.items(): - print((k, v)) + print((k, v)) ``` The print statement here constructs a tuple, which is often used in python. @@ -407,7 +432,7 @@ for k in e: > Note that in both cases the order is arbitrary. The `sorted` function can be used if you want keys in a sorted order; e.g. `for k in sorted(e):` ... > -> There are also other options if you want a dictionary with ordering. +> There are also [other options](https://docs.python.org/3.5/library/collections.html#collections.OrderedDict) if you want a dictionary with ordering. --- @@ -446,7 +471,7 @@ a[0] = 8888 print(b) ``` -There is a constructor for each type and this con be useful for converting between types: +There is a constructor for each type and this can be useful for converting between types: ``` xt = (2, 5, 7) xl = list(xt) @@ -460,20 +485,24 @@ print(xl) ``` def foo1(x): - x.append(10) + x.append(10) + print('x: ', x) def foo2(x): - x = x + [10] + x = x + [10] + print('x: ', x) def foo3(x): - return x + [10] + print('return value: ', x + [10]) + return x + [10] a = [5] -print(a) +print('a: ', a) foo1(a) -print(a) +print('a: ', a) foo2(a) -print(a) -foo3(a) -print(a) +print('a: ', a) +b = foo3(a) +print('a: ', a) +print('b: ', b) ``` > Note that we have defined some functions here - and the syntax @@ -509,6 +538,10 @@ print('of' in 'a number of words') print(3 in [1, 2, 3, 4]) ``` + +A useful keyword is `None`, which is a bit like "null". This can be a default value for a variable and should be tested with the `is` operator rather than `==` (for technical reasons that it isn't worth going into here). For example: `a is None` or `a is not None` are the preferred tests. + + <a class="anchor" id="If-statements"></a> ### If statements @@ -518,18 +551,18 @@ import random a = random.uniform(-1, 1) print(a) if a>0: - print('Positive') + print('Positive') elif a<0: - print('Negative') + print('Negative') else: - print('Zero') + print('Zero') ``` Or more generally: ``` a = [] # just one of many examples if not a: - print('Variable is true, or at least not empty') + print('Variable is true, or at least not empty') ``` This can be useful for functions where a variety of possible input types are being dealt with. @@ -541,7 +574,7 @@ This can be useful for functions where a variety of possible input types are bei The `for` loop works like in bash: ``` for x in [2, 'is', 'more', 'than', 1]: - print(x) + print(x) ``` where a list or any other sequence (e.g. tuple) can be used. @@ -565,7 +598,7 @@ alist = ['Some', 'set', 'of', 'items'] blist = list(range(len(alist))) print(list(zip(alist, blist))) for x, y in zip(alist, blist): - print(y, x) + print(y, x) ``` This type of loop can be used with any two lists (or similar) to iterate over them jointly. @@ -579,15 +612,17 @@ import random n = 0 x = 0 while n<100: - x += random.uniform(0, 1)**2 # where ** is a power operation - if x>50: - break - n += 1 + x += random.uniform(0, 1)**2 # where ** is a power operation + if x>50: + break + n += 1 print(x) ``` You can also use `continue` as in other languages. +> Note that there is no `do ... while` construct. + --- <a class="anchor" id="quick-intro"></a> @@ -645,7 +680,7 @@ with we'll look at a simple function but note a few key points: def myfunc(x, y, z=0): r2 = x*x + y*y + z*z r = r2**0.5 - return (r, r2) + return r, r2 rad = myfunc(10, 20) print(rad) @@ -657,17 +692,19 @@ print(rad) > Note that the `_` is used as shorthand here for a dummy variable > that you want to throw away. +> +> The return statement implicitly creates a tuple to return and is equivalent to `return (r, r2)` One nice feature of python functions is that you can name the arguments when you call them, rather than only doing it by position. For example: ``` def myfunc(x, y, z=0, flag=''): - if flag=='L1': - r = abs(x) + abs(y) + abs(z) - else: - r = (x*x + y*y + z*z)**0.5 - return r + if flag=='L1': + r = abs(x) + abs(y) + abs(z) + else: + r = (x*x + y*y + z*z)**0.5 + return r rA = myfunc(10, 20) rB = myfunc(10, 20, flag='L1') @@ -675,7 +712,7 @@ rC = myfunc(10, 20, flag='L1', z=30) print(rA, rB, rC) ``` -You will often see python functions called with these named arguments. +You will often see python functions called with these named arguments. In fact, for functions with more than 2 or 3 variables this naming of arguments is recommended, because it clarifies what each of the arguments does for anyone reading the code. --- @@ -687,7 +724,7 @@ that represent filenames and ID codes: e.g., `/vols/Data/pytreat/AAC, 165873, /v Write some code to do the following: * separate out the filenames and ID codes into separate lists (ID's - should be numerical values, not strings) + should be numerical values, not strings) - you may need several steps for this * loop over the two and generate a _string_ that could be used to rename the directories (e.g., `mv /vols/Data/pytreat/AAC /vols/Data/pytreat/S165873`) - we will cover how to actually execute these in a later practical * convert your dual lists into a dictionary, with ID as the key @@ -699,6 +736,7 @@ Write some code to do the following: ``` mstr = '/vols/Data/pytreat/AAC, 165873, /vols/Data/pytreat/AAG, 170285, /vols/Data/pytreat/AAH, 196792, /vols/Data/pytreat/AAK, 212577, /vols/Data/pytreat/AAQ, 385376, /vols/Data/pytreat/AB, 444600, /vols/Data/pytreat/AC6, 454578, /vols/Data/pytreat/V8, 501502, /vols/Data/pytreat/2YK, 667688, /vols/Data/pytreat/C3PO, 821971' + ``` diff --git a/getting_started/05_nifti.md b/getting_started/05_nifti.md index 9293ce18115c8dc186fdaef31c8ed300f20a749b..5e554469539e111084f5ae87aa29ad8c9f534316 100644 --- a/getting_started/05_nifti.md +++ b/getting_started/05_nifti.md @@ -117,7 +117,7 @@ If the voxel size of the image is different, then extra modifications will be re <a class="anchor" id="exercise"></a> ## Exercise -Write some code to read in a 4D fMRI image (you can find one [here] if +Write some code to read in a 4D fMRI image (you can find one [here](http://www.fmrib.ox.ac.uk/~mark/files/av.nii.gz) if you don't have one handy), calculate the tSNR and then save the 3D result. ``` diff --git a/getting_started/08_scripts.ipynb b/getting_started/08_scripts.ipynb index b4e816dbd9fa12d733bdf1578684acf2538d2ac4..16faa7ec08486151715108408828cb714ff3908a 100644 --- a/getting_started/08_scripts.ipynb +++ b/getting_started/08_scripts.ipynb @@ -275,7 +275,25 @@ ] } ], - "metadata": {}, + "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.5.2" + } + }, "nbformat": 4, "nbformat_minor": 2 }