{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Konzept 5: Datenstrukturen\n", "\n", "Computerprogramme ver- oder bearbeiten Daten.\n", "Diese Daten sollten vernünftigerweise in einer für den Menschen verständlichen Struktur vorliegen.\n", "Dabei ist es wichtig, gut zu verstehen von welcher Natur die abzubildenden Konzepte oder Strukturen sind.\n", "\n", "Datenstrukturen werden aus elementaren Basisdaten aufgebaut.\n", "Diese sind zum Beispiel Zeichenketten (engl. \"strings\"), Ganzzahlen (engl. \"integer\"), Fließkommazahlen (engl. \"float\"), Logische Werte (engl. \"boolean values\").\n", "\n", "Aus diesen werden höhere Strukturen aufgebaut,\n", "welche ihrerseits wieder zum Aufbau noch komplexerer Strukturen verwendet werden können.\n", "Hierfür gibt es ebenfalls Basisdatenstrukturen wie eine lineare Auflistung (`list`) oder Tupel (`tuple`), eine Assoziation (`dict`) oder eine Menge (`set`), usw.\n", "\n", "Es folgt nun eine Übersicht dieser Konstruktionsmittel." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tupel\n", "\n", "Das ist die einfachste Datenstruktur Python's.\n", "Es handelt sich hier um eine lineare Auflistung von Elementen zwischen zwei **runden** Klammern `(...,...,...)`.\n", "Diese Elemente sind \"fix\", d.h. es können weder Elemente hinzugefügt, noch verändert, noch entfernt werden.\n", "Diese Datenstruktur tritt schon in recht einfachen Fällen auf,\n", "z.B. Rückgabe mehrerer Elemente in einem `return`-Statement oder einer gleichzeitigen Zuweisung an Variablen." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(5, 'baum', -1, None)\n" ] } ], "source": [ "x = (5, \"baum\", -1, None)\n", "print(x)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n", "1\n", "2\n" ] } ], "source": [ "x, y, z = 4, 1, 2\n", "print(x)\n", "print(y)\n", "print(z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dies kann für Vertauschungen verwendet werden:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(1, 2)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a, b = 1, 2\n", "a, b" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(2, 1)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a, b = b, a\n", "a, b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Achtung**: Es gibt auch Tupel mit nur einem Eintrag.\n", "Dieser muss zwingend einen Beistrich nach dem Eintrag haben (ansonsten wird es als normale Klammer erkannt und wird ignoriert)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(1,)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "one = (1, )\n", "one" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Zugriff auf ein Element\n", "\n", "Indizierbare Objekte (`tuple`, `list`, `str`, ...) erlauben,\n", "mittels des Syntax `object[idx]` direkt auf das Element an der Stelle `idx` zuzugreifen.\n", "Indizierungen starten immer bei `0`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = (1, 12, 41, 27, 33)\n", "t[0]" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "41" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Verständnisfrage:** Was macht\n", "\n", "`t[t[0]]`\n", "\n", "und was wäre das Ergebnis dieses Ausdrucks? Probiere es aus!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Länge mittels `len(...)`" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Index beginnt bei 0?\n", "\n", "**Bemerkung:** Warum bei `0`? Das hat viele Gründe, einer ist, dass mittels negativer Indices von hinten Indiziert werden kann. Dabei ist `-1` das letzte Element, usw. Dies fügt sich wunderbar mit dem `len` Befehl zusammen, weil man für den positiven Index den negativen von der Länge einfach abziehen kann:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "33" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[-1]" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "33" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[len(t)-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eine Visualisierung aus dem [Python Tutorial](https://docs.python.org/2/tutorial/introduction.html#strings)\n", "\n", "```\n", " +---+---+---+---+---+---+\n", " | P | y | t | h | o | n |\n", " +---+---+---+---+---+---+\n", " 0 1 2 3 4 5 6\n", "-6 -5 -4 -3 -2 -1\n", "```\n", "\n", "Eine einfache Denkhilfe ist,\n", "sich den Index als die Zwischenstelle zwischen den Einträgen vorzustellen.\n", "Der `i`-te Eintrag ist dabei zwischen der `i-1`-ten und `i`-ten Stelle." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Zugriff auf mehrere Elemente: Teil-Sequenzen\n", "\n", "Es lassen sich auch zusammenhängende Teile extrahieren, wobei der Syntax so ist: `object[:]`.\n", "\n", "* `start`: erstes Element\n", "* `end`: erstes Element das **nicht** mehr in diesem Teil sein soll\n", "* `start` und `end` können auch weggelassen werden.\n", "\n", "Ein optionales drittes Argument kann für größere Sprünge verwendet werden.\n", "\n", "* `list[2:10:2]` jedes zweite Element von 2 bis 10.\n", "* `list[::-1]` die Liste in umgekehrter Reihenfolge (negative Schrittweite, ohne bestimmte Ränder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Kopie der Liste `t`, mit den identischen Elementen" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(1, 12, 41, 27, 33)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Elemente von Position 1 bis (nicht eingeschlossen) 3" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(12, 41)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[1:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Position 1 bis (nicht eingeschlossen) 5 mit Schrittweite 2" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(12, 27)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[1:5:2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"die ersten zwei\"" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(1, 12)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[:2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"alle, ab dem zweiten Index\"" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(41, 27, 33)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[2:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"die letzten zwei\"" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(27, 33)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[-2:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"jedes zweite\"" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(1, 41, 33)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[::2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"jedes zweite ab Index 1\"" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(12, 27)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[1::2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"umgedreht, in verkehrter Reihenfolge\"" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(33, 27, 41, 12, 1)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t[::-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Listen\n", "\n", "Ähnlich wie Tupel, sind Listen geornete Kontainer für beliebige Werte zwischen **eckigen** Klammern `[...,...,...]`.\n", "Sie unterscheiden sich jedoch dadurch,\n", "dass sowohl einzelne Einträge als auch deren Länge verändert werden kann." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[5, 'Baum', -1, None, 3.14159265]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = [5, \"Baum\", -1, None, 3.14159265]\n", "l" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Baum'" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Entfernen\n", "\n", "Ein Element an einer bestimmten Position wird mit `del [idx]` entfernt." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[5, 'Baum', -1, 3.14159265]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "del l[3]\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Verlängern mittels `.append(...)`" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[5, 'Baum', -1, 3.14159265, 'Gartenzwerg']" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l.append(\"Gartenzwerg\")\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Quiz:** Was passiert mit l, wenn die vorhergehende `append` Funktion zweimal ausgeführt wird?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Verwandt mit `append` ist die Methode **`pop()`**, welches das letzte Element aus der Liste entfernt und zurückgibt.\n", "Sehr nützlich, um einen dynmischen [Stack](http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29) in einer Schleife zu verwalten." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gartenzwerg\n", "3.14159265\n", "-1\n", "Baum\n", "5\n" ] } ], "source": [ "while len(l) > 0:\n", " e = l.pop()\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`l` ist nun leer:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Erweitern, Einfügen, Umdrehen, ...\n", "\n", "Neben diesen grundsätzlichen Funktionen gibt es noch einige weitere:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`list.extend(...)`: erweitern der Liste um alle Elemente in dem übergebenen iterierbaren Ausdruck." ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[42, 5, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "l = [42, 5, -1]\n", "l.extend(range(10))\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`list1 + list2`: zwei Listen können addiert werden." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[5, 1, 'u', 'v']" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l1 = [5, 1]\n", "l2 = [\"u\", \"v\"]\n", "l1 + l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`insert(i, obj)`: einfügen an Stelle `i`" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[1, 'kk', 2, 3]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f = [1, 2, 3]\n", "f.insert(1, \"kk\")\n", "f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`.reverse()` dreht die Elemente der Liste um, ohne eine neue Liste zu erzeugen!\n", "Daher findet hier auch keine Zuweisung statt." ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[3, 2, 'kk', 1]" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f.reverse()\n", "f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ähnlich wie `.reverse` sortiert `.sort` ebenfalls \"in-place\":" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "vorher: [4, 5, 2, 5, 9, 1, 3]\n", "nachher: [1, 2, 3, 4, 5, 5, 9]\n" ] } ], "source": [ "g = [4, 5, 2, 5, 9, 1, 3]\n", "print(\"vorher: %r\" % g)\n", "g.sort()\n", "print(\"nachher: %r\" % g)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Bemerkung:** eng verwandt ist dies mit dem Schlüsselwort `reversed(...)`.\n", "Es hat den großen Unterschied, dass die Reihenfolge *innerhalb* der Liste nicht verändert wird.\n", "Das ist üblicherweise das gewünschte Verhalten!\n", "Dies ist auch mit dem Verhalten von `f[::-1]` äquivalent." ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[11, 5, 7, 3, 2]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p = [2, 3, 7, 5, 11]\n", "list(reversed(p))" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2, 3, 7, 5, 11]" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "bzw. **`sorted(...)`** um eine neue Liste mit den sortierten Elementen zu erhalten." ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2, 3, 5, 7, 11]" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`sorted(..., key = ...)`** wird verwendet, um die Elemente nach einer bestimmten (sortierbaren) Eigenschaft zu sortieren. Dabei wird dem Parameter `key` eine Funktion übergeben, die jedes Element auf das zu sortierende Objekt abbildet. z.B. ein Attribut eines Objektes, oder das Ergebnis einer Funktion oder Methode.\n", "\n", "Hier ein Beispiel, wie verschiedene Strings nach ihrer Länge (`len`-Funktion) sortiert werden:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['x', 'U', 'ab', 'Gras', 'Julia']" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted([\"ab\", \"x\", \"Julia\", \"Gras\", \"U\"], key = len)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... und hier werden Strings unabhängig von Groß- und Kleinschreibung sortiert.\n", "Der Aufruf der `.upper()` Methode in einer lambda-Funktion wandelt vor der Sortierung jeden Eintrag in Großbuchstaben um." ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['AB', 'abc', 'def', 'Hijk', 'omk', 'xyz']" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted([\"AB\", \"abc\", \"Hijk\", \"def\", \"xyz\", \"omk\"], key = lambda e : e.upper())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Bemerkung:** Hier handelt es sich außerdem um einen Iterator, welcher erst bei Bedarf (engl. \"lazy evaluation\") tatsächlich die Liste abarbeiter.\n", "Dieses Abarbeiten wird mit dem `list(...)` Befehl explizit erzwungen, ist aber üblicherweise nicht notwendig (z.B. in `for` oder `while` Schleifen).\n", "\n", "`p[::-1]` liefert keinen Iterator zurück:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[11, 5, 7, 3, 2]\n" ] } ], "source": [ "print(p[::-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Bemerkung**: Veränderungen an doppelt referenzierte Listen führen dazu, dass die Änderung in beiden Variablen sichtbar ist.\n", "Das könnte zu Verwirrungen führen.\n", "Manchmal ist es daher notwendig, eine Kopie der Liste anzufertigen!" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[5, 3, 1, -2, -5]\n", "[5, 3, 1, -2, -5]\n" ] } ], "source": [ "u = [5, 3, 1, -2, -5]\n", "v = u\n", "print(u)\n", "print(v)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[5, 999, 1, -2, -5]\n", "[5, 999, 1, -2, -5]\n" ] } ], "source": [ "u[1] = 999\n", "print(u)\n", "print(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Erstellen einer Kopie der Liste (nicht der einzelnen Werte):" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[5, 888, 1, -2, -5]\n", "[5, 888, 1, -2, -5]\n", "[5, 999, 1, -2, -5]\n" ] } ], "source": [ "w = u[:]\n", "u[1] = 888\n", "print(u)\n", "print(v)\n", "print(w)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Range" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die in Python eingebaute Funktion `range(...)` gibt Ganzzahlen in einer Liste aus." ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "range(0, 10)" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "und mit zwei oder drei Argumenten gibt man einen Start bei ungleich 0 an, bzw. die Schrittweite:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "range(10, 30, 5)" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(10, 30, 5)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "range(-10, 10, 2)" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(-10, 10, 2)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "range(100, 0, -11)" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(100, 0, -11)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class range in module builtins:\n", "\n", "class range(object)\n", " | range(stop) -> range object\n", " | range(start, stop[, step]) -> range object\n", " | \n", " | Return an object that produces a sequence of integers from start (inclusive)\n", " | to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n", " | start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.\n", " | These are exactly the valid indices for a list of 4 elements.\n", " | When step is given, it specifies the increment (or decrement).\n", " | \n", " | Methods defined here:\n", " | \n", " | __contains__(self, key, /)\n", " | Return key in self.\n", " | \n", " | __eq__(self, value, /)\n", " | Return self==value.\n", " | \n", " | __ge__(self, value, /)\n", " | Return self>=value.\n", " | \n", " | __getattribute__(self, name, /)\n", " | Return getattr(self, name).\n", " | \n", " | __getitem__(self, key, /)\n", " | Return self[key].\n", " | \n", " | __gt__(self, value, /)\n", " | Return self>value.\n", " | \n", " | __hash__(self, /)\n", " | Return hash(self).\n", " | \n", " | __iter__(self, /)\n", " | Implement iter(self).\n", " | \n", " | __le__(self, value, /)\n", " | Return self<=value.\n", " | \n", " | __len__(self, /)\n", " | Return len(self).\n", " | \n", " | __lt__(self, value, /)\n", " | Return self integer -- return number of occurrences of value\n", " | \n", " | index(...)\n", " | rangeobject.index(value, [start, [stop]]) -> integer -- return index of value.\n", " | Raise ValueError if the value is not present.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " | \n", " | start\n", " | \n", " | step\n", " | \n", " | stop\n", "\n" ] } ], "source": [ "help(range)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## List Comprehension\n", "\n", "Passend zu Listen gibt es ein Feature von Python zum eleganten Verarbeiten von geordneten Listen, sogenannte \"*list comprehensions*\":" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der Ausdruck `2 * i + 3` am Beginn hängt von dem \"i\" (genannt \"Laufvariable\") ab." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[ 2 * i + 3 for i in range(10)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Neben diesem einfachen Beispiel, gibt es auch komplexere Varianten.\n", "Hier mit zwei Listen in i und j" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[10, 20, 30, 11, 21, 31, 12, 22, 32]" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[ i + j for i in range(3) for j in range(10, 40, 10) ]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eine nachgestellte Bedingung an die Laufvariable" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[-9, -6, -3, 0, 3, 6, 9]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[ k for k in range(-10, 10) if k % 3 == 0]" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[50.41, 36.0]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Die Listen können beliebig sein\n", "temps = [-10.1, -11.2, -8.5, -7.1, -6.0]\n", "[ temp**2 for temp in temps if temp > -8]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Bemerkung**: Eine technische Finesse an \"list comprehensions\" ist,\n", "dass deren Ergebnis wieder eine Liste ist.\n", "Daher ist es nicht ungewöhnlich, verschachtelte list comprehensions anzutreffen!" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],\n", " [2, 4, 6, 8, 10, 12, 14, 16, 18, 20],\n", " [3, 6, 9, 12, 15, 18, 21, 24, 27, 30],\n", " [4, 8, 12, 16, 20, 24, 28, 32, 36, 40],\n", " [5, 10, 15, 20, 25, 30, 35, 40, 45, 50],\n", " [6, 12, 18, 24, 30, 36, 42, 48, 54, 60],\n", " [7, 14, 21, 28, 35, 42, 49, 56, 63, 70],\n", " [8, 16, 24, 32, 40, 48, 56, 64, 72, 80],\n", " [9, 18, 27, 36, 45, 54, 63, 72, 81, 90],\n", " [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Die 10x10 Multiplikationstabelle ist schnell erzeugt\n", "[ [i*j for j in range(1,11)] for i in range(1,11)]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[[1],\n", " [2, 4],\n", " [3, 6, 9],\n", " [4, 8, 12, 16],\n", " [5, 10, 15, 20, 25],\n", " [6, 12, 18, 24, 30, 36],\n", " [7, 14, 21, 28, 35, 42, 49],\n", " [8, 16, 24, 32, 40, 48, 56, 64],\n", " [9, 18, 27, 36, 45, 54, 63, 72, 81],\n", " [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# bzw. mit einer weiteren Bedingung an die innere list comprehension\n", "[[i*j for j in range(1,11) if i-j > -1] for i in range(1,11)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Zeichenketten (engl. Strings)\n", "\n", "Eine ganz wichtige Kategorie von Ausdrücken sind Zeichenketten (engl. \"strings\").\n", "Es handelt sich um einen unveränderlichen Vektor von Buchstaben,\n", "welche einzelne Wörter, Sätze oder ganze Daten/Dateiinhalte bilden können.\n", "Strings werden zwischen einfachen oder doppelten Anführungszeichen eingegeben,\n", "wobei dann die jeweils anderen Anführungszeichen \"gefahrlos\" innerhalb der Zeichenkette verwendet werden können:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Wort\n", "Satz mit einfachen 'Anführungszeichen'.\n", "Andersherum mit \"doppelten\" Anführungszeichen\n" ] } ], "source": [ "print(\"Wort\")\n", "print(\"Satz mit einfachen 'Anführungszeichen'.\")\n", "print('Andersherum mit \"doppelten\" Anführungszeichen')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ein besonderes Zeichen ist der Backslash \"\\\".\n", "Das darauf folgende Zeichen kann eine besondere bedeutung haben, z.B steht `\\n` für eine neue Zeile." ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Neue Zeile\n", "innerhalb des Strings\n" ] } ], "source": [ "print(\"Neue Zeile\\ninnerhalb des Strings\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Um das Verhalten des Backslashs zu unterdrücken,\n", "wird der Zeichenkette ein kleines \"`r`\" (für \"raw\") vorangestellt.\n", "Dies ist z.B. für LaTeX Kommandos nützlich, da diese Befehle mit einem Backslash beginnen." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "keine \\neu Zeile mit \\LaTeX{}\n" ] } ], "source": [ "print(r\"keine \\neu Zeile mit \\LaTeX{}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Nebenbemerkung:** Um $\\LaTeX{}$ tatsächlich darstellen zu können, muss man hier im IPython Notebook den Interpreter aufrufen:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "Kleine Formel mit Variablenersetzung: $$\\int_{-10}^{10} \\frac{1-x}{\\sin{x}^2+1}\\,\\mathrm{d}x$$" ], "text/plain": [ "" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import HTML\n", "a, b = -10, 10\n", "HTML(r\"Kleine Formel mit Variablenersetzung: $$\\int_{%s}^{%s} \\frac{1-x}{\\sin{x}^2+1}\\,\\mathrm{d}x$$\" % (a, b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Es ist möglich, mehrzeilige Zeichenketten anzugeben. Dafür werden die umschließenden Anführungszeichen verdreifacht.\n", "Das wird für [Dokumentationstexte](4-2-dokumentation.ipynb), Dateneingabe, oder Übersichtlichkeit verwendet." ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x = r\"\"\"Ein (Python?)-Schlangenbeschwörer:\n", "\n", " ,'._,`.\n", " (-.___.-)\n", " (-.___.-)\n", " `-.___.-' \n", " (( @ @| . __\n", " \\ ` | ,\\ |`. @| | | _.-._\n", " __`.`=-=mm===mm:: | | |`. | | | ,'=` '=`.\n", " ( `-'|:/ /:/ `/ @| | | |, @| @| /---)W(---\\\n", " \\ \\ / / / / @| | ' (----| |----) ,~\n", " |\\ \\ / /| / / @| \\---| |---/ |\n", " | \\ V /||/ / `.-| |-,' |\n", " | `-' |V / \\| |/ @'\n", " | , |-' __| |__\n", " | .;: _,-. ,--\"\"..| |..\"\"--.\n", " ;;:::' \" ) (`--::__|_|__::--')\n", " ,-\" _, / \\`--...___...--'/ \n", " ( -:--'/ / /`--...___...--'\\\n", " \"-._ `\"'._/ /`---...___...---'\\\n", " \"-._ \"---. (`---....___....---')\n", " .' \",._ ,' ) |`---....___....---'|\n", " /`._| `| | (`---....___....---') \n", " ( \\ | / \\`---...___...---'/\n", " `. `, ^\"\" `:--...___...--;'\n", " `.,' hh `-._______.-'\n", "\n", " --- http://www.chris.com/ascii/ ---\n", "\"\"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Als kleines Extra spiegeln wir ihn:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " :reröwhcsebnegnalhcS-)?nohtyP( niE\n", " \n", " .`,_.', \n", " )-.___.-( \n", " )-.___.-( \n", " '-.___.-` \n", " __ . |@ @ (( \n", " _.-._ | | |@ .`| \\, | ` \\ \n", " .`=' `=', | | | .`| | | ::mm===mm=-=`.`__ \n", " \\---(W)---/ |@ |@ ,| | | |@ /` /:/ /:|'-` ( \n", " ~, )----| |----( ' | |@ / / / / \\ \\ \n", " | /---| |---\\ |@ / / |/ / \\ \\| \n", " | ',-| |-.` / /||/ V \\ | \n", " '@ /| |\\ / V| '-` | \n", " __| |__ '-| , | \n", " .--\"\"..| |..\"\"--, .-,_ :;. | \n", " )'--::__|_|__::--`( ) \" ':::;; \n", " /'--...___...--`\\ / ,_ \"-, \n", " \\'--...___...--`/ / /'--:- ( \n", " \\'---...___...---`/ /_.'\"` _.-\" \n", " )'---....___....---`( .---\" _.-\" \n", " |'---....___....---`| ) ', _.,\" '. \n", " )'---....___....---`( | |` |_.`/ \n", " /'---...___...---`\\ / | \\ ( \n", " ';--...___...--:` \"\"^ ,` .` \n", " '-._______.-` hh ',.` \n", " \n", " --- /iicsa/moc.sirhc.www//:ptth --- \n" ] } ], "source": [ "for line in x.splitlines():\n", " line = u\"%-80s\" % line\n", " print(line[::-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eventuell ist aufgefallen, dass vor der Zeichenkette neben dem \"`r`\" auch ein \"`u`\" steht?\n", "Das ist ein Einstellung,\n", "um [Unicode](http://en.wikipedia.org/wiki/Unicode) als Kodierung der Buchstaben zu verwenden.\n", "Nur so werden die Umlaute der deutschen Sprache wieder richtig dargestellt.\n", "Dies ist nur für Python Version 2 notwendig, Python 3 verwendet standardmäßig Unicode." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dict(ionary)\n", "\n", "Ein `dict` ist eine assoziative Datenstruktur.\n", "Elemente werden zwischen zwei Mengen surjektiv abgebildet.\n", "Erzeugt wird diese Datenstruktur mittels **geschwungener** Klammern `{ ... : ... , ... : ... , ... }` bzw. dem Schlüsselwort `dict`.\n", "Der Sinn ist, dass eine Beziehung hergestellt wird, welche z.B. eine Namensgebung für bestimmte Eigenschaften sein kann.\n", "Der \"Name\" wird hier \"Schlüssel\" (engl. \"key\") genannt und der dazugehörige Wert \"Wert\" (engl. \"value\").\n", "\n", "Dies ist ganz analog zu einer Variablen,\n", "jedoch lebt diese Variable nun innerhalb einer Datenstruktur.\n", "Das `dict` merkt sich dabei nicht die Reihenfolge der Elemente!\n", "\n", "Ein Beispiel:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'Christian': 19, 'Claus': 28, 'Ciara': 23, 'Clara': 21}\n" ] } ], "source": [ "alter = {\"Clara\": 21, \"Christian\": 19, \"Ciara\": 23, \"Claus\": 28}\n", "print(alter)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'jane': 172, 'jim': 181, 'joe': 190, 'julia': 165}" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "size = dict(jim = 181, jane = 172, joe = 190, julia = 165)\n", "size" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Elemente können ähnlich wie Listen ausgelesen werden:" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "23" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alter[\"Ciara\"]" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "165" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "size[\"julia\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ebenso verhält es sich mit Lösch- und Größenfunktionen:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(alter)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'Christian': 19, 'Ciara': 23, 'Clara': 21}" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "del alter[\"Claus\"]\n", "alter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Iterationen** über maps gehen leicht von der Hand. Entweder nur über die \"`keys`\" oder sowohl über die Schlüsselwörter als auch über die Werte:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Christian\n", "Ciara\n", "Clara\n" ] } ], "source": [ "for key in alter:\n", " print(key)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Christian => 19\n", "Ciara => 23\n", "Clara => 21\n" ] } ], "source": [ "for key, value in alter.items():\n", " print(\"%-10s => %s\" % (key, value))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Bemerkung:** die Methode `.items` ist hier entscheidend." ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function items:\n", "\n", "items(...) method of builtins.dict instance\n", " D.items() -> a set-like object providing a view on D's items\n", "\n" ] } ], "source": [ "help(alter.items)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Geordnetes Dict\n", "\n", "Die \"Map\" an sich ist nicht sortiert.\n", "Es gibt jedoch Fälle, wo dies wünschenswert wäre.\n", "Hierfür gibt es `OrderedDict` in dem [collections module](https://docs.python.org/2/library/collections.html):" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from collections import OrderedDict" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "OrderedDict([('z', 11), ('a', -1), ('j', 99)])" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "od = OrderedDict()\n", "od[\"z\"] = 11\n", "od[\"a\"] = -1\n", "od[\"j\"] = 99\n", "od" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Verschachtelte Strukturen\n", "\n", "Es ist nicht ungewöhnlich, mit verschachtelten Strukturen zu tun zu haben.\n", "Dabei gibt es nur wenige Einschränkungen, was alles möglich ist.\n", "(z.B. darf der Schlüssel eines `dict` nur eine nichtmodifizierbare Datenstruktur sein (Zahl, String, Tupel))" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'stunden': 6,\n", " 'termine': [{'raum': 'PC Lab', 'zeit': 'Montag, 9:00'},\n", " {'raum': 'PC Lab', 'zeit': 'Dienstag, 9:00'}],\n", " 'titel': 'Python Kurs',\n", " 'typ': 'K',\n", " 'vortragende': [{'email': 'harald@schil.ly', 'name': 'Harald Schilly'}]}" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Eine Lehrveranstaltung\n", "\n", "programmierpraktikum = {\n", " \"titel\": \"Python Kurs\",\n", " \"typ\": \"K\",\n", " \"stunden\" : 6,\n", " \"vortragende\" : [\n", " {\n", " \"name\": \"Harald Schilly\",\n", " \"email\": \"harald@schil.ly\"\n", " }\n", " ],\n", " \"termine\": [\n", " {\"zeit\": \"Montag, 9:00\", \"raum\": \"PC Lab\"},\n", " {\"zeit\": \"Dienstag, 9:00\", \"raum\": \"PC Lab\"},\n", " ]\n", "}\n", "\n", "programmierpraktikum" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Auf alle Elemente kann zugegriffen werden, bzw. Werte verändert werden:" ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'PC Lab'" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ort des zweiten Termins\n", "programmierpraktikum[\"termine\"][1][\"raum\"]" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[{'email': 'harald@schil.ly', 'name': 'Harald Schilly'},\n", " {'name': 'Guido van Rossum',\n", " 'url': 'http://en.wikipedia.org/wiki/Guido_van_Rossum'}]" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Hinzufügen eines weiteren Vortragenden\n", "programmierpraktikum[\"vortragende\"].append(\n", " {\"name\": \"Guido van Rossum\", \n", " \"url\": \"http://en.wikipedia.org/wiki/Guido_van_Rossum\"})\n", "programmierpraktikum[\"vortragende\"]" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "Guido van Rossum" ], "text/plain": [ "" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Link zum neuen Vortragenden:\n", "from IPython.display import HTML\n", "guido = programmierpraktikum[\"vortragende\"][-1]\n", "HTML(\"{name}\".format(**guido))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Anaconda (Python 3)", "language": "python", "name": "anaconda3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }