diff --git a/Lektion0_Einfuehrung_und_Installation.ipynb b/Lektion0_Einfuehrung_und_Installation.ipynb index 712f137..26b466a 100644 --- a/Lektion0_Einfuehrung_und_Installation.ipynb +++ b/Lektion0_Einfuehrung_und_Installation.ipynb @@ -9,7 +9,7 @@ "In diesem Notebook wollen wir Sie mit den Grundlagen des Kurses sowie dem Aufbau des Jupyter-Servers und des Jupyter-Notebooks vertraut machen. Bitte lesen Sie die folgenden Abschnitte aufmerksam durch und vervollständigen Sie die Installation des Kursmaterials am Ende des Notebooks.\n", "\n", "## Das Kursmaterial:\n", - "Das Kursmaterial streckt sich über mehrere Lektionen und wird Ihnen die für das Physikalische Grundpraktikum benötigten Grundlagen der Datenauswertung vermitteln. Hierbei fokussieren sich die verschiedenen Lektionen auf verschiedene Aspekte der Datenauswertung mit Python, welche Sie im Zuge des Praktikums benötigen werden. \n", + "Das Kursmaterial streckt sich über mehrere Lektionen und wird Ihnen die für das Physikalische Grundpraktikum benötigten Grundlagen der Datenauswertung vermitteln. Hierbei fokussieren sich die verschiedenen Lektionen auf verschiedene Aspekte der Datenauswertung mit Python.\n", "\n", "Das Kursmaterial wird Ihnen hierbei als eine Art „Online-Workshop“ zur Verfügung gestellt. Das bedeutet Sie können die verschiedenen Lektionen sich jederzeit in Eigenverantwortung erarbeiten. Jede Lektion beinhaltet einige Beispiele mit Erklärungen, welche durch kleinere Aufgaben unterstützt werden. Beispiellösungen für die einzelnen Aufgaben befinden sich ebenfalls in den Notebooks. Sollte Ihnen mal eine Aufgabe nicht auf Anhieb gelingen schauen Sie bitte nicht direkt in die Lösungen. Knobeln Sie ruhig erst ein wenig herum und probieren Sie verschiedene Ansätze aus. \n", "\n", @@ -17,6 +17,8 @@ "\n", "Bitte beachten Sie, dass dieser Kurs Ihnen lediglich die Grundalgen liefert und zur Auffrischung Ihrer Kenntnisse gedacht ist. Wir empfehlen Ihnen daher vor beginn des Grundpraktikums bereits einen anderen Kurs, wie zum Beispiel Programmieren für Physiker oder Einführung in die Programmierung, gehört zu haben.\n", "\n", + "Sollten Sie mal gar nicht weiterwissen, können Sie sich gerne auch an die Assistenten des Versuchs wenden. Eventuell haben auch einige Ihrer Kommilitonen bereits Erfahrung im Umgang mit Python sammeln können. Sie können die Aufgaben auch gerne in einer Gruppe erarbeiten. Hier sollten Sie jedoch sicherstellen, dass Sie die benötigten Konzepte verstanden haben und diese somit später anwenden können.\n", + "\n", "\n", "## Jupyter-Notebooks ausführen\n", "\n", @@ -28,7 +30,7 @@ "\n", "Um Zugang zum Jupyter-Hub zu erhalten, müssen Sie sich zunächst mit Ihrem Uni-Account anmelden. Danach erscheint eine Auswahlseite, auf der Sie die Art der Jupyter Umgebung auswählen. Für das Praktikum ist die Standardumgebung die richtige Wahl, s. Bild unten.\n", "\n", - "![images/Screenshot_ZDV_JupyterHub.png](images/Screenshot_ZDV_JupyterHub.png)\n", + "![images/Screenshot_ZDV_JupyterHub.png](./images/Screenshot_ZDV_JupyterHub.png)\n", "\n", "Klicken Sie auf die Schaltfläche **Spawn**, dann öffnet sich das Notebook Dashboard.\n", "\n", @@ -202,13 +204,6 @@ "\n", "Wird Jupyterlab statt Jupyter genutzt, dann kann es sein, dass die besondere Formatierung nicht funktioniert. Dies ist kein Problem, da es sich dabei um eine rein optische Verbesserung handelt." ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/Lektion1_Definieren_von_Parametern_und_Funktionen.ipynb b/Lektion1_Definieren_von_Parametern_und_Funktionen.ipynb index 73e3235..6d220e0 100644 --- a/Lektion1_Definieren_von_Parametern_und_Funktionen.ipynb +++ b/Lektion1_Definieren_von_Parametern_und_Funktionen.ipynb @@ -301,21 +301,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "ZeroDivisionError", - "evalue": "division by zero", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_6083/2354412189.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m1\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" - ] - } - ], + "outputs": [], "source": [ "1/0" ] @@ -340,7 +328,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.116447Z", @@ -354,25 +342,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.132372Z", "start_time": "2019-10-27T12:25:06.119281Z" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "5" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a" ] @@ -386,7 +363,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.149182Z", @@ -407,7 +384,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.164477Z", @@ -421,20 +398,9 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "6.666666666666667" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "variable_die_das_ergebnis_eine_multiplikation_beinhaltet" ] @@ -450,25 +416,14 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.180459Z", "start_time": "2019-10-27T12:25:06.167499Z" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "21" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a = 4\n", "b = 3\n", @@ -486,7 +441,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.195614Z", @@ -500,7 +455,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.211590Z", @@ -514,25 +469,14 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.231469Z", "start_time": "2019-10-27T12:25:06.212585Z" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "12" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a * b" ] @@ -546,20 +490,9 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "i = 1\n", "i = i + 1\n", @@ -568,20 +501,9 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "i += 1\n", "i" @@ -596,20 +518,9 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a = 5\n", "a *= 2\n", @@ -618,20 +529,9 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3.3333333333333335" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a /=3\n", "a" @@ -646,25 +546,14 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.247553Z", "start_time": "2019-10-27T12:25:06.233424Z" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a = 2\n", "b = 5\n", @@ -674,25 +563,14 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2019-10-27T12:25:06.279581Z", "start_time": "2019-10-27T12:25:06.251320Z" } }, - "outputs": [ - { - "data": { - "text/plain": [ - "10.0" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a = 2\n", "b = 5.0\n", @@ -711,20 +589,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1j" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "1j" ] @@ -738,20 +605,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(5+2j)" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "5 + 2j" ] @@ -765,21 +621,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'j5' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_6354/3143615836.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mj5\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mNameError\u001b[0m: name 'j5' is not defined" - ] - } - ], + "outputs": [], "source": [ "j5" ] @@ -894,17 +738,9 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-706.32\n" - ] - } - ], + "outputs": [], "source": [ "# Zeilenabschnitte, die mit einer Raute beginnen sind\n", "# ein Kommentar und werden beim ausführen des Codes\n", @@ -1007,18 +843,9 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "SyntaxError", - "evalue": "invalid syntax (815514423.py, line 7)", - "output_type": "error", - "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_6354/815514423.py\"\u001b[0;36m, line \u001b[0;32m7\u001b[0m\n\u001b[0;31m aufschlageschwindigkeitdessteins = fallzeitdesstein*/erdbeschleunigung # m/s\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" - ] - } - ], + "outputs": [], "source": [ "erdbeschleunigung = -9.81 # m/s**2 \n", "fallhoehedesasteins = -1200 # km\n", @@ -1035,16 +862,9 @@ "source": [ "Wie können Sie Fehler gleich zu beginng vermeiden?\n", " \n", - "Gerade beim schreiben von längeren Code-Blöcken schleichen sich sehr leicht Fehler ein, welche schwerer zu beheben sein können. Zum Glück handelt es sich bei Python ja um eine Interpretersprache, d.h. wir können Code direkt ausführen um Ihn auf seine Richtigkeit zu überprüfen. Daher bietet es sich insbesondere in Jupyter-Notebooks an Zellen regelmäßig auszuführen (z.B. immer wenn Sie zwei Zeilen Code geschrieben haben) um eventuelle Fehler frühzeitig zu erkennen. " + "Gerade beim schreiben von längeren Code-Blöcken schleichen sich sehr leicht Fehler ein, welche schwerer zu beheben sein können. Zum Glück handelt es sich bei Python ja um eine Interpretersprache, d.h. wir können Code direkt ausführen um Ihn auf seine Richtigkeit zu überprüfen. Daher bietet es sich insbesondere in Jupyter-Notebooks an Zellen regelmäßig auszuführen um eventuelle Fehler frühzeitig zu erkennen (z.B. immer wenn Sie zwei Zeilen Code geschrieben haben). " ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "metadata": {}, @@ -1053,7 +873,7 @@ "\n", "Wie eben bereits erwähnt, gibt es neben den Zahlen-Datentypen `int`, `float` und `complex` auch noch den Datentyp einer Zeichenkette `str`. Zeichenketten werden in Programmiersprachen vielseitig verwendet z.B. bei einer Nutzereingabe (z.B. einem Passwort), Dateiname bei einer Installation, oder bei Textrückgaben von Programmen. Letzteres haben Sie bereits in Aufgabe 2 a. mithilfe der `print`-Funktion gesehen.\n", "\n", - "Für das PGP-1 wollen wir uns zunächst darauf beschränken, dass Zeichenketten in so genannten **Formatstrings** dazu genutzt werden können, schönere `print` Rückgaben zu erzeugen, bzw. wir mit Zeichenketten Achsenbeschriftungen an Graphen anbringen können. \n", + "Für das PGP wollen wir uns zunächst darauf beschränken, dass Zeichenketten in so genannten **Formatstrings** dazu genutzt werden können, schönere `print` Rückgaben zu erzeugen, wir mit Zeichenketten Achsenbeschriftungen an Graphen anbringen können, oder Pfade zu Dateien angeben können um Messwerte einzulesen. \n", "\n", "Zunächst erst aber einmal eine einfache Zeichenkette:" ] @@ -1185,7 +1005,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Hierbei zeigt `:` an, dass sie eine spezielle Formatierung verwenden möchten. Die Zahl hinter dem `.` gibt an, wie viele Nachkommastellen Sie anzeigen lassen möchten. Das `f` bedeutet, dass es sich bei der Zahl um eine Gleitkommazahl handelt." + "Hierbei zeigt `:` an, dass sie eine spezielle Formatierung verwenden möchten. Die Zahl hinter dem `.` gibt an, wie viele Nachkommastellen Sie anzeigen lassen möchten. Das `f` bedeutet, dass es sich bei der Zahl um eine \"Fix-Point\" darstellung handelt." ] }, { @@ -1199,7 +1019,49 @@ "Lassen Sie nun Ihre berechneten Werte aus Aufgabe 2 mithilfe von `print` erneut ausgeben. Nutzen Sie jedoch dieses Mal **Formatstrings** für eine schönere und bedeutungsvollere Rückgabe. Achten Sie dabei ins besonders auf:\n", "\n", "* Die Angabe der richtigen Einheiten.\n", - "* Das Runden der berechneten Werte der Anzahl an signifikanten Stellen entsprechend. " + "* Das Runden der berechneten Werte der Anzahl an signifikanten Stellen entsprechend. \n", + " \n", + "
\n", + "
\n", + "\n", + "\n", + "**Lösung Code (click me):**\n", + "\n", + "\n", + "\n", + "```python\n", + " \n", + "# Lösung 3 a.):\n", + "s0 = -1.2 \n", + "\n", + "gE = -9.81\n", + "gM = -1.62\n", + "gS = -274\n", + "\n", + "tE = (s0*2/gE)**0.5\n", + "tM = (s0*2/gM)**0.5\n", + "tS = (s0*2/gS)**0.5\n", + "vS = (tS * gS)*3.6\n", + "# Lösung 3. b.):\n", + " \n", + "print(f'Die Kugel schlägt nach {tE:.3f} s auf der Erdoberfläche auf.')\n", + "print(f'Die Kugel schlägt nach {tM:.2f} s auf der Mondoberfläche auf.')\n", + "print(f'Die Kugel schlägt nach {tS:.4f} s auf der Sonnenoberfläche auf.')\n", + "print(f'Die Kugel ereicht hier eine Geschindigkeit von {vS:.3f} km/h.')\n", + " \n", + "```\n", + "\n", + "
\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Neben dem Formatierungssymbol `f` gibt es noch viele [weitere Möglichkeiten Werte zu formatieren](https://www.w3schools.com/python/ref_string_format.asp). Sollten Sie einmal sich unsicher sein, wie sie etwas mittels Python darstellen oder programmieren können hilft oftmals eine schnelle Suche mit Hilfe ihrer Lieblingssuchmaschine. Python ist eine der am häufigsten genutzten Programmiersprachen weltweit und daher stehen die Chancen gut, dass das Problem oder Fehler welchen Sie zu lösen versuchen bereits schon einmal diskutiert worden sind. Das mag zwar im ersten Moment etwas befremdlich erscheinen, ist jedoch enorm hilfreich. Insbesondere Foren wie [stackoverflow](https://stackoverflow.com/) können hier sehr hilfreich sein. \n", + "\n", + "Wir werden uns noch einmal in der zweiten Lektion etwas mehr mit Operatoren welche wir auf Zeichenketten anwenden können befassen." ] }, { @@ -1210,7 +1072,7 @@ "\n", "Anstatt Berechnungen wie bei einem Taschenrechner immer wieder manuell einzugeben, ermöglicht uns eine Programmiersprache das Definieren von Funktionen. Funktionen können hierbei ähnlich wie mathematische Funktionen definiert und behandelt werden. Im folgenden wollen wir uns dies im Fall des Ohmschen Gesetzes, welches durch \n", "\n", - "$$U(R, I) = R \\cdot I$$ \n", + "$$U(I) = R \\cdot I$$ \n", "\n", "beschrieben wird, angucken. Hierbei wird die Spannung $U$ durch die Variablen $R$ (Widerstand) und $I$ (Strom) beschrieben. Dies gilt auch analog für Funktionen in einer Programmiersprache:" ] @@ -1226,41 +1088,191 @@ }, "outputs": [], "source": [ - "def Spannung(Widerstand, Strom): # U(R,I)\n", - " return Widerstand * Strom # Wiedergabe der Funktion" + "def voltage(current): # U(I)\n", + " resistance = 100 # Ohm\n", + " return resistance * current # Wiedergabe der Funktion" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Bitte beachten Sie, dass die Rückgabe `return` der Funktion mit Hilfe der Tab-Taste eingerückt wurde. Dieser Syntax wird von Python vorgegeben und muss eingehalten werden.\n", + "Hierbei gibt \n", "\n", - "Diese Funktion können wir nun auf Messdaten anwenden. Wir Messen z.B. bei einem Widerstand von $1\\,\\text{k}\\Omega$ einen Strom von $10\\,\\text{mA}$:" + "```python\n", + "def voltage(current):\n", + "```\n", + "\n", + "an, dass wir eine Funktion **def**inieren möchte mit dem Namen `voltage` welche die variable `current` als Argument nimmt. Damit Python weiß, dass sich die folgenden Zeilen auf die Funktion beziehen müssen diese mit Hilfe der Tab-Taste eingerückt wurde. Dieser Syntax wird von Python vorgegeben und muss eingehalten werden. Er sorgt dafür, dass ihr Code übersichtlich und leserlich geschrieben ist. Die Zeile \n", + "\n", + "```python\n", + " resistance = 100 # Ohm\n", + "```\n", + "\n", + "zeigt an, dass wir die Spannung für einen 100 Ohm Widerstand berechnen möchten und die Zeile \n", + "\n", + "```python\n", + " return resistance * current \n", + "```\n", + "\n", + "gibt an welche Ausgabe die Funktion zurückgeben soll. Nach dem wir eine Funktion definiert haben können wir sie folgt nutzen:\n" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-10-27T12:25:06.412442Z", - "start_time": "2019-10-27T12:25:06.402410Z" - } - }, + "metadata": {}, "outputs": [], "source": [ - "# Leider müssen wir hier auf die Einheiten selbst achten.\n", - "# Deshalb ist es ratsam, sich die Einheiten zu den Werten zu notieren.\n", - "U = Spannung(1000, 0.01) # in V \n", - "U " + "voltage(0.1) # Berechnet die benötigte Spannung um 100 mA\n", + "# durch einen 100 Ohm Widerstand fließen zu lassen." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Neben mathematischen Funktionen, können Funktionen in einer Programmiersprache auch viel allgemeinere Aufgaben erfüllen bzw. komplexe Algorithmen beinhalten. Hierfür benötigen wir meist mehr als nur eine Zeile. Um Python verständlich zu machen, dass mehre Zeilen zu einer Funktion gehören müssen wir die entsprechenden Zeilen wie zuvor den `return`-Befehl einrücken." + "Stellen Sie sich vor Sie möchten nicht nur den Strom sondern auch die Spannung variieren. Im obigen Beispiel müssten sie hierzu jedes Mal die Definition des Widerstandes innerhalb der Funktion anpassen \n", + "\n", + "```python \n", + "def voltage(current): # U(I)\n", + " resistance = 250 # Ohm\n", + " return resistance * current # Wiedergabe der Funktion\n", + "```\n", + "\n", + "und die entsprechende Zelle neu ausführen. Dies wäre sehr mühselig und daher sollten solche `hardcoded` Variablen möglichst vermieden werden. Um einen beliebigen Widerstand zu zulassen können Sie die Funktion auch wie folgt definieren:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def voltage(current, resistance):\n", + " return resistance * current \n", + "\n", + "voltage(0.1, 250)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " \n", + "#### Aufgabe 5.a. Umgang mit dem Ohmschen Gesetz:\n", + "\n", + "Bei einem $500\\,\\Omega$ Widerstand wird eine Spannung $U$ von 10, 20 und 50 Volt angelegt. Wie hoch sollte der jeweils entsprechende Strom $I$ ausfallen und welche Leistung wird in dem Widerstand umgesetzt? \n", + "\n", + "Definieren Sie die entsprechende Funktion in Python und berechnen Sie die Werte. Nutzen Sie für die Ausgabe Ihrer Ergebnisse formated-strings.\n", + "\n", + "**Tipp:**\n", + "\n", + "Die Leistung, welche in einem ohmschen Widerstand umgesetzt wird, lässt sich durch\n", + "\n", + "$$P(U, I ) = U \\cdot I $$\n", + "\n", + "berechnen, wobei $U$ die angelegte Spannung und $I$ der elektrische Strom ist. \n", + "\n", + "
\n", + "
\n", + "\n", + "\n", + "**Lösung Zahlenwerte (click me):**\n", + "\n", + "\n", + " \n", + "Strom:\n", + "* I(10, 500) = 0.02 A\n", + "* I(20, 500) = 0.04 A\n", + "* I(50, 500) = 0.10 A\n", + "\n", + "Leistung:\n", + "* P(10, 500) = 0.20 W\n", + "* P(20, 500) = 0.80 W\n", + "* P(50, 500) = 5.00 W\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + "\n", + "\n", + "**Lösung Code (click me):**\n", + "\n", + "\n", + "\n", + "```python\n", + "def power(voltage, current):\n", + " return voltage * current\n", + "\n", + "def current(voltage, resistor):\n", + " return voltage/resistor\n", + "\n", + "print('Strom:')\n", + "print(f'I(10, 500) = {current(10, 500):.2f} A')\n", + "print(f'I(20, 500) = {current(20, 500):.2f} A')\n", + "print(f'I(50, 500) = {current(50, 500):.2f} A')\n", + "\n", + "print('\\nLeistung:') # \\n sorgt für einen Zeilenumbruch\n", + "print(f'P(10, 500) = {power(10, current(10, 500)):.2f} W')\n", + "print(f'P(20, 500) = {power(20, current(20, 500)):.2f} W')\n", + "print(f'P(50, 500) = {power(50, current(50, 500)):.2f} W')\n", + "```\n", + "
\n", + " \n", + " \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Es ist auch möglich für Argumente von Funktionen Standardwerte festzulegen, welche genutzt werden, sofern der Nutzer keine eigenen Angaben macht. Z.B.:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def voltage(current, resistance=100):\n", + " return resistance * current \n", + "\n", + "voltage(0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "voltage(0.1, 250)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hierbei wird nun standardmäßig der Wert 100 Ohm genutzt sofern keine weitere Angabe gemacht wird. In diesem Fall bezeichnet man diese optionalen Argumente der Funktion nicht als `argument` oder kurz `*args` sondern als `keyword argument` oder kurz `**kwargs`. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wir können uns an einem etwas kompliziertem Beispiel vor augenführen wieso dies der Fall ist. Definieren wir uns zunächst eine Funktion mit einem Argument und drei Schlüsselwort-Argumenten: " ] }, { @@ -1274,13 +1286,20 @@ }, "outputs": [], "source": [ - "def complex_function(a, b, c, d):\n", + "def complex_function(a, b=1, c=2, d=3):\n", " result = a + b\n", " result = result * c\n", " result = result / d\n", " return result" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sollten wir nichts anderes spezifizieren wird wie im obigen Beispiel der Standardwert für `b`, `c` und `d` verwendet. " + ] + }, { "cell_type": "code", "execution_count": null, @@ -1292,76 +1311,306 @@ }, "outputs": [], "source": [ - "complex_function(1, 2, 3, 4)" + "complex_function(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Bitte beachten Sie, dass Variablen, welche in einer Funktion definiert und genutzt werden, auch nur dort zur Verfügung stehen. Versuchen Sie, die entsprechenden Variablen im Notebook zu verwenden, werden Sie einen Fehler bekommen." + "Wir können nun die Werte für `b`, `c` oder `d` über die Position des Argumentes angeben..." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2020-02-08T14:01:53.810639Z", - "start_time": "2020-02-08T14:01:53.785432Z" - } - }, + "metadata": {}, "outputs": [], "source": [ - "result" + "complex_function(1, 1, 5) # b=1, c=5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Sollten Sie das Ergebnis dennoch in einer Variablen speichern wollen, können Sie dies natürlich machen:" + "... oder über den Namen des `keyword arguments` und somit den Standardwert für zum Beispiel `b` beibehalten:" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2020-02-08T14:04:10.690109Z", - "start_time": "2020-02-08T14:04:10.670371Z" - } - }, + "metadata": {}, "outputs": [], "source": [ - "result = complex_function(1, 2, 3, 4)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2020-02-08T14:04:10.890200Z", - "start_time": "2020-02-08T14:04:10.870502Z" - } - }, - "outputs": [], - "source": [ - "result" + "complex_function(1, c=5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Für das Grundpraktikum sind längere und kompliziertere Funktionen eher die Ausnahme. Sie werden in Veranstaltungen wie \n", + "Dies geht natürlich auch mit mehren Argumenten gleichzeitig." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "complex_function(1, c=5, d=8)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Neben Argumenten und keyword-Argugmenten können Funktionen auch ohne jegliche Argumente definiert werden. Das gleiche gilt für das `return`-statement. Diese Funktionen werden jedoch eher beim Schreiben von Programmen und weniger beim Auswerten von Messdaten benötigt. Hier ein Beispiel:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def my_func():\n", + " print(1+1)\n", + " \n", + "my_func()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Auch beim Definieren bzw. Aufrufen von Funktionen können verschiedene Fehler auftreten, sofern wir diese Falsch benutzen. Im nachfolgenden wollen wir uns ein paar der beliebteren Fehler angucken." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def my_func(a):\n", + "return a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dieser Fehler ist relative einfach. Er deutet an, dass Python nach `def my_func(a):` eine eingerückte Zeile erwartet. \n", + "\n", + "Beim Aufrufen einer Funktion ist darauf zu achten, dass wir diese auch richtig Aufrufen. Zum Beispiel kann es passieren, dass wir entweder zu wenige oder zu viele Argumente an eine Funktion übergeben... " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def my_func(a, b):\n", + " return a + b\n", + "\n", + "my_func(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... oder gar die falschen Argumente:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "complex_function(1, f=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Damit wir solche Fehler nicht begehen hat auch Python hier eine Hilfe für uns eingebaut. Sie können sich auf mehreren Arten und Weisen anzeigen lassen welche Argumente eine Funktion von uns haben möchte. Zum Beispiel mittels..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "help(complex_function)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... oder ..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "?complex_function" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... oder Sie gehen mit dem Coursor in den Namen der entsprechenden Funktion und drücken hintereinander zweimal die Tasten `shift` und `tab`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "complex_function" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Diese Hilfe-Tools sind insbesondere dann hilfreich sofern Sie Ihnen unbekannte Funktionen aus Erweiterungen für die Standard-Python-Bibliothek verwenden. Diese werden wir im späteren Verlauf noch sehen, wenn wir mit `numpy arrays` und `matplotlib` arbeiten." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Funktionen sind immer dann hilfreich, sofern Sie eine Operation mehr als einmal ausführen müssen. Dabei können Sie Funktionen auch in komplexere Aufgaben bzw. auch andere Funktionen einbinden. Hierdurch können Sie ganze Programme schreiben, welche in der Regel aus einer Verschachtelung von verschiedenen Funktionen besteht." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Betrachten und verstehen Sie das folgende Beispiel.\n", + "\n", + "* Welchen Wert wird am Ende Value haben? \n", + "* Wie oft rufen wir hier die Funktion `funktion1` insgesammt auf?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def funktion1(a):\n", + " return a + 2\n", + "\n", + "def funktion2(bar):\n", + " c = funktion1(bar)\n", + " c = c + 3\n", + " c = funktion1(c)\n", + " return c\n", + " \n", + " \n", + "value = 1\n", + "value = funktion1(value)\n", + "value = funktion2(value)\n", + "value = funktion2(value)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Beim Verschachteln von Funktionen sollten Sie auch immer auf globale und lokale Variablen achten. Lokale variablen sind immer nur in der jeweiligen Funktion gültig. Globale Variablen können auch außerhalb der entsprechenden Funktion genutzt werden. Gehen wir hierfür zurück zu unserem Beispiel der Spannung. Dieses mal jedoch definieren wir den Widerstand als eine globale Variable." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "resistance = 200\n", + "\n", + "def voltage(current):\n", + " return resistance * current \n", + "\n", + "voltage(0.1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Obwohl `resistance` lediglich außerhalb der Funktion definiert ist können wir den Parameter auch innerhalb von `voltage` nutzen da `resistance` für die Funktion `voltage` als eine globale Variable d.h. in einer Ebene überhalt von `voltage` definiert worden ist. Kompliziert? gucken wir uns das nachfolgende Beispiel in welchem wir eine Funktion in einer Funktion definieren an, um das Verhalten etwas genauer zu verstehene:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def funktion3(a):\n", + " bar = 2\n", + " def funktion4():\n", + " return a + bar\n", + " c = funktion4()\n", + " return c\n", + "\n", + "funktion3(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bar" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "funktion4()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wie ihr sehen könnt, ist für uns weder die Variable `b` noch die Funktion `funktion2`. Da diese nur innerhalb sprich lokal von `funktion1` definiert worden sind. Andererseits ist jedoch die variable `b` innerhalb der `funktion2` bekannt da `b` in der gleichen \"Ebene\" wie Funktion `funktion2` definiert worden ist und diese somit für `funktion2` als global angesehen werden kann. \n", + "\n", + "Python folgt dieser Logik, damit wir unseren Programmen eine Struktur geben können und Funktionen, welche in ein und derselben ebene definiert worden sind, miteinander verschachteln können. Im Allgemeinen ist jedoch davon abzuraten globale Parameter zu definieren. Parameter sollten immer innerhalb einer Funktion definiert, oder als Argumente an die Funktion übergeben werden. Dies erhöht die Übersicht und verringert die Fehleranfälligkeit." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Jedoch gilt für das Grundpraktikum: längere und kompliziertere Funktionen sind eher die Ausnahme. Sie werden noch mehr über komplexere Programme, Algorithmen und Klassen in Veranstaltungen wie \n", "\n", "* Computer in der Wissenschaft\n", "* Programmieren für Physiker\n", "* Einführung in die Programmierung\n", "\n", - "noch mehr über Programme und Algorithmen lernen." + "lernen." ] }, { @@ -1370,20 +1619,76 @@ "source": [ "
\n", " \n", - "#### Aufgabe 3. Umgang mit dem Ohmschen Gesetz:\n", + "#### Aufgabe 5.b. Umgang mit dem Ohmschen Gesetz:\n", "\n", - "Bei einem $500\\,\\Omega$ Widerstand wird eine Spannung $U$ von 5, 10, 20 und 50 Volt angelegt. Wie hoch sollte der jeweils entsprechende Strom $I$ ausfallen und welche Leistung wird in dem Widerstand umgesetzt? \n", + "Nehmen Sie an, dass Ihr Widerstand in Aufgabe 5 a. einen Fehler von $+/-20\\,\\Omega$ und ihre angelegte Spannung eine Ungenauigkeit von $+/-10\\,\\%$ aufweist. Wie groß wäre der Fehler des gemessenen Stroms und der Leistung bei ihrer $50\\,$V Messung? Zeigen Sie, dass Sie den Fehler des Stroms und der Leistung als\n", + " \n", + "$$\\Delta I(U,R) = |I| \\cdot \\sqrt{\\bigg(\\frac{\\Delta U}{U}\\bigg)^2 + \\bigg(\\frac{\\Delta R}{R}\\bigg)^2}$$\n", + " \n", + "bzw. \n", "\n", - "Des Weiteren nehmen Sie an, dass Ihr Widerstand einen Fehler von $+/-20\\,\\Omega$ und ihre angelegte Spannung eine Ungenauigkeit von $+/-10\\,\\%$ aufweist. Wie groß wäre der Fehler des gemessenen Stroms bei ihrer $50\\,$V Messung? Benutzen Sie hierfür die Gaus'sche Fehlerfortpflanzung und definieren Sie die entsprechende Funktion in Python.\n", + "$$\\Delta I(U,R) = |P| \\cdot \\sqrt{\\bigg(\\frac{\\Delta U}{U}\\bigg)^2 + \\bigg(\\frac{\\Delta I}{I}\\bigg)^2}$$\n", + " \n", + "schreiben können. Benutzen Sie verschatelte Funktionen um die jeweiligen Fehler zu berechnen.\n", + " \n", + "**Tipp.:**\n", + " \n", + "Sie können den Betrag beim definieren der Python-Funktion vorerst vernachlässigen.\n", "\n", - "**Tipp:**\n", "\n", - "Die Leistung, welche in einem ohmschen Widerstand umgesetzt wird, lässt sich durch\n", + "
\n", + "
\n", + "\n", "\n", - "$$P(U, I ) = U \\cdot I $$\n", + "**Lösung Zahlenwerte (click me):**\n", "\n", - "berechnen, wobei $U$ die angelegte Spannung und $I$ der elektrische Strom ist. \n", - "
" + "
\n", + " \n", + "Strom:\n", + "I(50, 500) = (0.10 +/- 0.01) A\n", + "\n", + "Leistung:\n", + "P(50, 500) = (5.00 +/- 0.73) W\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + "\n", + "\n", + "**Lösung Code (click me):**\n", + "\n", + "\n", + "\n", + "```python\n", + "def power(voltage, current):\n", + " return voltage * current\n", + "\n", + "def delta_power(voltage, current, delta_voltage, delta_current):\n", + " uncertainties = (delta_voltage/voltage)**2 + (delta_current/current)**2\n", + " return power(voltage, current) * uncertainties**0.5\n", + "\n", + "def current(voltage, resistor):\n", + " return voltage/resistor\n", + "\n", + "def delta_current(voltage, resistor, delta_voltage, delta_resistor):\n", + " uncertainties = (delta_voltage/voltage)**2 \n", + " uncertainties += (delta_resistor/resistor)**2 # Etas sparsamer\n", + " return current(voltage, resistor) * uncertainties**0.5\n", + "\n", + "print('Strom:')\n", + "i = current(50, 500)\n", + "di = delta_current(50, 500, 50*0.1, 20)\n", + "print(f'I(50, 500) = ({i:.2f} +/- {di:.2f}) A')\n", + "\n", + "print('\\nLeistung:') \n", + "print(f'P(50, 500) = ({power(50, i):.2f} +/- {delta_power(50, i, 50*0.1, di):.2f}) W')\n", + "```\n", + "
\n", + " \n", + "\n", + "
" ] }, { @@ -1394,15 +1699,6 @@ "Es ist ratsam, gleich von Anfang an Funktionen zu dokumentieren. Hierzu dienen in Python die sogenannten `Doc-Strings`. Sie beinhalten Informationen über die Funktion selbst, ihre verwendeten Parameter und ihre Ausgabe. Zum Beispiel für das Ohmschen Gesetzes würde ein solcher Doc-String wie folgt aussehen:" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Spannung" - ] - }, { "cell_type": "code", "execution_count": null, @@ -1416,7 +1712,7 @@ "source": [ "def Spannung(Strom, Widerstand):\n", " '''\n", - " Diese Funktion berechnet die Spannung eines Ohmschen \n", + " Diese Funktion berechnet die Spannung eines ohm'schen \n", " Widerstands.\n", " \n", " Args:\n", @@ -1434,7 +1730,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Herzlichen Glückwunsch Sie haben das Ende von Lektion 1. erreicht....." + "Hierdurch können Sie die bereits gezeigte Python-Help verwenden, um sich zusätzliche Informationen zu Ihren Funktionen anzeigen zu lassen. Dies kann insbesondere bei größeren Projekten sehr hilfreich sein." ] }, { @@ -1442,7 +1738,25 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "help(Spannung)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "?Spannung" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Herzlichen Glückwunsch Sie haben das Ende von Lektion 1. " + ] } ], "metadata": { diff --git a/Lektion2_Messtabellen.ipynb b/Lektion2_Messtabellen_Einfache_Algorithmen.ipynb similarity index 63% rename from Lektion2_Messtabellen.ipynb rename to Lektion2_Messtabellen_Einfache_Algorithmen.ipynb index 0c3f4d4..c75fcc6 100644 --- a/Lektion2_Messtabellen.ipynb +++ b/Lektion2_Messtabellen_Einfache_Algorithmen.ipynb @@ -542,6 +542,290 @@ "metadata": {}, "outputs": [], "source": [] + }, + { + "cell_type": "markdown", + "id": "1f5981ff", + "metadata": {}, + "source": [ + "## Arbeiten mit Messreihen:\n", + "\n", + "Bisher hat uns das programmieren eher mehr Arbeit gemacht als uns welche abgenommen. Zeitersparnis bekommen wir, wenn wir viele Rechnungen hintereinander ausführen müssen. Hierfür gibt es die **for**-Schleife. Diese Schleife führt die gleichen Zeilen eins Codes wiederholt für die Elemente in einer Liste aus:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "7c1708d8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wert: 1\n", + "Wert: 2\n", + "Wert: 3\n", + "Wert: 4\n", + "Ergebnis: 6\n" + ] + } + ], + "source": [ + "liste = [1, 2, 3, 4]\n", + "\n", + "for wert in liste:\n", + " print('Wert:', wert)\n", + " rechnung = wert + 2\n", + "print('Ergebnis:', rechnung)" + ] + }, + { + "cell_type": "markdown", + "id": "d5d5d551", + "metadata": {}, + "source": [ + "Bei einer Schleife ist darauf zu achten, dass der Anweisungsblock, welcher wiederholt ausgeführt werden soll, mit 4x Leerzeichen eingrückt wurde. Dies entspricht einmal die **Tab-Taste**:\n", + "\n", + "\"Tab-Taste\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "950a88a9", + "metadata": {}, + "outputs": [], + "source": [ + "liste = [1, 2, 3, 4]\n", + "print('Hier läuft das Hauptprogramm')\n", + "\n", + "for wert in liste:\n", + " print('Schleife')\n", + " print('Wert:', wert)\n", + " rechnung = wert + 2\n", + " \n", + "print('Hier läuft wieder das Hauptprogramm')\n", + "rechnung = rechnung + 5\n", + "print('Letztes Ergebnis + 5: ', rechnung)" + ] + }, + { + "cell_type": "markdown", + "id": "98c72ce5", + "metadata": {}, + "source": [ + "Statt das Ergebnis lediglich per `print`-Anweisung darstellen zu lassen, können wir auch unser Wissen um Listen benutzen und die berechneten Werte einer neuen Liste anfügen:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "43275304", + "metadata": {}, + "outputs": [], + "source": [ + "# (Funktion haben wir bereits in der Vorbereitung definiert)\n", + "def Spannung(Strom, Widerstand):\n", + " '''\n", + " Diese Funktion berechnet die Spannung eines Ohmschen \n", + " Widerstands.\n", + " \n", + " Args:\n", + " Strom (float): Der gemessene Strom in mA.\n", + " Widerstand (float): Der Wert des verwendeten Widerstands\n", + " in Ohm.\n", + " \n", + " Returns:\n", + " float: Die berechnete Spannung in V.\n", + " '''\n", + " return Widerstand * Strom/1000" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a7692d4", + "metadata": {}, + "outputs": [], + "source": [ + "Stromwerte = [101, 105, 98, 87, 112] # mA\n", + "Spannungswerte = [] # Einheit? <-- Deshalb Docstrings und Help!\n", + "Widerstand = 100 # Ohm\n", + "\n", + "for Strom in Stromwerte:\n", + " res = Spannung(Strom, Widerstand)\n", + " Spannungswerte.append(res)\n", + "\n", + "Spannungswerte" + ] + }, + { + "cell_type": "markdown", + "id": "c339e688", + "metadata": {}, + "source": [ + "Python ermöglicht uns auch eine kompaktere Schreibweise, die so genannte \"list comprehension\": " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "96656272", + "metadata": {}, + "outputs": [], + "source": [ + "Spannungswerte = [Spannung(Strom, 100) for Strom in Stromwerte]\n", + "Spannungswerte" + ] + }, + { + "cell_type": "markdown", + "id": "c2870b72", + "metadata": {}, + "source": [ + "Wir können auch über mehrere Daten gleichzeitig \"loopen\". Hierzu kann die `zip` Anweisung genutzt werden. `zip` verbindet hierbei die einzelnen Elemente einer Liste wie bei einem Reißverschluss miteinander:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51d82509", + "metadata": {}, + "outputs": [], + "source": [ + "Werte1 = ['A', 'B', 'C', 'D']\n", + "Werte2 = [0, 1, 2, 3]\n", + "\n", + "for w1, w2 in zip(Werte1, Werte2):\n", + " print(w1, ' und ', w2)" + ] + }, + { + "cell_type": "markdown", + "id": "1ceaf5a6", + "metadata": {}, + "source": [ + "Dies kann zum Beispiel dann hilfreich sein, wenn sich mehr als eine Variable ändern soll, z.B. bei einer Messreihe für die Schallgeschwindigkeit in Luft:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "af93a63c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[335.4904, 347.3442, 343.6145, 337.275, 331.6212, 342.0115, 336.2262]\n", + "[335.4904, 347.3442, 343.6145, 337.275, 331.6212, 342.0115, 336.2262]\n" + ] + } + ], + "source": [ + "# Gemessene Werte:\n", + "frequenzen = [30.17, 30.63, 30.01, 29.98, 30.12, 29.87, 29.94] #kHz\n", + "wellenlängen = [11.12, 11.34, 11.45, 11.25, 11.01, 11.45, 11.23] # mm\n", + "\n", + "# Variante 1:\n", + "schallgeschindigkeiten = [] # m/s\n", + "\n", + "for f, l in zip(frequenzen, wellenlängen):\n", + " schallgeschindigkeiten.append(f*l)\n", + "\n", + "print(schallgeschindigkeiten)\n", + "\n", + "# oder Variante 2:\n", + "schallgeschindigkeiten2 = [f*l for f,l in zip(frequenzen, wellenlängen)]\n", + "print(schallgeschindigkeiten2)" + ] + }, + { + "cell_type": "markdown", + "id": "322e67e9", + "metadata": {}, + "source": [ + "Wir können auch die `zip`-Anweisung mit mehr als nur zwei Listen verwenden:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6c8d6f27", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a und 1 und x\n", + "b und 2 und y\n", + "c und 3 und z\n" + ] + } + ], + "source": [ + "l1 = ['a', 'b', 'c']\n", + "l2 = [1, 2, 3]\n", + "l3 = ['x', 'y', 'z']\n", + "\n", + "for i,j,k in zip(l1, l2, l3):\n", + " print(i, 'und', j, 'und', k)" + ] + }, + { + "cell_type": "markdown", + "id": "0f1e9a18", + "metadata": {}, + "source": [ + "
\n", + " \n", + "#### Aufgabe 4.b.: Werte berechnen:\n", + "Kopieren Sie Ihre Lösung von Aufgabe 4.a. aus der Vorbereitung in das Notebook und berechnen Sie nun für die Messwerte aus Aufgabe 4 a. die Leistung $P$ und den Widerstand $R$ sowie deren Fehler. Nutzen Sie hierfür die ausführliche schrebweise der **for**-Schleife im Fall des Widerstands $R$ und den list-comprehension Syntax für die Leistung $P$. Fügen Sie die berechneten Werte als neue Spalten an die Liste *daten* an. \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "8a0add34", + "metadata": {}, + "outputs": [], + "source": [ + "# Hier eine kleine Hilfestellung für den Start:\n", + "# Messwerttabelle aus Aufgabe 4. a.:\n", + "messwert_nummer = list(range(1,7,1))\n", + "spannungs_wert = [12., 11.78, 12.56, 12.34, 12.01, 11.94]\n", + "strom_werte = [110, 98, 102, 124, 105, 95]\n", + "dspannung_wetre = [0.32, 0.15, 0.63, 0.12, 0.20, 0.17]\n", + "dstrom_werte = [10]*len(messwert_nummer)\n", + "widerstand = []\n", + "\n", + "daten = [messwert_nummer, spannungs_wert, strom_werte, dspannung_wetre, dstrom_werte]\n", + "\n", + "# Beispiel für die Berechnung des Widerstandes:\n", + "def res(i, u):\n", + " r = u/i\n", + " return r\n", + "\n", + "for strom, spannung in zip(daten[2], daten[1]):\n", + " widerstand.append(res(strom, spannung))\n", + " \n", + "daten.append(widerstand)\n", + "\n", + "# Jetzt sind Sie gefragt:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "210f65ba", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/Lektion3_Numpy_Arrays.ipynb b/Lektion3_Numpy_Arrays.ipynb new file mode 100644 index 0000000..876982d --- /dev/null +++ b/Lektion3_Numpy_Arrays.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "efc3f58e", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Kapitel_1._Einstieg_in_die_Welt_von_Python.ipynb b/Lektion5_Plotten_mit_Hilfe_von_matplotlib.ipynb similarity index 83% rename from Kapitel_1._Einstieg_in_die_Welt_von_Python.ipynb rename to Lektion5_Plotten_mit_Hilfe_von_matplotlib.ipynb index 2a51c07..3351d1f 100644 --- a/Kapitel_1._Einstieg_in_die_Welt_von_Python.ipynb +++ b/Lektion5_Plotten_mit_Hilfe_von_matplotlib.ipynb @@ -7,242 +7,6 @@ "# Kapitel 1. Einstieg in die Welt von Python:\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In Ihrer Vorbereitung haben Sie bisher die folgenden Konzepte kennengelernt:\n", - "\n", - "* Aufbau eines Jupyter-Notebooks (Aufgabe 1).\n", - "* Einfache Rechenoperationen (Aufgabe 2 a.)\n", - "* Einfache Zeichenketten (engl. Strings) und formatierte Strings (Aufgabe 2 b.).\n", - "* Das Definieren von Funktionen (Aufgabe 3.)\n", - "* Das Definieren von Messtabellen.\n", - "\n", - "Hierauf wollen wir an unserem heutigen Versuchstag aufbauen." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Arbeiten mit Messreihen:\n", - "\n", - "Bisher hat uns das programmieren eher mehr Arbeit gemacht als uns welche abgenommen. Zeitersparnis bekommen wir, wenn wir viele Rechnungen hintereinander ausführen müssen. Hierfür gibt es die **for**-Schleife. Diese Schleife führt die gleichen Zeilen eins Codes wiederholt für die Elemente in einer Liste aus:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-11-04T12:07:49.905202Z", - "start_time": "2019-11-04T12:07:49.889579Z" - } - }, - "outputs": [], - "source": [ - "liste = [1, 2, 3, 4]\n", - "\n", - "for wert in liste:\n", - " print('Wert:', wert)\n", - " rechnung = wert + 2\n", - "print('Ergebnis:', rechnung)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Bei einer Schleife ist darauf zu achten, dass der Anweisungsblock, welcher wiederholt ausgeführt werden soll, mit 4x Leerzeichen eingrückt wurde. Dies entspricht einmal die **Tab-Taste**:\n", - "\n", - "\"Tab-Taste\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-11-04T12:08:53.901374Z", - "start_time": "2019-11-04T12:08:53.885753Z" - } - }, - "outputs": [], - "source": [ - "liste = [1, 2, 3, 4]\n", - "print('Hier läuft das Hauptprogramm')\n", - "\n", - "for wert in liste:\n", - " print('Schleife')\n", - " print('Wert:', wert)\n", - " rechnung = wert + 2\n", - " \n", - "print('Hier läuft wieder das Hauptprogramm')\n", - "rechnung = rechnung + 5\n", - "print('Letztes Ergebnis + 5: ', rechnung)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Statt das Ergebnis lediglich per `print`-Anweisung darstellen zu lassen, können wir auch unser Wissen um Listen benutzen und die berechneten Werte einer neuen Liste anfügen:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# (Funktion haben wir bereits in der Vorbereitung definiert)\n", - "def Spannung(Strom, Widerstand):\n", - " '''\n", - " Diese Funktion berechnet die Spannung eines Ohmschen \n", - " Widerstands.\n", - " \n", - " Args:\n", - " Strom (float): Der gemessene Strom in mA.\n", - " Widerstand (float): Der Wert des verwendeten Widerstands\n", - " in Ohm.\n", - " \n", - " Returns:\n", - " float: Die berechnete Spannung in V.\n", - " '''\n", - " return Widerstand * Strom/1000" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-11-04T12:10:08.503300Z", - "start_time": "2019-11-04T12:10:08.472059Z" - } - }, - "outputs": [], - "source": [ - "Stromwerte = [101, 105, 98, 87, 112] # mA\n", - "Spannungswerte = [] # Einheit? <-- Deshalb Docstrings und Help!\n", - "Widerstand = 100 # Ohm\n", - "\n", - "for Strom in Stromwerte:\n", - " res = Spannung(Strom, Widerstand)\n", - " Spannungswerte.append(res)\n", - "\n", - "Spannungswerte" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Python ermöglicht uns auch eine kompaktere Schreibweise, die so genannte \"list comprehension\": " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-11-04T12:11:40.799393Z", - "start_time": "2019-11-04T12:11:40.783772Z" - } - }, - "outputs": [], - "source": [ - "Spannungswerte = [Spannung(Strom, 100) for Strom in Stromwerte]\n", - "Spannungswerte" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Wir können auch über mehrere Daten gleichzeitig \"loopen\". Hierzu kann die `zip` Anweisung genutzt werden. `zip` verbindet hierbei die einzelnen Elemente einer Liste wie bei einem Reißverschluss miteinander:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-11-04T12:12:42.522873Z", - "start_time": "2019-11-04T12:12:42.507254Z" - } - }, - "outputs": [], - "source": [ - "Werte1 = ['A', 'B', 'C', 'D']\n", - "Werte2 = [0, 1, 2, 3]\n", - "\n", - "for w1, w2 in zip(Werte1, Werte2):\n", - " print(w1, ' und ', w2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dies kann zum Beispiel dann hilfreich sein, wenn sich mehr als eine Variable ändern soll, z.B. bei einer Messreihe für die Schallgeschwindigkeit in Luft:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-11-04T12:13:30.363510Z", - "start_time": "2019-11-04T12:13:30.347888Z" - } - }, - "outputs": [], - "source": [ - "# Gemessene Werte:\n", - "frequenzen = [30.17, 30.63, 30.01, 29.98, 30.12, 29.87, 29.94] #kHz\n", - "wellenlängen = [11.12, 11.34, 11.45, 11.25, 11.01, 11.45, 11.23] # mm\n", - "\n", - "# Variante 1:\n", - "schallgeschindigkeiten = [] # m/s\n", - "\n", - "for f, l in zip(frequenzen, wellenlängen):\n", - " schallgeschindigkeiten.append(f*l)\n", - "\n", - "print(schallgeschindigkeiten)\n", - "\n", - "# oder Variante 2:\n", - "schallgeschindigkeiten2 = [f*l for f,l in zip(frequenzen, wellenlängen)]\n", - "print(schallgeschindigkeiten2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Wir können auch die `zip`-Anweisung mit mehr als nur zwei Listen verwenden:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2019-11-04T12:13:49.912658Z", - "start_time": "2019-11-04T12:13:49.897039Z" - } - }, - "outputs": [], - "source": [ - "l1 = ['a', 'b', 'c']\n", - "l2 = [1, 2, 3]\n", - "l3 = ['x', 'y', 'z']\n", - "\n", - "for i,j,k in zip(l1, l2, l3):\n", - " print(i, 'und', j, 'und', k)" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -251,7 +15,7 @@ " \n", "#### Aufgabe 4.b.: Werte berechnen:\n", "Kopieren Sie Ihre Lösung von Aufgabe 4.a. aus der Vorbereitung in das Notebook und berechnen Sie nun für die Messwerte aus Aufgabe 4 a. die Leistung $P$ und den Widerstand $R$ sowie deren Fehler. Nutzen Sie hierfür die ausführliche schrebweise der **for**-Schleife im Fall des Widerstands $R$ und den list-comprehension Syntax für die Leistung $P$. Fügen Sie die berechneten Werte als neue Spalten an die Liste *daten* an. \n", - "
" + "
" ] }, {