{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Software Entwicklung \n",
    "\n",
    "## Kapitel 3: Listen und Tupel"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 3.6 Tupel\n",
    "\n",
    "*Tupel* sind wie Listen ein Datentyp, mit dem *mehrere Werte* verwaltet werden können. Aber anders als Listen\n",
    "kann ein einmal erzeugtes Tupel nicht verändert werden, d.h.\n",
    "\n",
    "* es können keine weiteren Werte hinzugefügt werden\n",
    "* es können keine Werte aus dem Tupel entfernt werden\n",
    "* es kann kein Wert innerhalb des Tupels verändert werden\n",
    "\n",
    "Aufgrund dieser Einschränkungen werden Tupel i.d.R. schneller verarbeitet als Listen.\n",
    "\n",
    "Tupel werden durch runde Klammern begrenzt."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "tupel = (3, 7, 4, 9)\n",
    "print(len(tupel))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Lesender Zugriff ist wiederum mit einem Index möglich."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "tupel = (3, 7, 4, 9)\n",
    "print(tupel[2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Schreibender Zugriff wird aufgrund des Read-Only-Charakters von Tupeln verwehrt. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "tupel = (3, 7, 4, 9)\n",
    "tupel[2] = 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Die Elemente eines Tupels können mit einem einzigen Befehl separaten Variablen zugewiesen werden. Die Anzahl der\n",
    "aufnehmenden Variablen muss aber exakt der Länge des Tupels entsprechen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "tupel = (3, 7, 4, 9)\n",
    "e1, e2, e3, e4 = tupel\n",
    "print(e4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Wie die Liste ist auch ein Tupel eine Sequenz, die mit Hilfe der <code>for</code>-Schleife\n",
    "durchlaufen werden kann."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "for zahl in (3, 7, 4, 9):\n",
    "    print(zahl)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Listen und Tupel können verschachtelt werden, d.h. eine Liste kann wiederum Listen und/oder Tupel enthalten bzw. \n",
    "die Elemenente eines Tupels können auch Listen oder Tupel sein."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "tupel = ((3, 7), (4, 9))\n",
    "print(len(tupel))\n",
    "print(tupel[1][0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "ergebnis = []\n",
    "for zeilennummer in range(1, 6):\n",
    "    neue_zeile = []\n",
    "    for index in range(zeilennummer):\n",
    "        neue_zeile.append(zeilennummer)\n",
    "    ergebnis.append(neue_zeile)\n",
    "print(ergebnis)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Gelegentlich möchte man eine Liste \"durchnummerieren\", d.h. neben den eigentlichen Listenelementen\n",
    "auch den Index des Listenelements ausweisen:\n",
    "\n",
    "<code>['A', 'B', 'C']</code> -> <code>[(0, 'A'), (1, 'B'), (2, 'C')]</code>\n",
    "\n",
    "Genau dieses leistet die Built-In-Funktion <code>enumerate</code>, die aus einer Liste eine Sequenz  \n",
    "von derartigen Tupeln generiert. Und wie bei <code>range</code> muss das Ergebnis erst noch in eine Liste\n",
    "umgewandelt werden, um wirklich das obige Verhalten nachzubilden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "print(list(enumerate(['A', 'B', 'C'])))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Ein häufiger Anwendungsfall einer <code>enumerate</code>-Sequenz ist die Verwendung in einer \n",
    "<code>for</code>-Schleife. Die entstehenden Tupel können unmittelbar in zwei einzelne Variablen \n",
    "übernommen werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "liste = [3, 7, 4, 9]\n",
    "for index, zahl in enumerate(liste):\n",
    "    print(f\"{index+1}. Zahl ist {zahl}\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ein weiterer Anwendungsfall, der häufig auftritt, ist das Zusammenfassen mehrerer Listen zu einer, sodass jedes Element einer Position aus allen Listen in eine Tupel an entsprechender Stelle der neuen Liste gesetzt wird. Es sollen also alle ersten Elemente aller Listen in Form eines Tupels als erstes Element der neuen Liste gesetzt werden, dann alle zweiten Elemente als Tupel als zweites Element der neuen Liste, usw..\n",
    "\n",
    "**Beispiel:** Die Listen `[0, 1, 2]`, `['A', 'B', 'C']` und `['X', 'Y', 'Z']` sollen in einer neuen Liste folgendermaßen zusammengefasst werden: `[(0, 'A', 'X'), (1, 'B', 'Y'), (2, 'C', 'Z')]`\n",
    "\n",
    "Dies lässt sich sehr einfach mit der Built-In-Funktion `zip` realisieren, die beliebig viele Listen als Argumente übergeben bekommt und ein Zip-Objekt zurückgibt, das sich in eine Liste umwandeln lässt, die die jeweiligen Elemente als Tupel enthält, so wie oben gewünscht."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "liste1 = [0, 1, 2]\n",
    "liste2 = ['A', 'B', 'C']\n",
    "liste3 = ['X', 'Y', 'Z']\n",
    "\n",
    "neue_liste = list(zip(liste1, liste2, liste3))\n",
    "\n",
    "print(neue_liste)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`zip` wird am häufigsten genutzt, um mehrere Listen parallel zu durchlaufen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "liste1 = [0, 1, 2]\n",
    "liste2 = ['A', 'B', 'C']\n",
    "liste3 = ['X', 'Y', 'Z']\n",
    "\n",
    "for elem_aus_liste1, elem_aus_liste2, elem_aus_liste3 in zip(liste1, liste2, liste3):\n",
    "    print(f'Die Listen enthalten folgende Elemente: Liste 1: {elem_aus_liste1}, Liste 2: {elem_aus_liste2}, Liste 3: {elem_aus_liste3}')"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Möglich wird dies, weil man in Python die einzelnen Elemente eines Tupels direkt an einzelne Variablen zuweisen kann."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mein_tupel = (1, 2, 3)\n",
    "elem1, elem2, elem3 = mein_tupel\n",
    "print(elem1)\n",
    "print(elem2)\n",
    "print(elem3)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Genauso wird in der obigen `for`-Schleifen mit `zip` pro Position der entsprechende Tupel entnommen und an die Schleifenvariablen der `for`-Schleife aufgeteilt. Die beiden untenstehenden Vorgehensweisen sind also gleich, wenn die zweite auch die schnellere und gebräuchlichere ist."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "liste1 = [0, 1, 2]\n",
    "liste2 = ['A', 'B', 'C']\n",
    "liste3 = ['X', 'Y', 'Z']\n",
    "\n",
    "print('1. Vorgehensweise mit explizitem Zwischenspeichern und Auspacken des Tupels:')\n",
    "for tupel_elem in zip(liste1, liste2, liste3):\n",
    "    elem_aus_liste1, elem_aus_liste2, elem_aus_liste3 = tupel_elem\n",
    "    print(f'Die Listen enthalten folgende Elemente: Liste 1: {elem_aus_liste1}, Liste 2: {elem_aus_liste2}, Liste 3: {elem_aus_liste3}')\n",
    "\n",
    "\n",
    "\n",
    "print('\\n2. Vorgehensweise mit direktem Auspacken des Tupels ohne Zwischenspeichern (gebräuchlichere Variante)')\n",
    "for elem_aus_liste1, elem_aus_liste2, elem_aus_liste3 in zip(liste1, liste2, liste3):\n",
    "    print(f'Die Listen enthalten folgende Elemente: Liste 1: {elem_aus_liste1}, Liste 2: {elem_aus_liste2}, Liste 3: {elem_aus_liste3}')"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.9.9"
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "metadata": {
     "collapsed": false
    },
    "source": []
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
