From 99f4a5ef29b19be964a70fb480455e8de92ad6a9 Mon Sep 17 00:00:00 2001 From: Phil Weir Date: Sat, 4 Sep 2021 17:44:27 +0100 Subject: [PATCH] updates for computationally calculated dependencies --- .gitignore | 1 + 001-what-is-python/index.html | 1 + 002-basic-control-structures/Answers.ipynb | 118 ++ .../Basic control structures II.ipynb | 132 ++- .../Basic control structures.ipynb | 1053 +++++------------ ...thon Course - 002a - And so we begin.ipynb | 41 +- 006-latency/Latency.ipynb | 224 +++- 022-burette/A Magnum of Opera.ipynb | 2 +- course-structure-5day.txt | 16 + 9 files changed, 795 insertions(+), 793 deletions(-) create mode 100644 002-basic-control-structures/Answers.ipynb create mode 100644 course-structure-5day.txt diff --git a/.gitignore b/.gitignore index 88847ca..5e73597 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ __pycache__ .mypy_cache .venv .vscode +env diff --git a/001-what-is-python/index.html b/001-what-is-python/index.html index 0ecb9c0..3d58824 100644 --- a/001-what-is-python/index.html +++ b/001-what-is-python/index.html @@ -45,6 +45,7 @@

(Who am I?)

  • Studied numeric modelling
  • Scientific programmer in industry (Dundalk)
  • Web, data and infrastructure consultant
  • +
  • Open Source as a Service
  • diff --git a/002-basic-control-structures/Answers.ipynb b/002-basic-control-structures/Answers.ipynb new file mode 100644 index 0000000..cd1536a --- /dev/null +++ b/002-basic-control-structures/Answers.ipynb @@ -0,0 +1,118 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f70a0f3e", + "metadata": {}, + "source": [ + "# 002: Basic Control Structures" + ] + }, + { + "cell_type": "markdown", + "id": "aec9a83f", + "metadata": {}, + "source": [ + "## Zipping Up" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b5663e8e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Set my_dictionary[ a ] to be 23\n", + "Set my_dictionary[ b ] to be 42\n", + "Set my_dictionary[ c ] to be 12\n", + "Set my_dictionary[ d ] to be 9\n", + "Set my_dictionary[ e ] to be 5\n", + "Set my_dictionary[ f ] to be 1\n", + "{'a': 23, 'b': 42, 'c': 12, 'd': 9, 'e': 5, 'f': 1}\n", + "Set my_dictionary[ 23 ] to be a\n", + "Set my_dictionary[ 42 ] to be b\n", + "Set my_dictionary[ 12 ] to be c\n", + "Set my_dictionary[ 9 ] to be d\n", + "Set my_dictionary[ 5 ] to be e\n", + "Set my_dictionary[ 1 ] to be f\n", + "{23: 'a', 42: 'b', 12: 'c', 9: 'd', 5: 'e', 1: 'f'}\n" + ] + } + ], + "source": [ + "# Loop through them to make a dictionary, where the first list is the keys,\n", + "# and the second list is the values.\n", + "# You might want to make this into a function where the first argument is\n", + "# the first list, and the second argument is the second list\n", + "def zip_two_lists(key_list, value_list):\n", + " my_dictionary = {}\n", + " for i in range(len(key_list)):\n", + " my_key = key_list[i]\n", + " my_value = value_list[i]\n", + "\n", + " print('Set my_dictionary[', my_key, '] to be ', my_value)\n", + " my_dictionary[my_key] = my_value\n", + " return my_dictionary\n", + "\n", + "# Print out your new dictionary\n", + "my_list_of_keys = ['a', 'b', 'c', 'd', 'e', 'f']\n", + "my_list_of_values = [23, 42, 12, 9, 5, 1]\n", + "my_new_dictionary = zip_two_lists(my_list_of_keys, my_list_of_values)\n", + "print(my_new_dictionary)\n", + "my_new_dictionary = zip_two_lists(my_list_of_values, my_list_of_keys)\n", + "print(my_new_dictionary)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e131b7ca", + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 23, 'b': 42, 'c': 12, 'd': 9, 'e': 5, 'f': 1}" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_dct = {}\n", + "for key, value in zip(my_list_of_keys, my_list_of_values):\n", + " new_dct[key] = value\n", + "new_dct" + ] + } + ], + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/002-basic-control-structures/Basic control structures II.ipynb b/002-basic-control-structures/Basic control structures II.ipynb index 16d538a..fa4e18f 100644 --- a/002-basic-control-structures/Basic control structures II.ipynb +++ b/002-basic-control-structures/Basic control structures II.ipynb @@ -2281,6 +2281,115 @@ " return False" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Decorators" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Decorators will be explored more as time permits, but to help you recognise them as we move through, a brief explanation: these are brief annotations directly above `def` (for functions and methods). They tell Python to wrap the function/method with a function-of-a-function. In another phrasing, a decorator takes a function and soups it up. This looks like:\n", + "\n", + "```python\n", + "@mydecorator\n", + "def afunction():\n", + " ...\n", + "``` \n", + "\n", + "In this case `mydecorator` will somehow modify the function's attributes or effects - examples are `@coroutine` for marking a function as async, `@staticmethod` for marking a class's method as static, and `@timer` for timing a function when it is called. You can even make your own - decorators are usually functions with a function as an argument, so you know all the syntax you need. It might look something like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def val2string(f):\n", + " def modified_f(val1, val2):\n", + " normal_result = f(val1, val2)\n", + " return str(normal_result)\n", + " return modified_f" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above creates a new function called `modified_f` (note that function definitions can live anywhere, including in a function, just like any other variable definition). It is a two-argument function, which returns the stringified version of the original function, called with the same arguments. For instance:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'4'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@val2string\n", + "def add(a, b):\n", + " return a + b\n", + "\n", + "@val2string\n", + "def mul(a, b):\n", + " return a * b\n", + "add(1, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"['this', 'that']\"" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "add(['this'], ['that'])" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'12'" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mul(6, 2)" + ] + }, { "cell_type": "markdown", "metadata": { @@ -2348,27 +2457,6 @@ "* comprehensions" ] }, - { - "cell_type": "markdown", - "metadata": { - "hideCode": false, - "hidePrompt": false, - "slideshow": { - "slide_type": "notes" - } - }, - "source": [ - "We haven't talked about a number of structures, but a couple you may come across that we don't cover in this course, are asynchronous routines (`async`, `await`) that follow the coroutine paradigm; and decorators, which allow us to mark certain functions and methods to be wrapped by a function-of-a-function. This looks like:\n", - "\n", - "```python\n", - "@mydecorator\n", - "def afunction():\n", - " ...\n", - "``` \n", - "\n", - "In this case `mydecorator` will somehow modify the function's attributes or effects - examples are `@coroutine` for marking a function as async, `@staticmethod` for marking a class's method as static, and `@timer` for timing a function when it is called." - ] - }, { "cell_type": "markdown", "metadata": { @@ -2803,7 +2891,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.7.11" }, "livereveal": { "theme": "beige", diff --git a/002-basic-control-structures/Basic control structures.ipynb b/002-basic-control-structures/Basic control structures.ipynb index 79f969b..d1add5d 100644 --- a/002-basic-control-structures/Basic control structures.ipynb +++ b/002-basic-control-structures/Basic control structures.ipynb @@ -53,11 +53,11 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "x=8 # comment" + "x= # comment" ] }, { @@ -97,22 +97,11 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "scrolled": true }, - "outputs": [ - { - "data": { - "text/plain": [ - "16" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "2 * x" ] @@ -154,20 +143,11 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Something else\n", - "0.6666666666666666\n" - ] - } - ], - "source": [ - "if Out[8] / 2 == x:\n", + "outputs": [], + "source": [ + "if Out[1] / 2 == x:\n", " print(\"Something else\")\n", "print(2/3)" ] @@ -246,18 +226,9 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "SyntaxError", - "evalue": "EOL while scanning string literal (, line 4)", - "output_type": "error", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m4\u001b[0m\n\u001b[0;31m print(\"Yes I do')\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m EOL while scanning string literal\n" - ] - } - ], + "outputs": [], "source": [ "if (x < 2) or (x > 100):\n", " print(\"Do I know you?\")\n", @@ -321,7 +292,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -347,23 +318,13 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "I am 35 - am I old?\n", - "...checking if Phil is old...\n", - "Not at all, spring chicken.\n" - ] - } - ], + "outputs": [], "source": [ "phils_age = 35\n", "name = \"Phil\"\n", @@ -389,31 +350,20 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "slide" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "'JUST A NORMAL STRING'" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "\"just a normal string\".upper()" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": { "scrolled": true, "slideshow": { @@ -426,6 +376,68 @@ " print(\"The string was lowercase\")" ] }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Something for Nothing\n", + "\n", + "How do we express _no_ value? Not zero, or false, but the complete absence of any meaningful type or value. This is covered by `null` in C-like languages, but in Python, we call it `None`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "if None:\n", + " print('Nothing doing')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, + "source": [ + "None, perhaps unsurprisingly, is treated as \"false-y\" in a conditional expression like `if`. It doesn't play well with other types either..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "None + 1" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, + "source": [ + "Side-note: for those already familiar with Python functions, you may wish to note that a function with no return value, implicitly returns `None`." + ] + }, { "cell_type": "markdown", "metadata": { @@ -462,7 +474,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -494,24 +506,9 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['Accept Nobel prize',\n", - " 'Finish PhD',\n", - " 'Inspire a new generation',\n", - " 'Learn Python',\n", - " 'Publish research']" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "sorted(things_to_do)" ] @@ -560,24 +557,13 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "'Inspire a new generation'" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "things_to_do[4]" ] @@ -629,22 +615,11 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'THINGS_TO_DO[4]'" - ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "In[40].upper()" + "In[4]" ] }, { @@ -682,31 +657,13 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['Learn Python', 'Finish PhD', 'Publish research', 'Accept Nobel prize', 'Inspire a new generation']\n" - ] - }, - { - "data": { - "text/plain": [ - "['Finish PhD', 'Publish research', 'Accept Nobel prize']" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "print(things_to_do)\n", "things_to_do[1:4]" @@ -725,72 +682,39 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "['Learn Python', 'Finish PhD']" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "things_to_do[:2]" ] }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "['Accept Nobel prize', 'Inspire a new generation']" - ] - }, - "execution_count": 51, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "things_to_do[3:]" ] }, { "cell_type": "code", - "execution_count": 52, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "['Accept Nobel prize', 'Inspire a new generation']" - ] - }, - "execution_count": 52, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "things_to_do[-2:]" ] @@ -808,24 +732,13 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "slide" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "['Learn Python', 'Inspire a new generation']" - ] - }, - "execution_count": 55, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "things_to_do[::4]" ] @@ -852,28 +765,13 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "['Inspire a new generation',\n", - " 'Accept Nobel prize',\n", - " 'Publish research',\n", - " 'Finish PhD',\n", - " 'Learn Python']" - ] - }, - "execution_count": 56, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "things_to_do[::-1]" ] @@ -924,7 +822,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" @@ -966,27 +864,9 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "My favourite number is\n" - ] - }, - { - "data": { - "text/plain": [ - "9" - ] - }, - "execution_count": 64, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "print(\"My favourite number is\")\n", "my_meetup_dot_com_profile['favourite number']" @@ -1005,60 +885,37 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "'is the magic number'" - ] - }, - "execution_count": 65, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "my_meetup_dot_com_profile[3]" ] }, { - "cell_type": "code", - "execution_count": 66, + "cell_type": "markdown", "metadata": { - "scrolled": true - }, - "outputs": [ - { - "ename": "KeyError", - "evalue": "2", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmy_meetup_dot_com_profile\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mKeyError\u001b[0m: 2" - ] + "slideshow": { + "slide_type": "notes" } - ], + }, "source": [ - "my_meetup_dot_com_profile[2]" + "...but not..." ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": { - "slideshow": { - "slide_type": "notes" - } + "scrolled": true }, + "outputs": [], "source": [ - "...but not..." + "my_meetup_dot_com_profile[2]" ] }, { @@ -1096,21 +953,11 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": { "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "TODO: ['Learn Python', 'Finish PhD', 'Publish research', 'Accept Nobel prize', 'Inspire a new generation', 'Find a nice retirement village in the Galapagos Islands'] \n", - "\n", - "MEETUP: {'first name': 'Ignatius', 'favourite number': 9, 'favourite programming language': 'FORTRAN66', 3: 'is the magic number', 'Interests': ['Python2', 'Python3', 'Scientific Python', 'Pottery']}\n" - ] - } - ], + "outputs": [], "source": [ "things_to_do.append(\"Find a nice retirement village in the Galapagos Islands\")\n", "\n", @@ -1141,20 +988,9 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['key1', 'key2', 'test', 'another_test']" - ] - }, - "execution_count": 68, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from collections import OrderedDict # we'll discuss importing shortly\n", "\n", @@ -1198,24 +1034,13 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "'Learn Python, Finish PhD, Publish research, Accept Nobel prize, Inspire a new generation, Find a nice retirement village in the Galapagos Islands'" - ] - }, - "execution_count": 70, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "', '.join(things_to_do)" ] @@ -1292,18 +1117,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "When z is 1 then y is 120.0\n", - "When z is 3 then y is 40.0\n" - ] - } - ], + "outputs": [], "source": [ "y = 120\n", "for z in range(1, 5, 2):\n", @@ -1375,20 +1191,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "range" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "type(range(5))" ] @@ -1412,24 +1217,13 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "[0, 1, 2, 3, 4]" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "list(range(5))" ] @@ -1458,45 +1252,13 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'range(0, 5)'" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "str(range(5))" ] }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "unsupported operand type(s) for +: 'float' and 'str'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m3.14\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m\" is almost pi\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'float' and 'str'" - ] - } - ], - "source": [ - "3.14 + \" is almost pi\"" - ] - }, { "cell_type": "markdown", "metadata": { @@ -1510,20 +1272,18 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "3.14 + \" is almost pi\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "str" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "type(str(3.14))" ] @@ -1541,17 +1301,9 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Let me hear you say Y.M.C.A. Let me hear you say Y.M.C.A. \n" - ] - } - ], + "outputs": [], "source": [ "lyric = \"\"\n", "for _ in range(2):\n", @@ -1592,29 +1344,9 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Learn Python :\n", - " using Python, this task will take 12 months to complete\n", - "Finish PhD :\n", - " using Python, this task will take 10 months to complete\n", - "Publish research :\n", - " using Python, this task will take 16 months to complete\n", - "Accept Nobel prize :\n", - " using Python, this task will take 18 months to complete\n", - "Inspire a new generation :\n", - " using Python, this task will take 24 months to complete\n", - "Find a nice retirement village in the Galapagos Islands :\n", - " using Python, this task will take 55 months to complete\n", - "You cannot retire for at least 11 years\n" - ] - } - ], + "outputs": [], "source": [ "total_months = 0\n", "for task in things_to_do:\n", @@ -1650,25 +1382,13 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "slide" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "first name\n", - "favourite number\n", - "favourite programming language\n", - "3\n", - "Interests\n" - ] - } - ], + "outputs": [], "source": [ "for field in my_meetup_dot_com_profile.keys():\n", " print(field)" @@ -1676,25 +1396,13 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "slide" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ignatius\n", - "9\n", - "FORTRAN66\n", - "is the magic number\n", - "['Python2', 'Python3', 'Scientific Python', 'Pottery']\n" - ] - } - ], + "outputs": [], "source": [ "for value in my_meetup_dot_com_profile.values():\n", " print(value)" @@ -1702,52 +1410,76 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "slide" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "first name = Ignatius\n", - "favourite number = 9\n", - "favourite programming language = FORTRAN66\n", - "3 = is the magic number\n", - "Interests = ['Python2', 'Python3', 'Scientific Python', 'Pottery']\n" - ] - } - ], + "outputs": [], "source": [ "for pair in my_meetup_dot_com_profile.items():\n", " print(pair[0], \"=\", pair[1])" ] }, { - "cell_type": "code", - "execution_count": 31, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "key1 = 1 2 3\n", - "key2 = a b c\n", - "key3 = do re mi\n" - ] - } - ], "source": [ + "#### Advanced Note\n", + "\n", + "If you know the number of values being assigned to a pair (or triple, etc.), you can comma-separate multiple new variable names to assign them all at once in the `for` loop, instead of having to manually assign them human-readable names afterwards." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, + "outputs": [], + "source": [ + "my_dict = {'key1': 123, 'key2': 234, 'key3': 345}\n", + "\n", + "for key, value in my_dict.items():\n", + " print(key, '=', value, 'short')\n", + " \n", + "# is the same as\n", + "\n", + "for pair in my_dict.items():\n", + " key = pair[0]\n", + " value = pair[1]\n", + " print(key, '=', value, 'long')\n", + "\n", + "print('...or even nested...')\n", + "\n", "my_dict = {'key1': [1, 2, 3], 'key2': ['a', 'b', 'c'], 'key3': ['do', 're', 'mi']}\n", "\n", "for key, (first, another, yet_another) in my_dict.items():\n", " print(key, '=', first, another, yet_another)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In fact, any standard form of assignment allows for this:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pear = ['stalk', 'flesh']\n", + "# Assigning a group variables at once\n", + "this, that = pear\n", + "print(this, that)" + ] + }, { "cell_type": "markdown", "metadata": { @@ -1778,24 +1510,9 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'FIRST NAME': 'Ignatius',\n", - " 'FAVOURITE NUMBER': 9,\n", - " 'FAVOURITE PROGRAMMING LANGUAGE': 'FORTRAN66',\n", - " '3': 'is the magic number',\n", - " 'INTERESTS': ['Python2', 'Python3', 'Scientific Python', 'Pottery']}" - ] - }, - "execution_count": 44, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "def dict_to_string_map(dictionary):\n", " new_dictionary = {}\n", @@ -1867,56 +1584,18 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "notes" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Set my_dictionary[ a ] to be 23\n", - "Set my_dictionary[ b ] to be 42\n", - "Set my_dictionary[ c ] to be 12\n", - "Set my_dictionary[ d ] to be 9\n", - "Set my_dictionary[ e ] to be 5\n", - "Set my_dictionary[ f ] to be 1\n", - "{'a': 23, 'b': 42, 'c': 12, 'd': 9, 'e': 5, 'f': 1}\n", - "Set my_dictionary[ 23 ] to be a\n", - "Set my_dictionary[ 42 ] to be b\n", - "Set my_dictionary[ 12 ] to be c\n", - "Set my_dictionary[ 9 ] to be d\n", - "Set my_dictionary[ 5 ] to be e\n", - "Set my_dictionary[ 1 ] to be f\n", - "{23: 'a', 42: 'b', 12: 'c', 9: 'd', 5: 'e', 1: 'f'}\n" - ] - } - ], + "outputs": [], "source": [ "# Loop through them to make a dictionary, where the first list is the keys,\n", "# and the second list is the values.\n", "# You might want to make this into a function where the first argument is\n", - "# the first list, and the second argument is the second list\n", - "def zip_two_lists(key_list, value_list):\n", - " my_dictionary = {}\n", - " for i in range(len(key_list)):\n", - " my_key = key_list[i]\n", - " my_value = value_list[i]\n", - "\n", - " print('Set my_dictionary[', my_key, '] to be ', my_value)\n", - " my_dictionary[my_key] = my_value\n", - " return my_dictionary\n", - "\n", - "# Print out your new dictionary\n", - "my_list_of_keys = ['a', 'b', 'c', 'd', 'e', 'f']\n", - "my_list_of_values = [23, 42, 12, 9, 5, 1]\n", - "my_new_dictionary = zip_two_lists(my_list_of_keys, my_list_of_values)\n", - "print(my_new_dictionary)\n", - "my_new_dictionary = zip_two_lists(my_list_of_values, my_list_of_keys)\n", - "print(my_new_dictionary)" + "# the first list, and the second argument is the second list" ] }, { @@ -1932,43 +1611,84 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_zip = zip(my_list_of_keys, my_list_of_values)\n", + "print(my_zip)\n", + "list(my_zip)" + ] + }, + { + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'a': 23, 'b': 42, 'c': 12, 'd': 9, 'e': 5, 'f': 1}" - ] - }, - "execution_count": 54, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ - "new_dct = {}\n", - "for key, value in zip(my_list_of_keys, my_list_of_values):\n", - " new_dct[key] = value\n", - "new_dct" + "Above you might notice that `zip` returns a variable of type `zip` - to get a printable list, we have to \"cast\" it to a list. Why would the Python architects give us a function that returns a type that is so specific to the function? What advantage could a `zip` type have over a `list` type?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The other approach to printing this, without casting it, is to use... `print`" ] }, { "cell_type": "code", - "execution_count": 56, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_zip = zip(my_list_of_keys, my_list_of_values)\n", + "print(*my_zip)" + ] + }, + { + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'a': 23, 'b': 42, 'c': 12, 'd': 9, 'e': 5, 'f': 1}" - ] - }, - "execution_count": 56, - "metadata": {}, - "output_type": "execute_result" - } - ], + "source": [ + "A new bit of syntax slipped in here! This is a spread operator, a little like other languages (e.g. `f(&args...)` in C++11) -- it takes an iterable (something you can loop through) and sets each value to a new argument." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "args = [1, 3, 5]\n", + "range(*args)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you're feeling _very_ smart, see if you can think why this `print` does not print anything..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(*my_zip)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's another handy way to use `zip`..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "dict(zip(my_list_of_keys, my_list_of_values))" ] @@ -1977,26 +1697,30 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can think of this like a transpose function, as if it were swapping rows and columns in a matrix." + "Can you think how to create the same dictionary using only the dict function and some lists?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For mathematicians, you can think of this like a transpose function, as if it were swapping rows and columns in a matrix." ] }, { "cell_type": "code", - "execution_count": 58, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[('a', 23), ('b', 42), ('c', 12), ('d', 9), ('e', 5), ('f', 1)]" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ + "print(my_list_of_keys, my_list_of_values)\n", "list(zip(my_list_of_keys, my_list_of_values))" ] }, @@ -2114,7 +1838,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "-" @@ -2149,24 +1873,13 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "-" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "3.141592653589793" - ] - }, - "execution_count": 62, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "math.pi" ] @@ -2184,22 +1897,11 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": null, "metadata": { "scrolled": true }, - "outputs": [ - { - "data": { - "text/plain": [ - "1.0" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "math.sin(math.pi / 2)" ] @@ -2240,17 +1942,9 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", "print(os.path.exists('/usr/bin/python'))" @@ -2280,17 +1974,9 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['/home/jovyan/python-course/002-basic-control-structures', '/usr/local/spark/python', '/usr/local/spark/python/lib/py4j-0.10.7-src.zip', '/opt/conda/lib/python37.zip', '/opt/conda/lib/python3.7', '/opt/conda/lib/python3.7/lib-dynload', '', '/opt/conda/lib/python3.7/site-packages', '/opt/conda/lib/python3.7/site-packages/IPython/extensions', '/home/jovyan/.ipython']\n" - ] - } - ], + "outputs": [], "source": [ "import sys\n", "print(sys.path)\n", @@ -2323,22 +2009,14 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": null, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.718281828459045\n" - ] - } - ], + "outputs": [], "source": [ "import math\n", "print(math.e)" @@ -2357,21 +2035,13 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.718281828459045\n" - ] - } - ], + "outputs": [], "source": [ "import math as m\n", "print(m.e)" @@ -2390,21 +2060,13 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.718281828459045\n" - ] - } - ], + "outputs": [], "source": [ "from math import e\n", "print(e)" @@ -2423,21 +2085,13 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sin(3)\n" - ] - } - ], + "outputs": [], "source": [ "from math import *\n", "from sympy import *\n", @@ -2527,26 +2181,11 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'3.141592653589793'" - ] - }, - "execution_count": 85, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Overwrite this cell with your code and run it\n", - "x = 4\n", - "\n", - "import math\n", - "pi_as_a_string = str(math.pi)" + "outputs": [], + "source": [ + "# Overwrite this cell with your code and run it" ] }, { @@ -2658,22 +2297,9 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Learn Python\n", - "Finish PhD\n", - "Publish research\n", - "Accept Nobel prize\n", - "Inspire a new generation\n", - "Find a nice retirement village in the Galapagos Islands\n" - ] - } - ], + "outputs": [], "source": [ "for i in range(len(things_to_do)):\n", " print(things_to_do[i])" @@ -2692,22 +2318,9 @@ }, { "cell_type": "code", - "execution_count": 76, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Learn Python\n", - "Finish PhD\n", - "Publish research\n", - "Accept Nobel prize\n", - "Inspire a new generation\n", - "Find a nice retirement village in the Galapagos Islands\n" - ] - } - ], + "outputs": [], "source": [ "for task in things_to_do:\n", " print(task)" @@ -2733,37 +2346,9 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The Zen of Python, by Tim Peters\n", - "\n", - "Beautiful is better than ugly.\n", - "Explicit is better than implicit.\n", - "Simple is better than complex.\n", - "Complex is better than complicated.\n", - "Flat is better than nested.\n", - "Sparse is better than dense.\n", - "Readability counts.\n", - "Special cases aren't special enough to break the rules.\n", - "Although practicality beats purity.\n", - "Errors should never pass silently.\n", - "Unless explicitly silenced.\n", - "In the face of ambiguity, refuse the temptation to guess.\n", - "There should be one-- and preferably only one --obvious way to do it.\n", - "Although that way may not be obvious at first unless you're Dutch.\n", - "Now is better than never.\n", - "Although never is often better than *right* now.\n", - "If the implementation is hard to explain, it's a bad idea.\n", - "If the implementation is easy to explain, it may be a good idea.\n", - "Namespaces are one honking great idea -- let's do more of those!\n" - ] - } - ], + "outputs": [], "source": [ "import this" ] @@ -2996,7 +2581,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.7.11" }, "livereveal": { "theme": "beige", diff --git a/002-basic-control-structures/Python Course - 002a - And so we begin.ipynb b/002-basic-control-structures/Python Course - 002a - And so we begin.ipynb index 62fa00c..bf12c65 100644 --- a/002-basic-control-structures/Python Course - 002a - And so we begin.ipynb +++ b/002-basic-control-structures/Python Course - 002a - And so we begin.ipynb @@ -74,24 +74,13 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "735" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "7*105" ] @@ -111,27 +100,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABYAAAAuCAYAAAAsnen7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACIUlEQVRIDe2XMVICMRSGQTkAUFpyBBx7Cr2BIycQSjscKmjxBnoDB2+gBT2jN4DSErkBfv+aZDJh2U2WUt7MY5OX5MvLS7L7qO12u9qxOplMPkPGWe1ImU6nIxDdEHMUGOg1wHUIVb0yGGiT8fL0Q6BQKoMBDYA/hUBbrwQGeAvgzULynslgoB1AbZ65sbWT1HVMUgSg4tr3xijWA1RhWdKerSQZ7AGzolnBikqL8ta2OzBGO7PartB7VMu23jlvsGXCGHl6gyrmL+g7tr/Y2xvD7Xn2yiPqc3Qkm9rQlW2PeTaYpWZmnqlsREuSF/Ja0kb99sxY+GM86vpeGA/37r/fp6ycHTc8/gpmv6P+GtiSqnvnmEl0/7WR7gJga0pTyA0zYM6gGWXd+yG6pexfgDH1xxSwPJaH0o2ZZOMDsKlt6dtiyue9Xu+bjtr1FnoJaLxYLFboA3qBbYfNhYV6lLgLEtU7odPe5iWMLex6ArvwnELhQlHnTZb2bXJDiwunC+Li8w+OG6/QLvrs1nygUCUU+tro/V0oSWA8VZIdJdFghQCi8g1pqUSDIfWBK42KkiiwCUHphvkzloKBdhgQpgM+I7dcCmbUMCUEdpZCMEClqUkhKAWbECi18jMiO670efC1CVAZkNKtUJTe6sgpHVvTLz/1KktHw3Y+DD/oPLSH9cIYh66aurJOaaEcDEU4iiVrE3X0FCKJ8jn9L8n9E/kLdP2UbYB86rYAAAAASUVORK5CYII=\n", - "text/latex": [ - "$\\displaystyle \\frac{x^{4}}{4}$" - ], - "text/plain": [ - " 4\n", - "x \n", - "──\n", - "4 " - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from sympy import * \n", "init_printing()\n", @@ -275,7 +246,7 @@ } }, "source": [ - "1. Open a new window/tab in Firefox and
    go to http://bit.ly/fat-qub-py-2021-start \n", + "1. Open a new window/tab in Firefox and
    go to https://bit.ly/fat-nitc-2021-start \n", "2. Enter your login\n", "3. Click the original link again\n", "3. Once it has finished loading you should see a list of files\n", @@ -301,7 +272,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.7.11" }, "livereveal": { "theme": "beige", diff --git a/006-latency/Latency.ipynb b/006-latency/Latency.ipynb index 59d844e..72716d1 100644 --- a/006-latency/Latency.ipynb +++ b/006-latency/Latency.ipynb @@ -246,6 +246,228 @@ "You can follow along typing with me or, if you find it hard to concentrate on what I am saying while you type, open up **`network_test_client_partial_1.py`**" ] }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Logging" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, + "source": [ + "A brief aside on logging - now that we are writing scripts instead of notebooks, there comes the question of where output goes. Sometimes output is part of our objective - for example, a graph, or a set of text results. Sometimes, we simply want a record of what happened and what issues were seen, that we can refer back to." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, + "source": [ + "Initially, we will likely use `print`, which shows text while not interrupting our flow - this can be extremely useful for barebones debugging..." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def fibonacci(up_to, dest=[]):\n", + " dest += [1, 1]\n", + " for _ in range(up_to):\n", + " dest.append(dest[-2] + dest[-1])\n", + " return dest" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 1, 2, 3, 5, 8, 13]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fibonacci(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, + "source": [ + "Sure" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['fibonacci sequence', 1, 1, 2, 3, 5, 8, 13]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dest = ['fibonacci sequence']\n", + "fibonacci(5, dest=dest)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "notes" + } + }, + "source": [ + "Sure" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 1, 2, 3, 5, 8, 13, 1, 1, 2, 3, 5, 8, 13]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fibonacci(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "???" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In a few short lines, there are only so many places a problem might be. But in a large code base, especially if it may be running automatically, being able to toggle logging on and off in a customisable way brings several benefits:\n", + "\n", + "* firing text out to any real destination will slow down a program and take space\n", + "* one big file is hard to manage, so output should be shared around to make it manageable\n", + "* debug info (e.g. time, line #) is great but should not mean extra code on every logged line\n", + "* turning logging on for some modules helps target output\n", + "\n", + "The logging module makes it easy." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "import logging\n", + "logging.info('Hello')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But not that easy. That should work in a normal script, but it's a little cleverer than `print` and so benefits from extra detail." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:root:Hello again\n" + ] + } + ], + "source": [ + "logging.basicConfig(\n", + " level=logging.DEBUG,\n", + " force=True # due to Jupyter...\n", + ")\n", + "logging.info('Hello again')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that changing the configured log-level will switch logging of `logging.info`, `logging.error`, etc on and off everywhere." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Time to carry on" + ] + }, { "cell_type": "markdown", "metadata": { @@ -1080,7 +1302,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.7.11" }, "livereveal": { "theme": "beige", diff --git a/022-burette/A Magnum of Opera.ipynb b/022-burette/A Magnum of Opera.ipynb index a9323e3..98d2783 100644 --- a/022-burette/A Magnum of Opera.ipynb +++ b/022-burette/A Magnum of Opera.ipynb @@ -1010,7 +1010,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.7.11" } }, "nbformat": 4, diff --git a/course-structure-5day.txt b/course-structure-5day.txt new file mode 100644 index 0000000..5f9256c --- /dev/null +++ b/course-structure-5day.txt @@ -0,0 +1,16 @@ +002: Basic Control Structures I +002: Basic Control Structures II + +019: git +004: A New Treatment for Arthritis +(020: Patterns) + +[homework: pandas] + +005: Latency +018: Words Apart +017: Preparing for an Audience [or next day] + +021: Alchemy a Sequel + +021: Alchemy a Sequel