{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Iterables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists are iterable, which is pretty much the *definition* of an iterable" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "l = [1, 2, 3, 4]" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "for element in l:\n", " print(element)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How about dictionary iteration?" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "d = {1: 'one', 2:'two'}" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1: 'one', 2: 'two'}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pairwise iteration: over keys and values in parallel" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 one\n", "2 two\n" ] } ], "source": [ "for key, value in d.items():\n", " print(key, value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Question**: can I use a dictionary to search for the value and get the key as an answer?\n", "**Answer**: use pairwise iteration like shown above, and search for the vale manually. Beware though that this is *linear search* and thus not nearly as fast as a dictionary key search." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "for key, value in d.items():\n", " if value == 'two':\n", " print(key)\n", " break" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Iterating over the dictionary itself (not using any iteration *method* of it) iterates over the *keys*" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n" ] } ], "source": [ "for key in d:\n", " print(key)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Iterating over the values" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one\n", "two\n" ] } ], "source": [ "for value in d.values():\n", " print(value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ``set`` constructor" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A set *literal*" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1, 2, 3}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = {1,2,3}\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Constructing a set from an iterable (in this case a string) absorbs what it iterates over." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'a', 'b', 'c'}" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = set('abc')\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consequentially, you can make a set from a dictionary" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1, 2}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = set(d)\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Fast vs. Simple" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "l = [1,2,3,4,5,6,7,8,9]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ``in`` operator on a list can only search through it from beginning to end. Here we use 9 comparisons. (In a list with millions of elements we would take at most millions of comparisons which is not fast.)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "9 in l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Manually implementing what the ``in`` operator does." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer = False\n", "for elem in l: # linear search!!\n", " if elem == 9:\n", " answer = True\n", " break\n", "answer" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using a ``set`` is a better way to determine membership. It is implemented as a hash table internally." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = {1,2,3,4,5,6,7,8,9}\n", "9 in s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Insertion order is **not** guaranteed to be preserved by a set, although it is in the simplest cases." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "for elem in s:\n", " print(elem)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ``for``, Iterables, ``range`` and Generators" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n" ] } ], "source": [ "for i in [0,1,2,3]:\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is the same like above, from a functionality point of view. Only cheaper, memorywise, because no 4 integers are kept in memory. (Think of millions of integers, again.)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n" ] } ], "source": [ "for i in range(4):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The *iterator protocol*, explained." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "r = range(4)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "it = iter(r)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(it)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Tuples, Tuple Unpacking, Returning Multiple Values from Functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Johannes: \"what's this?\"" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "def f():\n", " return 1, # comma?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Tuple unpacking*: syntactic sugar" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [], "source": [ "a, b = 1, 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "is the same as" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [], "source": [ "(a, b) = (1, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This allows us to swap two variables in one statement, for example" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [], "source": [ "a, b = b, a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Returning multiple values is the same as returning a tuple" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [], "source": [ "def f():\n", " return (1, 2, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is the same as ..." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "def f():\n", " return 1, 2, 3" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "retval = f()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is returned in both cases is a tuple" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2, 3)" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "retval" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tuple" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(retval)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The same is more expressively written as ..." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "a, b, c = f() # tuple unpacking" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Back to Johannes' question: ``1,`` is a one-tuple" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "def f():\n", " return 1," ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "retval = f()" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2, 3)" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "retval" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The same concept - *tuple unpacking* - is used in pairwise iteration btw." ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "d = { 1: 'one', 2: 'two'}" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 one\n", "2 two\n" ] } ], "source": [ "for key, value in d.items():\n", " print(key, value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Object Oriented Programming" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An empty class" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "class Message:\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creating a object of that class" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [], "source": [ "m = Message()" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "__main__.Message" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A constructor, to be called when an object is created" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "class Message:\n", " # prio\n", " # dlc\n", " # msg1\n", " # ...\n", " def __init__(self, prio, dlc, msg1):\n", " print('prio:', prio, 'dlc:', dlc, 'msg1:', msg1)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "prio: 1 dlc: 5 msg1: whatever message that could be\n" ] } ], "source": [ "m = Message(1, 5, 'whatever message that could be')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The same, only using *keyword parameters* for better readability and maintainability" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "prio: 1 dlc: 5 msg1: whatever message that could be\n" ] } ], "source": [ "m = Message(prio=1, dlc=5, msg1='whatever message that could be')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Order is irrelevant when using keyword parameters" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "prio: 1 dlc: 5 msg1: whatever message that could be\n" ] } ], "source": [ "m = Message(dlc=5, prio=1, msg1='whatever message that could be')" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "<__main__.Message at 0x7f41f5ff26a0>" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "``self`` is *the object* that is being created. You can use it to hold *members* (to remember values)." ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [], "source": [ "class Message:\n", " def __init__(self, prio, dlc, msg1):\n", " self.prio = prio\n", " self.dlc = dlc\n", " self.msg1 = msg1" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "prio: 1\n", "dlc: 5\n", "msg1: whatever message that could be\n" ] } ], "source": [ "m = Message(dlc=5, prio=1, msg1='whatever message that could be')\n", "print('prio:', m.prio)\n", "print('dlc:', m.dlc)\n", "print('msg1:', m.msg1)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [], "source": [ "msglist = []\n", "msglist.append(Message(dlc=5, prio=1, msg1='whatever message that could be'))\n", "msglist.append(Message(prio=5, dlc=1, msg1='another wtf message'))" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[<__main__.Message at 0x7f41f5ff4160>, <__main__.Message at 0x7f41f5ff41c0>]" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "msglist" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ``datetime``" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Date and time is a complex matter. The ``datetime`` module has all of it." ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "import datetime" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "datetime.datetime(2020, 10, 28, 12, 34, 19, 291130)" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "now = datetime.datetime.now()\n", "now" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "datetime.datetime" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(now)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [], "source": [ "import time\n", "now_timestamp = time.time()" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1603884859.3412576" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "now_timestamp" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "datetime.datetime(2020, 10, 28, 12, 34, 19, 341258)" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "now = datetime.datetime.fromtimestamp(now_timestamp)\n", "now" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [], "source": [ "then = datetime.datetime(2019, 10, 22)" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "datetime.timedelta(days=372, seconds=45259, microseconds=341258)" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "now - then" ] } ], "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.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }