1
0
Fork 0
mirror of https://gitlab.rlp.net/pgp/pgp1-python-einfuehrung synced 2024-10-12 13:24:22 +00:00
pgp1-python-einfuehrung/Lektion1_Definieren_von_Parametern_und_Funktionen.ipynb

1783 lines
58 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lektion 1. Definieren von Parametern und Funktionen:\n",
"\n",
"In unserer heutigen digitalen Welt sind Computer nicht mehr aus unserem Alltag wegzudenken. Ob in der Finanzwelt, Industrie aber auch in der Wissenschaft erledigen Computer in Sekundenschnelle komplizierte Rechnungen und helfen dem Anwender komplizierte Sachverhalte vereinfacht wiederzugeben. Daher empfiehlt es sich insbesondere als Physiker zumindest die Grundlagen einer beliebigen Programmiersprache zu beherrschen.\n",
"\n",
"Im Folgenden werden wir uns gemeinsam die Grundzüge der Programmiersprache **Python** erarbeiten. Ein besonderes Augenmerk liegt hierbei auf den verschiedenen Herausforderungen, die das Analysieren von experimentellen Daten mit sich bringt. Um Sie bestens auf die Anforderungen im **physikalischen Grundpraktikum (PGP)** vorzubereiten, lernen wir im Folgenden wie man:\n",
"\n",
"* einfache Rechnungen mit Python durchführt\n",
"* \"Mathematische\" Funktionen definiert\n",
"* Funktionen auf größere Zahlenmengen anwendet\n",
"* Daten in Form von Graphen richtig darstellt\n",
"* eine Ausgleichsgerade von Datenpunkten berechnen kann.\n",
"\n",
"Damit Sie das neu erlernte Wissen direkt vertiefen können, wird dieses Notebook an verschiedenen Stellen kleinere Aufgaben für Sie bereithalten. Die Aufgaben sind durch orangefarbene Boxen hervorgehoben. Es gilt alle Aufgaben zu bearbeiten!\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Grundlagen zu Python bzw. Jupyter Notebooks:\n",
"\n",
"Bevor wir mit dem eigentlichen Programmieren beginnen, müssen wir uns erst einmal mit unserem so genannten Interpreter (**Jupyter Notebook**) vertraut machen. Bei der Programmiersprache **Python** handelt es sich um eine so genannte **Interpretersprache**. Dies bedeutet, dass eingegebene Befehle, ähnlich wie bei einem Taschenrechner, direkt ausgeführt werden."
]
},
{
"cell_type": "markdown",
"metadata": {
"ExecuteTime": {
"end_time": "2018-11-17T13:26:34.382179Z",
"start_time": "2018-11-17T13:26:34.350979Z"
}
},
"source": [
"<div class=task>\n",
" \n",
"#### Aufgabe 1.: Zum Vertraut werden mit dem Jupyter Notebook\n",
"\n",
"Im folgenden wollen wir erst einmal mit den Grundlagen des Notebooks vertraut machen. Insbesondere wollen wir lernen, wie wir eine Markdown- und eine Code-Zelle erstellen, bearbeiten und ausführen. \n",
"\n",
"* Erstellen Sie zunächst eine Code-Zelle unterhalb dieser Aufgaben-Zelle und berechnen Sie die Summe zweier beliebiger ganzer Zahlen. Gehen Sie dabei wie folgt vor:\n",
" 1. Klicken Sie die Zelle dieser Aufgabe an, sodass die Zelle eine blaue Umrandung bekommt (je nach Bildschirmauflösung könnten Sie nur links einen blauen Balken erkennen). Sie befinden sich nun im so genannten \"Command Modus\". In diesem Modus können Sie mit Hilfe der Pfeiltasten durch das Notebook navigieren oder die Struktur des Notebooks bzw. seiner Zellen mit Hilfe von Tasten/Tastenkombinationen modifizieren.\n",
" 2. Benutzen Sie nun die Taste **B**, um eine Code-Zelle unterhalb (**B**elow) dieser Zelle zu erstellen. Sie werden feststellen, dass Ihr Navigator direkt zu der neu erstellten Zelle springt (blaue Umrandung).\n",
" 3. Um nun diese neu erstellte Code-Zelle zu editieren, klicken Sie diese mit dem Mauszeiger an. Die Zellenumrandung sollte von Blau auf Grün wechseln. Dies zeigt an, dass Sie sich nun im Editiermodus für diese Zelle befinden.\n",
" 4. Nun können Sie die Summe aus zwei beliebigen ganzen Zahlen mithilfe des Syntax\n",
" ```python\n",
" 3 + 5\n",
" ```\n",
" berechnen.\n",
" 5. Um diese Code-Zelle auszuführen, müssen Sie anschließend die Tastenkombination: **STRG + ENTER** oder **SHIFT + ENTER** benutzen. Das Ergebnis wird direkt unterhalb der Zelle angezeigt.\n",
" \n",
" \n",
"* Erstellen Sie nun eine Markdown-Zelle oberhalb ihrer Code-Zelle. Hierfür müssen Sie wie folgt vorgehen: \n",
" 1. Klicken Sie die zuvor erstellte Code-Zelle an. Die Zelle sollte eine grüne Umrandung anzeigen, da Sie sich nach wie vor im Editiermodus befinden.\n",
" 2. Drücken Sie die **ESC**-Taste, um vom Editier- in den Command-Modus zu wechseln (blaue Umrandung).\n",
" 3. Drücken Sie nun die Taste **A**, um eine neue Code-Zelle oberhalb (**A**bove) Ihrer angewählten Zelle zu erstellen. Der Navigator wird wieder automatisch zu der neu erstellten Zelle springen.\n",
" 4. Drücken Sie nun die Taste **M**, um die Code-Zelle in eine Markdown-Zelle zu verwandeln. Sie werden feststellen, dass eine Markdown-Zelle im Vergleich zu einer Code-Zelle kein \"In []:\"-Anzeige links der Zelle hat. \n",
" 5. Wechseln Sie nun in der Markdown-Zelle in den Editiermodus (grüne Umrandung), indem Sie diese anklicken. \n",
" 6. Fügen Sie nun die folgenden Objekte in die Markdown-Zelle mit dem entsprechenden Syntax ein:\n",
" * Eine level 1 und level 2 Überschrift\n",
" * Eine numerische Aufzählung (1. 2. und 3.) wobei 1. ein fett gedrucktes Wort 2. ein kursive geschriebenes Wort und 3. ein Wort im true type beinhalten soll.\n",
" * Fügen Sie dem zweiten Aufzählungspunkt (2.) drei nicht nummerierte Unterpunkte hinzu.\n",
" \n",
"**Hinweise:**\n",
"In *Kapitel 0* wurden Ihnen bereits alle benötigten Formatierungen angezeigt. Sie können diese nachgucken, indem Sie in das Notebook *Kapitel 0* wechseln und die entsprechende Markdown-Zelle mittels Doppelklick anwählen. \n",
"<div/> "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Neben diesen nützlichen Befehlen gibt es noch weitere tolle Kürzel wie zum Beispiel:\n",
"* **D + D**, um eine Zelle zu **löschen** \n",
"* **Y** verwandelt eine aktuelle **Markdown**-Zelle in eine **Code**-Zelle\n",
"* **Strg** + **Shift** + **Minus** splittet eine Zelle an der Position des Cursors\n",
"* **F** für \"Find and Replace\" (nützlich wenn Sie zum Beispiel einen Variablennamen austauschen wollen)\n",
"* **I** + **I**, um den *\"Kernel\"* zu stoppen (wichtig falls Sie mal eine unendliche LOOP gebaut haben)\n",
"\n",
"Des Weiteren können Sie [hier](https://www.cheatography.com/weidadeyue/cheat-sheets/jupyter-notebook/) eine Auflistung weiterer Jupyter-Befehle finden."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Noch ein kleiner Tipp:\n",
"\n",
"Diese Notebooks sollen ein interaktives Erlernen von Python ermöglichen. D.h. sollte Ihnen etwas unklar sein nach einem Beispiel erstellen Sie ruhig einfach eine neue Zelle **A**bove oder **B**elow und probieren Sie es aus!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Python als Taschenrechner:\n",
"\n",
"Neben dem einfachen Summieren zweier Zahlen ermöglicht uns Python natürlich auch das Verwenden weiterer Operatoren. Hierbei haben die Operatoren, ähnlich wie in der Mathematik, gewisse Prioritäten (*Punkt vor Strich*). Die Operation mit dem niedrigeren Prioritätswert wird zu erst ausgeführt. \n",
"\n",
"<table border=\"1\" class=\"docutils\">\n",
"<colgroup>\n",
"<col width=\"25%\">\n",
"<col width=\"40%\">\n",
"<col width=\"11%\">\n",
"<col width=\"24%\">\n",
"</colgroup>\n",
"<thead valign=\"bottom\">\n",
"<tr class=\"row-odd\"><th class=\"head\">Operator</th>\n",
"<th class=\"head\">Ergebnis</th>\n",
"<th class=\"head\">Priorität</th>\n",
"</tr>\n",
"</thead>\n",
"<tbody valign=\"top\">\n",
"<tr class=\"row-even\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">+</span> <span class=\"pre\">y</span></tt></td>\n",
"<td>Die Summe von <em>x</em> und <em>y</em></td>\n",
"<td>6</td>\n",
"</tr>\n",
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">-</span> <span class=\"pre\">y</span></tt></td>\n",
"<td>Differenz von <em>x</em> und <em>y</em></td>\n",
"<td>5</td>\n",
"</tr>\n",
"<tr class=\"row-even\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">*</span> <span class=\"pre\">y</span></tt></td>\n",
"<td>Produkt von <em>x</em> und <em>y</em></td>\n",
"<td>4</td>\n",
"</tr>\n",
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">/</span> <span class=\"pre\">y</span></tt></td>\n",
"<td>Quotient von <em>x</em> und <em>y</em></td>\n",
"<td>3</td>\n",
"</tr>\n",
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">%</span> <span class=\"pre\">y</span></tt></td>\n",
"<td>Rest von <tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">/</span> <span class=\"pre\">y</span></tt></td>\n",
"<td>2</td>\n",
"</tr>\n",
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">**</span> <span class=\"pre\">y</span></tt></td>\n",
"<td><em>x</em> bei der Potenz von <em>y</em></td>\n",
"<td>1</td>\n",
"</tr>\n",
"</tbody>\n",
"</table>\n",
"\n",
"Hier ein paar Beispiele:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.038328Z",
"start_time": "2019-10-27T12:25:06.026497Z"
}
},
"outputs": [],
"source": [
"2 / 3 - 2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.053766Z",
"start_time": "2019-10-27T12:25:06.042411Z"
}
},
"outputs": [],
"source": [
"3**2 * 2 - 8 "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-08T13:42:34.321719Z",
"start_time": "2020-02-08T13:42:34.291969Z"
}
},
"outputs": [],
"source": [
"4**0.5"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.069278Z",
"start_time": "2019-10-27T12:25:06.057589Z"
}
},
"outputs": [],
"source": [
"3**2**2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wie in der Mathematik können wir auch bei Python Klammern verwenden, um die Rechenreihenfolge zu ändern:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.085191Z",
"start_time": "2019-10-27T12:25:06.071226Z"
}
},
"outputs": [],
"source": [
"3**2 * 2 - 8 "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"3**2 * (2 - 8 ) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=task>\n",
" \n",
"#### Aufgabe 2. Der Taschenrechner:\n",
"\n",
"Im folgenden wollen wir nun das einfache Rechnen üben berechnen Sie die folgenden Zahlen:\n",
" \n",
"1. $ 155 - 5^2 + 25 \\cdot (5 - 10) $\n",
"2. $ \\sqrt{155} + \\sqrt[3]{14} $\n",
"3. $ 2^{(5-3)^4} $\n",
"\n",
"Um Ihnen nicht nur die Aufgaben, sondern auch die Lösungen bereitzustellen werden Sie die nachfolgende oder ähnliche Felder finden. Sofern Sie ihren Mauszeiger über das Wort bewegen und es anklicken wird der entsprechende Hilfetext erscheinen. Verwenden Sie diese jedoch erst sofern Sie fertig sind oder wirklich nicht mehr weiterwissen. Meistens verbirgt sich die Lösungen zu den Aufgaben in den vorher gezeigten Beispielen. \n",
"\n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Hinsweise (click me):**\n",
"\n",
"</summary>\n",
"\n",
"* Hinweise erstellen Sie für jede Aufgabe eine neue Zelle damit Ihnen das Ergebnis angezeigt wird.\n",
"* Wie können Wurzeln mit Hilfe von Exponenten dargestellt werden?\n",
"\n",
"</details>\n",
" \n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Zahlenwerte (click me):**\n",
"\n",
"</summary>\n",
"\n",
"1. 5\n",
"2. 14.86\n",
"3. 65536\n",
"\n",
"</details>\n",
" \n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Code (click me):**\n",
"\n",
"</summary>\n",
"\n",
"1. `155 - 5**2 + 25 * (5 - 10)` \n",
"2. `155**(1/2) + 14**(1/3)` \n",
"3. `2**((5-3)**4)`\n",
"\n",
"</details>\n",
" \n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sehr schön Sie haben bereits die zweite Aufgabe gemeistert. Leider läuft beim Programmieren nicht immer alles auf Anhieb glatt und Fehler sind keine Seltenheit. Zum erfolgreichen Programmieren gehört es daher unabdingbar dazu, dass Sie Fehlermeldungen verstehen und beheben können. Zum Glück ist Python in dieser Hinsicht eine sehr informative Sprache, so dass Sie mit ein wenig Übung Fehlermeldung ganz leicht verstehen können. Jetzt am Anfang gibt es noch nicht viel, dass wir falsch machen können. Gucken wir uns einmal einen einfachen und beliebten Fehler an:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"1/0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sie sehen das Python den von Ihnen eingebene Befehl nicht ausführen kann und Ihnen daher eine Fehlermeldung mit einem sogennanten Traceback zurückgibt:\n",
"\n",
"![images/Fehlermeldung_div0.png](images/Fehlermeldung_div0.png)\n",
"\n",
"Im Allgemeinen besteht so ein Traceback aus einer Information welcher Aufschluss über die Art des Fehlers gibt, hier `ZeroDivisionError` und einer Zeilen und Code Angebe welche Ihnen die fehlerhafte Codezeile anzeigt. Bei machen Fehlern kann es jedoch auch sein, dass der Fehler sich in einer vorherigen Zeile befindet, jedoch erst später auftritt. Hierfür werden wir später nochmal Beispiele sehen. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kommen wir nun jedoch ersteinmal wieder zum Rechnen zurück. Um unsere Rechnungen besser zu strukturieren, können wir Zahlen auch Variablen zuordnen. Hierzu verwenden wir das Gleichheitszeichen, um einer Variablen (*links*) einem Wert (*rechts*) zuzuordnen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.116447Z",
"start_time": "2019-10-27T12:25:06.102883Z"
}
},
"outputs": [],
"source": [
"a = 5"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.132372Z",
"start_time": "2019-10-27T12:25:06.119281Z"
}
},
"outputs": [],
"source": [
"a"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Variablen können neben einfachen Buchstaben auch mittels komplexerer Ausdrücke dargestellt werden. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.149182Z",
"start_time": "2019-10-27T12:25:06.135155Z"
}
},
"outputs": [],
"source": [
"variable = 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Und wir können neben Zahlen auch das Ergebnis komplexere Rechnungen einer Variablen zuordnen: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.164477Z",
"start_time": "2019-10-27T12:25:06.151305Z"
}
},
"outputs": [],
"source": [
"variable_die_das_ergebnis_eine_multiplikation_beinhaltet = a * variable"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"variable_die_das_ergebnis_eine_multiplikation_beinhaltet"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Theoretisch ist es möglich auch Großbuchstaben und andere Zeichen in Variablennamen zu verwenden. Hier empfiehlt es sich aber den [Standard welcher in der Python-Community](https://www.python.org/dev/peps/pep-0008/#id43) genutzt wird zu halten. Dies führt dazu, dass Code einheitlicher und somit besser verständlich ist. Bei Variablennamen wird empfohlen nur Kleinbuchstaben und Unterstriche für die Worttrennung zu verwenden. Darüber hinaus sollten als Namen nach möglichkeit Nomen verwendet werden. \n",
"\n",
"Bei der Definition von Variablen ist es wichtig, auf die Reihenfolge zu achten. Dies gilt nicht nur innerhalb einer Zelle..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.180459Z",
"start_time": "2019-10-27T12:25:06.167499Z"
}
},
"outputs": [],
"source": [
"a = 4\n",
"b = 3\n",
"a = 7\n",
"\n",
"a * b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... sondern auch für die Reihenfolge, in der die Code-Zellen ausgeführt werden (Angezeigt durch In []:). "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.195614Z",
"start_time": "2019-10-27T12:25:06.183176Z"
}
},
"outputs": [],
"source": [
"a = 7"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.211590Z",
"start_time": "2019-10-27T12:25:06.197947Z"
}
},
"outputs": [],
"source": [
"a = 4"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.231469Z",
"start_time": "2019-10-27T12:25:06.212585Z"
}
},
"outputs": [],
"source": [
"a * b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Rechenoperatoren können auch mit dem `=`-Zeichen verbunden werden. Dies ermöglicht es das Überschreiben einer Variablen zu verkürzen:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i = 1\n",
"i = i + 1\n",
"i"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i += 1\n",
"i"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dies geht mit allen gängigen Rechenoperatoren:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = 5\n",
"a *= 2\n",
"a"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a /=3\n",
"a"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ein weiterer Vorteil (bzw. auch Nachteil) ist, dass Python eine so genannte *dynamische* Datentypenvergabe nutzt. Um besser zu verstehen, was dies bedeutet, gucken wir uns das nachfolgende Beispiel an. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.247553Z",
"start_time": "2019-10-27T12:25:06.233424Z"
}
},
"outputs": [],
"source": [
"a = 2\n",
"b = 5\n",
"c = a * b\n",
"c"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.279581Z",
"start_time": "2019-10-27T12:25:06.251320Z"
}
},
"outputs": [],
"source": [
"a = 2\n",
"b = 5.0\n",
"c = a * b\n",
"c "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In der oberen Zelle ist **c** vom Datentyp `int` (*Integer*), was einer ganzen Zahl entspricht. In der unteren Zelle jedoch ist **c** vom Datentyp `float` (*Floating Point Number*) also eine Gleitkommazahl. Dies liegt daran, das wir in der unteren Zelle **b** als Gleitkommazahl definiert haben. Um uns Arbeit abzunehmen, hat Python für uns im Hintergrund dynamisch entschieden, dass somit **c** ebenfalls vom Typ `float` sein muss. \n",
"\n",
"Neben den primitiven Datentypen `float` und `int` gibt es noch die wichtigen Datentypen `str` (*string*) was einer Zeichenkette entspricht (z.B. Buchstaben, Wörter und Sätze), `complex` für Komplexe Zahlen und `bool` für Wahrheitswerte. Complexe Zahlen lassen sich mit hilfe des Buchstaben `j` wie folgt darstellen:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"1j"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Realer und imaginärer Anteil:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"5 + 2j"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Achtet bei Komplexen Zahlen dadrauf, dass das `j` direkt auf die Zahl folgt. Das folgende führt zu einem Fehler:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"j5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"da Python `j5` als einen Variablennamen interpretiert."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wahrheitswerte werden wir noch etwas später kennenlernen. In aller Regel sind erstmal nur die Typen `int`, `float` und `str` für das Auswerten von Daten von Bedeutung."
]
},
{
"cell_type": "markdown",
"metadata": {
"ExecuteTime": {
"end_time": "2018-11-25T16:19:02.118966Z",
"start_time": "2018-11-25T16:19:02.087766Z"
}
},
"source": [
"<div class=task>\n",
" \n",
"#### Aufgabe 3.a.: Beschleunigte Bewegung\n",
"\n",
"Die zurückgelegte Distanz eines Objekts, welches eine beschleunigte Bewegung ausführt (z.B. der freie Fall einer Kugel in einem Gravitationsfeld), kann mit Hilfe von \n",
"\n",
"$$s(t) = \\frac{1}{2}\\cdot a \\cdot t^2 + v_0 \\cdot t + s_0$$\n",
"\n",
"beschrieben werden. Hierbei beschreibt $t$ die verstrichene Zeit, $a$ die Beschleunigung, $v_0$ die Startgeschwindigkeit und $s_0$ die Startposition des Objekts. Erstellen Sie unterhalb der Aufgabe eine neue Code-Zelle und berechnen Sie die folgenden Werte:\n",
"\n",
"Wie lange bräuchte ein Stift, welcher in einer Höhe von $s_0 = 1.2\\,$m losgelassen wird ($v_0 = 0\\,\\text{m}/\\text{s}$)... \n",
"\n",
"* ... im Schwerefeld der Erde $(g_\\text{E} = - 9.81\\,\\text{m}/\\text{s}^2)$ ...\n",
"* ... im Schwerefeld des Mondes $(g_\\text{M} = - 1.62\\,\\text{m}/\\text{s}^2)$ ...\n",
"* ... im Schwerefeld der Sonne $(g_\\text{S} = - 274\\,\\text{m}/\\text{s}^2)$ ...\n",
"\n",
"... bis er auf dem Boden aufschlägt? (Reibungseffekte sind zu vernachlässigen)\n",
"\n",
"Mit welcher Geschwindigkeit (in km/h) schlägt der Stift auf die Sonnenoberfläche auf? Verwenden Sie sinnvolle Namen für die Parameter.\n",
"\n",
"**Hinweis:** \n",
"Sofern Sie alle Berechnungen innerhalb einer Zelle ausführen wollen, können Sie mithilfe der `print`-Funktion die Ergebnisse \"ausdrucken\"/anzeigen lassen. Gehen Sie dabei wie folgt vor:\n",
"```python\n",
"print(Variablennamen1, Variablennamen2, Variablennamen3 ...)\n",
"```\n",
"oder\n",
"```python\n",
"print(Variablennamen1) \n",
"print(Variablennamen2)\n",
"print(Variablennamen3)\n",
"```\n",
" \n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Zahlenwerte (click me):**\n",
"\n",
"</summary>\n",
"\n",
"* $t_E \\approx 0.5\\,$s\n",
"* $t_M \\approx 1.2\\,$s\n",
"* $t_S \\approx 0.1\\,$s\n",
"* $v_S \\approx -92\\,$ km/h \n",
"\n",
"\n",
"</details>\n",
"\n",
"\n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Code (click me):**\n",
"\n",
"</summary>\n",
"\n",
"```python\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",
"print(tE, tM, tS)\n",
"print(vS)\n",
"```\n",
"\n",
"</details>\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wie Sie vielleicht bemerkt haben, konnten wir bei unserer Rechnung ähnlich wie beim Taschenrechner keine Einheiten angeben. Dies kann manchmal etwas verwirrend sein, gerade wenn Einheiten auch noch ineinander umgerechnet werden. Z.B m/s bzw. s in km/h.\n",
"\n",
"Es gibt in Python die Möglichkeit SI-Einheiten zu verwenden, dies erfordert jedoch das Einbinden von sogenannten „Packages“. Packages sind kleine und große „Erweiterungen“ für Python welche es dem Nutzer ermöglichen neue Dinge, welche über die Standardfunktion von Python hinaus gehen zu verwenden. Hierzu zählen auch das Zeichnen/Plotten von Graphen und das Fitten von Messdaten. Für einfache Anwendungen reicht es jedoch aus Einheiten als Kommentare darzustellen. Darüber hinaus sollten Sie immer Versuchen ein gleichbleibendes Einheitensystem in Ihren Rechnungen zu verwenden und lediglich die Ergebnisse in die gewünschte Form umwandeln. Dies sieht dann wie folgt aus:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Zeilenabschnitte, die mit einer Raute beginnen sind\n",
"# ein Kommentar und werden beim ausführen des Codes\n",
"# ignoriert. \n",
"# Kommentare können vielseitig angewendet werden.\n",
"# Sie können zum einen zur Dokumentation dienen\n",
"# und zum anderen können Sie helfen Probleme im\n",
"# Code zu analysieren und zu verstehen.\n",
"\n",
"\n",
"t_freier_fall = 20 # s\n",
"g_erde = -9.81 # m/s**2\n",
"v_erde = t_freier_fall * g_erde # m/s\n",
"v_erde *= 3.6 # km/h\n",
"print(v_erde)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wie bereits beschrieben können Sie Kommentare auch dazu verwenden gewisse Operationen zu überspringen, um eventuelle Zwischenergebnisse zu testen:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t_freier_fall = 20 # s\n",
"g_erde = -9.81 # m/s**2\n",
"v_erde = t_freier_fall * g_erde # m/s\n",
"# v_erde *= 3.6 # km/h\n",
"print(v_erde)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=task>\n",
" \n",
"#### Aufgabe 4. Erstes Debugging:\n",
"\n",
"Wie bereits erwähnt gehört das Beheben von Fehlern bzw. das sogenannte Debugging leider zum Programmieren dazu. Im Laufe dieses Online-Workshops werden wir Sie daher immer wieder mit Fehlermeldungen konfrontieren, so dass Sie lernen diese zu verstehen und zu beheben. \n",
" \n",
"In der nachfolgenden Zelle haben sich zwei Fehler eingeschlichen führen Sie die Zelle aus um die entsprechenden Tracebacks zu erhalten und beheben Sie nacheinander die Fehler. Wie könnten Sie den Code verändern, um die Fehleranfälligkeit zu reduzieren? \n",
"\n",
" \n",
"**Tipp:**\n",
" \n",
"Sie können sich die Zeilenindex Ihrer Codezelle anzeigen lassen in dem Sie erst die entsprechende Zelle anwählen, mit Hilfe der `ESC`-Taste in den Kommandomodus (blaue Zellumrandung) wechseln und die `L`-Taste verwenden. \n",
" \n",
"Sobald Sie den ersten Fehler behoben haben, führen Sie die Zelle erneut aus um den zweiten Traceback zu erhalten.\n",
" \n",
"\n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Hinweis Fehler 1. (click me):**\n",
"\n",
"</summary>\n",
"\n",
"Bei einem Syntaxfehler handelt es sich meistens um einen Fehler bei dem Operatoren falsch verwendet werden. Achten Sie bei der Fehlermeldung auf die Zeilenangabe und das kleine Dachsymbol, welches Ihnen den Ort des Fehlers aufzeigt. Wie ist denn nochmal die Geschwindigkeit in einer gleichförmig beschleunigten Bewegung definiert? \n",
" \n",
"![images/Fehlermeldung_div0.png](images/A4_syntax_error.png)\n",
"\n",
"</details>\n",
" \n",
" \n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Hinweis Fehler 2. (click me):**\n",
"\n",
"</summary>\n",
"\n",
"Diese Fehlermeldung ist eindeutig. Vergleichen Sie nocheinmal genau die Schreibweise des Parameters in Zeile 2 mit dem fehlerhaften Namen. Wie können Sie die Häufgkeit dieser Art von Fehler am besten reduzieren?\n",
"\n",
"</details>\n",
"\n",
"\n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Zusatzerklärung (click me, aber erst nach lösen der Aufgabe ;-) ):**\n",
"\n",
"</summary>\n",
"\n",
"Ist Ihnen aufgefallen, dass Ihnen zu erst der `SyntaxError` angezeigt wurde obwohl dieser erst in einer späteren Zeile auftritt als der `NameError`? Dies liegt daran, das Python beim ausführen Ihres Codes zunächst den gesammten Code überprüft ob dieser auch Interpretiert werden kann, bevor er ausgeführt wird. \n",
"\n",
"</details>\n",
"\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"erdbeschleunigung = -9.81 # m/s**2 \n",
"fallhoehedesasteins = -1200 # km\n",
"\n",
"fallbeschleunigungmond = -1.62 #m/s**2\n",
"fallzeitmond = (fallhoehedesasteins*2000*fallbeschleunigungmond)**0.5 # s\n",
"fallzeitdesstein = (fallhoehedeassteins*2000*erdbeschleunigung)**0.5 # s\n",
"aufschlageschwindigkeitdessteins = fallzeitdesstein*/erdbeschleunigung # m/s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"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 um eventuelle Fehler frühzeitig zu erkennen (z.B. immer wenn Sie zwei Zeilen Code geschrieben haben). "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Zeichenketten\n",
"\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 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:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.297413Z",
"start_time": "2019-10-27T12:25:06.284068Z"
}
},
"outputs": [],
"source": [
"'Dies ist eine Zeichenkette'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hierbei kann eine Zeichenkette auch alle Symbole enthalten, die euer Interpreter unterstützt. In Jupyter sind dies alle gewohnten Zeichen wie Buchstaben, Zahlen, Sonderzeichen und Leerzeichen: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.328594Z",
"start_time": "2019-10-27T12:25:06.301834Z"
}
},
"outputs": [],
"source": [
"s1 = '0123456789'\n",
"s2 = 'äöü'\n",
"s3 = '*+~`´?ß-@€'\n",
"s4 = 'python 3.7>'\n",
"\n",
"print(s1,s2,s3,s4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Einen **Formatstring** können wir über zwei Arten generieren"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-08T13:40:14.532316Z",
"start_time": "2020-02-08T13:40:14.507294Z"
}
},
"outputs": [],
"source": [
"a = 'eins'\n",
"b = 2\n",
"\n",
"print('Dies ist Syntaxvariante {}'.format(a))\n",
"print()\n",
"print(f'Dies ist Syntaxvariante {b}') "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Neben dem Einfügen von Strings oder Zahlen in eine Zeichenkette können wir die eingefügten Werte auch formatieren:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-08T13:41:34.601805Z",
"start_time": "2020-02-08T13:41:34.577256Z"
}
},
"outputs": [],
"source": [
"pi = 3.1415926535\n",
"\n",
"print(f'Dies ist pi auf 4 signifikante Stellen gerundet: {pi:.4f}')\n",
"print()\n",
"print('Dies ist pi auf 4 signifikante Stellen gerundet: {:.4f}'.format(pi))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... oder sofern Sie eine Rückgabe lieber über mehrere Zeilen ausgeben lassen möchten, können Sie dies wie folgt machen:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-08T13:43:48.431735Z",
"start_time": "2020-02-08T13:43:48.411817Z"
}
},
"outputs": [],
"source": [
"U = 12.0 #V\n",
"dU = 0.1 #V\n",
"I = 0.30 #mA\n",
"dI = 0.01 #mA\n",
"\n",
"R = U/I #kOhm \n",
"dR = R * ((dU / U)**2 + (dI / I)**2)**0.5\n",
"\n",
"print(f'''An einem Widerstand R wurden die folgenden Werte gemessen:\n",
"Spannung: {U}+/-{dU} V\n",
"Strom: {I}+/-{dI} mA\n",
"Hierraus resultiert ein Widerstand von {R}+/-{dR:.2f} kOhm ''') "
]
},
{
"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 \"Fix-Point\" darstellung handelt."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=task>\n",
" \n",
"#### Aufgabe 3.b.: Beschleunigte Bewegung Zusatz\n",
" \n",
"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. \n",
" \n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Code (click me):**\n",
"\n",
"</summary>\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",
"</details>\n",
"</div>"
]
},
{
"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."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Definieren von Funktionen:\n",
"\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(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:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.397242Z",
"start_time": "2019-10-27T12:25:06.383825Z"
}
},
"outputs": [],
"source": [
"def voltage(current): # U(I)\n",
" resistance = 100 # Ohm\n",
" return resistance * current # Wiedergabe der Funktion"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hierbei gibt \n",
"\n",
"```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": {},
"outputs": [],
"source": [
"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": [
"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": [
"<div class=task>\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",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Zahlenwerte (click me):**\n",
"\n",
"</summary>\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",
"</details> \n",
"\n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Code (click me):**\n",
"\n",
"</summary>\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",
"</details> \n",
" \n",
" \n",
"</div>"
]
},
{
"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: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-08T14:00:35.030562Z",
"start_time": "2020-02-08T14:00:35.020705Z"
}
},
"outputs": [],
"source": [
"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,
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-08T14:00:35.310478Z",
"start_time": "2020-02-08T14:00:35.290633Z"
}
},
"outputs": [],
"source": [
"complex_function(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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": {},
"outputs": [],
"source": [
"complex_function(1, 1, 5) # b=1, c=5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... oder über den Namen des `keyword arguments` und somit den Standardwert für zum Beispiel `b` beibehalten:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"complex_function(1, c=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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",
"lernen."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=task>\n",
" \n",
"#### Aufgabe 5.b. Umgang mit dem Ohmschen Gesetz:\n",
"\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",
"$$\\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",
"\n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Zahlenwerte (click me):**\n",
"\n",
"</summary>\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",
"</details> \n",
"\n",
"<br> \n",
"<details markdown=\"1\">\n",
"<summary markdown=\"1\">\n",
"\n",
"**Lösung Code (click me):**\n",
"\n",
"</summary>\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",
"</details> \n",
" \n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Tipp: \n",
"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": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.429738Z",
"start_time": "2019-10-27T12:25:06.416013Z"
}
},
"outputs": [],
"source": [
"def Spannung(Strom, Widerstand):\n",
" '''\n",
" Diese Funktion berechnet die Spannung eines ohm'schen \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": "markdown",
"metadata": {},
"source": [
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"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": {
"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": 4
}