Skip to content
Snippets Groups Projects
seminar04.ipynb 80.2 KiB
Newer Older
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "# 4: Fallstudie: Schnittstellenentwurf\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "[Chapter 4: Case Study: interface design](http://greenteapress.com/thinkpython/html/thinkpython005.html)\n",
    "\n",
Michel Schwab's avatar
Michel Schwab committed
    "In diesem Kapitel lernen wir anhand einer Fallstudie, wie wir Funktionen entwerfen können, die gut zusammenarbeiten.\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "\n",
    "Wir lernen außerdem das `turtle`-Modul kennen, mit dessen Hilfe wir Graphiken erzeugen können.\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "\n",
    "**Auch hier gilt wieder: Stellen Sie sicher, dass Sie die Konzepte der vorherigen Notebooks verstanden haben bevor Sie fortfahren.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1>Inhaltsverzeichnis<span class=\"tocSkip\"></span></h1>\n",
    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Ihre-Lernziele\" data-toc-modified-id=\"Ihre-Lernziele-1\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>Ihre Lernziele</a></span></li><li><span><a href=\"#Exkurs:-Was-mir-an-Python-gefällt\" data-toc-modified-id=\"Exkurs:-Was-mir-an-Python-gefällt-2\"><span class=\"toc-item-num\">2&nbsp;&nbsp;</span>Exkurs: Was mir an Python gefällt</a></span></li><li><span><a href=\"#Python-für-das-turtle-Modul\" data-toc-modified-id=\"Python-für-das-turtle-Modul-3\"><span class=\"toc-item-num\">3&nbsp;&nbsp;</span>Python für das <code>turtle</code>-Modul</a></span></li><li><span><a href=\"#Das-turtle-Modul\" data-toc-modified-id=\"Das-turtle-Modul-4\"><span class=\"toc-item-num\">4&nbsp;&nbsp;</span>Das <code>turtle</code>-Modul</a></span></li><li><span><a href=\"#Einfache-Wiederholung\" data-toc-modified-id=\"Einfache-Wiederholung-5\"><span class=\"toc-item-num\">5&nbsp;&nbsp;</span>Einfache Wiederholung</a></span></li><li><span><a href=\"#4-Übungen\" data-toc-modified-id=\"4-Übungen-6\"><span class=\"toc-item-num\">6&nbsp;&nbsp;</span>4 Übungen</a></span><ul class=\"toc-item\"><li><span><a href=\"#Verkapselung\" data-toc-modified-id=\"Verkapselung-6.1\"><span class=\"toc-item-num\">6.1&nbsp;&nbsp;</span>Verkapselung</a></span></li><li><span><a href=\"#Verallgemeinerung\" data-toc-modified-id=\"Verallgemeinerung-6.2\"><span class=\"toc-item-num\">6.2&nbsp;&nbsp;</span>Verallgemeinerung</a></span></li><li><span><a href=\"#Schnittstellenentwurf\" data-toc-modified-id=\"Schnittstellenentwurf-6.3\"><span class=\"toc-item-num\">6.3&nbsp;&nbsp;</span>Schnittstellenentwurf</a></span></li><li><span><a href=\"#Refactoring\" data-toc-modified-id=\"Refactoring-6.4\"><span class=\"toc-item-num\">6.4&nbsp;&nbsp;</span>Refactoring</a></span></li></ul></li><li><span><a href=\"#Ein-Entwicklungsplan\" data-toc-modified-id=\"Ein-Entwicklungsplan-7\"><span class=\"toc-item-num\">7&nbsp;&nbsp;</span>Ein Entwicklungsplan</a></span></li><li><span><a href=\"#Docstring\" data-toc-modified-id=\"Docstring-8\"><span class=\"toc-item-num\">8&nbsp;&nbsp;</span>Docstring</a></span></li><li><span><a href=\"#Debugging\" data-toc-modified-id=\"Debugging-9\"><span class=\"toc-item-num\">9&nbsp;&nbsp;</span>Debugging</a></span></li><li><span><a href=\"#Glossar\" data-toc-modified-id=\"Glossar-10\"><span class=\"toc-item-num\">10&nbsp;&nbsp;</span>Glossar</a></span></li><li><span><a href=\"#Übung\" data-toc-modified-id=\"Übung-11\"><span class=\"toc-item-num\">11&nbsp;&nbsp;</span>Übung</a></span><ul class=\"toc-item\"><li><span><a href=\"#Aufgabe-1\" data-toc-modified-id=\"Aufgabe-1-11.1\"><span class=\"toc-item-num\">11.1&nbsp;&nbsp;</span>Aufgabe 1</a></span></li><li><span><a href=\"#Aufgabe-2\" data-toc-modified-id=\"Aufgabe-2-11.2\"><span class=\"toc-item-num\">11.2&nbsp;&nbsp;</span>Aufgabe 2</a></span></li><li><span><a href=\"#Aufgabe-3\" data-toc-modified-id=\"Aufgabe-3-11.3\"><span class=\"toc-item-num\">11.3&nbsp;&nbsp;</span>Aufgabe 3</a></span></li><li><span><a href=\"#Aufgabe-4\" data-toc-modified-id=\"Aufgabe-4-11.4\"><span class=\"toc-item-num\">11.4&nbsp;&nbsp;</span>Aufgabe 4</a></span></li><li><span><a href=\"#Aufgabe-5\" data-toc-modified-id=\"Aufgabe-5-11.5\"><span class=\"toc-item-num\">11.5&nbsp;&nbsp;</span>Aufgabe 5</a></span></li></ul></li></ul></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ihre Lernziele\n",
    "\n",
    "Beschreiben Sie in 2-3 Stichpunkten kurz was Sie im Seminar heute lernen wollen. Klicken Sie dazu doppelt auf diesen Text und bearbeiten Sie dann den Text:\n",
    "\n",
    "- \n",
    "- \n",
    "- \n",
    "\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "## Exkurs: Was mir an Python gefällt\n",
    "\n",
    "Man kann schnell und einfach ein Programm aufschreiben und testen. Man muss es weder kompilieren, noch viel \"unnötige\" Syntax kennen:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def factorial(n):\n",
    "    if n < 2:\n",
    "        return 1\n",
    "    else:\n",
    "        return n * factorial(n - 1)\n",
    "\n",
    "print(factorial(5))"
   ]
  },
Miriam Brauer's avatar
Miriam Brauer committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "## Das `turtle`-Modul\n",
    "Führen Sie den folgenden Code aus, um zu testen, ob das `turtle`-Modul installiert ist.\n",
    "\n",
    "Es sollte sich ein Fenster öffnen, in dem ein kleiner Pfeil zu sehen ist -- dieser repräsentiert die Schildkröte (\"turtle\"). Schließen Sie das Fenster. (Danach erscheint ggf. eine Fehlermeldung -- nicht erschrecken, diese ist im Allgemeinen harmlos.) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import turtle\n",
    "bob = turtle.Turtle()\n",
    "turtle.mainloop()\n",
    "turtle.bye()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "      \n",
    "In Jupyter gibt es manchmal Probleme mit dem `turtle`-Modul. **Wichtig ist, dass Sie stets das Turtle-Fenster schließen.** Manchmal hilft es, den Code nochmal auszuführen oder im Kernel-Menü den Punkt \"Restart & Clear Output\" aufzurufen. Wenn es gar nicht klappt, dann nutzen Sie für die Turtle-Programmierung bitte nicht Jupyter-Notebooks, sondern Python-Dateien und führen diese direkt mit Python aus.   \n",
    "Manchmal vergisst Jupyter Notebooks auch, dass bereits eine Schildkröte existiert, in diesem Fall initialisieren Sie diese bitte einfach am Anfang des gewünschten Code-Blocks.        \n",
    "[diese Webseite](https://www.pythonsandbox.com/turtle) funktioniert für das turtle Modul gegebenenfalls besser als die Jupyter Notebooks, die bei Fehlern teilweise abstürzen. Sie können also dort programmieren und erst am Ende den Code hier ins Notebook einfügen.\n",
    "\n",
    "\n",
    "Probieren Sie nun Folgendes (kopieren Sie den Code in den folgenden Block):"
schwabmi's avatar
schwabmi committed
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "```python\n",
    "import turtle\n",
    "bob = turtle.Turtle()\n",
    "print(bob)\n",
    "turtle.mainloop() \n",
schwabmi's avatar
schwabmi committed
    "turtle.bye()\n",
    "```"
Miriam Brauer's avatar
Miriam Brauer committed
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Das `turtle`-Modul (mit kleinem `t`) stellt eine Funktion `Turtle` (mit großem `T`) bereit, die ein Turtle-Objekt erzeugt -- dieses weisen wir einer Variable mit dem Namen `bob` zu. Wenn wir `bob` mit `print` ausgeben, erhalten wir eine Ausgabe ähnlich\n",
    "\n",
    "```\n",
    "<turtle.Turtle object at 0xb7bfbf4c>\n",
    "```\n",
    "\n",
Michel Schwab's avatar
Michel Schwab committed
    "Das bedeutet, dass `bob` auf ein Objekt vom Typ `Turtle` verweist, wie es im `turtle`-Modul definiert wird.\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "Der Aufruf von `mainloop` weist das Fenster an, auf Nutzeraktivität zu warten. In diesem Fall kann man als NutzerIn allerdings kaum mehr tun, als das Fenster zu schließen.\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "Sobald wir eine Schildkröte erzeugt haben, können wir eine **Methode** aufrufen, um die Schildkröte im Fenster zu bewegen. Eine Methode ist einer Funktion ähnlich, aber die Syntax ist etwas anders. Zum Beispiel können wir die Schildkröte mit dem Aufruf von \n",
    "\n",
    "```python\n",
    "bob.fd(100)\n",
    "```\n",
    "\n",
    "nach vorne bewegen. Die Methode `fd` gehört zu dem Turtle-Objekt welches wir `bob` nennen. Wenn wir die Methode aufrufen, bitten wir `bob` nach vorne zu gehen (**f**orwar**d**).\n",
    "\n",
    "Das Argument von `fd` ist eine Strecke in Pixeln (den Bildpunkten auf dem Monitor), daher hängt die Entfernung, die `bob` geht, von unserer Monitorauflösung ab.\n",
    "\n",
Michel Schwab's avatar
Michel Schwab committed
    "Andere Methoden, die wir auf einer Schildkröte aufrufen können, sind `bk` für eine Rückwärtsbewegung (**b**ac**k**ward), `lt` für eine Linksdrehung (**l**eft **t**urn) und `rt` für eine Rechtsdrehung (**r**ight **t**urn). Das Argument für `lt` und `rt` ist ein Winkel in Grad.\n",
Michel Schwab's avatar
Michel Schwab committed
    "Jede Schildkröte hat außerdem einen \"Stift\", der entweder \"oben\" oder \"unten\" ist. Wenn der Stift unten ist, berührt der Stift sozusagen das Papier und die Schildkröte hinterlässt eine Spur wenn sie sich bewegt. Die Methoden `pu` und `pd` stehen für \"Stift hoch\" (**p**en **u**p) und \"Stift herunter\" (**p**en **d**own). Diese beiden Methoden brauchen kein Argument als Input.\n",
    "\n",
    "Fügen Sie die folgenden Zeilen zu Ihrem Programm hinzu, um einen rechten Winkel zu zeichnen (nachdem Sie `bob` erzeugt haben und bevor Sie `mainloop` aufrufen):\n",
    "\n",
    "```python\n",
    "bob.fd(100)\n",
    "bob.lt(90)\n",
    "bob.fd(100)\n",
    "```\n",
    "\n",
    "Wenn Sie dieses Programm ausführen, sollte sich `bob` zunächst nach Osten und dann nach Norden bewegen und dabei zwei Strecken zeichnen.\n",
    "\n",
    "Verändern Sie ihr Programm jetzt, so dass `bob` ein Quadrat zeichnet. Fahren Sie erst mit dem Kurs fort, wenn es funktioniert.\n",
    "\n",
    "\n",
    "<a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n",
    "\n",
    "(Quelle: Jason Eppink, Flickr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "## Einfache Wiederholung\n",
Michel Schwab's avatar
Michel Schwab committed
    "Vielleicht haben Sie Folgendes geschrieben:\n",
    "\n",
    "```python\n",
    "bob.fd(100)\n",
    "bob.lt(90)\n",
    "\n",
    "bob.fd(100)\n",
    "bob.lt(90)\n",
    "\n",
    "bob.fd(100)\n",
    "bob.lt(90)\n",
    "\n",
    "bob.fd(100)\n",
    "```\n",
    "\n",
    "Wir können das gleiche deutlich knapper mit einer `for`-Schleife formulieren. Testen Sie folgendes: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(4):\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "    print('Hello!')\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sie sollten folgende Ausgabe sehen:\n",
    "\n",
    "```\n",
    "Hello!\n",
    "Hello!\n",
    "Hello!\n",
    "Hello!\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### `range()`\n",
    "\n",
    "Die Funktion `range()` erstellt eine Liste mit Werten. Der erste Wert startet bei 0 und zählt dann die Anzahl an Zahlen hoch, die wir der Funktion als Argument übergeben. Wir kommen also bei einer Zahl eins kleiner als unser vorgegebener Endwert raus.\n",
    "\n",
    "*Beispiel*:\n",
    "\n",
    "`range(2) - [0,1]`\n",
    "\n",
    "`range(5) -> [0,1,2,3,4]`\n",
    "\n",
    "\n",
    "#### `for`-Schleife\n",
    "\n",
    "Die `for`-Schleife hat folgende Syntax:\n",
    "\n",
    "<font color = green>for</font> <font color = black>Variable</font> <font color = green>in</font>  <font color = purple>Sequenz</font>:\n",
    "```\t\n",
    "    Anweisung_1\n",
    "    ...\n",
    "\tAnweisung_n\n",
    "\n",
    "Die Schleife durchläuft nun die Liste mit jedem Schleifendurchlauf und die Variable `Variable` nimmt in jedem Durchlauf den nächsten Wert in der Liste an. Der Schleifenkörper besteht aus einer beliebig großen Anzahl von Anweisungen, die **eingerückt** (vier Leerzeichen bzw. einmal die tabulator-Taste) sein müssen.\n",
    "\n",
    "FYI: Der Name der Variablen kann frei gewählt werden. Falls es nur eine Zahl darstellt, wird häufig `i` genutzt.\n",
    "\n",
    "*Beispiele:*\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(3):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(4): # range() erstellt die Liste [0,1,2,3]\n",
    "    print(str(i) + \"-ter Schleifendurchlauf; i nimmt den Wert:\" ,  i ,\"an.\") # Anweisung ist eingerückt\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Manchmal nutzt man die Variable `i` gar nicht, sondern nutzt range() und die `for`-Schleife aus, um Code zu wiederholen. \n",
    "\n",
    "`for i in range(4):` durchläuft die Schleife viermal,\n",
    "\n",
    "`for i in range(10):` durchläuft die Schleife zehnmal.\n",
    "\n",
    "Die Zahl in `range()` kann also so interpretiert werden, wie häufig der Code wiederholt wird.\n",
    "\n",
    "*Beispiele:* "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for j in range(10):\n",
    "    print(\"Hello\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for too_long_variable_name in range(4):\n",
    "    print(\"a\")\n",
    "    print(\"\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "Das ist die einfachste Art und Weise, eine `for`-Schleife zu verwenden. Wir werden uns das später ausführlicher anschauen. Für jetzt sollte das reichen, damit Sie Ihr Programm zum Zeichnen eines Quadrats vereinfachen können. Bitte fahren Sie erst fort, wenn Sie ihr Programm mit Hilfe der `for`-Schleife vereinfacht haben.\n",
    "\n",
    "Es sollte sich ein Fenster öffnen, in dem ein kleiner Pfeil zu sehen ist -- dieser repräsentiert die Schildkröte (\"turtle\"). Schließen Sie das Fenster. (Danach erscheint ggf. eine Fehlermeldung -- nicht erschrecken, diese ist im Allgemeinen harmlos.) \n",
    "\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\"> Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Die `for`-Schleife besteht aus insgesamt 3 Zeilen. Dem Code, der sich immer wieder wiederholt (schauen Sie sich dazu an, was Sie im vorherigen Schritt geschrieben haben) und der Anweisung, die angibt, wie häufig sich der Code wiederholt. \n",
    "\n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "Probieren Sie nun Folgendes (im folgenden Block, den Sie dann schrittweise ergänzen):\n",
    "\n",
    "<a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n",
    "\n",
    "(Quelle: Jason Eppink, Flickr)\n",
    "\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "Folgende `for`-Schleife zeichnet ein Quadrat:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle\n",
    "\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "bob=turtle.Turtle()\n",
    "\n",
    "for i in range(4):\n",
    "    bob.lt(90)\n",
    "\n",
    "turtle.mainloop() \n",
    "turtle.bye()"
