{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python Schulung 18. und 19.5.2020" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Das `sys` Modul" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['/home/jfasch/var/jfasch-home-venv/lib64/python3.8/site-packages/ipykernel_launcher.py',\n", " '-f',\n", " '/home/jfasch/.local/share/jupyter/runtime/kernel-57bd7d77-6e54-4dcd-b7a8-452f82f88569.json']" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import sys\n", "sys.argv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Multiline Strings und Docstrings" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "s = 'hallo'" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "s = '''hallo\n", "welt\n", "und\n", "noch\n", "was'''" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hallo\n", "welt\n", "und\n", "noch\n", "was\n" ] } ], "source": [ "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiline Strings werden gerne zur Dokumentation verwendet:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def f():\n", " '''das ist die Doku für diese Funktion\n", " \n", " Die Parameter sind ... aeh wir haben keine'''\n", " return 'hallo'" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'hallo'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'das ist die Doku für diese Funktion\\n \\n Die Parameter sind ... aeh wir haben keine'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.__doc__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Im interaktiven Modus gibts die Funktion `help()`, die die Formatierung übernimmt" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function f in module __main__:\n", "\n", "f()\n", " das ist die Doku für diese Funktion\n", " \n", " Die Parameter sind ... aeh wir haben keine\n", "\n" ] } ], "source": [ "help(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Datentypen (Ausflug)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nachdem `f` ein Member `__doc__` hat, ist `f` offenbar ein Objekt. Welches denn?" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "function" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aha. Cool. `f` ist vom Typ `function`. Welche Typen hamma denn noch so?" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 42\n", "type(i)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = 'hello'\n", "type(s)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "list" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = [1, 'zwei', \"drei\"]\n", "type(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Objekte bieten Funktionalität: Methoden" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'HELLO'" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.upper()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 'zwei', 'drei', 4, 5, 'sechs']" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l.append(4)\n", "l.extend([5,'sechs'])\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aber zurueck zur funktion ..." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'das ist die Doku für diese Funktion\\n \\n Die Parameter sind ... aeh wir haben keine'" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.__doc__" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function f in module __main__:\n", "\n", "f()\n", " das ist die Doku für diese Funktion\n", " \n", " Die Parameter sind ... aeh wir haben keine\n", "\n" ] } ], "source": [ "help(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Variablen und deren Unterbau" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "a = 42" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "42\n" ] } ], "source": [ "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`id`: Objektidentität" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'0x7fe9d8578dc0'" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hex(id(a))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variablen sind Namen, die Objekte referenzieren. Objekte haben einen Typ, Namen nicht.\n", "Jetzt zum Beispiel wechselt die Variable `a` ihren Typ:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "float" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = 1.5\n", "type(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Das Objekt, auf das `a` nun zeigt, hat eine neue Identität." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'0x7fe9c4454d90'" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hex(id(a))" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "list" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = [1,2,3]\n", "type(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ausflug \"Pythonic\": Zuweisung mit Hilfe von \"Tuple Unpacking\"" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 zwei 3.0\n" ] } ], "source": [ "a, b, c = 1, 'zwei', 3.0\n", "print(a,b,c)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 zwei 3.0\n" ] } ], "source": [ "(a,b,c) = (1, 'zwei', 3.0)\n", "print(a,b,c)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2, 3)" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = (1,2,3)\n", "t" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tuples sind *immutable*" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tuples sind immutable: append() geht nur mit Listen\n" ] } ], "source": [ "try:\n", " t.append(4)\n", "except AttributeError:\n", " print('tuples sind immutable: append() geht nur mit Listen')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ausdrucksstark weil kurz und trotzdem lesbar:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zwei 1\n" ] } ], "source": [ "a, b = b, a\n", "print(a, b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Assignment details, Referenzen (vgl, Folie 78): beide Namen `a` und `b` referenzieren das gleiche Objekt." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'0x7fe9d8578dc0'" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = 42\n", "hex(id(a))" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'0x7fe9d8578dc0'" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = a\n", "hex(id(b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## *Mutability* am Beispiel `list`" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3]\n", "[1, 2, 3]\n" ] } ], "source": [ "l1 = [1,2,3]\n", "l2 = l1\n", "print(l1)\n", "print(l2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`l1` und `l2` referenzieren das gleiche Objekt. Wenn man eine Variable verwendet, um es zu modifizieren, ist die Modifikation auch über die andere Variable sichtbar." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4]\n" ] } ], "source": [ "l1.append(4)\n", "print(l1)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Integers haben unendliche Breite" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Bis 64 Bit native CPU, ab dann wird in Software gerechnet." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 42\n", "type(i)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "100" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 10**2\n", "i" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1000000" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 10**6\n", "i" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "18446744073709551615" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 2**64 - 1\n", "i" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "18446744073709551616" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i += 1\n", "i" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 2**1000\n", "i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Division und Floor Division" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.5" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 3/2\n", "i" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 3//2\n", "i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Konvertierung durch Konstruktoren" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 42\n", "type(i)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = '42'\n", "type(s)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "type" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(int)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'abc'" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = str('abc')\n", "s" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'abc'" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = 'abc' # einfacher\n", "s" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'42'" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = str(42)\n", "s" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = int(42)\n", "i" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = int('42')\n", "i" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "das war kein Integer in dem String\n" ] } ], "source": [ "try:\n", " i = int('abc')\n", "except ValueError:\n", " print('das war kein Integer in dem String')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Welchen Typ haben Typen?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "42 ist vom Type `int`. `int` ist ein Name für etwas. Was ist dieses Etwas?" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "print(int)" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int('42')" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "int = 1\n", "print(int)" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hilfe, wir haben den int gelöscht\n" ] } ], "source": [ "try:\n", " int('42')\n", "except TypeError:\n", " print('Hilfe, wir haben den int gelöscht')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Retten wir den `int`" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(int)" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(42)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "type" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(type(int))" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "type" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int = type(42)\n", "type(int)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int('42') # uff" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `list` und Mutability" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "140641996429568\n" ] }, { "data": { "text/plain": [ "[1, 2, 3]" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = [1,2,3]\n", "print(id(l))\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`append()` und `extend()` ändern das Object *in place*" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "140641996429568\n" ] }, { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l.append(4)\n", "print(id(l))\n", "l" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "140641996429568\n" ] }, { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 7]" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l.extend([5,6,7])\n", "print(id(l))\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`+` erzeugt ein neues Objekt (die Operanden bleiben unverändert)" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "140641996429632\n", "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n", "140641996429568\n", "[1, 2, 3, 4, 5, 6, 7]\n" ] } ], "source": [ "new_l = l + [8,9]\n", "print(id(new_l))\n", "print(new_l)\n", "print(id(l))\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Was kann eine liste noch? (Bitte unbedingt die Dokumentation lesen.)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "7 in l" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hurra\n" ] } ], "source": [ "if 7 in l:\n", " print('hurra')" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l * 2" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'abcabc'" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'abc' * 2 # absolutes Killerfeature :-)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[3]" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 3, 4, 5, 6, 7]" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "del l[0]\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`in` ist durch *sequentielle suche* implementiert (dict ist besser, siehe unten)" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "7 in l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Index-Operator: per Position in der Liste" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "7" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Suche in Listen von Records ist umständlich (und langsam). Das geht mit Dictionaries besser." ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [], "source": [ "users = [('joerg', 'faschingbauer'), ('andreas', 'pfeifer')]" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('andreas', 'pfeifer')\n" ] } ], "source": [ "for u in users:\n", " if u[1] == 'pfeifer':\n", " gefundener_user = u\n", " break\n", "print(gefundener_user)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tuple und Immutability" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2, 3)" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = (1,2,3)\n", "t" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "()" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = tuple()\n", "t" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tuple mit einem Element? Straightforward würde man glauben, so:" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] }, { "data": { "text/plain": [ "int" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = (1)\n", "print(t)\n", "type(t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**What?**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die runden Klammern werden hier nicht als Tuple-Begrenzer interpretiert, sondern als Mittel, die Operator-Präzedenz zu overriden. Der folgende Ausdruck ..." ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "18446744073709551615" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 2**64 - 1\n", "i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... wird implizit interpretiert als ..." ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "i = (2**64) - 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eine andere Evaluierungsreihenfolge kann man erzwingen durch `()`" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "9223372036854775808" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = 2 ** (64 - 1)\n", "i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... oder auch ..." ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = (1)\n", "i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "D.h. um `()` für ein einstelliges Tuple zu verwenden, schreibt man ..." ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1,)" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = (1,)\n", "t" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Besseres Laufzeitverhalten durch Geeignetere Datenstrukturen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Große Datenmengen in einer Liste abzulegen ist nicht gut: man sucht in einer solchen *linear*. Enter Dictionaries." ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [], "source": [ "d = {3:'drei', 1:'one', 4:'vier'} # vorstellungsvermoegen: 3 milliarden elemente" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'vier'" ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d[4]" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [], "source": [ "users = {'faschingbauer': 'joerg', 'kurz': 'sebastian'}" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'sebastian'" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gefundener_user = users['kurz']\n", "gefundener_user" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Errors**" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "nix gibt\n" ] } ], "source": [ "try:\n", " gefundener_user = users['hugo']\n", "except KeyError:\n", " print('nix gibt') # was machma jetzt?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Will man keine Exception behandeln (vielleicht weil das Nichtvorhandenseins eines Elementes keine Ausnahme, sondern die Regel ist):" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [], "source": [ "gefundener_user = users.get('hugo')\n", "if gefundener_user:\n", " print('jetzt machma was mim hugo')\n", "else:\n", " users['hugo'] = 'victor'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Boolean: *Short Circuit Evaluation*" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [], "source": [ "def f():\n", " print('f')\n", " return True\n", "def g():\n", " print('g')\n", " return False" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f\n", "g\n" ] } ], "source": [ "if f() and g():\n", " print('beides')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aha: der ganze Ausdruck ist `False`, aber um das festzustellen, müssen beide Operanden evaluiert werden. D.h. beide Funktionen werden aufgerufen." ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "g\n" ] } ], "source": [ "if g() and f():\n", " print('beides')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aha: wenn man weiss, dass der linke Operand bereits `False` ist, wird sich das Gesamtergebnis nicht mehr ändern." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Analog bei `or` ..." ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f\n", "jaja\n" ] } ], "source": [ "if f() or g():\n", " print('jaja')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aha: wenn der linke `True` ist, kann man sich den rechten sparen." ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "g\n", "f\n", "jaja\n" ] } ], "source": [ "if g() or f():\n", " print('jaja')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aha: wenn der linke `False` ist, kann der rechte noch ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `while` Loops, und warum sie nicht *Pythonic* sind" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Potscherte Berechnung der Summe 1..100 (100 inklusive)" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5050\n" ] } ], "source": [ "summe = 0\n", "i = 0\n", "while i<=100:\n", " summe += i\n", " i += 1\n", "print(summe)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Das geht besser, wenn man ein wenig mehr weiss ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`range()`**" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "range(0, 10)" ] }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(10)" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "for i in range(10):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der einzige Zweck von `range()` ist, zu *iterieren*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`sum()`**" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum([1,2,3])" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum((1,2,3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sum()` *iteriert* und bildet die Summe. `list` und `tuple` sind *iterables* der primitiveren Sorte." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`sum()` und `range()`**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`range()`** ist ein *Iterable* der intelligenteren Sorte" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 98, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(range(1,4)) # inklusive 1, exklusive 4 -> 1..3 wie oben" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5050" ] }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(range(1,101))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Problem gelöst!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mehr über `range()`: Iterator Protocol (Folie 161)" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "range(0, 3)\n" ] } ], "source": [ "r = range(3)\n", "print(r)" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "source": [ "it = iter(r)\n", "it" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(it) # das letzte " ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ENDE DER FOR SCHLEIFE\n" ] } ], "source": [ "try:\n", " next(it)\n", "except StopIteration:\n", " print('ENDE DER FOR SCHLEIFE')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Iterator Protocol**: `iter` und `next` werden von `for` intern verwendet" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n" ] } ], "source": [ "r = range(3)\n", "\n", "# zu Beginn: iter(r)\n", "for i in r: # für jede Iteration: next(it)\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mutability, Shallow und Deep Copy" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [], "source": [ "l1 = [1,2,3]\n", "l2 = l1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beide Variablen referenzieren *das selbe Objekt*: ihr *Objektidentität* ist die gleiche." ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "id(l1) == id(l2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`is` macht das gleiche, nur kürzer: vergleicht Objektidentitäten, *nicht* Objektinhalt." ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 is l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So würde man Objektinhalt vergleichen:" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 == l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Listen sind *mutable*: beide Variablen referenzieren das selbe Objekt. Wenn man es über eine Variable modifiziert, sieht man die Modifikation über die andere:" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4]\n" ] } ], "source": [ "l1.append(4)\n", "print(l1)" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Shallow Copy mit dem Slice-Operator" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Kopieren, um sich (vermeintlich, siehe unten) vor Modifiktionen zu schützen:" ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l3 = l1[:]\n", "l3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`l3` ist eine Kopie von `l1`: hat eine andere Objektidentität" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 is l3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inhalt ist der gleiche (klar)" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 == l3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hier der gewünschte Effekt:" ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 5]" ] }, "execution_count": 117, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1.append(5)\n", "l1" ] }, { "cell_type": "code", "execution_count": 118, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Deep Copy (`copy.deepcopy()`)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Problem: geschachtelte Datenstrukturen (hier eine Liste, die eine Liste enthält)" ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 119, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 = [1, [100, 200, 300], 3]\n", "len(l1)" ] }, { "cell_type": "code", "execution_count": 120, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[100, 200, 300]" ] }, "execution_count": 120, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Shallow copy ..." ] }, { "cell_type": "code", "execution_count": 121, "metadata": {}, "outputs": [], "source": [ "l2 = l1[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gleicher Inhalt ..." ] }, { "cell_type": "code", "execution_count": 122, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 122, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 == l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Verschiedene Objekte ..." ] }, { "cell_type": "code", "execution_count": 123, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 123, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 is l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aber: **Shallow Copy**: das von Index 1 referenzierte Objekt ist von beiden aus gesehen das selbe ..." ] }, { "cell_type": "code", "execution_count": 124, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 124, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1[1] == l2[1]" ] }, { "cell_type": "code", "execution_count": 125, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 125, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1[1] is l2[1]" ] }, { "cell_type": "code", "execution_count": 126, "metadata": {}, "outputs": [], "source": [ "l1[1].append(400)" ] }, { "cell_type": "code", "execution_count": 127, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, [100, 200, 300, 400], 3]" ] }, "execution_count": 127, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l2" ] }, { "cell_type": "code", "execution_count": 128, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 128, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1[1] is l2[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lösung (wenn man das als Problem erachtet)" ] }, { "cell_type": "code", "execution_count": 129, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, [100, 200, 300], 3]" ] }, "execution_count": 129, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import copy\n", "l1 = [1, [100, 200, 300], 3]\n", "l2 = copy.deepcopy(l1)\n", "l2" ] }, { "cell_type": "code", "execution_count": 130, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 130, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 is l2" ] }, { "cell_type": "code", "execution_count": 131, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 131, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1[1] is l2[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternative Lösung: reiche einfach Tuples weiter, dann ersparst du dir Kopien" ] }, { "cell_type": "code", "execution_count": 132, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ist eh alles gut, kann keiner ran\n" ] } ], "source": [ "l1 = [1, (100, 200, 300), 3]\n", "l2 = l1[:]\n", "try:\n", " l2[1].append(400)\n", "except:\n", " print('ist eh alles gut, kann keiner ran')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Funktionen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die built-in `max()` Funktion" ] }, { "cell_type": "code", "execution_count": 133, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 133, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max(1,2)" ] }, { "cell_type": "code", "execution_count": 134, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "666" ] }, "execution_count": 134, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max(1,2,5,1,666) # kann auch mit mehreren Parametern" ] }, { "cell_type": "code", "execution_count": 135, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 135, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max([1,2,3]) # mit Listen" ] }, { "cell_type": "code", "execution_count": 136, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 136, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max(range(10)) # mit beliebigen Iterables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wenn man unbedingt will, kann man sie auch selbst definieren. Hier mit genau zwei Parametern." ] }, { "cell_type": "code", "execution_count": 137, "metadata": {}, "outputs": [], "source": [ "def maximum(a,b):\n", " if a < b:\n", " return b\n", " else:\n", " return a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Typ: `function`" ] }, { "cell_type": "code", "execution_count": 138, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "function" ] }, "execution_count": 138, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(maximum)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Integers sind vergleichbar: *unterstützen den `<` Operator*" ] }, { "cell_type": "code", "execution_count": 139, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 139, "metadata": {}, "output_type": "execute_result" } ], "source": [ "maximum(1,2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Strings unterstützen ihn auch" ] }, { "cell_type": "code", "execution_count": 140, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'joerg'" ] }, "execution_count": 140, "metadata": {}, "output_type": "execute_result" } ], "source": [ "maximum('joerg', 'andreas')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Äpfel können allerdings nicht mit Birnen verglichen werden (dieses \"Feature\" existiert hingegen in zumindest Javascript und PHP)" ] }, { "cell_type": "code", "execution_count": 141, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "parameter mit falschem typ uebergeben\n" ] } ], "source": [ "try:\n", " maximum(1,'joerg')\n", "except TypeError:\n", " print('parameter mit falschem typ uebergeben')" ] }, { "cell_type": "code", "execution_count": 142, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "vergleich zwischen aepfeln und birnen nicht erlaubt\n" ] } ], "source": [ "try:\n", " maximum(42, '42')\n", "except TypeError:\n", " print('vergleich zwischen aepfeln und birnen nicht erlaubt')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Funktionen sind \"First Class Objects\"" ] }, { "cell_type": "code", "execution_count": 143, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "function" ] }, "execution_count": 143, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(maximum)" ] }, { "cell_type": "code", "execution_count": 144, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "140641996137808" ] }, "execution_count": 144, "metadata": {}, "output_type": "execute_result" } ], "source": [ "id(maximum)" ] }, { "cell_type": "code", "execution_count": 145, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "140641996137808" ] }, "execution_count": 145, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = maximum\n", "id(m)" ] }, { "cell_type": "code", "execution_count": 146, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 146, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m(1,2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Gotcha: Mutable Default Parameters (Folie 90 ff.)" ] }, { "cell_type": "code", "execution_count": 147, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([],)" ] }, "execution_count": 147, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def add_to_list(a, l=[]):\n", " l.append(a)\n", " return l\n", "add_to_list.__defaults__" ] }, { "cell_type": "code", "execution_count": 148, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 666]" ] }, "execution_count": 148, "metadata": {}, "output_type": "execute_result" } ], "source": [ "meine_liste = [1,2,3]\n", "meine_liste = add_to_list(666, meine_liste)\n", "meine_liste" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Defaultwert von `l` wurde nicht benutzt:" ] }, { "cell_type": "code", "execution_count": 149, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([],)" ] }, "execution_count": 149, "metadata": {}, "output_type": "execute_result" } ], "source": [ "add_to_list.__defaults__" ] }, { "cell_type": "code", "execution_count": 150, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1]" ] }, "execution_count": 150, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 = add_to_list(1)\n", "l1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nun wurde der Defaultwert das erste mal benutzt" ] }, { "cell_type": "code", "execution_count": 151, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([1],)" ] }, "execution_count": 151, "metadata": {}, "output_type": "execute_result" } ], "source": [ "add_to_list.__defaults__" ] }, { "cell_type": "code", "execution_count": 152, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2]" ] }, "execution_count": 152, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l2 = add_to_list(2)\n", "l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mit allerhand Seiteneffekten. **Bitte aufpassen: so einen Fehler sucht man ewig!**" ] }, { "cell_type": "code", "execution_count": 153, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([1, 2],)" ] }, "execution_count": 153, "metadata": {}, "output_type": "execute_result" } ], "source": [ "add_to_list.__defaults__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Globale und lokale Variablen (Folie 92)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eine Zuweisung an eine noch nicht existierende Variable macht diese" ] }, { "cell_type": "code", "execution_count": 154, "metadata": {}, "outputs": [], "source": [ "def f():\n", " x = 1\n", " return x" ] }, { "cell_type": "code", "execution_count": 155, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 155, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*By Default* sind Variablen lokal. D.h. man muss nichts extra machen, um Unfälle zu vermeiden." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`f()`'s `x` hat keine Wechselwirkungen mit einer eventuellen globalen Variable:" ] }, { "cell_type": "code", "execution_count": 156, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 156, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 666\n", "f()" ] }, { "cell_type": "code", "execution_count": 157, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "666" ] }, "execution_count": 157, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Will man Wechselwirkungen, erzwingt man sie" ] }, { "cell_type": "code", "execution_count": 158, "metadata": {}, "outputs": [], "source": [ "def g():\n", " global x\n", " x = 1\n", " return x" ] }, { "cell_type": "code", "execution_count": 159, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 159, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g()" ] }, { "cell_type": "code", "execution_count": 160, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 160, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Anders beim Lesen von Variablen. Wenn es keine lokale gibt, wird im globalen Scope gesucht (genauer gesagt, im nächstäußeren Scope)" ] }, { "cell_type": "code", "execution_count": 161, "metadata": {}, "outputs": [], "source": [ "def h():\n", " return x" ] }, { "cell_type": "code", "execution_count": 162, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 162, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Fehler, wenn die Variable nirgends existiert." ] }, { "cell_type": "code", "execution_count": 163, "metadata": {}, "outputs": [], "source": [ "def gibtsnetglobal():\n", " return gibtsnet" ] }, { "cell_type": "code", "execution_count": 164, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fehler: variable \"gibtsnet\" nicht im globalen scope\n" ] } ], "source": [ "try:\n", " gibtsnetglobal()\n", "except NameError:\n", " print('fehler: variable \"gibtsnet\" nicht im globalen scope')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercise: `uniq()` (Folie 94, Punkt 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Aufgabenstellung**\n", "Write a function `uniq()` that takes a sequence as input. It returns a list with duplicate elements removed, and where the contained elements appear in the same order that is present in the input sequence. The input sequence remains unmodified." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der Kandidat hatte die Aufgabe mittels Google gelöst :-), was erstens unsportlich und zweitens unnachhaltig ist, und drittens mir die Gelegenheit gab, etwas mehr über Dictionaries, Sets, Iterables und Performance zu erzählen." ] }, { "cell_type": "code", "execution_count": 165, "metadata": {}, "outputs": [], "source": [ "def uniq(seq):\n", " d = dict.fromkeys(seq)\n", " return list(d.keys())" ] }, { "cell_type": "code", "execution_count": 166, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 1, 666, 42]" ] }, "execution_count": 166, "metadata": {}, "output_type": "execute_result" } ], "source": [ "uniq(dict.fromkeys([2,1,666,2,42,666]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Funktioniert ja, aber was passiert hier eigentlich?" ] }, { "cell_type": "code", "execution_count": 167, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{42: 'xxx', 7: 'kksvjhbsk', 666: 'sgkysdudsvvc'}" ] }, "execution_count": 167, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = {}\n", "d[42] = 'xxx'\n", "d[7] = 'kksvjhbsk'\n", "d[666] = 'sgkysdudsvvc'\n", "d" ] }, { "cell_type": "code", "execution_count": 168, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_keys([42, 7, 666])" ] }, "execution_count": 168, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d.keys()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Das ist schon wieder so ein Iterable, wie `range()`. Diesmal zum *iterieren* über die Keys eine Dictionary." ] }, { "cell_type": "code", "execution_count": 169, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "42\n", "7\n", "666\n" ] } ], "source": [ "for k in d.keys():\n", " print(k)" ] }, { "cell_type": "code", "execution_count": 170, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{2: None, 1: None, 666: None, 42: None}" ] }, "execution_count": 170, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict.fromkeys([2,1,666,2,42,666])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`dict.fromkeys()` iteriert über seinen Input. Irgendein *Iterable*, z.B. `range()`" ] }, { "cell_type": "code", "execution_count": 171, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{0: None,\n", " 1: None,\n", " 2: None,\n", " 3: None,\n", " 4: None,\n", " 5: None,\n", " 6: None,\n", " 7: None,\n", " 8: None,\n", " 9: None}" ] }, "execution_count": 171, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict.fromkeys(range(10))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ausflug: was gibts sonst noch aus der Kategorie? Z.B. die built-in Function `enumerate()`" ] }, { "cell_type": "code", "execution_count": 172, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zero\n", "nine\n" ] } ], "source": [ "number_strings = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']\n", "print(number_strings[0])\n", "print(number_strings[9])" ] }, { "cell_type": "code", "execution_count": 173, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(0, 'zero')\n", "(1, 'one')\n", "(2, 'two')\n", "(3, 'three')\n", "(4, 'four')\n", "(5, 'five')\n", "(6, 'six')\n", "(7, 'seven')\n", "(8, 'eight')\n", "(9, 'nine')\n" ] } ], "source": [ "for elem in enumerate(number_strings):\n", " print(elem)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Schon wieder: der `dict` Constructor, wenn man ihm ein Iterable gibt, erwartet er `(key, value)` Paare als Elemente" ] }, { "cell_type": "code", "execution_count": 174, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{0: 'zero',\n", " 1: 'one',\n", " 2: 'two',\n", " 3: 'three',\n", " 4: 'four',\n", " 5: 'five',\n", " 6: 'six',\n", " 7: 'seven',\n", " 8: 'eight',\n", " 9: 'nine'}" ] }, "execution_count": 174, "metadata": {}, "output_type": "execute_result" } ], "source": [ "translations = dict(enumerate(number_strings))\n", "translations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hat man ein Iterable, will aber eine Liste, kann das der `list` Constructor" ] }, { "cell_type": "code", "execution_count": 175, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3]" ] }, "execution_count": 175, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list([1,2,3])" ] }, { "cell_type": "code", "execution_count": 176, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3]" ] }, "execution_count": 176, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[1,2,3][:]" ] }, { "cell_type": "code", "execution_count": 177, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" ] }, "execution_count": 177, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(10))" ] }, { "cell_type": "code", "execution_count": 178, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['a', 'b', 'c']" ] }, "execution_count": 178, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list('abc')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Zurück zu der Lösung des Übungsbeispiels:\n", " `return list(d.keys())`" ] }, { "cell_type": "code", "execution_count": 179, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{0: 'zero',\n", " 1: 'one',\n", " 2: 'two',\n", " 3: 'three',\n", " 4: 'four',\n", " 5: 'five',\n", " 6: 'six',\n", " 7: 'seven',\n", " 8: 'eight',\n", " 9: 'nine'}" ] }, "execution_count": 179, "metadata": {}, "output_type": "execute_result" } ], "source": [ "translations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Iteration über ein Dictionary ist Iteration über dessen Keys" ] }, { "cell_type": "code", "execution_count": 180, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "for elem in translations: \n", " print(elem)" ] }, { "cell_type": "code", "execution_count": 181, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "for elem in translations.keys():\n", " print(elem)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Zum Schluss: will man die Keys des Dictionary (`dict.fromkeys()`)" ] }, { "cell_type": "code", "execution_count": 182, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" ] }, "execution_count": 182, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(translations)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Zusammengefasst: hier eine \"schönere\" Lösung" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"Schöner\" heisst: *pythonic*. Die Input-Sequenz wird nicht kopiert (zum Unterschied von `dict.fromkeys()`). Jedes Element wird mit `yield` dem Aufrufer (vermutlich einem `for` Loop) zur Verfügung gestellt, *sobald es bekannt ist*. Zum Unterschied von `list(d.keys)`, wo wiederum *kopiert und alloziert* wird." ] }, { "cell_type": "code", "execution_count": 183, "metadata": {}, "outputs": [], "source": [ "def uniq(seq):\n", " seen = set()\n", " for elem in seq:\n", " if elem in seen:\n", " continue\n", " seen.add(elem)\n", " yield elem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Funktionen als Parameter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Funktionen sind *First Class Objects*. Wenn man also zum Beispiel einen Integer als Parameter übergeben kann, warum nicht auch eine Funktion?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Beispiel**: die built-in `map()` Funktion" ] }, { "cell_type": "code", "execution_count": 184, "metadata": {}, "outputs": [], "source": [ "it1 = range(10)\n", "it2 = range(10,20)\n", "def multiply(n1, n2):\n", " return n1*n2" ] }, { "cell_type": "code", "execution_count": 185, "metadata": {}, "outputs": [], "source": [ "combined_iterable = map(multiply, it1, it2)" ] }, { "cell_type": "code", "execution_count": 186, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "11\n", "24\n", "39\n", "56\n", "75\n", "96\n", "119\n", "144\n", "171\n" ] } ], "source": [ "for i in combined_iterable:\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## List Comprensions (Folie 125)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`map()` ist meistens schlecht lesbar. Vor allem bei simplen Transformationen bieten sich List Comprehensions an." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Beispiel**: generieren von Quadratzahlen" ] }, { "cell_type": "code", "execution_count": 187, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]" ] }, "execution_count": 187, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# kompliziert\n", "\n", "original = [0,1,2,3,4,5,6,7,8,9]\n", "quadrate = []\n", "for i in original:\n", " quadrat = i**2\n", " quadrate.append(quadrat)\n", "quadrate" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Erste naeherung zum Pythonism: `yield`. Noch immer schwer lesbar, dafür performanter" ] }, { "cell_type": "code", "execution_count": 188, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n", "16\n", "25\n", "36\n", "49\n", "64\n", "81\n" ] } ], "source": [ "def gen_squares(it):\n", " for i in it:\n", " yield i**2\n", "for num in gen_squares(original):\n", " print(num)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wenn man unbedingt eine Liste will ..." ] }, { "cell_type": "code", "execution_count": 189, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]" ] }, "execution_count": 189, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(gen_squares(original))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Sehr lesbar**: List Comprehension" ] }, { "cell_type": "code", "execution_count": 190, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]" ] }, "execution_count": 190, "metadata": {}, "output_type": "execute_result" } ], "source": [ "squares = [i**2 for i in original]\n", "squares" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generator Expressions: Lesbarkeit *und* Performance" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hier wird keine fette Liste alloziert, sondern (durch minimale syntaktische Änderung) ein *Generator* generiert" ] }, { "cell_type": "code", "execution_count": 191, "metadata": {}, "outputs": [ { "data": { "text/plain": [ " at 0x7fe9c43f2900>" ] }, "execution_count": 191, "metadata": {}, "output_type": "execute_result" } ], "source": [ "squares = (i**2 for i in original)\n", "squares" ] }, { "cell_type": "code", "execution_count": 192, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n", "16\n", "25\n", "36\n", "49\n", "64\n", "81\n" ] } ], "source": [ "for i in squares:\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code Review" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `pprint()` ist praktisch für Debug-Output" ] }, { "cell_type": "code", "execution_count": 193, "metadata": {}, "outputs": [], "source": [ "d = {\n", " 'item-a': { 'one': 1, 'two': 2},\n", " 'item-b': [1,2,3,4,5,6],\n", " 'item-c': 'string',\n", "}\n" ] }, { "cell_type": "code", "execution_count": 194, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'item-a': {'one': 1, 'two': 2}, 'item-b': [1, 2, 3, 4, 5, 6], 'item-c': 'string'}\n" ] } ], "source": [ "print(d) # alles in einer Zeile" ] }, { "cell_type": "code", "execution_count": 195, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{ 'item-a': {'one': 1, 'two': 2},\n", " 'item-b': [1, 2, 3, 4, 5, 6],\n", " 'item-c': 'string'}\n" ] } ], "source": [ "import pprint\n", "pprint.pprint(d, indent=4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Straightforward Datentransformation" ] }, { "cell_type": "code", "execution_count": 196, "metadata": {}, "outputs": [], "source": [ "userliste = [\n", " {\n", " 'Name': 'Joerg Faschingbauer',\n", " 'blah': 'nochwas',\n", " },\n", " {\n", " 'Name': 'Victor Hugo',\n", " 'blah': 'was auch immer da noch steht',\n", " },\n", " {\n", " 'Name': 'Sebastian Kurz',\n", " 'blah': 'blah',\n", " }\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Nicht pythonic**: Index-based Iteration zum generieren der Dropdown-Liste" ] }, { "cell_type": "code", "execution_count": 197, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Joerg Faschingbauer', 'Victor Hugo', 'Sebastian Kurz']" ] }, "execution_count": 197, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dropdownliste = []\n", "for i in range(len(userliste)):\n", " name = userliste[i]['Name']\n", " dropdownliste.append(name)\n", "dropdownliste" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "List Comprehension: kürzer und weniger fehleranfällig (weil kürzer und trotzdem lesbar: **pythonic**)" ] }, { "cell_type": "code", "execution_count": 198, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Joerg Faschingbauer', 'Victor Hugo', 'Sebastian Kurz']" ] }, "execution_count": 198, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dropdownliste = [user['Name'] for user in userliste]\n", "dropdownliste" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ausflug: More on Dictionaries (Folie 127ff.)" ] }, { "cell_type": "code", "execution_count": 199, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}" ] }, "execution_count": 199, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = dict(enumerate(['zero', 'one', 'two', 'three']))\n", "d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Keys sind iterable" ] }, { "cell_type": "code", "execution_count": 200, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n" ] } ], "source": [ "for k in d.keys():\n", " print(k)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Oder so ..." ] }, { "cell_type": "code", "execution_count": 201, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n" ] } ], "source": [ "for k in d:\n", " print(k)" ] }, { "cell_type": "code", "execution_count": 202, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3]" ] }, "execution_count": 202, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(d.keys())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Value sind iterable" ] }, { "cell_type": "code", "execution_count": 203, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zero\n", "one\n", "two\n", "three\n" ] } ], "source": [ "for v in d.values():\n", " print(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Key/Value Paare iterieren? Wie geht das denn nun?" ] }, { "cell_type": "code", "execution_count": 204, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(0, 'zero')\n", "(1, 'one')\n", "(2, 'two')\n", "(3, 'three')\n" ] } ], "source": [ "for item in d.items():\n", " print(item)" ] }, { "cell_type": "code", "execution_count": 205, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "key 0\n", "value zero\n", "key 1\n", "value one\n", "key 2\n", "value two\n", "key 3\n", "value three\n" ] } ], "source": [ "for item in d.items():\n", " key = item[0]\n", " value = item[1]\n", " print('key', key)\n", " print('value', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There must be a better way: **Tuple Unpacking**" ] }, { "cell_type": "code", "execution_count": 206, "metadata": {}, "outputs": [], "source": [ "a, b = 1, 2" ] }, { "cell_type": "code", "execution_count": 207, "metadata": {}, "outputs": [], "source": [ "(a, b) = (1, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tuple Unpacking bei Key/Value Iteration" ] }, { "cell_type": "code", "execution_count": 208, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "key 0\n", "value zero\n", "key 1\n", "value one\n", "key 2\n", "value two\n", "key 3\n", "value three\n" ] } ], "source": [ "for key, value in d.items():\n", " print('key', key)\n", " print('value', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Now for something completely different: `collections.namedtuple`" ] }, { "cell_type": "code", "execution_count": 209, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First Name joerg\n", "Last Name faschingbauer\n", "First Name sebastian\n", "Last Name kurz\n" ] } ], "source": [ "user_a = {\n", " 'firstname': 'joerg',\n", " 'lastname': 'faschingbauer',\n", "}\n", "\n", "user_b = {\n", " 'firstname': 'sebastian',\n", " 'lastname': 'kurz',\n", "}\n", "\n", "users = [user_a, user_b]\n", "for u in users:\n", " print('First Name', u['firstname'])\n", " print('Last Name', u['lastname'])\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There must be a better way" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Erste Näherung**: Definition einer Klasse, damit man nicht immer mit den nackten Dictionary-Keys arbeiten muss" ] }, { "cell_type": "code", "execution_count": 210, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First Name joerg\n", "Last Name faschingbauer\n", "First Name sebastian\n", "Last Name kurz\n" ] } ], "source": [ "class User:\n", " def __init__(self, firstname, lastname):\n", " self.firstname = firstname\n", " self.lastname = lastname\n", "\n", "user_a = User(firstname='joerg', lastname='faschingbauer')\n", "user_b = User('sebastian', 'kurz')\n", "users = [user_a, user_b]\n", "for u in users:\n", " print('First Name', u.firstname)\n", " print('Last Name', u.lastname)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There must be a better way. Oft, wenn man mit Daten hantiert, definiert man viele solcher Klassen mit immer anderem Inhalt. Dafür gibts **`collections.namedtuple`**." ] }, { "cell_type": "code", "execution_count": 211, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First Name joerg\n", "Last Name faschingbauer\n", "First Name sebastian\n", "Last Name kurz\n" ] } ], "source": [ "from collections import namedtuple\n", "\n", "User = namedtuple('User', ('firstname', 'lastname'))\n", "user_a = User(firstname='joerg', lastname='faschingbauer')\n", "user_b = User('sebastian', 'kurz')\n", "users = [user_a, user_b]\n", "for u in users:\n", " print('First Name', u.firstname)\n", " print('Last Name', u.lastname)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mehr zur Parameterübergabe: variabel lange Argumentlisten" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An einer Stelle im reviewten Code wurde `*` bei einem Funktionsaufruf verwendet. Das kann ich nicht so stehen lassen, sonder muss der Stackoverflowprogrammierung entgegenwirken. Und ein wenig weiter ausholen." ] }, { "cell_type": "code", "execution_count": 212, "metadata": {}, "outputs": [], "source": [ "def velocity(length_m, time_s):\n", " return length_m/time_s" ] }, { "cell_type": "code", "execution_count": 213, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 213, "metadata": {}, "output_type": "execute_result" } ], "source": [ "velocity(12, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Keyword Arguments** (Folie 91): lesbarer, wenn mehr als ein Parameter im Spiel ist." ] }, { "cell_type": "code", "execution_count": 214, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 214, "metadata": {}, "output_type": "execute_result" } ], "source": [ "velocity(time_s=2, length_m=12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parameter liegen in einer liste vor, und werden als *positionelle* Parameter übergeben:" ] }, { "cell_type": "code", "execution_count": 215, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 215, "metadata": {}, "output_type": "execute_result" } ], "source": [ "params = [12, 2]\n", "velocity(*params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ist das gleiche wie ..." ] }, { "cell_type": "code", "execution_count": 216, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 216, "metadata": {}, "output_type": "execute_result" } ], "source": [ "velocity(12, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parameter liegen als Dictionary vor, und werden als *Keyword Arguments* übergeben:" ] }, { "cell_type": "code", "execution_count": 217, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 217, "metadata": {}, "output_type": "execute_result" } ], "source": [ "params = {'length_m': 12, 'time_s': 2}\n", "velocity(**params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ist das gleiche wie ..." ] }, { "cell_type": "code", "execution_count": 218, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 218, "metadata": {}, "output_type": "execute_result" } ], "source": [ "velocity(time_s=2, length_m=12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wie sieht es auf der anderen Seite aus? In der Funktion?" ] }, { "cell_type": "code", "execution_count": 219, "metadata": {}, "outputs": [], "source": [ "def velocity(*args):\n", " m, s = args # explizites Entpacken der Positionellen Parameter\n", " return m/s" ] }, { "cell_type": "code", "execution_count": 220, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 220, "metadata": {}, "output_type": "execute_result" } ], "source": [ "velocity(12, 2)" ] }, { "cell_type": "code", "execution_count": 221, "metadata": {}, "outputs": [], "source": [ "def velocity(**kwargs):\n", " # explizies Rauskletzeln der Keyword Arguments\n", " m = kwargs['length_m']\n", " s = kwargs['time_s']\n", " return m/s" ] }, { "cell_type": "code", "execution_count": 222, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.0" ] }, "execution_count": 222, "metadata": {}, "output_type": "execute_result" } ], "source": [ "velocity(length_m=12, time_s=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## OO: eine erste Klasse" ] }, { "cell_type": "code", "execution_count": 223, "metadata": {}, "outputs": [], "source": [ "class User:\n", " def __init__(self, first, last, age):\n", " self.first = first\n", " self.last = last\n", " self.age = age\n", " def celebrate_another_birthday(self):\n", " self.age += 1\n", " def greet(self):\n", " print(f'Guten Tag, mein Name ist {self.first} {self.last}, und ich bin {self.age} Jahre alt')" ] }, { "cell_type": "code", "execution_count": 224, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "joerg faschingbauer 53\n" ] } ], "source": [ "user = User('joerg', 'faschingbauer', 53)\n", "print(user.first, user.last, user.age)" ] }, { "cell_type": "code", "execution_count": 225, "metadata": {}, "outputs": [], "source": [ "user.celebrate_another_birthday()" ] }, { "cell_type": "code", "execution_count": 226, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "54" ] }, "execution_count": 226, "metadata": {}, "output_type": "execute_result" } ], "source": [ "user.age" ] }, { "cell_type": "code", "execution_count": 227, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "print(type(user))" ] }, { "cell_type": "code", "execution_count": 228, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Guten Tag, mein Name ist joerg faschingbauer, und ich bin 54 Jahre alt\n" ] } ], "source": [ "user.greet()" ] } ], "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.2" } }, "nbformat": 4, "nbformat_minor": 4 }