{ "cells": [ { "cell_type": "markdown", "id": "b112e25b", "metadata": {}, "source": [ "# Kapitel 2: Variablen und Anweisungen\n", "__[Chapter 2: Variables and Statements](https://colab.research.google.com/github/AllenDowney/ThinkPython/blob/v3/chapters/chap02.ipynb)__\n", "\n", "Eine der mächtigsten Fähigkeiten von Programmiersprachen ist, **Variablen** zu verändern. Variablen sind Namen, die auf einen Wert verweisen.\n", "\n", "**Bevor Sie mit diesem Notebook starten, sollten Sie wiederholen, was Sie im letzten Notebook gelernt haben. Gehen Sie zurück und schauen Sie sich mindestens das Glossar an und wiederholen Sie die dort genannten Begriffe.**" ] }, { "cell_type": "markdown", "id": "019fa0dd-e50e-420b-94b1-40e0658f47d9", "metadata": {}, "source": [ "## Ihre Lernziele\n", "Sie können eine Übersicht der Inhalte dieses Notebooks einblenden mit *Strg + Shift + k*. \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", "## Exkurs: Was mir an Python gefällt\n", "\n", "Dieses Programm durchsucht alle Jupyter Notebooks in dem Verzeichnis in dem dieses Notebook gespeichert ist. " ] }, { "cell_type": "code", "execution_count": null, "id": "de4ca195-3433-4ff2-876f-5a63bd9cc9ee", "metadata": {}, "outputs": [], "source": [ "import os\n", " \n", "query = \"Experiment\"\n", "\n", "# Suche nach query in s; falls gefunden: Fundstelle + hervorgehobene Anfrage zurückgeben\n", "def search(s, query, context = 20):\n", " i = s.find(query)\n", " if i >= 0:\n", " return s[max(0, i-context):i] + \"*\" + s[i:i + len(query)] + \"*\" + s[i + len(query):min(len(s), i+context)]\n", " return None\n", "\n", "print(\"Suche nach '\" + query + \"':\")\n", "# alle Python-Notebooks im aktuellen Verzeichnis durchsuchen\n", "for entry in os.listdir():\n", " if entry.endswith(\".ipynb\"):\n", " with open(entry, \"rt\") as f:\n", " for line in f:\n", " result = search(line, query)\n", " if result:\n", " print(entry + \":\", result)" ] }, { "cell_type": "markdown", "id": "eb668bab-6740-474c-a0f2-659e67df4d7b", "metadata": {}, "source": [ "## Herunterladen des unterstützenden Codes\n", "Die folgende Zelle lädt eine Datei herunter und führt einen Code aus, der speziell für dieses Notebook verwendet wird. Sie müssen diesen Code nicht verstehen, aber Sie sollten die Zelle ausführen vor allen weiteren Zellen in diesem Notebook." ] }, { "cell_type": "code", "execution_count": null, "id": "d0775eaa-52a1-480f-a28d-a1754e9e61eb", "metadata": {}, "outputs": [], "source": [ "from os.path import basename, exists\n", "\n", "def download(url):\n", " filename = basename(url)\n", " if not exists(filename):\n", " from urllib.request import urlretrieve\n", "\n", " local, _ = urlretrieve(url, filename)\n", " print(\"Downloaded \" + str(local))\n", " return filename\n", "\n", "download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');\n", "download('https://github.com/AllenDowney/ThinkPython/raw/v3/diagram.py');\n", "\n", "import thinkpython" ] }, { "cell_type": "markdown", "id": "d0286422", "metadata": {}, "source": [ "# Variablen und Anweisungen\n", "\n", "Im vorherigen Kapitel haben wir Operatoren verwendet, um Ausdrücke zu schreiben, die arithmetische Berechnungen ausführen.\n", "\n", "In diesem Kapitel werden wir Variablen und Anweisungen, die `import` Anweisung und die `print` Funktion kennenlernen.\n", "Außerdem werde ich weitere Teile des Vokabulars einführen, das wir verwenden, um über Programme zu sprechen, so etwa beispielsweise \"Argument\" und \"Modul\".\n" ] }, { "cell_type": "markdown", "id": "7c7e9108-43a5-41c8-8cbb-990d7dc2cc2f", "metadata": {}, "source": [ "## Variablen" ] }, { "cell_type": "code", "execution_count": null, "id": "805ffc73-cc00-4c0b-b865-4f7acf1885bb", "metadata": {}, "outputs": [], "source": [ "from IPython.lib.display import YouTubeVideo\n", "YouTubeVideo('https://www.youtube.com/watch?v=jfOLXKPGXJ0&list=PL_pqkvxZ6ho3u8PJAsUU-rOAQ74D0TqZB&index=4')" ] }, { "cell_type": "markdown", "id": "4ac44f0c", "metadata": {}, "source": [ "Eine **Variable** ist ein Name, der sich auf einen Wert bezieht.\n", "Um eine Variable zu erschaffen, können wir eine spezielle Anweisung, genannt **Zuweisung**, schreiben. Diese sieht wie folgt aus:" ] }, { "cell_type": "code", "execution_count": null, "id": "59f6db42", "metadata": {}, "outputs": [], "source": [ "n = 17" ] }, { "cell_type": "markdown", "id": "52f187f1", "metadata": {}, "source": [ "Eine Zuweisung hat drei Bestandteile: den *Namen* der Variable ganz links, ein *Gleichheitszeichen*, `=`, und einen *Ausdruck* auf der rechten Seite.\n", "Im obigen Beispiel ist der Ausdruck eine ganze Zahl.\n", "Im folgenden Beispiel ist der Ausdruck eine Gleitkommazahl:" ] }, { "cell_type": "code", "execution_count": null, "id": "1301f6af", "metadata": {}, "outputs": [], "source": [ "pi = 3.141592653589793" ] }, { "cell_type": "markdown", "id": "3e27e65c", "metadata": {}, "source": [ "Und im nächsten Beispiel ist der Ausdruck eine Zeichenkette:" ] }, { "cell_type": "code", "execution_count": null, "id": "f7adb732", "metadata": {}, "outputs": [], "source": [ "nachricht = 'Und nun für was ganz anderes'" ] }, { "cell_type": "markdown", "id": "cb5916ea", "metadata": {}, "source": [ "Wenn wir eine Zuweisung ausführen, gibt es keine Ausgabe.\n", "Python erschafft die Variable und gibt ihr einen Wert, aber die Zuweisung hat keinen sichtbaren Effekt.\n", "Nachdem wir eine Variable erstellt haben, können wir diese als Ausdruck verwenden.\n", "Also können wir den Wert von `nachricht` folgendermaßen ausgeben:" ] }, { "cell_type": "code", "execution_count": null, "id": "6bcc0a66", "metadata": {}, "outputs": [], "source": [ "nachricht" ] }, { "cell_type": "markdown", "id": "e3fd81de", "metadata": {}, "source": [ "Wir können Variablen auch als Teil eines Ausdrucks mit arithmetischen Operatoren verwenden:" ] }, { "cell_type": "code", "execution_count": null, "id": "3f11f497", "metadata": {}, "outputs": [], "source": [ "n + 25" ] }, { "cell_type": "code", "execution_count": null, "id": "6b2dafea", "metadata": {}, "outputs": [], "source": [ "2 * pi" ] }, { "cell_type": "markdown", "id": "97396e7d", "metadata": {}, "source": [ "Und wir können eine Variable als Argument verwenden, wenn wir eine Funktion aufrufen:" ] }, { "cell_type": "code", "execution_count": null, "id": "72c45ac5", "metadata": {}, "outputs": [], "source": [ "round(pi)" ] }, { "cell_type": "code", "execution_count": null, "id": "6bf81c52", "metadata": {}, "outputs": [], "source": [ "len(nachricht)" ] }, { "cell_type": "markdown", "id": "af7974e4-6d01-43f7-b860-7c8dad808c9c", "metadata": {}, "source": [ "Legen Sie selbst ein paar Variablen an und weisen Sie ihnen Werte zu:" ] }, { "cell_type": "code", "execution_count": null, "id": "36344854-6839-4bd4-8bd6-8ce175efb2da", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "6fe6b8fd-4ed6-40a8-a845-6d6f8d0a97c8", "metadata": {}, "source": [ "## Zustandsdiagramme\n", "Eine übliche Art, Variablen zu skizzieren, ist das Schreiben des Namens mit\n", "einem Pfeil, der auf seinen Wert zeigt. " ] }, { "cell_type": "code", "execution_count": null, "id": "f5da0a13-dd3a-4f5d-855a-aa301b88fc6f", "metadata": {}, "outputs": [], "source": [ "import math\n", "\n", "from diagram import make_binding, Frame\n", "\n", "binding = make_binding(\"nachricht\", 'Und nun für was ganz anderes')\n", "binding2 = make_binding(\"n\", 17)\n", "binding3 = make_binding(\"pi\", 3.141592653589793)\n", "\n", "frame = Frame([binding2, binding3, binding])" ] }, { "cell_type": "code", "execution_count": null, "id": "d0d366c3-5625-4810-bacb-eca0811fe8d9", "metadata": {}, "outputs": [], "source": [ "from diagram import diagram, adjust\n", "\n", "width, height, x, y = [3.62, 1.01, 0.6, 0.76]\n", "ax = diagram(width, height)\n", "bbox = frame.draw(ax, x, y, dy=-0.25)\n", "#adjust(x, y, bbox)" ] }, { "cell_type": "markdown", "id": "6fc2ea1c-e9f5-4404-890f-e7a9ea798c9c", "metadata": {}, "source": [ "Diese Art von Abbildung wird **Zustandsdiagramm** genannt, weil sie zeigt, in welchem Zustand sich die einzelnen Variablen befinden (man kann sich das als den Geisteszustand der Variablen vorstellen).\n", "Wir werden im gesamten Buch Zustandsdiagramme verwenden, um ein Modell darzustellen, wie Python Variablen und ihre Werte speichert." ] }, { "cell_type": "markdown", "id": "ba252c85", "metadata": {}, "source": [ "## Variablennamen\n", "\n", "Variablennamen können so lang sein, wie wir möchten. Sie können sowohl Buchstaben als auch Zahlen beinhalten, dürfen aber nicht mit einer Zahl beginnen.\n", "Großbuchstaben sind erlaubt, es ist aber eher üblich, nur Kleinbuchstaben für Variablennamen zu verwenden.\n", "\n", "Das einzige Sonderzeichen, welches in einem Variablennamen auftauchen darf, ist der Unterstrich, `_`. Er wird oft in Namen mit mehreren Worten wie zum Beispiel `dein_name` oder `so_ist_es_besser_lesbar` verwendet.\n", "\n", "Wenn wir einer Variable einen nicht erlaubten Namen geben, erhalten wir einen Syntaxfehler.\n", "Der Name `million!` ist nicht erlaubt, da er das Sonderzeichen `!` enthält:" ] }, { "cell_type": "code", "execution_count": null, "id": "ac2620ef", "metadata": {}, "outputs": [], "source": [ "%%expect SyntaxError\n", "\n", "million! = 1000000" ] }, { "cell_type": "markdown", "id": "a1cefe3e", "metadata": {}, "source": [ "`0das_gibt_Aerger` ist nicht erlaubt, da es mit einer Zahl beginnt:" ] }, { "cell_type": "code", "execution_count": null, "id": "1a8b8382", "metadata": {}, "outputs": [], "source": [ "%%expect SyntaxError\n", "\n", "0das_gibt_Aerger = 1" ] }, { "cell_type": "markdown", "id": "94aa7e60", "metadata": {}, "source": [ "`class` ist ebenfalls nicht erlaubt, der Grund dafür ist aber weniger offensichtlich:" ] }, { "cell_type": "code", "execution_count": null, "id": "b6938851", "metadata": {}, "outputs": [], "source": [ "%%expect SyntaxError\n", "\n", "class = 'Selbstverteidigung gegen frisches Obst'" ] }, { "cell_type": "markdown", "id": "784cfb5c", "metadata": {}, "source": [ "Es stellt sich heraus, dass `class` ein **Schlüsselwort** ist, das bedeutet ein spezielles Wort, das verwendet wird, um die Struktur eines Programmes anzugeben.\n", "Schlüsselwörter können nicht als Variablennamen verwendet werden.\n", "\n", "Hier ist eine vollständige Liste aller Schlüsselwörter von Python:" ] }, { "cell_type": "markdown", "id": "127c07e8", "metadata": {}, "source": [ "```\n", "False await else import pass\n", "None break except in raise\n", "True class finally is return\n", "and continue for lambda try\n", "as def from nonlocal while\n", "assert del global not with\n", "async elif if or yield\n", "```" ] }, { "cell_type": "code", "execution_count": null, "id": "4a8f4b3e", "metadata": {}, "outputs": [], "source": [ "from keyword import kwlist\n", "\n", "len(kwlist)" ] }, { "cell_type": "markdown", "id": "6f14d301", "metadata": {}, "source": [ "Wir brauchen uns diese Liste nicht zu merken. In den meisten Entwicklungsumgebungen (Programmen zum Bearbeiten von Quellcode – wie z.B. Jupyter) werden diese Wörter farblich hervorgehoben und wir werden somit gewarnt, falls wir eines dieser Wörter als Variablennamen verwenden wollen.\n", "\n", "\n", "\n", "([Keep it simple, stupid](http://www.commitstrip.com/en/2016/09/01/keep-it-simple-stupid/), CommitStrip.com)" ] }, { "cell_type": "markdown", "id": "c954a3b0", "metadata": {}, "source": [ "## Die Import-Anweisung\n", "\n", "Um manche Features von Python nutzen zu können, müssen diese zunächst **importiert** werden.\n", "Die folgende Anweisung importiert zum Beispiel das `math` Modul:" ] }, { "cell_type": "code", "execution_count": null, "id": "98c268e9", "metadata": {}, "outputs": [], "source": [ "import math" ] }, { "cell_type": "markdown", "id": "ea4f75ec", "metadata": {}, "source": [ "Ein **Modul** ist eine Sammlung von Variablen und Funktionen.\n", "Das `math`-Modul stellt eine Variable namens `pi` zur Verfügung, die den Wert der mathematischen Konstante $\\pi$ enthält.\n", "Wir können ihren Wert folgendermaßen darstellen:" ] }, { "cell_type": "code", "execution_count": null, "id": "47bc17c9", "metadata": {}, "outputs": [], "source": [ "math.pi" ] }, { "cell_type": "markdown", "id": "c96106e4", "metadata": {}, "source": [ "Um eine Variable in einem Modul zu nutzen, müssen wir den **Punktoperator** (`.`) zwischen dem Namen des Moduls und dem Namen der Variable benutzen.\n", "\n", "Das `math`-Modul enthält auch Funktionen.\n", "Beispielsweise berechnet `sqrt` Quadratwurzeln:" ] }, { "cell_type": "code", "execution_count": null, "id": "fd1cec63", "metadata": {}, "outputs": [], "source": [ "math.sqrt(25)" ] }, { "cell_type": "markdown", "id": "185e94a3", "metadata": {}, "source": [ "Und `pow` potenziert eine Zahl mit einer zweiten Zahl:" ] }, { "cell_type": "code", "execution_count": null, "id": "87316ddd", "metadata": {}, "outputs": [], "source": [ "math.pow(5, 2)" ] }, { "cell_type": "markdown", "id": "5df25a9a", "metadata": {}, "source": [ "Bisher haben wir zwei Möglichkeiten gesehen, eine Zahl zu potenzieren: Wir können die Funktion `math.pow` oder den Potenzierungsoperator `**` verwenden.\n", "Beide Optionen sind in Ordnung, der Operator wird aber häufiger als die Funktion verwendet." ] }, { "cell_type": "markdown", "id": "6538f22b", "metadata": {}, "source": [ "## Ausdrücke und Anweisungen\n", "\n", "Bislang haben wir verschiedene Arten von **Ausdrücken** gesehen.\n", "Ein Ausdruck kann ein einzelner Wert sein, wie etwa eine ganze Zahl, eine Gleitkommazahl oder eine Zeichenkette.\n", "Er kann auch eine Ansammlung von Werten und Operatoren sein.\n", "Er kann außerdem Variablennamen und Funktionsaufrufe enthalten.\n", "Hier ist ein Ausdruck, der mehrere dieser Elemente beinhaltet:" ] }, { "cell_type": "code", "execution_count": null, "id": "7f0b92df", "metadata": {}, "outputs": [], "source": [ "19 + n + round(math.pi) * 2" ] }, { "cell_type": "markdown", "id": "000dd2ba", "metadata": {}, "source": [ "Wir haben auch schon einige Arten von Anweisungen gesehen.\n", "Eine **Anweisung** ist eine Einheit von Code, die eine Wirkung, aber keinen Wert hat. \n", "Zum Beispiel erstellt eine Zuweisung (die eine spezielle Anweisung ist) eine Variable und gibt ihr einen Wert, aber die Anweisung selbst hat keinen Wert." ] }, { "cell_type": "code", "execution_count": null, "id": "b882c340", "metadata": {}, "outputs": [], "source": [ "n = 17" ] }, { "cell_type": "markdown", "id": "cff0414b", "metadata": {}, "source": [ "Ähnlich verhält es sich mit der Import-Anweisung: sie importiert ein Modul, damit wir dessen Werte und Funktionen nutzen können, aber sie hat keinen sichtbaren Effekt:" ] }, { "cell_type": "code", "execution_count": null, "id": "299817d8", "metadata": {}, "outputs": [], "source": [ "import math" ] }, { "cell_type": "markdown", "id": "2aeb1000", "metadata": {}, "source": [ "Denn Wert eines Ausdrucks zu berechnen bezeichnet man als **Evaluation**.\n", "Die Ausführung einer Anweisung heißt **Ausführung**." ] }, { "cell_type": "markdown", "id": "f61601e4", "metadata": {}, "source": [ "## Die `print`-Funktion\n", "\n", "Wenn wir einen Ausdruck evaluieren, wird das Ergebnis dargestellt:" ] }, { "cell_type": "code", "execution_count": null, "id": "805977c6", "metadata": {}, "outputs": [], "source": [ "n + 1" ] }, { "cell_type": "markdown", "id": "efacf0fa", "metadata": {}, "source": [ "Wenn wir allerdings mehr als einen Ausdruck gleichzeitig evaluieren, wird nur der Wert des letzten gezeigt:" ] }, { "cell_type": "code", "execution_count": null, "id": "962e08ab", "metadata": {}, "outputs": [], "source": [ "n + 2\n", "n + 3" ] }, { "cell_type": "markdown", "id": "cf2b991d", "metadata": {}, "source": [ "Um mehr als einen Wert anzuzeigen, können wir die `print`-Funktion nutzen:" ] }, { "cell_type": "code", "execution_count": null, "id": "a797e44d", "metadata": {}, "outputs": [], "source": [ "print(n+2)\n", "print(n+3)" ] }, { "cell_type": "markdown", "id": "29af1f89", "metadata": {}, "source": [ "Diese funktioniert auch mit Gleitkommazahlen und Zeichenketten:" ] }, { "cell_type": "code", "execution_count": null, "id": "73428520", "metadata": {}, "outputs": [], "source": [ "print('Der Wert der Kreiszahl ist ungefähr')\n", "print(math.pi)" ] }, { "cell_type": "markdown", "id": "8b4d7f4a", "metadata": {}, "source": [ "Wir können auch eine Reihe von Ausdrücken, getrennt durch Kommata verwenden:" ] }, { "cell_type": "code", "execution_count": null, "id": "9ad5bddd", "metadata": {}, "outputs": [], "source": [ "print('Der Wert der Kreiszahl ist ungefähr', math.pi)" ] }, { "cell_type": "markdown", "id": "af447ec4", "metadata": {}, "source": [ "Beachten Sie, dass die `print`-Funktion eine Leerstelle zwischen den Werten platziert." ] }, { "cell_type": "markdown", "id": "7c73a2fa", "metadata": {}, "source": [ "## Argumente" ] }, { "cell_type": "code", "execution_count": null, "id": "edd0832f-501c-4a4c-97e0-835f30d274f6", "metadata": {}, "outputs": [], "source": [ "from IPython.lib.display import YouTubeVideo\n", "YouTubeVideo('https://www.youtube.com/watch?v=af9ORp1Pty0&list=PL_pqkvxZ6ho3u8PJAsUU-rOAQ74D0TqZB&index=19')" ] }, { "cell_type": "markdown", "id": "c90012b9-3656-48a7-a815-523e7c3b72c4", "metadata": {}, "source": [ "Wenn wir eine Funktion aufrufen, heißt der Ausdruck in den Klammern **Argument**.\n", "Normalerweise würde ich erklären, warum, aber in diesem Fall hat die technische Bedeutung des Begriffs fast nichts mit der gewöhnlichen Bedeutung des Wortes zu tun, daher werde ich es erst gar nicht versuchen.\n", "\n", "Einige der Funktionen, die wir bisher gesehen haben nehmen nur ein Argument auf, so wie `int`:" ] }, { "cell_type": "code", "execution_count": null, "id": "060c60cf", "metadata": {}, "outputs": [], "source": [ "int('101')" ] }, { "cell_type": "markdown", "id": "c4ad4f2c", "metadata": {}, "source": [ "Manche nehmen zwei auf, so wie `math.pow`:" ] }, { "cell_type": "code", "execution_count": null, "id": "2875d9e0", "metadata": {}, "outputs": [], "source": [ "math.pow(5, 2)" ] }, { "cell_type": "markdown", "id": "17293749", "metadata": {}, "source": [ "Manche können auch zusätzliche optionale Argumente aufnehmen.\n", "Zum Beispiel kann `int` ein zweites Argument annehmen, das die Basis der Zahl angibt:" ] }, { "cell_type": "code", "execution_count": null, "id": "43b9cf38", "metadata": {}, "outputs": [], "source": [ "int('101', 2)" ] }, { "cell_type": "markdown", "id": "c95589a1", "metadata": {}, "source": [ "Die Ziffernfolge „101“ zur Basis 2 entspricht der Zahl 5 zur Basis 10.\n", "\n", "`round` nimmt auch ein optionales zweites Argument auf, dieses gibt die Anzahl an Dezimalstellen an, auf die gerundet werden soll:" ] }, { "cell_type": "code", "execution_count": null, "id": "e8a21d05", "metadata": {}, "outputs": [], "source": [ "round(math.pi, 3)" ] }, { "cell_type": "markdown", "id": "21e4a448", "metadata": {}, "source": [ "Manche Funktionen können auch beliebig viele Argumente aufnehmen, so zum Beispiel `print`:" ] }, { "cell_type": "code", "execution_count": null, "id": "724128f4", "metadata": {}, "outputs": [], "source": [ "print('So', 'viele', 'wie', 'gewünscht')" ] }, { "cell_type": "markdown", "id": "667cff14", "metadata": {}, "source": [ "Wenn wir eine Funktion aufrufen und zu viele Argumente für diese angeben führt das zu einem `TypeError`:" ] }, { "cell_type": "code", "execution_count": null, "id": "69295e52", "metadata": {}, "outputs": [], "source": [ "%%expect TypeError\n", "\n", "float('123.0', 2)" ] }, { "cell_type": "markdown", "id": "5103368e", "metadata": {}, "source": [ "Wenn wir zu wenige Argumente angeben führt das ebenfalls zu einem `TypeError`." ] }, { "cell_type": "code", "execution_count": null, "id": "edec7064", "metadata": {}, "outputs": [], "source": [ "%%expect TypeError\n", "\n", "math.pow(2)" ] }, { "cell_type": "markdown", "id": "5333c416", "metadata": {}, "source": [ "Und wenn wir ein Argument eines Datentyps liefern, der nicht mit der Funktion kompatibel ist, ergibt auch das einen `TypeError`:" ] }, { "cell_type": "code", "execution_count": null, "id": "f86b2896", "metadata": {}, "outputs": [], "source": [ "%%expect TypeError\n", "\n", "math.sqrt('123')" ] }, { "cell_type": "markdown", "id": "548828af", "metadata": {}, "source": [ "Diese Art der Kontrolle kann am Anfang lästig sein, aber sie hilft uns, Fehler zu erkennen und zu korrigieren." ] }, { "cell_type": "markdown", "id": "be2b6a9b", "metadata": {}, "source": [ "## Kommentare \n", "\n", "Sobald Programme größer und komplexer werden, wird es schwer, sie zu verstehen. Die Information, die im Programmcode steckt, ist sehr dicht und es fällt oft schwer, nur durch einen Blick auf den Programmcode herauszufinden, was der Code macht und warum. \n", "\n", "Daher ist es eine gute Idee, Notizen in natürlicher Sprache einzufügen, die erklären, was das Programm macht. Diese Notizen heißen **Kommentare** und sie beginnen mit dem Zeichen `#`:" ] }, { "cell_type": "code", "execution_count": null, "id": "607893a6", "metadata": {}, "outputs": [], "source": [ "pi = 3.141592653589793\n", "radius = 7\n", "# die Fläche eines Kreises berechnen\n", "flaeche = 2 * pi * radius**2" ] }, { "cell_type": "markdown", "id": "519c83a9", "metadata": {}, "source": [ "Wir können Kommentare auch am Ende einer Zeile hinzufügen:" ] }, { "cell_type": "code", "execution_count": null, "id": "615a11e7", "metadata": {}, "outputs": [], "source": [ "flaeche = 2 * pi * radius**2 # die Fläche eines Kreises berechnen" ] }, { "cell_type": "markdown", "id": "87c8d10c", "metadata": {}, "source": [ "Alles ab `#` bis zum Ende der Zeile wird ignoriert und hat keine Auswirkung auf die Ausführung des Programms.\n", "\n", "- Kommentare werden in der Entwicklungsumgebung oft farblich hervorgehoben, was zusätzlich die Orientierung erleichtert.\n", "- Kommentare sind am hilfreichsten, wenn sie das nicht-Offensichtliche erklären\n", "- Wir können davon ausgehen, dass der$*$die Leser$*$in herausfinden kann, *was* das Programm macht, daher sollten wir eher erklären *warum* das an der Stelle gemacht wird.\n", "\n", "Der folgende Kommentar ist beispielsweise redundant und daher nutzlos:\n" ] }, { "cell_type": "code", "execution_count": null, "id": "cc7fe2e6", "metadata": {}, "outputs": [], "source": [ "v = 8 # 8 der Variable v zuordnen" ] }, { "cell_type": "markdown", "id": "eb83b14a", "metadata": {}, "source": [ "Dieser Kommentar dagegen enthält nützliche Information, die sich nicht im Quellcode befindet:" ] }, { "cell_type": "code", "execution_count": null, "id": "7c93a00d", "metadata": {}, "outputs": [], "source": [ "v = 8 # Geschwindigkeit in Kilometern pro Stunde" ] }, { "cell_type": "markdown", "id": "6cd60d4f", "metadata": {}, "source": [ "Mit aussagekräftigen Variablennamen können wir uns Kommentare sparen, allerdings werden Ausdrücke durch sehr komplexe oder lange Namen schwer lesbar. Wir müssen also einen guten Mittelweg finden.\n", "\n", "Finden Sie heraus, was das folgende Programm tut und fügen Sie aussagekräftige Kommentare hinzu:" ] }, { "cell_type": "code", "execution_count": null, "id": "b2503cf2-b1ee-43b7-8420-11091c3dd1e3", "metadata": {}, "outputs": [], "source": [ "import math \n", "\n", "x1 = 5\n", "y1 = 4\n", "x2 = 1\n", "y2 = 1\n", "\n", "distance_h = x1 - x2\n", "distance_v = y1 - y2\n", "\n", "distance = math.sqrt(distance_h**2 + distance_v**2)\n", "\n", "print(\"distance((x1, y1), (x2, y2)) = \", distance)" ] }, { "cell_type": "markdown", "id": "c97c7d01-0aa8-463a-b312-8ae312ccba2b", "metadata": {}, "source": [ "Wieviele Kommentare in einem Programm gut und notwendig sind ist durchaus umstritten. Wenn Sie mögen, können Sie einen Ausschnitt des Diskurses dazu hier verfolgen:\n", "\n", "\n", "- [\"Good code is its own best documentation.\" (Steve McConnell)](http://de.wikipedia.org/wiki/Steve_McConnell)\n", "- [\"Yes your Code does need comments\" (Mike Grouchy)](http://mikegrouchy.com/blog/2013/03/yes-your-code-does-need-comments.html)\n", "- [Funny comments](https://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered)\n", "\n", "\n", "([Programming Elements – Comments](https://prairieworldcomicsblog.wordpress.com/2018/01/26/programming-elements-comments/), William Wise)" ] }, { "cell_type": "markdown", "id": "7d61e416", "metadata": {}, "source": [ "## Debugging\n", "\n", "Programme können drei Arten von Fehlern enthalten:\n", "\n", "- **Syntax-Fehler** (\"syntax error\") – Fehler in der **Syntax**, also der Struktur, des Programmes. Das Programm ist nicht ausführbar bis der Fehler behoben ist. Vor allem zu Beginn, werden Sie vermutlich viele Syntax- Fehler machen, zum Beispiel indem Sie eine Klammer vergessen. Je mehr Übung Sie haben, desto weniger Syntax-Fehler werden Sie machen. Zudem werden Sie diese auch schneller finden. \n", "- **Laufzeit-Fehler** (\"runtime error\") – Laufzeit-Fehler treten erst auf, während das Programm läuft. Sie werden auch **Ausnahme** (\"exception\") genannt, da sie üblicherweise bedeuten, dass etwas außergewöhnliches (und schlechtes) passiert ist. In einfachen Programmen sind Laufzeitfehler selten, Sie werden Ihnen vermutlich noch eine Weile nicht begegnen. \n", "- **Semantische Fehler** (\"semantic error\") sind Fehler in der **Semantik** – also Fehler, die mit der Bedeutung des Programms zusammenhängen. Das Programm läuft ohne eine Fehlermeldung auszugeben, aber das Ergebnis ist nicht so wie erwartet. Das Programm tut genau das, was Sie ihm gesagt haben. Semantische Fehler zu finden ist schwierig, da von der Ausgabe aus rückwärts durch das Programm gearbeitet werden muss. Häufig ist es hilfreich zusätzliche `print`-Anweisungen einzufügen, die Zwischenergebnisse ausgeben, sodass der Punkt gefunden werden kann, an dem die erwarteten Ergebnisse von den tatsächlichen abweichen. \n" ] }, { "cell_type": "markdown", "id": "6cd52721", "metadata": {}, "source": [ "Wie wir bereits gesehen haben, handelt es sich bei einem nicht erlaubten Variablennamen um einen Syntax-Fehler:" ] }, { "cell_type": "code", "execution_count": null, "id": "86f07f6e", "metadata": {}, "outputs": [], "source": [ "%%expect SyntaxError\n", "\n", "million! = 1000000" ] }, { "cell_type": "markdown", "id": "b8971d33", "metadata": {}, "source": [ "Wenn wir einen Operator mit einem Datentyp verwenden, den dieser nicht unterstützt, ist das ein Laufzeit-Fehler:" ] }, { "cell_type": "code", "execution_count": null, "id": "682395ea", "metadata": {}, "outputs": [], "source": [ "%%expect TypeError\n", "\n", "'126' / 3" ] }, { "cell_type": "markdown", "id": "e51fa6e2", "metadata": {}, "source": [ "Zuletzt noch ein Beispiel für einen semantischen Fehler.\n", "Nehmen wir an, wir wollen den Durchschnitt von `1` und `3` berechnen, vergessen aber die Reihenfolge der Operationen zu beachten und schreiben Folgendes:" ] }, { "cell_type": "code", "execution_count": null, "id": "2ff25bda", "metadata": {}, "outputs": [], "source": [ "1 + 3 / 2" ] }, { "cell_type": "markdown", "id": "0828afc0", "metadata": {}, "source": [ "Wird dieser Ausdruck evaluiert, produziert er keine Fehlermeldung, also liegt hier kein Syntax- oder Laufzeit-Fehler vor.\n", "Aber das Ergebnis ist trotzdem nicht der Durchschnitt von `1` und `3`, also ist das Programm nicht korrekt.\n", "Dies ist ein semantischer Fehler, da das Programm zwar läuft, es aber nicht tut, was es tun soll." ] }, { "cell_type": "markdown", "id": "07396f3d", "metadata": {}, "source": [ "## Glossar\n", "\n", "- Variable:\n", "- Zuweisung: Eine Zuweisung ist eine Anweisung, bei der einer Variable ein Wert zugewiesen wird\n", "- Zuweisungsanweisung:\n", "- Keyword:\n", "- Import-Anweisung:\n", "- Modul:\n", "- Punktoperator:\n", "- evaluieren:\n", "- Anweisung:\n", "- ausführen:\n", "- Argument:\n", "- Kommentar:\n", "- Laufzeit-Fehler:\n", "- Ausnahme:\n", "- Semantischer Fehler:\n", "- `print`-Funktion:\n", "\n", "\n", "Ergänzen Sie die Liste in eigenen Worten. Das ist eine gute Erinnerungs- und Übungsmöglichkeit." ] }, { "cell_type": "markdown", "id": "70ee273d", "metadata": {}, "source": [ "## Übung" ] }, { "cell_type": "code", "execution_count": null, "id": "c9e6cab4", "metadata": {}, "outputs": [], "source": [ "# Diese Zelle weist Jupyter an, detaillierte Debugging-Informationen bereitzustellen, wenn ein\n", "# Laufzeit-Fehler passiert. Führen Sie sie daher aus, bevor Sie mit den Übungsaufgaben beginnen.\n", "\n", "%xmode Verbose" ] }, { "cell_type": "markdown", "id": "7256a9b2", "metadata": {}, "source": [ "### Fragen Sie einen virtuellen Assistenten\n", "\n", "Auch hier möchte ich Sie dazu ermutigen, einen virtuellen Assistenten zu benutzen, um mehr über die Themen in diesem Kapitel zu erfahren.\n", "\n", "Sie können zum Beispiel die [Sprachmodelle der HU](https://ki.cms.hu-berlin.de/de/large-language-models-an-der-hu) nutzen, sofern Sie sich im Netz der HU befinden oder sich [per VPN verbunden](https://www.cms.hu-berlin.de/de/dl/netze/vpn) haben.\n", "\n", "Wenn Sie sich für eines der aufgeführten Keywords interessieren, könnten Sie fragen: „Warum ist class ein Keyword?“ oder „Warum können Variablennamen keine Keywords sein?“\n", "\n", "Sie haben vielleicht bemerkt, dass `int`, `float` und `str` keine Python-Keywords sind.\n", "Sie sind Variablen, die Datentypen repräsentieren, und können als Funktionen verwendet werden.\n", "Es ist also *erlaubt*, eine Variable oder Funktion mit einem dieser Namen zu haben, aber es wird dringend davon abgeraten. Fragen Sie einen Assistenten: „Warum ist es schlecht, int, float und string als Variablennamen zu verwenden?“\n", "\n", "Fragen Sie auch: „Was sind eingebaute Funktionen in Python?“\n", "Wenn Sie sich für eine dieser Funktionen interessieren, fragen Sie nach weiteren Informationen dazu.\n", "\n", "In diesem Kapitel haben wir das Modul `math` importiert und einige der Variablen und Funktionen verwendet, die es zur Verfügung stellt. Fragen Sie einen Assistenten: „Welche Variablen und Funktionen befinden sich im math Modul?“ und „Welche anderen Module außer math werden zum Kern von Python gezählt?“" ] }, { "cell_type": "markdown", "id": "f92afde0", "metadata": {}, "source": [ "### Aufgabe 1\n", "\n", "Wenn wir etwas Neues lernen, sollten wir es immer gleich ausprobieren. Wir sollten auch versuchen, absichtlich ein paar Fehler einzubauen, um zu sehen, was dann passiert und zu lernen, wie die Fehlermeldungen aussehen. \n", "\n", "- Wir haben gesehen, dass `n = 42` erlaubt ist. Was ist mit `42 = n`?" ] }, { "cell_type": "code", "execution_count": null, "id": "02492a50-8c57-4ff2-89d6-b7aee56ace1a", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "23695a85-af17-4c18-8f6e-0b097b4aace7", "metadata": {}, "source": [ "- Und wie sieht es mit `x = y = 1` aus? (Lassen Sie sich danach die Werte für `x` und `y` mit Hilfe der `print`-Funktion ausgeben.)" ] }, { "cell_type": "code", "execution_count": null, "id": "f155a57c-13fa-43e8-82fa-140dcfe4749e", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "b10a289b-638a-4c2d-b3c1-e9895f9f26f0", "metadata": {}, "source": [ "- In einigen Programmiersprachen müssen Anweisungen mit einem Semikolon, `;`, beendet werden. Was passiert, falls wir in Python ein Semikolon ans Ende einer Anweisung schreiben?" ] }, { "cell_type": "code", "execution_count": null, "id": "279c1809-8c52-4e23-8b97-f0b36fcef40d", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "98d78f94-12c8-41fa-b884-853cf961b0a8", "metadata": {}, "source": [ "- Und was passiert, wenn wir einen Punkt, `.`, ans Ende einer Anweisung schreiben?" ] }, { "cell_type": "code", "execution_count": null, "id": "5a6fc1ab-a0fe-4b1b-ad0c-efa46c51f959", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "98b4fcad-cd82-4380-b1f5-895181ae94c4", "metadata": {}, "source": [ "- Was geschieht, wenn Sie den Namen eines Moduls falsch schreiben und versuchen, `maath` zu importieren?" ] }, { "cell_type": "code", "execution_count": null, "id": "1ac92469-267c-49af-af3f-8480e9bd8059", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "9d562609", "metadata": {}, "source": [ "### Aufgabe 2\n", "\n", "Nutzen Sie Python als Taschenrechner. Denken Sie auch hier wieder daran, dass wir nicht zwingend Ihre mathematischen Fähigkeiten testen wollen. Nutzten Sie erst die Hinweise und versuchen Sie einander zu helfen, aber zögern Sie nicht uns zu fragen. Es ist wichtiger, dass Sie verstehen, wie Sie die Aufgabe in Python umsetzen, als die mathematischen Grundlagen zu verstehen.\n", "\n", "\n", "- Wie groß ist das Volumen einer Kugel mit dem Radius 5?\n", "\n", "\n", "<details>\n", " <summary type=\"button\" class=\"btn btn-info\">Hinweis</summary>\n", " <div class=\"alert alert-info\" role=\"alert\">\n", "\n", "Die Formel zum Berechnen des Volumens ist: $v = 4/3⋅π⋅r^3$ \n", "\n", " \n", " </div> \n", "</details>" ] }, { "cell_type": "code", "execution_count": null, "id": "18de7d96", "metadata": {}, "outputs": [], "source": [ "pi = 3.141592653589793\n", "# Geben Sie hier Ihren Ausdruck zur Berechnung ein\n" ] }, { "cell_type": "markdown", "id": "e6efaa50-7662-46ea-90e1-de82e321f34c", "metadata": {}, "source": [ "<details>\n", " <summary type=\"button\" class=\"btn btn-success\">Lösung</summary>\n", " <div class=\"alert alert-success\" role=\"alert\">\n", "\n", "Das Volumen ist 523,599.\n", " \n", " </div> \n", "</details>" ] }, { "cell_type": "markdown", "id": "6449b12b", "metadata": {}, "source": [ "**Part 2.** Eine trigonometrische Regel besagt, dass für jeden Wert von $x$, $(\\cos x)^2 + (\\sin x)^2 = 1$. Lassen Sie uns sehen, ob das für einen bestimmten Wert von $x$ wie zum Beispiel 42 zutrifft.\n", "\n", "Erstellen Sie eine Variable namens `x` mit diesem Wert.\n", "Nutzen Sie dann `math.cos` und `math.sin`, um den Sinus und den Cosinus von $x$ sowie die Summe ihrer Quadrate zu berechnen." ] }, { "cell_type": "markdown", "id": "96953cee-b713-47b3-8767-fcb3642394c7", "metadata": {}, "source": [ "<details>\n", " <summary type=\"button\" class=\"btn btn-info\">Hinweis</summary>\n", " <div class=\"alert alert-info\" role=\"alert\">\n", "\n", "Die Variable wird in Klammern an die Funktion übergeben, dies hat die Form \"Modul.Funktion(Variable)\".\n", "\n", " \n", " </div> \n", "</details>" ] }, { "cell_type": "code", "execution_count": null, "id": "de812cff", "metadata": {}, "outputs": [], "source": [ "# Geben Sie hier Ihren Ausdruck zur Berechnung ein\n" ] }, { "cell_type": "markdown", "id": "4ac41dca-6490-4a8f-bbe5-cf77a2909c00", "metadata": {}, "source": [ "<details>\n", " <summary type=\"button\" class=\"btn btn-success\">Lösung</summary>\n", " <div class=\"alert alert-success\" role=\"alert\">\n", " \n", "Das Ergebnis sollte nahe bei 1 liegen. Es ist möglicherweise nicht genau 1, da die Fließkommaarithmetik nicht exakt ist, sondern nur annähernd korrekt. \n", "</div> \n", "</details>" ] }, { "cell_type": "markdown", "id": "4986801f", "metadata": {}, "source": [ "**Part 3.** Außer `pi` ist noch eine weitere Variable, `e`, im `math` Modul definiert, welche die Basis des natürlichen Logarithmus, in mathematischer Notation \"$e$\", repräsentiert. Wenn Sie sich mit diesem Wert nicht auskennen, fragen Sie einen virtuellen Assistenten „Was ist `math.e`?“ Lassen Sie uns nun $e^2$ auf drei verschiedene Arten berechnen:\n", "\n", "* Verwenden Sie `math.e` und den Potenzierungsoperator (`**`).\n", "\n", "* Verwenden Sie `math.pow`, um `math.e` auf die Potenz `2` zu erhöhen.\n", "\n", "* Verwenden Sie `math.exp`, das als Argument einen Wert $x$ nimmt und $e^x$ berechnet.\n", "\n", "Ihnen fällt vielleicht auf, dass das letzte Ergebnis leicht von den anderen zwei abweicht.\n", "Schauen Sie, ob Sie herausfinden können, welches das Richtige ist." ] }, { "cell_type": "markdown", "id": "316ffc26-6b79-490e-aee7-84670505dc97", "metadata": {}, "source": [ "<details>\n", " <summary type=\"button\" class=\"btn btn-info\">Hinweis</summary>\n", " <div class=\"alert alert-info\" role=\"alert\">\n", "Die Variable wird in Klammern an die Funktion übergeben, dies hat die Form \"Modul.Funktion(Variable)\". Statt einer Variable kann auch eine weitere Funktion übergeben werden, solange sie ein gültiges Ergebnis (eine Zahl) an die übergeordnete Funktion übergibt.\n", " </div> \n", "</details>" ] }, { "cell_type": "code", "execution_count": null, "id": "54bc23ce-e82a-4b7c-816e-8ecf13ae974a", "metadata": {}, "outputs": [], "source": [ "# Geben Sie hier Ihren Ausdruck zur Berechnung ein\n" ] }, { "cell_type": "code", "execution_count": null, "id": "aff052ca-1e28-4a13-b63b-e440920646f6", "metadata": {}, "outputs": [], "source": [ "# Geben Sie hier Ihren Ausdruck zur Berechnung ein\n" ] }, { "cell_type": "code", "execution_count": null, "id": "4d730af9-f237-44c6-a8dc-5c8f0575e75e", "metadata": {}, "outputs": [], "source": [ "# Geben Sie hier Ihren Ausdruck zur Berechnung ein\n" ] }, { "cell_type": "markdown", "id": "e66990f0-6442-4c13-968a-a89b6cbccf71", "metadata": {}, "source": [ "<details>\n", " <summary type=\"button\" class=\"btn btn-success\">Lösung</summary>\n", " <div class=\"alert alert-success\" role=\"alert\">\n", "Die ersten beiden Aufgaben liefern das Ergebnis 7.3890560989306495.\n", " \n", "Die letzte Aufgabe liefert das Ergbnis 7.38905609893065.\n", " </div> \n", "</details>" ] }, { "cell_type": "markdown", "id": "b436a292-a82a-42f6-8215-73ccc22b568c", "metadata": {}, "source": [ " Speichern Sie dieses Notebook, so dass Ihre Änderungen nicht verlorengehen (nicht auf einem Pool-Rechner). Rufen Sie dazu im Menü *File* den Punkt *Download as* → *Notebook* auf und nutzen Sie beispielsweise einen USB-Stick, E-Mail, Google Drive, Dropbox oder Ihre [HU-Box](https://box.hu-berlin.de/). \n" ] }, { "cell_type": "markdown", "id": "1bda5b12-5432-4822-9fbe-c112576b96d2", "metadata": {}, "source": [ "\n", "Herzlichen Glückwunsch! Sie haben das 2. Kapitel geschafft!" ] }, { "cell_type": "markdown", "id": "27e14f5c-6f38-4cd6-81b3-709a3faceb02", "metadata": {}, "source": [ "<img src=\"https://scm.cms.hu-berlin.de/ibi/python/-/raw/master/img/by-nc-sa.png\" alt=\"CC BY-NC-SA\" style=\"width: 150px;\"/>\n", "\n", "Der Text dieses Notebooks ist als freies Werk unter der Lizenz [CC BY-NC-SA 4.0 ](https://creativecommons.org/licenses/by-nc-sa/4.0/) verfügbar.\n", "Der Code dieses Notebooks ist als freies Werk unter der Lizenz [MIT License](https://mit-license.org/) verfügbar.\n", "\n", "Es handelt sich um übersetzte und leicht veränderte Notebooks von [Allen B. Downey](https://allendowney.com) aus [Think Python: 3rd Edition](https://allendowney.github.io/ThinkPython/index.html).\n" ] } ], "metadata": { "kernelspec": { "display_name": "", "name": "" }, "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 5 }