Miriam Brauer's avatar
Miriam Brauer committed
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dieser Code ist etwas anders als der vorherige Code zum Zeichnen eines Quadrats. Nachdem die letzte Seite des Quadrats gezeichnet wird, wird noch eine 90° Drehung durchgeführt. Diese zusätzliche Drehung kostet etwas Zeit, aber der Code ist einfacher, wenn in jedem Schleifendurchlauf die gleiche Folge von Anweisungen ausgeführt wird. Ein Nebeneffekt ist, dass die Schildkröte am Ende wieder in der Ausgangsposition mit Blick zur Ausgangsrichtung steht."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "##  4 Übungen\n",
Michel Schwab's avatar
Michel Schwab committed
    "In den folgenden Abschnitten folgen einige Übungen zur \"Schildkrötenwelt\". Sie sollten Ihnen Spaß bereiten, haben aber auch einen Sinn. Versuchen Sie diesen herauszufinden und gehen Sie abschnittweise vor. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "### Verkapselung\n",
Michel Schwab's avatar
Michel Schwab committed
    " - **Aufgabe 1:** Schreiben Sie eine Funktion `square`, die einen Parameter  `t` erwartet, welcher eine Schildkröte ist. Die Funktion soll die Schildkröte nutzen, um ein Quadrat zu zeichnen.\n",
schwabmi's avatar
schwabmi committed
    " \n",
    " \n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Sie haben diese Funktion bereits geschrieben. Wie können Sie die Anweisungen verkapseln?\n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Schreiben Sie den Kopf der Funktion, überlegen Sie wie Sie die Parameterschildkröte nennen wollen?\n",
    "\n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Stellen Sie sicher, dass die Schildkröte in der Funktion immer gleich heißt (genau wie das Argument, das im Funktionsaufruf übergeben wird), sodass alle Anweisungen ausgeführt werden \n",
    "\n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    " - **Aufgabe 2:** Schreiben Sie einen Funktionsaufruf, der `bob` als Argument an `square` übergibt und rufen Sie ihr Programm auf.\n",
    " \n",
    " \n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\"> Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Initialisieren Sie die Schildkröte `bob`, da es sein kann, dass die Schildkröte nicht gefunden wird. Übergeben Sie `square` die Variable `bob`.\n",
    "\n",
    "  </div>       \n",
    "</details>"
Miriam Brauer's avatar
Miriam Brauer committed
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n",
    "\n",
    "(Quelle: Jason Eppink, Flickr)\n",
    "\n",
    "In der ersten Aufgabe sollten Sie den Code zum Zeichnen eines Quadrates in eine Funktion packen und dann in Aufgabe 2 die Funktion aufrufen, indem Sie eine Schildkröte als Argument an die Funktion übergeben. So könnte eine mögliche Lösung aussehen:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "bob = turtle.Turtle()\n",
Michel Schwab's avatar
Michel Schwab committed
    "\n",
    "def square(t):\n",
    "    for i in range(4):\n",
    "        t.fd(100)\n",
    "        t.lt(90)\n",
    "\n",
