{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Zusammengesetzte Datentypen" ] }, { "cell_type": "markdown", "source": [ "Zusammengesetzte Datentypen sind strukturierte Sammlungen von Objekten. In Python sind vier solcher \"zusammengesetzter Datentypen\" vordefiniert: Tupel, Listen, Sets und Dictionaries. Tupel und Listen sind zugleich sequentielle Datentypen. Manche der Operationen und Operatoren, die wir schon im Zusammenhang mit Strings kennengelernt haben, können deswegen auch auf Tupel und Listen angewandt werden." ], "metadata": { "collapsed": false } }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Tupel\n", "\n", "Tupel sind eine geordnete Abfolge von Elementen verschiedenen Datentyps. Das heißt, sie sind genau wie Strings ein sequentieller Datentyp. Tupel sind außerdem **unveränderbar**, genau wie Strings.\n", "Sie werden zum Beispiel verwendet, um unkompliziert die Werte zweier Variablen zu tauschen (siehe Beispiel unten). Im Kapitel zu Funktionen werden wir Tupeln auch noch einmal begegnen.\n", "\n", ":::{figure-md} markdown-fig\n", "<img src=\"tuple_object.png\" alt=\"Beispiel\" class=\"bg-transparent\" width=\"50%\">\n", "\n", "Beispielobjekt vom Typ Tupel\n", ":::\n" ] }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Leeres Tupel erstellen\n", "tpl = ()\n", "print(tpl)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Tupel mit einem Element: Komma nicht vergessen!\n", "tpl = (1,)\n", "print(tpl)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Tupel mit drei Elementen erstellen\n", "tpl = (\"a\", 4, 5)\n", "print(tpl)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Auf Element mit dem Index 0 zugreifen\n", "tpl[0]" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Tupel verketten\n", "(3, 1) + (\"Hallo\", 5.0)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "\n", "tpl[0:1]" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "tpl[1:3]" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Länge\n", "len(tpl)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Wie oft kommt das Element 4 im Tupel tpl vor?\n", "tpl.count(4)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Werte zweier Variablen austauschen\n", "x = 4\n", "y = 5\n", "# So geht es nicht:\n", "# x = y\n", "# y = x\n", "# Variante 1: Kompliziert\n", "temp = x\n", "x = y\n", "y = temp\n", "# Variante 2: Unkompliziert\n", "(x, y) = (y, x)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Tupel kann man nicht veränern\n", "# tpl[1] = 10" ], "metadata": { "collapsed": false } }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Listen\n", "\n", "Geordnete Abfolge von Elementen, die gewöhnlich denselben Datentyp haben, aber theoretisch verschiedene Datentypen haben könnten. Listen sind **veränderbar**, das heißt, dass Listenelemente ausgetauscht werden können.\n", "\n", ":::{figure-md} markdown-fig\n", "<img src=\"list_object.png\" alt=\"Beispiel\" class=\"bg-transparent\" width=\"50%\">\n", "\n", "Beispielobjekt vom Typ Liste\n", ":::\n", "\n", "Liste aller Methoden, die für Objekte vom Typ Liste definiert sind: [https://docs.python.org/3/tutorial/datastructures.html#more-on-lists](https://docs.python.org/3/tutorial/datastructures.html#more-on-lists)." ] }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Leere Liste erstellen\n", "lst = []\n", "print(lst)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Liste mit vier Elementen desselben Datentyps ertellen\n", "lst = [1, 3, 8, 3]\n", "print(lst)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Liste mit drei Elementen verschiedener Datentypen erstellne\n", "lst_2 = [\"a\", 3, 5, True]\n", "print(lst)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Listen können auch selbst Listen enthalten: sie heißen dann \"verschachtelte Listen\"\n", "lst_3 = [[1, 2], [8, 3]]\n", "print(lst)" ], "metadata": { "collapsed": false, "is_executing": true } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Länge\n", "len(lst)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Auf Element mit dem Index 2 zugreifen\n", "lst[2]" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Auf das erste Element der zweiten Liste in der verschachtelten Liste lst_3 zugreifen\n", "lst_3[1][0]" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Element verrechnen\n", "lst[2] + 1" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Elment austauschen\n", "lst[1] = 23\n", "print(lst)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Element am Ende der Liste hinzufügen\n", "lst.append(50)\n", "print(lst)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Zwei Listen kombinieren: Alternative 1\n", "# liste_1 und liste_2 werden nicht verändert\n", "liste_1 = [1, 4, 3]\n", "liste_2 = [6, 8, 1]\n", "liste_3 = liste_1 + liste_2\n", "print(liste_3)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Zwei Listen kombinieren: Alternative 2\n", "# liste_1 wird verändert\n", "liste_1.extend(liste_2)\n", "print(liste_1)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Letztes Element ausgeben und entfernen\n", "liste_1.pop()" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Bestimmtes Element entfernen: Hier ist die Zahl nicht der Index sondern der Wert\n", "liste_1.remove(4)\n", "print(liste_1)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Wie oft kommt das Element 8 in der Liste liste_1 vor?\n", "liste_1.count(8)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Listen, deren Elemente Strings sind, kann man auch in einen String umwandeln:\n", "str_liste = [\"a\", \"b\", \"c\"]\n", "\"\".join(str_liste)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# String in Liste umwandeln\n", "dateiname = \"kafka_strafkolonie_1919\"\n", "dateiname.split(\"_\")" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Um Objekte mit anderen Datentypen in eine Liste umzuwandeln, kann man auch die Funktion list() verwenden\n", "# list() konvertiert Strings zeichenweise:\n", "list(\"Rose\")" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Neue sortierte Liste erstellen: liste_1 wird dabei nicht verändert\n", "liste_sortiert = sorted(liste_1)\n", "print(liste_sortiert)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Liste sortieren: liste_1 wird dabei verändert\n", "liste_1.sort()\n", "print(liste_1)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Reihenfolge der Elemente umkehren\n", "liste_1.reverse()\n", "print(liste_1)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Alias erstellen: Also ein zweiter Name für dasselbe Objekt\n", "kalt = [0, 4, 1, 9]\n", "kuehl = kalt\n", "kuehl.append(7)\n", "print(kalt)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Liste klonen\n", "warm = [20, 31, 25, 28]\n", "heiss = warm[:]\n", "heiss.append(32)\n", "print(warm)" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "Beim Klonen wird ein neues Objekt erstellt; ein Alias ist dagegen nur ein weiterer Name, der auf dasselbe Objekt zeigt. Um den Unterschied zwischen den beiden Operationen besser nachzuvollziehen, könnt ihr den Code auf [https://pythontutor.com/python-debugger.html#mode=edit](https://pythontutor.com/python-debugger.html#mode=edit) eingeben und ausführen. Die Seite visualisiert, was in jeder Codezeile passiert.\n" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "### Zusammenfassung: Operationen auf sequentiellen Datentypen\n", "\n", "Die folgende Tabelle ist der offiziellen Dokumentation zu Python 3.11.3 entnommen und gibt einen Überblick über die Operationen, die auf die drei sequentiellen Datentypen Strings, Tupel und Listen angewendet werden können. `s` steht für irgendein Objekt mit einem sequentiellen Datentyp.\n", "\n", "| Operator | Bedeutung |\n", "|--------------------------|-------------------------------------------------------------------------|\n", "| x in s | `True`, wenn ein Element in `s` gleich `x` ist, sonst `False` |\n", "| x not in s | `False`, wenn ein Element in `s` gleich `x` ist, sonst `True` |\n", "| s + t | Konkatenationsoperator: verkettet `s` und `t` |\n", "| s * n, n * s | `s` wird `n` Mal mit sich selbst addiert |\n", "| s\\[i\\] | auf das `i`-te Element von `s` zugreifen |\n", "| s\\[i:j\\] | Untersequenz / Teilsequenz aus `s` von Index `i` bis `j` |\n", "| s\\[i:j:k\\] | Untersequenz / Teilsequenz aus `s` von Index `i` bis `j` mit Schritt `k` |\n", "| len(s) | Länge von `s` |\n", "| min(s) | kleinstes Element in `s` |\n", "| max(s) | größtes Element in `s` |\n", "| s.index(x\\[, i\\[, j\\]\\]) | Index beim ersten Vorkommnis von `x` in `s` (zwischen Index `i` und `j`) |\n", "| s.count(x) | Gesamtzahl aller Vorkommnisse von `x` in `s` |\n", "\n", "\n", "Quelle: [Python 3.11.3 Documentation](https://docs.python.org/3/library/stdtypes.html#typesseq-common)" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "### Sets\n", "\n", "Sets sind ungeordnete Sammlungen von Objekten, die gewöhnlich denselben Datentyp haben, aber theoretisch verschiedene Datentypen haben können. Objekte in einem Set dürfen sich nicht wiederholen. In Python gibt es zum einen den Typ `set`, der **veränderbar** ist, und den Typ `frozenset`, der **unveränderbar** ist. Sets werden zum Beispiel dazu verwendet, um Duplikate aus einer Sequenz zu entfernen, oder Mengenoperationen durchzuführen: zum Beispiel kann man die Vereinigung, die Differenz oder die Schnittmenge zweier Mengen bilden. Sets sind kein sequentieller Datentyp, und die Operationen, die für sequentielle Datentypen definiert sind, können auf Sets nicht angewendet werden.\n", "\n", ":::{figure-md} markdown-fig\n", "<img src=\"set_object.png\" alt=\"Beispiel\" class=\"bg-transparent\" width=\"50%\">\n", "\n", "Beispielobjekt vom Typ Set\n", ":::\n" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Leeres Set erstellen - Achtung: {} erstellt ein neues Dictionary!\n", "menge = set()" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Set mit mehreren Objekten verschiedener Datentypen erstellen\n", "menge = {\"apfel\", 4, True}" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Set mit mehreren Objekten desselben Datentyps erstellen\n", "menge = {\"apfel\", \"banane\", \"kiwi\"}" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Länge\n", "len(menge)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Mitgliedschaftsoperatoren kann man auch auf sets anwenden\n", "\"banane\" in menge\n", "\"banane\" not in menge" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Überprüfen, ob menge eine Teilmenge von menge_2 ist\n", "menge_2 = {\"apfel\"}\n", "menge_2.issubset(menge)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Schnittmenge ausgeben lassen\n", "menge_intersect = menge.intersection(menge_2)\n", "print(menge_intersect)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Differenz zwischen menge und menge_2 ausgeben lasen\n", "menge = {\"apfel\", \"banane\", \"kiwi\"}\n", "menge_2 = {\"apfel\"}\n", "menge_diff = menge.difference(menge_2)\n", "print(menge_diff)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Vereinigung der beiden Mengen\n", "menge = {\"apfel\", \"banane\", \"kiwi\"}\n", "menge_2 = {\"orange\"}\n", "menge_union = menge.union(menge_2)\n", "print(menge_union)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Um Objekte mit anderen Datentypen in Sets umzuwandeln, kann man die bereits bekannte Funktion set() verwenden:\n", "# Bei der Umwandlung werden Duplikate entfernt\n", "blumen = [\"Rose\", \"Tulpe\", \"Tulpe\", \"Narzisse\"]\n", "blumen_set = set(blumen)\n", "print(blumen_set)" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "### Dictionaries\n", "\n", "Python Dictionaries werden dazu verwendet, um Daten als Schlüssel-Wert-Paar zu speichern. Dictionaries sind ähnlich wie Listen, aber die Einträge sind nicht geordnet und anstelle eines Zahlindexes ist jedem Wert ein Schlüssel zugeordnet, über den auf den Wert zugegriffen werden kann. Werte können alle bisher bekannten Datentypen haben und dürfen sich wiederholen, aber Schlüssel müssen unveränderbar und einzigartig sein. Das heißt: Schlüssel können zum Beispiel Strings sein, aber keine Listen. Dictionaries sind genauso wie Sets also kein sequentieller Datentyp, und die Operationen, die für sequentielle Datentypen definiert sind, können auf Dictionaries nicht angewendet werden. Dictionaries werden immer dann verwendet, wenn es sinnvoll ist, dass der Index sinntragend ist.\n", "\n", ":::{figure-md} markdown-fig\n", "<img src=\"dict_object.png\" alt=\"Beispiel\" class=\"bg-transparent\" width=\"50%\">\n", "\n", "Beispielobjekt vom Typ Dictionary\n", ":::" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Leeres Dictionary erstellen\n", "dct = {}" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Dictionary mit mehreren Einträgen erstellen\n", "noten = {\"Emma\": 3, \"Gero\": 2, \"Hanna\": 3 }" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Auf einen Wert zugreifen mit Zugriffsoperator\n", "# Wenn der Schlüssel nicht vorhanden ist, wird eine Fehlermeldung ausgegeben\n", "noten[\"Emma\"]" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Auf einen Wert zugreifen mit get()-Methode\n", "# Wenn der Schlüssel nicht vorhanden ist, wird die Nachricht \"Schlüssel nicht gefunden\" ausgegeben\n", "noten.get(\"Emma\", \"Schlüssel nicht gefunden\")" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Eintrag hinzufügen\n", "noten[\"Lee\"] = 2" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Wert ändern\n", "noten[\"Emma\"] = 2" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Eintrag entfernen mit Schlüsselwort del\n", "# Wenn der Schlüssel nicht vorhanden ist, wird eine Fehlermeldung ausgegeben\n", "del noten[\"Emma\"]" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Eintrag entfernen und entfernten Wert ausgeben mit pop()-Methode\n", "# Wenn der Schlüssel nicht vorhanden ist, wird die Nachricht \"Schlüssel nicht gefunden\" ausgegeben\n", "noten.pop(\"Emma\", \"Schlüssel nicht gefunden\")" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Mitgliedschaftsoperatoren kann man auch auf Dictionaries anwenden:\n", "# Der Operator wird automatisch auf die Schlüssel angewandt, nicht die Werte)\n", "# Überprüfen, ob ein Schlüssel vorhanden ist (geht natürlich auch mit not in)\n", "\"John\" in noten" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Alle Schlüssel ausgeben lassen\n", "noten.keys()" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Alle Werte ausgeben lassen\n", "noten.values()" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Überprüfen, ob ein Wert vorhanden ist\n", "2 in noten.values()" ], "metadata": { "collapsed": false } }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Quellen\n", "\n", "```{bibliography}\n", " :list: enumerated\n", " :filter: keywords % \"compounds\" or keywords % \"mit_05\" or keywords % \"mit_06\" or title % \"Common Sequence Operations\"\n", "```" ] } ], "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.0" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }