Browse Source

Add chapter 7.

master
paulusja 2 years ago
parent
commit
9c12a4f513
5 changed files with 832 additions and 0 deletions
  1. 352
    0
      07kapitel/070 Exceptions.ipynb
  2. 234
    0
      07kapitel/070a Uebung.ipynb
  3. 53
    0
      07kapitel/071 Pip.ipynb
  4. 171
    0
      07kapitel/072a Uebung.ipynb
  5. 22
    0
      07kapitel/rise.css

+ 352
- 0
07kapitel/070 Exceptions.ipynb View File

@@ -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",
"<code>try</code> absichert und anschließend mit <code>except</code> 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 <code>except</code>-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 <code>except</code> 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 <code>try</code>-Block noch Aufräumarbeiten durchführen\n",
"ohne zu berücksichtigen, ob ein Fehler aufgetreten ist. Das kann durch <code>finally</code>\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 <code>try</code>-Block muss\n",
"\n",
"* entweder mindestens ein <code>except</code>-Block\n",
"* oder der <code>finally</code>-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 <code>raise</code>."
]
},
{
"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 <code>Exception</code> 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
}

+ 234
- 0
07kapitel/070a Uebung.ipynb View File

@@ -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 <code>get_it_or_none1</code>, 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 <code>None</code>.\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 <code>get_it_or_none2</code> mit der gleichen\n",
"Funktionalität. Allerdings verzichten Sie dieses Mal auf die Prüfung und Fangen\n",
"eine evtl. auftretende Exception, um dann <code>None</code> 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 <code>None</code> 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",
"<code>get</code>, 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",
"<code>dict.get( \\< key \\>, \\< default \\> ) </code>\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
}

+ 53
- 0
07kapitel/071 Pip.ipynb View File

@@ -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
}

+ 171
- 0
07kapitel/072a Uebung.ipynb View File

@@ -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 <code>datetime</code> und\n",
"importieren Sie daraus die Objekte <code>datetime</code> und <code>timedelta</code>.\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
}

+ 22
- 0
07kapitel/rise.css View File

@@ -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%;
}

Loading…
Cancel
Save