Michel Schwab's avatar
Michel Schwab committed
    "square(bob)\n",
    "\n",
    "turtle.mainloop() \n",
    "turtle.bye()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "Die beiden innersten Anweisungen (`t.fd` und `t.lt`) sind doppelt eingerückt, weil sie innerhalb der `for`-Schleife sind, die wiederum innerhalb der Funktionsdefinition steht. Die übernächste Zeile (`square(bob)`) ist wieder bündig mit dem linken Rand ausgerichtet, also sowohl außerhalb der `for`-Schleife, als auch außerhalb der Funktionsdefinition.\n",
    "\n",
    "Innerhalb der Funktion verweist `t` auf die gleiche Schildkröte `bob`, so dass `t.lt(90)` die gleiche Auswirkung hat wie `bob.lt(90)`. Hätten wir dann in der Funktion nicht direkt `bob` aufrufen können oder den Parameter stattdessen `bob` nennen können? Prinzipiell schon, aber die Idee ist, dass `t` irgendeine Schildkröte sein kann, nicht nur `bob`, so dass wir beispielsweise eine zweite Schildkröte erzeugen und sie als Argument an `square` übergeben können:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "alice = turtle.Turtle()\n",
Michel Schwab's avatar
Michel Schwab committed
    "square(alice)\n",
    "\n",
    "turtle.mainloop() \n",
    "turtle.bye()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "Ein Stück Quellcode in eine Funktion zu packen, nennt man \"Verkapselung\" (Englisch: *encapsulation*). Ein Vorteil der Verkapselung ist, dass für ein Stück Code ein Name vergeben wird, der wie eine Art Dokumentation wirkt, also sagt, was der Code macht. Ein anderer Vorteil ist, dass wir den Code leicht wiederverwenden können, denn es ist deutlich praktischer, eine Funktion zweimal aufzurufen, als den Quellcode im Funktionsrumpf zu kopieren.\n",
    "\n",
    "\n",
    "![I honestly didn't think you could even USE emoji in variable names. Or that there were so many different crying ones.](https://imgs.xkcd.com/comics/code_quality.png)\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "([Code Quality](https://xkcd.com/1513/), Randall Munroe) [Erklärung des Comics](https://www.explainxkcd.com/wiki/index.php/1513:_Code_Quality) falls Sie mehr lesen wollen."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "### Verallgemeinerung\n",
    "\n",
    "- **Aufgabe 3:** Ergänzen Sie die Funktion `square` um einen weiteren Parameter namens `length`. Ändern Sie den Rumpf der Funktion so, dass die Seitenlänge des gezeichneten Quadrats `length` entspricht. Passen Sie dann den Funktionsaufruf an, sodass ein weiteres Argument als Länge übergeben wird. Starten Sie ihr Programm noch einmal und testen Sie es mit verschiedenen Werten für die Länge. \n",
    "\n",
schwabmi's avatar
schwabmi committed
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-info\"> Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Kopieren Sie die Funktion aus dem vorherigen Abschnitt oder arbeiten Sie in dem bereits geschriebenen Code. So können Sie vermeiden, dass Fehler entstehen, die im vorherigen Abschnitt noch nicht vorhanden waren.\n",
    "      \n",
    "  </div>       \n",
    "</details>\n"
Miriam Brauer's avatar
Miriam Brauer committed
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Der nächste Schritt ist, einen Parameter `length` zu `square` hinzuzufügen. Hier ist eine Lösung:\n",
    "\n",
    "<a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n",
    "\n",
    "(Quelle: Jason Eppink, Flickr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle\n",
    "\n",
    "bob=turtle.Turtle()\n",
    "\n",
    "def square(t, length):\n",
    "    '''zeichnet ein Quadrat der Länge length'''\n",
    "    for i in range(4):\n",
    "        t.fd(length)\n",
    "        t.lt(90)\n",
    "\n",
Michel Schwab's avatar
Michel Schwab committed
    "square(bob, 400)\n",
    "\n",
    "turtle.mainloop() \n",
    "turtle.bye()"
Miriam Brauer's avatar
Miriam Brauer committed
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Das Hinzufügen des Parameters stellt eine **Verallgemeinerung** dar; denn die Funktion wird dadurch allgemeiner: vorher hatte das gezeichnete Quadrat immer die gleiche Größe, jetzt kann es jede beliebige Größe haben.\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "- **Aufgabe 4:** Kopieren Sie die Definition der Funktion `square` und benennen Sie die Kopie in `polygon` um. Fügen Sie einen weiteren Parameter namens `n` hinzu und ändern Sie den Funktionsrumpf so, dass ein n-seitiges [reguläres Vieleck](https://de.wikipedia.org/wiki/Regelm%C3%A4%C3%9Figes_Polygon) (Polygon) gezeichnet wird. \n",
    "\n",
    "\n",
    "**Hinweis:** Die Außenwinkel eines n-seitigen Vielecks betragen `360/n` Grad.\n",
schwabmi's avatar
schwabmi committed
    "\n",
    "Versuchen Sie zunächst selber die Aufgabe zu lösen, anbei folgen ein paar Hinweise, die Sie verwenden können. \n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Ändern Sie den Funktionskopf, indem Sie den Parameter `n` hinzufügen.\n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Anders als bei einem Quadrat ist der Winkel nicht mehr `90`Grad. Berechnen Sie den Außenwinkel und speichern Sie ihn in einer Variable. Verändern Sie die Drehung so, dass Sie nicht immer 90° beträgt, sondern an den berechneten Winkel angepasst ist.\n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Nun müssen wir noch anpassen, dass die Schildkröte nicht jedes Mal vier Seiten zeichnet, sondern soviele Seiten zeichnet wie es Ecken gibt. Dazu müssen wir die Schleife an einer Stelle ändern.\n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>"
Miriam Brauer's avatar
Miriam Brauer committed
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dieser Schritt ist ebenfalls eine Verallgemeinerung. Anstatt eines Quadrates kann die Funktion `polygon` nun reguläre Vielecke mit beliebig vielen Seiten zeichnen. So könnte eine Lösung aussehen:\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "\n",
    "<a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "(Quelle: Jason Eppink, Flickr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle\n",
    "\n",
    "bob=turtle.Turtle()\n",
    "\n",
    "def polygon(t, n, length):\n",
    "    '''zeichnet ein Vieleck mit n Ecken und der Seitenlänge length'''\n",
    "    angle = 360 / n\n",
    "    for i in range(n):\n",
    "        t.fd(length)\n",
    "        t.lt(angle)\n",
    "\n",
Michel Schwab's avatar
Michel Schwab committed
    "polygon(bob, 7, 70)\n",
    "\n",
    "turtle.mainloop() \n",
    "turtle.bye()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dieses Beispiel zeichnet ein siebenseitiges Vieleck mit einer Seitenlänge von 70.\n",
    "\n",
    "Bei einer Funktion mit mehr als nur ein paar Argumenten kann man leicht vergessen, was die Argumente bedeuten oder in welcher Reihenfolge sie angegeben werden müssen. In diesem Fall ist es eine gute Idee, die Namen der Parameter in der Argumentliste explizit anzugeben:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle\n",
    "\n",
    "bob=turtle.Turtle()\n",
    "\n",
    "polygon(bob, n=7, length=70)\n",
    "\n",
    "turtle.mainloop() \n",
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Diese werden **Schlüsselwortargumente** genannt, denn Sie enthalten die Parameter als \"Schlüsselwörter\" (diese sollten nicht mit Python-Schlüsselwörtern wie z.B. `while` oder `def` verwechselt werden).\n",
    "\n",
    "Durch diese Syntax wird das Programm lesbarer. Sie erinnert uns auch daran, wie Argumente und Parameter funktionieren: Wenn wir eine Funktion aufrufen, werden unsere Argumente den Parametern zugewiesen.\n",
    "\n",
    "\n",
    "Der nächste Schritt ist, eine Funktion `circle` zu schreiben, die einen Radius `r` als Parameter erwartet."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "### Schnittstellenentwurf\n",
Michel Schwab's avatar
Michel Schwab committed
    "- **Aufgabe 5:** Schreiben Sie eine Funktion `circle`, die eine Schildkröte `t` und einen Radius `r` als Parameter erwartet und annähernd einen Kreis zeichnet, indem sie die Funktion `polygon` mit einer geeigneten Seitenlänge und Anzahl von Seiten aufruft. Testen Sie ihre Funktion mit verschiedenen Werten für `r`.\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "\n",
schwabmi's avatar
schwabmi committed
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-info\"> Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Die Formel für die Umfangsberechnung ist: $2 * π * r$.\n",
    "      \n",
    "      Finden Sie den Umfang des Kreises heraus und stellen Sie sicher, dass $length * n$ gleich dem Umfang ist. \n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "Wie gewohnt folgen nun einige Hinweise. Versuchen Sie zunächst die Aufgabe ohne Hilfe zu lösen.\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Schreiben Sie zunächst den Kopf der Funktion `circle`. Welche Parameter müssen der Funktion übergeben werden?  \n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Anschließend können Sie sich mit dem Rumpf der Funktion `circle` beschäftigen. Hier wollen wir `polygon` aufrufen. Welche Informationen müssen Sie an `polygon` übergeben? Schauen Sie sich die Funktion an, um rauszufinden, welche Parameter Sie übergeben müssen. Überlegen Sie, wie Sie aus den Parametern der Funktion `circle` die benötigten Werte berechnen können. \n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "      \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Berechnen Sie den **Umfang** des Kreises ($2 * π * r$). $π$ können Sie entweder mit $3.14$ angeben oder mit dem `math`-Modul importieren (`import math` und `math.pi` sind hier hilfreich).\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "  </div>       \n",
    "</details>\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Legen Sie die Anzahl an Seiten ( `n` ) fest, die Sie verwenden wollen. Wir schauen uns später an, wie Sie `n` in Abhängigkeit des Kreises berechnen können. Wenn Sie dafür eine Idee haben verwenden Sie diese gerne, ansonsten können Sie zunächst eine beliebige Anzahl an Seiten festlegen. (Wird diese Zahl zu groß, wird Python sehr langsam und stürzt eventuell ab, ist sie zu klein gewählt sieht der Kreis sehr eckig aus. Probieren Sie verschiedene Werte für `n` zwischen 0 und 80 und wählen Sie einen Wert, der Ihnen geeignet scheint, zb. `n=50`.\n",
    "  \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Berechnen Sie nun die Länge `length` jeder einzelnen Seite in Abhängigkeit vom Umfang und der Anzahl an Seiten `n`, indem Sie den Umfang durch die Anzahl an Seiten teilen.\n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>\n"
Miriam Brauer's avatar
Miriam Brauer committed
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hier ist eine einfache Lösung von `circle`, die die Funktion `polygon` nutzt, um ein reguläres 50-seitiges Vieleck zu zeichnen:\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "\n",
    "<a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n",
    "\n",
    "(Quelle: Jason Eppink, Flickr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle, math\n",
    "\n",
    "\n",
    "def polygon(t, n, length):\n",
    "    '''zeichnet ein Vieleck mit n Ecken und der Seitenlänge length'''\n",
Michel Schwab's avatar
Michel Schwab committed
    "    angle = 360 / n\n",
    "    for i in range(n):\n",
    "        t.fd(length)\n",
    "        t.lt(angle)\n",
    "        \n",
    "\n",
    "def circle(t, r):\n",
    "    '''zeichnet einen Kreis mit Radius r'''\n",
    "    circumference = 2 * math.pi * r\n",
    "    n = 50\n",
    "    length = circumference / n\n",
    "    polygon(t, n, length)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import turtle\n",
    "\n",
    "bob=turtle.Turtle()\n",
    "\n",
    "circle(bob, r=20)\n",
    "\n",
    "turtle.mainloop() \n",
    "turtle.bye()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Die erste Zeile berechnet den Umfang eines Kreises mit dem Radius `r` mit Hilfe der Formel 2 π r. Da wir `math.pi` nutzen wollen, müssen wir zunächst `math` importieren. Die Konvention ist, dass `import`-Anweisungen stets am Anfang eines Python-Programms stehen.\n",
    "\n",
Michel Schwab's avatar
Michel Schwab committed
    "Weil `n` die Anzahl der Liniensegmente in unserer Näherung eines Kreises ist, ist `length` die Länge jedes einzelnen Segmentes. Daher zeichnet `polygon` ein reguläres 50-seitiges Vieleck als Näherung eines Kreises mit Radius `r`.\n",
    "\n",
    "Eine Beschränkung dieser Lösung ist, dass `n` eine Konstante ist. Daher sind für sehr große Kreise die Liniensegmente zu lang und für kleine Kreise verschwenden wir Zeit mit dem Zeichnen sehr kleiner Segmente. Eine Lösung wäre, die Funktion zu verallgemeinern und `n` als Parameter hinzuzufügen. Dies gäbe dem Nutzer (wer auch immer `circle` aufruft) mehr Kontrolle, aber die Schnittstelle wäre weniger aufgeräumt.\n",
    "\n",
    "Die **Schnittstelle** (Englisch *Interface*) einer Funktion ist eine Zusammenfassung dessen, wie die Funktion genutzt wird: Was sind ihre Parameter? Was macht die Funktion? Was ist ihr Rückgabewert? etc. Eine Schnittstelle ist  \"aufgeräumt\", wenn sie der/m Aufrufenden ermöglicht das zu tun, was er oder sie möchte, ohne sich mit unnötigen Details beschäftigen zu müssen.\n",
    "\n",
    "In unserem Beispiel gehört `r` zur Schnittstelle, da es den Kreis beschreibt, der gezeichnet werden soll. Dagegen ist `n` weniger passend, denn es gehört zu den Details, wie der Kreis gezeichnet wird. \n",
    "\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "Anstatt die Schnittstelle zu \"verunreinigen\" ist es besser, einen passenden Wert für `n` in Abhängigkeit vom Umfang des Kreises zu wählen:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle, math\n",
    "\n",
    "\n",
    "def polygon(t, n, length):\n",
    "    '''zeichnet ein Vieleck mit n Ecken und der Seitenlänge length'''\n",
Michel Schwab's avatar
Michel Schwab committed
    "    angle = 360 / n\n",
    "    for i in range(n):\n",
    "        t.fd(length)\n",
    "        t.lt(angle)\n",
    "        \n",
    "def circle(t, r):\n",
    "    '''zeichnet einen Kreis mit Radius r'''\n",
    "    circumference = 2 * math.pi * r\n",
    "    n = int(circumference / 3) + 3 #n in Abhängigkeit vom Umfang berechnet\n",
    "    length = circumference / n\n",
    "    polygon(t, n, length)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
schwabmi's avatar
schwabmi committed
    "Jetzt ist die Anzahl der Liniensegmente eine ganze Zahl, die nah bei `Umfang/3` liegt, sodass die Länge jedes Segments ungefähr 1/3 beträgt. Das ist klein genug, damit der Kreis gut aussieht, aber auch groß genug, um eine effiziente Zeichnung zu ermöglichen und passt daher für jede Kreisgröße. \n",
Miriam Brauer's avatar
Miriam Brauer committed
    "Wir  addieren 3, damit das Vieleck mindestens drei Seiten hat.\n",
schwabmi's avatar
schwabmi committed
    "### Refactoring\n",
    "- **Aufgabe 6:** Schreiben Sie eine verallgemeinerte Funktion `circle`, die Sie `arc` nennen. Diese erwartet einen zusätzlichen Parameter `angle`, welcher angibt, welcher Anteil des Kreises gezeichnet werden soll. Die Funktion `arc` soll also einen [Kreisbogen](https://de.wikipedia.org/wiki/Kreisbogen) zeichnen. Der Wert von `angle` ist dabei in Grad, so dass für `angle=360` ein vollständiger Kreis gezeichnet werden sollte.\n"
Miriam Brauer's avatar
Miriam Brauer committed
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Als wir `circle` geschrieben haben, konnten wir `polygon` wiederverwenden, denn ein regelmäßiges Vieleck mit vielen Seiten ist eine gute Näherung für einen Kreis. Aber mit der Funktion `arc` klappt das nicht so einfach - wir können kein Vieleck und keinen Kreis nutzen, um einen Kreisbogen zu zeichnen.\n",
    "\n",
schwabmi's avatar
schwabmi committed
    "Eine Alternative ist, mit einer Kopie von `polygon` zu beginnen und diese zu `arc` zu verändern.\n",
    "Hier finden Sie einige Hinweise wie Sie dabei vorgehen könnten:\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Schreiben Sie zunächst den Kopf der Funktion `arc`. Welche Parameter müssen der Funktion übergeben werden? Kopieren Sie den Rumpf von `polygon` unter den Funktionskopf als Basis, die Sie nun verändern.  \n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "      \n",
    "Die Formel zur Berechnung der Länge eines Kreisbogens ist: $2 * π * r * angle / 360$. Speichern Sie dies in einer Variabble und geben Sie dieser einen passenden Namen.\n",
schwabmi's avatar
schwabmi committed
    "   \n",
    "   </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Berechnen Sie `n` in Abhängigkeit der Länge des Kreisbogens, analog zu der Berechnung von `n` in `circle`.  Berechnen Sie analog zu `length` in `circle` die Schrittlänge mit Hilfe von `n` und der Länge des Kreisbogens.\n",
schwabmi's avatar
schwabmi committed
    "  </div>       \n",
    "</details>\n",
    "\n",
    "<details>\n",
    "    <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n",
    "  <div class=\"alert alert-info\" role=\"alert\">\n",
    "\n",
    "Berechnen Sie den Winkel der Drehung in Abhängigkeit vom eingegebenen Winkel und der Anzahl an gezeichneten Abschnitten `n` analog zur Berechnung der Schrittlänge. Nun sollten Sie alle notwendigen Zahlen haben, verwenden Sie diese für die Schleife, die in `polygon` geschrieben wurde.\n",
schwabmi's avatar
schwabmi committed
    "      \n",
    "  </div>       \n",
    "</details>\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "Das Ergebnis könnte dann so aussehen:\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "\n",
    "\n",
    "<a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n",
    "\n",
    "(Quelle: Jason Eppink, Flickr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle \n",
    "\n",
    "def arc(t, r, angle):\n",
    "    '''zeichnet einen Kreisbogen in Abhängigkeit von Radius r und Winkel angle'''\n",
    "    arc_length = 2 * math.pi * r * angle / 360\n",
    "    n = int(arc_length / 3) + 1\n",
    "    step_length = arc_length / n\n",
    "    step_angle = angle / n\n",
    "    \n",
    "    for i in range(n):\n",
    "        t.fd(step_length)\n",
Michel Schwab's avatar
Michel Schwab committed
    "        t.lt(step_angle)\n",
    "        \n",
    "        \n",
    "#turtle.mainloop()\n",
    "#turtle.bye()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Der folgende Funktionsaufruf sollte jetzt einen Drittel eines Kreises zeichnen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import turtle \n",
    "\n",
    "bob = turtle.Turtle()\n",
    "\n",
    "arc(bob, 80, 120)\n",
    "\n",
    "turtle.mainloop()\n",
    "turtle.bye()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Die eigentliche Aufgabe ist geschafft. Nun fällt uns aber noch etwas auf:\n",
    "\n",
    "Die zweite Hälfte dieser Funktion sieht aus wie `polygon`, aber wir können `polygon` nicht einfach wiederverwenden ohne die Schnittstelle zu verändern. Wir könnten `polygon` generalisieren, so dass es einen Winkel als ein weiteres Argument erwartet, aber dann wäre `polygon` kein angemessener Name mehr. Nennen wir diese verallgemeinerte Funktion also stattdessen `polyline`: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
Michel Schwab's avatar
Michel Schwab committed
    "import turtle\n",
    "\n",
    "def polyline(t, n, length, angle):\n",
    "    '''zeichnet einen Teil eines Vielecks in Abhängigkeit von der Anzahl der Ecken n, der Länge length \n",
    "    und der Drehung an jeder Ecke (angle)'''\n",
    "    for i in range(n):\n",
    "        t.fd(length)\n",
Michel Schwab's avatar
Michel Schwab committed
    "        t.lt(angle)\n",
    "\n",
    "        \n",
    "#turtle.mainloop()\n",
    "#turtle.bye()"