diff --git a/07kapitel/070 Exceptions.ipynb b/07kapitel/070 Exceptions.ipynb new file mode 100644 index 0000000..b48a508 --- /dev/null +++ b/07kapitel/070 Exceptions.ipynb @@ -0,0 +1,352 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Software Entwicklung \n", + "\n", + "## Kapitel 7: Ausnahmebehandlung und Paketverwaltung" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### 7.1 Exceptions\n", + "\n", + "#### 7.1.1 Was sind Exceptions?\n", + "\n", + "Immer wieder treten bei der Ausführung von Python-Code Fehler auf. Das kann auf fehlerhafte\n", + "Programmierung hindeuten, z.B. bei folgendem Code:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "liste = []\n", + "print(liste[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Solche Programmierfehler sollten natürlich vermieden werden.\n", + "\n", + "Manchmal ist der Entwickler aber unschuldig, z.B. wenn der Plattenplatz zum Speichern nicht \n", + "mehr ausreicht oder der Anwender ungültige Werte eingibt. Solche Laufzeitfehler führen zu\n", + "Ausnahmen oder *Exceptions*." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "zaehler = int(input(\"Zähler: \"))\n", + "nenner = int(input(\"Nenner: \"))\n", + "print(zaehler/nenner)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Manche dieser Exceptions können auch durch vorheriges Überprüfen nicht vollständig\n", + "ausgeschlossen werden (z.B. Abbruch einer Netzverbindung). Wie kann trotzdem verhindert werden,\n", + "dass das Programm abbricht?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### 7.1.2 Fangen von Exceptions\n", + "\n", + "Ein Programmabruch kann verhindert werden, indem man den kritischen Codeblock mittels\n", + "try absichert und anschließend mit except angibt, was im\n", + "Falle einer Exception zu tun ist." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "try:\n", + " zaehler = int(input(\"Zähler: \"))\n", + " nenner = int(input(\"Nenner: \"))\n", + " print(zaehler/nenner)\n", + "except:\n", + " print(\"Ungültige Eingaben!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Es ist auch möglich, genauere Informationen über die aufgetretene Exception zu erhalten, indem\n", + "sie einer Variablen zugewiesen wird." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "try:\n", + " zaehler = int(input(\"Zähler: \"))\n", + " nenner = int(input(\"Nenner: \"))\n", + " print(zaehler/nenner)\n", + "except Exception as e:\n", + " print(e.__class__)\n", + " print(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Möchte man unterschiedliche Behandlungen für unterschiedliche Exception-Klassen\n", + "hinterlegen, so können mehrere except-Blöcke mit Angabe der Klasse\n", + "verwendet werden." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "try:\n", + " zaehler = int(input(\"Zähler: \"))\n", + " nenner = int(input(\"Nenner: \"))\n", + " print(zaehler/nenner)\n", + "except ValueError:\n", + " print(\"Sie haben keine ganze Zahl eingegeben\")\n", + "except ZeroDivisionError:\n", + " print(\"Divison durch Null\")\n", + "except:\n", + " print(\"Irgendwas anderes\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Die Programmausführung wird nach dem letzten except normal fortgesetzt.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "def division(z, n):\n", + " try:\n", + " zaehler = int(z)\n", + " nenner = int(n)\n", + " return zaehler / nenner\n", + " except:\n", + " print(\"Fehler!\")\n", + " return None\n", + "\n", + "division(1, 0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Gelegentlich möchte man nach dem try-Block noch Aufräumarbeiten durchführen\n", + "ohne zu berücksichtigen, ob ein Fehler aufgetreten ist. Das kann durch finally\n", + "erreicht werden." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "def division(z, n):\n", + " try:\n", + " zaehler = int(z)\n", + " nenner = int(n)\n", + " return zaehler / nenner\n", + " except:\n", + " print(\"Fehler!\")\n", + " finally:\n", + " print(\"Aufräumen\")\n", + " return None\n", + "\n", + "division(1, 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Nach einem try-Block muss\n", + "\n", + "* entweder mindestens ein except-Block\n", + "* oder der finally-Block\n", + "* oder beides\n", + "\n", + "angegeben werden." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### 7.1.3 Werfen von Exceptions\n", + "\n", + "Gelegentlich möchte man auch selbst eine Exception auslösen, wenn man eine\n", + "unzulässige Situation entdeckt. Der Python-Befehl hierzu lautet raise." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "def division(z, n):\n", + " if n == 0:\n", + " raise Exception(\"Division durch Null nicht erlaubt!\")\n", + " return z/n\n", + "\n", + "division(1, 0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Neben der allgemeinen Exception beinhaltet der Python-Standard noch eine\n", + "Vielzahl weiterer [Exception-Klassen](https://docs.python.org/3/library/exceptions.html#exception-hierarchy),\n", + "die auch beim Werfen einer Exception genutzt werden können." + ] + } + ], + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/07kapitel/070a Uebung.ipynb b/07kapitel/070a Uebung.ipynb new file mode 100644 index 0000000..308e1d7 --- /dev/null +++ b/07kapitel/070a Uebung.ipynb @@ -0,0 +1,234 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "pycharm": { + "name": "#%% md\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "_Aufgabe 1_\n", + "\n", + "Schreiben Sie eine Funktion get_it_or_none1, die ein Dictionary und einen\n", + "Schlüsselwert als Parameter erhält. Sie soll den im Dictionary gespeicherten Wert\n", + "zurückgeben, wenn er enthalten ist, andernfalls None.\n", + "\n", + "Vermeiden Sie bei der Implementierung das Auftreten einer Exception, indem Sie vor\n", + "dem Zugriff prüfen, ob der Schlüssel enthalten ist." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def get_it_or_none1(dict_arg, key):\n", + " if key in dict_arg:\n", + " return dict_arg[key]\n", + " else:\n", + " return None\n", + " \n", + "my_dict = {'a': 1, 2: 'b'}\n", + "print(get_it_or_none1(my_dict, 'a'))\n", + "print(get_it_or_none1(my_dict, 'b'))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "_Aufgabe 2_\n", + "\n", + "Implementieren Sie eine Funktion get_it_or_none2 mit der gleichen\n", + "Funktionalität. Allerdings verzichten Sie dieses Mal auf die Prüfung und Fangen\n", + "eine evtl. auftretende Exception, um dann None zurückzugeben." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def get_it_or_none2(dict_arg, key):\n", + " try:\n", + " return dict_arg[key]\n", + " except:\n", + " return None\n", + " \n", + "my_dict = {'a': 1, 2: 'b'}\n", + "print(get_it_or_none2(my_dict, 'a'))\n", + "print(get_it_or_none2(my_dict, 'b'))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "_Aufgabe 3_\n", + "\n", + "Überprüfen Sie die Laufzeit der beiden Varianten, indem Sie jede Funktion\n", + "10000-mal so aufrufen, dass None zurückgegeben wird. Was ist schneller?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "import timeit\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "import timeit\n", + "\n", + "my_dict = {}\n", + "print(timeit.timeit('get_it_or_none1(my_dict, 0)', 'from __main__ import get_it_or_none1, my_dict', number=10000))\n", + "print(timeit.timeit('get_it_or_none2(my_dict, 0)', 'from __main__ import get_it_or_none2, my_dict', number=10000))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "_Aufgabe 4_\n", + "\n", + "Tatsächlich besitzt ein Python-Dictionary eine bisher nicht eingeführte Methode\n", + "get, der neben dem Schlüssel auch ein Default-Wert übergeben werden kann,\n", + "der zurückgegeben wird, wenn der Schlüssel nicht enthalten ist.\n", + "\n", + "dict.get( \\< key \\>, \\< default \\> ) \n", + "\n", + "Überprüfen Sie auch die Laufzeit dieses Ansatzes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "print(timeit.timeit('my_dict.get(0, None)', 'from __main__ import my_dict', number=10000))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Wie erklären Sie sich die Ergebnisse?" + ] + } + ], + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/07kapitel/071 Pip.ipynb b/07kapitel/071 Pip.ipynb new file mode 100644 index 0000000..cd4426b --- /dev/null +++ b/07kapitel/071 Pip.ipynb @@ -0,0 +1,53 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Software Entwicklung \n", + "\n", + "## Kapitel 7: Ausnahmebehandlung und Paketverwaltung\n", + "\n", + "### 7.2 Python Package Index\n", + "\n", + "Eine Vielzahl von frei verfügbaren Paketen\n", + "wird auf der Website [pypi.org](https://pypi.org/) angeboten. Die Installation\n", + "der dort verfügbaren Pakete erledigt man normalerweise mit dem\n", + "Python Paketmanager *Pip*. Der Name ist übrigens ein rekursives (!) Akronym (leider ohne\n", + "Abbruchbedingung) und steht für \" **P**ip **i**nstalliert **P**akete\".\n", + "\n", + "Genaueres zur Nutzung von *Pip* liefert z.B. das Lehrvideo\n", + "[Python Paketmanagement](https://youtu.be/yrgh9TjOzMY). Wir gehen in der Veranstaltung das Prozedere einmal gemeinsam durch.\n" + ] + } + ], + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/07kapitel/072a Uebung.ipynb b/07kapitel/072a Uebung.ipynb new file mode 100644 index 0000000..3bb668b --- /dev/null +++ b/07kapitel/072a Uebung.ipynb @@ -0,0 +1,171 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "pycharm": { + "name": "#%% md\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "_Aufgabe 1_\n", + "\n", + "Schreiben Sie eine Funktion *prim_sum_up_to*, die die Summe aller Primzahlen von 2 bis *n* berechnet, wobei *n* als\n", + "Parameter übergeben wird." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def prim_sum_up_to(end):\n", + " prims = []" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def prim_sum_up_to(n):\n", + " result = 0\n", + " for m in range(2, n+1):\n", + " if is_prim(m):\n", + " result += m\n", + " return result\n", + "\n", + "def is_prim(n):\n", + " divisor = 2\n", + " while divisor * divisor <= n:\n", + " if n % divisor == 0:\n", + " return False\n", + " divisor += 1\n", + " return True\n", + "\n", + "print(prim_sum_up_to(100))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "_Aufgabe 2_\n", + "\n", + "Sobald Sie die Funktion mit größeren *n* aufrufen, steigt die Laufzeit des Programms an. Um zu verhindern,\n", + "dass der Anwender fälschlicherweise annimmt, dass das Programm abgestürzt ist, soll jede Sekunde ein\n", + "Stern ausgegeben werden, bis das Ergebnis vorliegt.\n", + "\n", + "Verwenden Sie hierfür das in der Standardbibliothek enthaltene Modul datetime und\n", + "importieren Sie daraus die Objekte datetime und timedelta.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "from datetime import datetime, timedelta\n", + "\n", + "last_run = datetime.now()\n", + "intervall = timedelta(seconds=1)\n", + "\n", + "def do_only_every_second():\n", + " global last_run\n", + " if last_run + intervall > datetime.now():\n", + " return\n", + " print(\"*\", end='')\n", + " last_run = datetime.now()\n", + "\n", + "\n", + "def is_prim(n):\n", + " divisor = 2\n", + " while divisor * divisor <= n:\n", + " if n % divisor == 0:\n", + " return False\n", + " divisor += 1\n", + " do_only_every_second()\n", + " return True\n", + "\n", + "print(f'\\n{prim_sum_up_to(1000000)}')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Vielleicht können Sie das Prinzip in einem zukünftigen Praktikum nutzen, wenn nicht bei jedem Schleifendurchlauf\n", + "etwas passieren soll...." + ] + } + ], + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/07kapitel/rise.css b/07kapitel/rise.css new file mode 100644 index 0000000..c70f5af --- /dev/null +++ b/07kapitel/rise.css @@ -0,0 +1,22 @@ +body.rise-enabled div.inner_cell>div.input_area { + font-size: 150%; +} + +body.rise-enabled div.output_subarea.output_text.output_result { + font-size: 150%; +} +body.rise-enabled div.output_subarea.output_text.output_stream.output_stdout { + font-size: 150%; +} + +body.rise-enabled div.output_subarea.output_html.rendered_html.output_result { + font-size: 150%; +} + +body.rise-enabled td { + font-size: 120%; +} + +body.rise-enabled th { + font-size: 120%; +} \ No newline at end of file