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