From 396e3a51baee1125158b1a25514513167adc214b Mon Sep 17 00:00:00 2001 From: Malte Woidt <m.woidt@tu-bs.de> Date: Tue, 15 Nov 2022 21:14:44 +0100 Subject: [PATCH] =?UTF-8?q?Dritte=20=C3=9Cbung=20und=20L=C3=B6sung=20f?= =?UTF-8?q?=C3=BCr=20Aufgabe=201=20und=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Uebung01/Uebung01_LSG.ipynb | 588 ++++++++++++++++++ .../{Uebung02.ipynb => Uebung02_LSG.ipynb} | 275 +++++++- Uebung03/OOP-Grundlagen.ipynb | 445 +++++++++++++ Uebung03/Uebung03.ipynb | 218 +++++++ 4 files changed, 1496 insertions(+), 30 deletions(-) create mode 100644 Uebung01/Uebung01_LSG.ipynb rename Uebung02/{Uebung02.ipynb => Uebung02_LSG.ipynb} (81%) create mode 100644 Uebung03/OOP-Grundlagen.ipynb create mode 100644 Uebung03/Uebung03.ipynb diff --git a/Uebung01/Uebung01_LSG.ipynb b/Uebung01/Uebung01_LSG.ipynb new file mode 100644 index 0000000..f32071c --- /dev/null +++ b/Uebung01/Uebung01_LSG.ipynb @@ -0,0 +1,588 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "18aad444-cf2f-4db2-843b-9481d9529894", + "metadata": {}, + "source": [ + "# <font color='blue'>**Übung 1 - Grundlagen Python**</font>" + ] + }, + { + "cell_type": "markdown", + "id": "bb2e9a17-024f-4329-82e7-c185f2163b63", + "metadata": {}, + "source": [ + "## <font color='blue'>**Die Grundlagen von Python Teil 1**</font>\n", + "Dieses Notebook wird in der ersten Übung verwendet. Es stellt den ersten Teil der Python Grundlagen dar. In diesem Notebook geht es um die ersten Gehversuche mit der Programmiersprache Python. Das Notebook besteht, wie alle folgenden, aus einigen Beispielen, die in der Übung erklärt werden. Im Anschluss gibt es Aufgaben zum selber ausprobieren. Da wir im Moment ganz am Anfang der Übung stehen, hat dieses Notebook noch keine zusammenhängende Aufgabe, sondern soll vor allem Grundlagen erläutern. Das wird sich mit den kommenden Übungen ändern. Zu den Übungen gibt es Grundlagen Notebooks, die zum Nachschlagen der wichtigsten Informationen der Übung dienen sollen und teilweise einige Informationen enthalten, die in der Übung aus Zeitgründen nicht ausführlich besprochen werden.\n", + "\n", + "### **Weitere Notebooks, die dir helfen könnten**\n", + "* Jupyter Grundlagen\n", + "* Python Grundlagen\n", + "\n", + "### **Vorkenntnisse**\n", + "* Keine" + ] + }, + { + "cell_type": "markdown", + "id": "70133fc6-40c9-4e4b-b106-f64d2e145e63", + "metadata": {}, + "source": [ + "# <font color='blue'>**Abschnitt 1 - Verwendung von Python als Taschenrechner**</font>\n", + "## <font color='blue'>*Aufgabe*</font>\n", + "Berechne die Oberfläche eines Würfels mit der Kantenlänge 3,2394" + ] + }, + { + "cell_type": "markdown", + "id": "9f8951be-3086-4427-9dc5-be3263af2a58", + "metadata": {}, + "source": [ + "## <font color='blue'>*Lösung*</font>" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "592319ed-cc88-4291-8834-3b3db239f620", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "62.96227415999999" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3.2394**2*6 #Kommazahlen werden mit einem . geschrieben. Ein Würfel hat 6 Flächen. Jede Fläche hat den Inhalt Kantenlänge zum quadrat. Punkt- vor Strichrechnung funktioniert hierbei wie man es erwaten würde" + ] + }, + { + "cell_type": "markdown", + "id": "a55562c9-557d-4864-9fa9-c0090413a8c7", + "metadata": {}, + "source": [ + "## <font color='blue'>*Grundlagen*</font>\n", + "Python ist in diesem Notebook im interaktiven Modus gestartet. In diesem Modus kann das auszuführende Programm Zeile für Zeile eingegeben werden, wobei jede Zeile nach der Eingabe ausgeführt wird. Im einfachsten Fall kann man Python wie einen Taschenrechner verwenden." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57d2a9b3-6be4-4d8e-9ad7-7263b48aae1b", + "metadata": {}, + "outputs": [], + "source": [ + "3+5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48a1c463-27b0-43bc-8b97-395887ed9e5a", + "metadata": {}, + "outputs": [], + "source": [ + "3**4\n", + "6-2.9301" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7a9e863-b61e-48a4-a34c-4e04e826c660", + "metadata": {}, + "outputs": [], + "source": [ + "3+4*3" + ] + }, + { + "cell_type": "markdown", + "id": "da7f9a36-3736-408a-9bb1-93eaddb1d805", + "metadata": {}, + "source": [ + "Die Notebook-Codezellen können auch mehr als eine Zeile enthalten. Bei der Ausführung werden alle Zeilen an den Python-Interpreter geschickt, der sie nacheinander ausführt. In den Beispielen ist zu sehen, dass das Ergebnis der letzten Zeile ausgegeben wird\n", + "Die Ausgaben sind sogenannte Debug-Ausgaben, weil in der letzten Zeile ein Wert \"übrigbleibt\". Alle anderen Werte werden zwar berechnet, gehen aber verloren.\n", + "Um mit den Ergebnissen etwas anzufangen, kann man sie z.B. ausgeben. Die Funktionalität heißt print" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff16400c-027b-460f-a13f-608359e2bf17", + "metadata": {}, + "outputs": [], + "source": [ + "print(3+4)\n", + "print(8+9)\n", + "print(2**4)" + ] + }, + { + "cell_type": "markdown", + "id": "36b551f4-6f32-4e94-9b69-ae2a9a663053", + "metadata": {}, + "source": [ + "Die Werte, die print ausgeben soll, stehen in runden Klammern hinter dem print. Python ist Textzeilen basiert. In jeder Zeile kann nur ein Befehl, also ein print, stehen. Der Befehl kann dabei aber beliebig kompliziert werden.\n", + "Es können nicht nur Berechnungen angestellt werden, sondern auch Werte verglichen werden" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da039e49-2726-4716-a346-75c03beeb7f7", + "metadata": {}, + "outputs": [], + "source": [ + "print (3+7<9*4)" + ] + }, + { + "cell_type": "markdown", + "id": "97149c54-b9e5-4658-9aa9-4065c169f2d3", + "metadata": {}, + "source": [ + "Etwas vorsicht ist geboten, das die Abfrage, ob zwei Werte gleich sind mit einem == durchgeführt wird" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1e7851e-4adc-467e-a14f-55d2591e497e", + "metadata": {}, + "outputs": [], + "source": [ + "print (7*9==53)" + ] + }, + { + "cell_type": "markdown", + "id": "1daeb6f0-29dd-467f-a0ce-ed09177fba97", + "metadata": {}, + "source": [ + "# <font color='blue'>**Abschnitt 2 - Definition von Variablen**</font>" + ] + }, + { + "cell_type": "markdown", + "id": "50800ef0-0245-4fd1-80b2-93c623d4121b", + "metadata": {}, + "source": [ + "## <font color='blue'>*Aufgabe*</font>\n", + "Berechne die Oberfläche, das Volumen und die Länge aller Kanten eines Quaders mit den Abmessungen (HxBxT) 2,3x4,9x2,1\n" + ] + }, + { + "cell_type": "markdown", + "id": "ba41fef8-6c52-4b19-b3ff-bb0a0c507d2c", + "metadata": {}, + "source": [ + "## <font color='blue'>*Lösung*</font>" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e6120a8a-9674-4057-abf7-ec0b362728e4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "52.78\n", + "23.667\n" + ] + } + ], + "source": [ + "h=2.3\n", + "b=4.9\n", + "t=2.1\n", + "flaeche=h*t*2 #Die linke und rechte fläche\n", + "flaeche+=h*b*2 #Die Fläche vorn und hinten\n", + "flaeche+=b*t*2 #Die Fläache oben und unten\n", + "print(flaeche)#die Gesamtfläche ausgeben\n", + "volumen=h*b*t #Das Volumen ist höhe mal breite mal tiefe\n", + "print(volumen)# Volumen ausgeben" + ] + }, + { + "cell_type": "markdown", + "id": "ccd72eba-be65-4441-96c5-2e3c638f8956", + "metadata": {}, + "source": [ + "## <font color='blue'>*Grundlagen*</font>\n", + "Prinzipiell ließe sich die Aufgabe wie die letzte Aufgabe bearbeiten. Das Prolem ist nur, dass der Ansatz keinen Vorteil gegenüber der Verwendung eines Taschenrechners hat. Bis jetzt wurden Werte nur berechnet und ausgegeben. Wir können Werte jedoch auch in Variablen speichern,die wir später wiederverwenden können. Nehmen wir als Beispiel wieder den Würfel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dad88763-7981-476b-8ffd-7feb5ee4eca2", + "metadata": {}, + "outputs": [], + "source": [ + "h=3.2394\n", + "print(h)\n", + "volumen=h**3\n", + "flaeche=h*h*6\n", + "print(volumen)\n", + "print(flaeche)" + ] + }, + { + "cell_type": "markdown", + "id": "0067ed23-13cf-4a45-8de7-964ab7453777", + "metadata": {}, + "source": [ + "Variablen sollten sinvoll benannt werden. Sonderzeichen sind in Variablennamen nicht zulässig und der Name darf nicht mit einer Zahl beginnen\n", + "Wir könnten diese Zellefür andere Kantenlängen schnell verändern und erneut ausführen" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85d667b1-34c3-4ddf-bfcd-2ff7f04c722d", + "metadata": {}, + "outputs": [], + "source": [ + "print (volumen/flaeche)" + ] + }, + { + "cell_type": "markdown", + "id": "345f62ac-aaaf-439b-b9de-b695e17f4f42", + "metadata": {}, + "source": [ + "Variablen aus bereits ausgeführten Zellen sind nach beendigung der Ausführung weiter verfügbar. Ihr Wert kann jederzeit geändert werden. Das = kopiert den Wert einer Variable. Die Variablen sind also nicht dauerhaft gleich" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a9d0b0c-0ac7-49ea-9c01-dd52f5fc2be2", + "metadata": {}, + "outputs": [], + "source": [ + "variable=volumen\n", + "print (volumen)\n", + "print (variable)\n", + "volumen=9\n", + "print (volumen)\n", + "print (variable)" + ] + }, + { + "cell_type": "markdown", + "id": "636203fb-d387-40e3-b566-bfbc3b3488d3", + "metadata": {}, + "source": [ + "Berechnungen werden immer mit dem Wert durchgeführt den die Variable hat, wenn die Zelle ausgeführt hat. Die Zelle die das Oberflächenverhältnis bestimmt gibt jetzt einen anderen Wert aus.\n", + "Variablen können immer statt eines Wertes verwendet werden. Auch die Beispiele mit Vergleichen funktioniert" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c139e606-a307-460a-a85e-4b79d4966839", + "metadata": {}, + "outputs": [], + "source": [ + "print(flaeche==h**2*6)\n", + "print(flaeche==3.2394**2*6)" + ] + }, + { + "cell_type": "markdown", + "id": "f82757ab-69a7-474c-81b4-58fbdf7f450c", + "metadata": {}, + "source": [ + "Beim Vergleich von Fließkommazahlen am PC auf Gleichheit ist etwas Vorsicht geboten. Der Vergleich ist exakt, die Berechnungen unterliegen aber Rundungsfehlern! Diese können relevant werden, wenn mit Zahlen unterschiedlicher Größenordnung gerechnet wird" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdb8e497-c51b-4de1-bd35-6707a1079611", + "metadata": {}, + "outputs": [], + "source": [ + "a=(11**10)/(3**-5)\n", + "b=((3**-5)/(11**10))\n", + "\n", + "print(a==1/b)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9c53e76-5d73-444b-b424-69b493231406", + "metadata": {}, + "outputs": [], + "source": [ + "print(a-1/b)\n", + "print(a)\n" + ] + }, + { + "cell_type": "markdown", + "id": "508ca08a-ae3a-462e-884d-733950eddbe7", + "metadata": {}, + "source": [ + "### *Ein kleiner Tip um später Schreibarbeit zu sparen*\n", + "Beim Programmieren gibt es oft Situationen, in denen man den Wert einer Variablen verändern möchte, indem man z.B. den Wert der Variable mal 6 nehmen möchte. Wenn wir z.B. den Flächeninhalt einer Fläche des obigen Würfels berechnen wollen und dann die Gesamtoberfläche ginge das so" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2972a23a-541f-41a6-9267-f40d3cfaf044", + "metadata": {}, + "outputs": [], + "source": [ + "flaeche=h*h\n", + "print(flaeche)\n", + "flaeche=flaeche*6\n", + "print(flaeche)" + ] + }, + { + "cell_type": "markdown", + "id": "04e27b56-89cc-4b9e-b551-23f4db2beb59", + "metadata": {}, + "source": [ + "Eine Variable kann also auf beiden Seiten des = auftauchen. Auf der rechten Seite mit dem alten Wert bevor ihr der neue Wert zugewiesen wird. Da solche Zeilen in Programmen extrem häufig vorkommen gibt es eine Kurzschreibweise" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee23a3c0-60f0-4c43-bae6-91eb8920a4be", + "metadata": {}, + "outputs": [], + "source": [ + "flaeche=h*h\n", + "flaeche*=6\n", + "print(flaeche)" + ] + }, + { + "cell_type": "markdown", + "id": "16cc99c7-a7f7-42cd-ba6a-8410ef9dfec7", + "metadata": {}, + "source": [ + "Das funktioniert auch mit allen anderen Rechenarten" + ] + }, + { + "cell_type": "markdown", + "id": "43fc8099-4463-4142-8667-53dfdce8daac", + "metadata": {}, + "source": [ + "# <font color='blue'>**Abschnitt 3 - Verwendung von Zeichenketten**</font>" + ] + }, + { + "cell_type": "markdown", + "id": "523caae5-6106-43d9-8568-2147ada140ff", + "metadata": {}, + "source": [ + "## <font color='blue'>*Aufgabe*</font>\n", + "Die bisherigen Beispiele haben wir nur Werte ausgegeben. Ohne das Programm komplett zu verstehen sind diese Werte relativ nutzlos, weil nirgendwo angegeben wird, was sie bedeuten. Erweitere das Programm aus Abschnitt 2 so, dass vor jedem Ausgegebene eine Ausgabe erfolgt die beschreibt, was der Wert bedeutet\n", + "## <font color='blue'>*Lösung*</font>" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c30d3f3e-ab88-4141-88e7-06794115ae2f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Der Quader hat die Abmessungen HxBxT\n", + "2.3\n", + "4.9\n", + "2.1\n", + "Die Oberfläche des Quaders ist\n", + "52.78\n", + "Das Volumen des Quaders ist\n", + "23.667\n" + ] + } + ], + "source": [ + "h=2.3\n", + "b=4.9\n", + "t=2.1\n", + "print (\"Der Quader hat die Abmessungen HxBxT\")\n", + "print(h)\n", + "print(b)\n", + "print(t)\n", + "flaeche=h*t*2 #Die linke und rechte fläche\n", + "flaeche+=h*b*2 #Die Fläche vorn und hinten\n", + "flaeche+=b*t*2 #Die Fläache oben und unten\n", + "print(\"Die Oberfläche des Quaders ist\")\n", + "print(flaeche)#die Gesamtfläche ausgeben\n", + "print (\"Das Volumen des Quaders ist\")\n", + "volumen=h*b*t #Das Volumen ist höhe mal breite mal tiefe\n", + "print(volumen)# Volumen ausgeben" + ] + }, + { + "cell_type": "markdown", + "id": "36e32f85-7977-462f-9ef8-618b186075dd", + "metadata": {}, + "source": [ + "\n", + "## <font color='blue'>*Grundlagen*</font>\n", + "In vielen Programmier-Situationen ist es hilfreich, auch Text ausgeben zu können. Text wird in Python grundlegend anders behandelt als Zahlen. Auch wenn der Text nur Ziffern enthält bleibt er ein Text. Text kann z.B. in Anführungszeichen eingegeben werden" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af7d575d-a213-4dd6-8f49-1ec32cf9d683", + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Hallo Welt\")" + ] + }, + { + "cell_type": "markdown", + "id": "7dc61c90-01c7-4aa0-a61d-704cb4e559bd", + "metadata": {}, + "source": [ + "So kann man die vorherigen Übungsprogramme schon etwas verbessern" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "96820aa0-5539-496b-a626-374962669204", + "metadata": {}, + "outputs": [], + "source": [ + "h=3.2394\n", + "print(\"Ein Würfel mit einer Kantenlänge von:\")\n", + "print(h)\n", + "volumen=h**3\n", + "flaeche=h*h*6\n", + "print(\"hat ein Volumen von:\")\n", + "print(volumen)\n", + "print(\"und eine Fläche von:\")\n", + "print(flaeche)" + ] + }, + { + "cell_type": "markdown", + "id": "dcdc957d-4355-4281-8e7d-797867dc1da3", + "metadata": {}, + "source": [ + "Text lässt sich nicht nur ausgeben, sondern auch in Variablen speichern. Die Variablen lassen sich auch mit den Rechenoperatoren verändern (zumindest mit dem + und dem \\*). Die Bedeutung ist aber eine andere " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97115c66-bb2c-4b4a-80e6-712cd0de260b", + "metadata": {}, + "outputs": [], + "source": [ + "text1=\"hallo\"\n", + "text2=\"welt\"\n", + "print (text1+text2)\n", + "print (text1+\" \"+text2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c65f62bf-0a89-4075-b260-7559edaf2a96", + "metadata": {}, + "outputs": [], + "source": [ + "text3=text1+\" \"+text2\n", + "print(text3*3)" + ] + }, + { + "cell_type": "markdown", + "id": "b6aa71e5-81c7-4b9b-9b95-9d9b457d716d", + "metadata": { + "tags": [] + }, + "source": [ + "# <font color='blue'>**Aufgabe zum selbst probieren**</font>\n", + "Verbessere das Programm zur Quaderberechnung. Wie bisher werden Länge, Breite und Tiefe über drei Variablen vorgegeben. Neben den bisherigen Ausgaben soll das Verhältnis zwischen Oberfläche und Volumen berechnet werden. Außerdem soll die Ausgabe verbessert werden. Im bisherigen Beispiel erfolgt die Ausgabe eines Wertes immer eine Zeile unter der Beschreibung. Die Ausgabe deines Programmes soll zum schluss etwa so aussehen:\n", + "\n", + "```\n", + "Ein Quader mit den Abmessungen (LxBxT): 2.3x3.9x2.1\n", + "hat ein Volumen von 23.667m3\n", + "bei einer Oberfläche von 52.78m2\n", + "Das Verhältnis von Oberfläche zu Volumen ist 2.230109435978379\n", + "Die Gesamtlänge seiner Kanten beträgt 37.2m\n", + "```\n", + "\n", + "Wie viele Dezimalstellen genau ausgegeben werden ist hierbei egal. Eine Lösung um das zu kontrollieren finden wir in späteren Übungen. Wenn die Codezelle mit anderen Werten für Länge, Breite und Tiefe ausgeführt wird, sollen sich die Ausgabewerte entsprechend anpassen" + ] + }, + { + "cell_type": "markdown", + "id": "a69e45f4-0957-40c6-bc3f-3b7808297f76", + "metadata": {}, + "source": [ + "## <font color='blue'>*Lösung*</font>" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa0cced0-059f-4290-8f47-62f7215a929e", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "fe45f476-750e-4ded-81f7-96e6cb63be52", + "metadata": {}, + "source": [ + "### Hinweis zur Aufgabe\n", + "Prinzipiell besteht die Schwierigkeit in der Ausgabe von Text und Zahlen in einer Zeile. Es sind zwei Lösungsmöglichkeiten. Wenn du die Python-Grundlagen zur Hilfe nimmst, kannst du zwei Lösungswege finden. Eine möglichkeit wäre, die Zahlenwerte in Text umzuwandeln und mit den in der Übung gezeigten Hilfsmitteln die Ausgabezeilen \"zusammenzubauen\"" + ] + } + ], + "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.8.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Uebung02/Uebung02.ipynb b/Uebung02/Uebung02_LSG.ipynb similarity index 81% rename from Uebung02/Uebung02.ipynb rename to Uebung02/Uebung02_LSG.ipynb index 370f570..dc145ea 100644 --- a/Uebung02/Uebung02.ipynb +++ b/Uebung02/Uebung02_LSG.ipynb @@ -64,11 +64,54 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "6b0c8c9d-f3b6-47fc-9de7-04f557ed5511", "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Die 25 Fibonacci-Zahl ist 46368\n" + ] + } + ], + "source": [ + "fn_2=0\n", + "fn_1=1#definiert Variablen für die letzte und vorletzte Fibonacci Zahl\n", + "for i in range(3,26):#Eine Schleife, bei der i als Zählvariable bei 3 Anfängt und die Schleife bei i==25 endet\n", + " fn=fn_2+fn_1 #Die aktuelle Fibonaci Zahl ist die Summer der beiden vorhergehenden. Beim ersten Schleifendurchlauf wird also die 3. Berechnet, weswegen i bei 3 startet\n", + " fn_2=fn_1#Für die Berechnung der nächsten Fibonacci-Zahl ist die jetzt letzte Zahl die vorletzte\n", + " fn_1=fn#und die gerade berechnete die letzte bekannte Fibonacci Zahl\n", + "print (\"Die \",i,\" Fibonacci-Zahl ist\",fn)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "da506129-3e45-4420-befb-478572d73bc6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Die 25 Fibonacci-Zahl ist 46368\n" + ] + } + ], + "source": [ + "#Alernativ kann man das ganze auch mit einer while-Schleife implementieren\n", + "fn_2=0\n", + "fn_1=1#definiert Variablen für die letzte und vorletzte Fibonacci Zahl\n", + "i=3#Die erste berechnete Fibonacci-Zahl wird die 3. sein\n", + "while i<=25: #so lange i kleiner oder gleich 25 ist\n", + " fn=fn_2+fn_1 #Die aktuelle Fibonaci Zahl ist die Summer der beiden vorhergehenden. Beim ersten Schleifendurchlauf wird also die 3. Berechnet, weswegen i bei 3 startet\n", + " fn_2=fn_1#Für die Berechnung der nächsten Fibonacci-Zahl ist die jetzt letzte Zahl die vorletzte\n", + " fn_1=fn#und die gerade berechnete die letzte bekannte Fibonacci Zahl\n", + " i+=1# hierbei nicht vergessen, dass die Zählvariable selbst weitergezählt werden muss\n", + "print (\"Die \",i-1,\" Fibonacci-Zahl ist\",fn)#Die Schleife zählt in ihrem letzten durchgang i noch eins weiter hoch, sodass in der Ausgabe i-1 stehen muss, das ließe sich auch anders Programmieren" + ] }, { "cell_type": "markdown", @@ -83,19 +126,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "7309e508-227e-4431-901b-4125b0f8ed65", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "fn_2=0\n", + "fn_1=1\n", + "n=2" + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "8e27cc1a-62c2-4003-a6ab-4c8baff3cfaf", "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Die 7 Fibonacci-Zahl ist 8\n" + ] + } + ], + "source": [ + "fn=fn_2+fn_1\n", + "n+=1\n", + "print (\"Die \",n,\" Fibonacci-Zahl ist\", fn)\n", + "fn_2=fn_1\n", + "fn_1=fn\n" + ] }, { "cell_type": "markdown", @@ -126,11 +187,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "dc85e62c-a188-46ab-b7c5-55fc44d8bbbf", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "def Fib(nr):##Definition eine Funktion mit dem Namen Fib. Ein Parameter. Außerdem ein Hilfe-Text für help(Fib) (der Optional ist)\n", + " \"\"\"\n", + " Diese Funktion berechnet eine Fibonacci-Zahl\n", + " \"\"\"\n", + " fn_2=0#der Inhalt entspricht der Aufgabe 1\n", + " fn_1=1\n", + " for i in range(3,nr+1):#hier Aufpassen. Das Range Intervall enthält die zweite Zahl gerade nicht mehr. Um z.B. die 20 Zahl auszurechnen muss range(3,21) verwendet werden!\n", + " fn=fn_2+fn_1\n", + " fn_2=fn_1\n", + " fn_1=fn\n", + " return fn" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0e9c8780-e30c-4b89-9e46-df58801dc17f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4181" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Fib(20)" + ] }, { "cell_type": "markdown", @@ -191,10 +285,30 @@ "def ausgabe(name,wert):\n", " print(\"Der Wert mit dem Namen \"+name+\" hat den Wert \"+str(wert))\n", "y=10\n", - "ausgabe(\"X\",5)\n", + "ausgabe(\"X\",5)#Diese Zeile\n", "ausgabe(\"Y\",y)" ] }, + { + "cell_type": "code", + "execution_count": 10, + "id": "707035e8-7c5a-4391-9cee-8e62e3a6353f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Der Wert mit dem Namen X hat den Wert 5\n" + ] + } + ], + "source": [ + "name=\"X\"\n", + "wert=5\n", + "print(\"Der Wert mit dem Namen \"+name+\" hat den Wert \"+str(wert))" + ] + }, { "cell_type": "markdown", "id": "8a2f2e31-b96a-4fcd-9ce5-88d9d2c5cee4", @@ -285,7 +399,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 22, "id": "38b648f0-321b-43ec-aeaf-82fd5efdefb7", "metadata": {}, "outputs": [ @@ -480,19 +594,71 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "a13a6dc5-a537-4104-ae5c-6e6fb3700a69", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "def istPrimzahl(nr):#Eine Funktion definieren\n", + " if nr==1:#Überprüfen ob der Parameter gleich 1 war. 1 ist per Definition keine Primzahl\n", + " return False#Falls nr gleich 1 dann False zurückgeben, da 1 keine Primzahl. Das return beendet die Funktion. Daher wird in diesem Fall das folgende gar nicht mehr ausgeführt\n", + " elif nr==0:#Das gleiche für die 0, die auch keine Primzahl ist\n", + " return False\n", + " for t in range(2,nr//2+1):#Für alle Zahlen t von 2 an bis nr//2 (da kann man aufhören da die Zahl durch größere Zahlen als ihre hälfte nicht ganzzahlig teilbar sein kann). Die +1 wieder aus dem selben Grund wie bei den Fibonacci-Zahlen\n", + " if nr%t==0:#Falls die Zahl nr ganzzahlig durch t teilbar ist, ist sie keine Primzahl\n", + " return False#Deswegen in diesem Fall False zurückgeben. Das beendet die Funktion und damit auch die Schleife. WI\n", + " return True#Ist die Funktion bis hierhin ohne return durchgelaufen, was die Zahl nr durch keinen Testteiler teilbar. Sie ist eine Primzahl! Hier liegt der Grund, wieso die Fälle\n", + " #nr==0 und nr==1 gesondert abgefangen werden mussten. in diesen Fällen wäre das range in der Schleife range(2,1), da 0//2==0 und 1//2==0. In diesem Fall wäre die Range\n", + " #leer und die for schleife würde übersprungen bzw. 0 mal ausgeführt . Das würde dann immer ein True als Rückgabewert bedeuten, was in diesen beiden Fällen aber falsch ist." + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "b4c83fc4-ac7f-4384-a442-a7a268696085", "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 ist eine Primzahl\n", + "3 ist eine Primzahl\n", + "5 ist eine Primzahl\n", + "7 ist eine Primzahl\n", + "11 ist eine Primzahl\n", + "13 ist eine Primzahl\n", + "17 ist eine Primzahl\n", + "19 ist eine Primzahl\n", + "23 ist eine Primzahl\n", + "29 ist eine Primzahl\n", + "31 ist eine Primzahl\n", + "37 ist eine Primzahl\n", + "41 ist eine Primzahl\n", + "43 ist eine Primzahl\n", + "47 ist eine Primzahl\n", + "53 ist eine Primzahl\n", + "59 ist eine Primzahl\n", + "61 ist eine Primzahl\n", + "67 ist eine Primzahl\n", + "71 ist eine Primzahl\n", + "73 ist eine Primzahl\n", + "79 ist eine Primzahl\n", + "83 ist eine Primzahl\n", + "89 ist eine Primzahl\n", + "97 ist eine Primzahl\n", + "es gibt 25 Primzahlen\n" + ] + } + ], + "source": [ + "n=0#Ein Zähler für gefundene Primzahlen. Bis jetzt haben wir 0 Primzahlen gefunden\n", + "for x in range(0,101):#x läuft von 0 bis inklusive 100\n", + " if istPrimzahl(x):#Testen ob x eine Primzahl ist\n", + " print(x,\" ist eine Primzahl\")#Falls ja die Zahl ausgeben\n", + " n+=1#Weil eine Primzahl gefunden wurde die Zahl der gefundenen Primzahlen um 1 erhöhen\n", + "print (\"es gibt\",n,\" Primzahlen\")# Ausgeben wie viele Primzahlen wir gefunden haben" + ] }, { "cell_type": "markdown", @@ -531,21 +697,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "62f4cfe0-7e29-42eb-939f-87de2b568c13", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "def statistik(werte):#Eine Funktion statistik definieren. Der Parameter ist eine Liste von Werten\n", + " mean=0#Eine Variable für den Mittelwert\n", + " for x in werte:# x nimmt nacheinander den Wert aller Elemente der Liste an\n", + " mean+=x #Den aktuellen Wert zum Mittelwert hinzuzählen\n", + " mean/=len(werte)#An diesem Punkt ist mean die Summe aller Werte. Für den Mittelwert müssen wir durch die Anzahl der Werte in der Liste teilen\n", + " sigma=0#Eine Variable für die Standardabwichung\n", + " for x in werte:#Wir brauchen noch einmal eine Schleife über alle Werte der Liste\n", + " sigma+=(x-mean)**2#Das quadrat der Differenz von Wert und Mittelwert zur Variable addieren\n", + " sigma/=len(werte)#Und durch die Anzahl der Elemente teilen\n", + " sigma=sigma**0.5#Anschließend die Wurzel berechnen. Das ist hoch 0.5\n", + " return mean,sigma#Den Mittelwert und die Standardabweichung als Ergebnis zrückgeben" + ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 11, "id": "12c1ee6c-2e1f-453f-b530-d89638bf1ecd", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Der Mittelwert ist 0.516335426194055\n", + "Die Standardabweichung ist:0.2891832330043811\n" + ] + } + ], "source": [ "vals=[0.6964376821627082, 0.26266291048512347, 0.6745158617205556, 0.5288863107123398, 0.9274827629604636, 0.5243575061460061, 0.13385032676535535, 0.5411765303585021, 0.8198672857283978, 0.520437008812458, 0.562041573670414, 0.8561634972894122, 0.9623313631899726, 0.31907914320612074, 0.26119438987542387, 0.13520243670788368, 0.09469575247376472, 0.4246904822161435, 0.9133966307845354, 0.6420660225100518, 0.5785388233096391, 0.5238427408012839, 0.6647315475249502, 0.23571241136003973, 0.05961979239799975, 0.2165498289343185, 0.27159399814957363, 0.7655112819065766, 0.3431093024220383, 0.032247101142615864, 0.3015891143198096, 0.8097960606785481, 0.6796579318567529, 0.04436335567039129, 0.3407031394453095, 0.9458530157190131, 0.4218758395390574, 0.800645477912877, 0.7122317776120418, 0.16153560000189693, 0.8135112166616905, 0.6482516503330767, 0.19497040057189519, 0.7385295095967741, 0.5853177365981909, 0.7420310625532276, 0.9973422543876882, 0.6452433133176014, 0.08077974197489635, 0.46872138143040165, 0.4054095407349284, 0.9820027392529405, 0.1336574018638953, 0.7951695379763538, 0.526730196167776, 0.5838599467003179, 0.0101539445719665, 0.48955298718235196, 0.03312143865023964, 0.8037955706420147, 0.3720197208314814, 0.48910812354462607, 0.24786536056996467, 0.1308221105399613, 0.041839203867548025, 0.9577432390272803, 0.5173227078055732, 0.6214831882992236, 0.2735357256248029, 0.6800368701292161, 0.7925116477725586, 0.9995034932317471, 0.5874671327858604, 0.862421214533514, 0.528701106919735, 0.812381203902576, 0.5914815145860267, 0.6983657416025035, 0.9147650053289076, 0.1193325169156918, 0.2749890766516555, 0.7890513406461243, 0.10338960814994036, 0.497040228474409, 0.7482023492365272, 0.5720468814904877, 0.4042269451026068, 0.9831530451459302, 0.15738865410556224, 0.05169634869621442, 0.6801435501291248, 0.3197438911718855, 0.01245122578094271, 0.6284172563073083, 0.9055888582598005, 0.7634333890207554, 0.8039480668851395, 0.03594773926272621, 0.5331691153755076, 0.7424130320454684]\n", - "statistik(vals)" + "mean,sigma=statistik(vals)\n", + "print(\"Der Mittelwert ist\", mean)\n", + "print(\"Die Standardabweichung ist\", sigma,sep=\":\")" ] }, { @@ -559,7 +748,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 43, "id": "565d45c1-30f9-47bc-aed6-c95d29a744fd", "metadata": {}, "outputs": [ @@ -695,7 +884,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 50, "id": "b138b8bb-6766-4e77-ba01-8606459aa438", "metadata": {}, "outputs": [ @@ -704,7 +893,7 @@ "output_type": "stream", "text": [ "9\n", - "[9, 2, 3, 4, 5]\n" + "[9, 2, 3, 4, 5, 9]\n" ] } ], @@ -715,6 +904,7 @@ "var2=var1\n", "var2=12\n", "Liste2[0]=9\n", + "Liste1.append(9)\n", "print (var1)\n", "print (Liste1)" ] @@ -729,7 +919,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 47, "id": "ecc55c5d-e9d2-40aa-b2bd-189f176c19be", "metadata": {}, "outputs": [ @@ -737,15 +927,25 @@ "name": "stdout", "output_type": "stream", "text": [ - "Liste2 ist jetzt eine Zahl mit dem Wert 5\n", - "Liste1 ist weiterhin die Liste [9, 2, 3, 4, 5]\n" + "Liste2 ist jetzt eine Zahl mit dem Wert 5\n" + ] + }, + { + "ename": "NameError", + "evalue": "name 'Liste1' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn [47], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m Liste2\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m5\u001b[39m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mListe2 ist jetzt eine Zahl mit dem Wert \u001b[39m\u001b[38;5;124m\"\u001b[39m,Liste2)\n\u001b[1;32m----> 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mListe1 ist weiterhin die Liste\u001b[39m\u001b[38;5;124m\"\u001b[39m,Liste1,sep\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m:\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;31mNameError\u001b[0m: name 'Liste1' is not defined" ] } ], "source": [ "Liste2=5\n", "print(\"Liste2 ist jetzt eine Zahl mit dem Wert \",Liste2)\n", - "print(\"Liste1 ist weiterhin die Liste\",Liste1)" + "print(\"Liste1 ist weiterhin die Liste\",Liste1,sep=\":\")" ] }, { @@ -828,6 +1028,21 @@ "print(meineListe)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "433c1215-837d-4f41-9816-c1d9475285f6", + "metadata": {}, + "outputs": [], + "source": [ + "meineListe=[1,2,3,4,5]\n", + "#meineFunktion()\n", + "parameter=meineListe\n", + "parameter[0]=10\n", + "#Ende meine Funktion\n", + "print(meineListe)" + ] + }, { "cell_type": "markdown", "id": "73036041-e0cd-48c8-8d8b-2a751e48413d", @@ -951,7 +1166,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/Uebung03/OOP-Grundlagen.ipynb b/Uebung03/OOP-Grundlagen.ipynb new file mode 100644 index 0000000..4018221 --- /dev/null +++ b/Uebung03/OOP-Grundlagen.ipynb @@ -0,0 +1,445 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f0b13807-b3b2-4f55-9581-9f8d4ffaa3b5", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "### **Einleitendes Thema - Struktur und Übersicht mittels Objektorientierter Programmierung**\n", + "Objektorientierte Programmierung folgt der Idee, zusammengehörige Daten (also Variablen) gemeinsam mit Funktionalität in Klassen zusammenzufassen.\\\n", + "Dabei werden mehrere Ziele verfolgt. Zum einen ergibt sich eine einfachere Möglichkeit ein Programm in logische Teilaspekte zu zerlegen. Wir haben mit den Listen schon eine Klasse kennengelernt. Bei der Objektorientierten Programmierung können wir uns eigene Klassen nach belieben definieren. Nehmen wir an, wir wollen die Beziehung mehrerer Menschen untereinander in einem Programm abbilden. Jeder Mensch hat einen Namen, ein Alter, vieleicht Kinder und kann verheiratet sein. Das sind 4 Variablen für jeden Menschen, die zusammengehören. Immer wenn ein weiterer Mensch diesem Programm hinzugefügt wird, müssen diese 4 Variablen definiert werden. Es wäre daher sinvoll, sie auch zusammen zu gruppieren. Das ermöglichen Klassen. Eine Klasse ist eine Art Schablone, z.B. für einen Menschen. Erschaffen wir in unserem Programm einen konkreten Menschen, nennt man diesen eine Instanz der Klasse Mensch. Die 4 Variablen, die zusammengefasst diesen Menschen beschreiben nennt man dann Attribute. Einer Klasse können auch sogenannte Methoden zugeordnet werden. Das sind Funktionen, die spezifisch etwas mit dieser speziellen Klasse machen. Z.B. hat die Klasse ```list``` eine Methode ```append```, die ihr schon kennengelernt habt" + ] + }, + { + "cell_type": "markdown", + "id": "78480fdf-603c-48e5-b671-5b634c94fbaa", + "metadata": {}, + "source": [ + "### **Kompaktes Fallbeispiel - Mensch (human)**" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "58bf74f7-2ed4-49bc-b9a6-cc5ce29bf7a4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Jenny:\n", + "Steffi ist 0 Jahre alt\n", + "Ralph ist 0 Jahre alt\n", + " \n", + "Paul hat keine Kinder\n", + "\n", + "Paul:\n", + "Steffi ist 0 Jahre alt\n", + "Ralph ist 0 Jahre alt\n", + " \n", + "Paul\n", + "Jenny\n", + "Es gibt 4 Menschen\n", + "\n", + "Name: Paul, Alter: 31 Jahre\n" + ] + } + ], + "source": [ + "#Klasse\n", + "class Human(object):#Eine Klasse für Menschen\n", + " # Klassenattribute\n", + " numberOfPeople = 0\n", + " # Konstruktor. Wird automatisch ausgeführt, wenn eine Instanz der Klasse erzeugt wird\n", + " def __init__(self,\n", + " name, \n", + " age):\n", + " # Objektattribute\n", + " self.name = name\n", + " self.age = age\n", + " self.children = []\n", + " self.marriagePartner = None\n", + " Human.numberOfPeople += 1\n", + " # Klassenmethoden\n", + " def getNumberOfPeople():\n", + " print(f\"Es gibt {Human.numberOfPeople} Menschen\\n\")\n", + " \n", + " # Objektmethoden\n", + " def givingBirth(self, \n", + " name):\n", + " child=Human(name,age=0)\n", + " self.children.append(child)\n", + " return child\n", + " \n", + " \n", + " def seeChildren(self):\n", + " if self.children != []:\n", + " print(f\"{self.name}:\")\n", + " for child in self.children:\n", + " print(f\"{child.name} ist {child.age} Jahre alt\" )\n", + " print(\" \")\n", + " else: print(f\"{self.name} hat keine Kinder\\n\")\n", + " \n", + " def marry(self, marriagePartner):\n", + " self.marriagePartner = marriagePartner\n", + " marriagePartner.marriagePartner = self\n", + " \n", + " def seeMarriagePartner(self):\n", + " if self.marriagePartner != None:\n", + " print(self.marriagePartner.name)\n", + " \n", + " #Spezielle Objektmethode\n", + " def __repr__(self):\n", + " outstring = f\"Name: {self.name}, Alter: {self.age} Jahre\"\n", + " return outstring\n", + " def __del__(self):\n", + " Human.numberOfPeople -= 1\n", + "\n", + "# Demonstration der Funktionalitaet\n", + " \n", + "jenny = Human(\"Jenny\", 32)#Erzeugt eine Instanz der Klasse Human\n", + "paul = Human(\"Paul\", 31)\n", + "\n", + "jenny.givingBirth(\"Steffi\")#Ruft eine Objektmethode auf (bzw. nutzt Funktionalität, die ein Mensch zur Verfügung stellt)\n", + "jenny.givingBirth(\"Ralph\")\n", + "\n", + "jenny.seeChildren()\n", + "paul.seeChildren()\n", + "\n", + "paul.children = jenny.children\n", + "paul.seeChildren()\n", + "\n", + "jenny.marry(paul)\n", + "\n", + "jenny.seeMarriagePartner()\n", + "paul.seeMarriagePartner()\n", + "\n", + "Human.getNumberOfPeople()#Auch die Klasse als ganzes kann sogenannte Klassenmethoden besitzen\n", + "\n", + "# Definierte spezielle Methode __repr__ erlaubt direkte Ausgabe von Objekten des Typs Human\n", + "print(paul)" + ] + }, + { + "cell_type": "markdown", + "id": "9837909c-0cc2-43bd-9692-bb149a7a87ba", + "metadata": {}, + "source": [ + "---\n", + "# **Übersicht - Objektoriente Programmierung mit Python**\n", + "In diesem Grundlagen Notebook wird ein Überblick über das Objekt orientierte Programmieren (OOP) gegeben. Wir beschäftigen uns mit dem Erstellen von Klassen, zusammen mit Ihren Attributen und Methoden. \n", + "Die wichtige Konstruktormethode ```__init__(self, ...)``` wird eingeführt und es werden verschiedene Beispiele für Klassen gegeben." + ] + }, + { + "cell_type": "markdown", + "id": "6f8e9e7e-e6f8-4f62-a531-5912723861ff", + "metadata": { + "tags": [] + }, + "source": [ + "### **Lernziele des Notebooks**\n", + "* Klassen und Objekte\n", + "* Attribute\n", + " * statische Attribute/ Klassenattribute\n", + " * Für Konstanten\n", + " * default-Werte\n", + " * Überblick aller Objekte\n", + " * Objektattribute/ Instanzvariablen\n", + "* Methoden\n", + " * Klassenmethoden\n", + " * Objektmethoden\n", + " * Konstruktor\n", + " * magic methods (Definition von Operatoren)" + ] + }, + { + "cell_type": "markdown", + "id": "77967f78-0ab4-4922-81a2-0e05975daf87", + "metadata": { + "tags": [] + }, + "source": [ + "### **Klassen und Objekte**\n", + "\n", + "Klassen kann man sich wie selbst definierte (komplexe) Datentypen vorstellen. Die Objekte sind dann Variablen dieses Datentyps. Im Fallbeispiel wurde z.B. die Klasse ```Human``` definiert, ```jenny``` und ```paul``` werden dann als Objekte dieser Klasse instanziiert. Es ist eine Konvention, Klassennamen mit einem Großbuchstaben zu beginnen, und Objektnamen mit einem Kleinbuchstaben zu beginnen. \n", + "\n", + "Für eine Klassendefinition reicht prinzipiell ein Klassenname aus\n", + "``` python\n", + "class ExampleClass:\n", + " pass\n", + "```\n", + "> Mit dem Stichwort ```pass``` wird hier ein Platzhalter für noch kommenden Code erzeugt, mit dem wir später der Klasse Elemente hinzufügen werden. <br>\n", + "\n", + "Ein Objekt ```exampleObject``` der Klasse ```ExampleClass``` kann nun mittels\n", + "```python\n", + "exampleObject = ExampleClass()\n", + "```\n", + "initialisiert werden." + ] + }, + { + "cell_type": "markdown", + "id": "d48b0115", + "metadata": { + "tags": [] + }, + "source": [ + "### **Attribute**\n", + "\n", + "Attribute sind Variablen, die zu einer Klasse oder einem Objekt gehören. Sie können beispielsweise die Eigenschaften eines Objektes beschreiben, wie zum Beispiel in dem Fallbeispiel das Alter ```self.age```.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "a7be4b61-84a2-41b8-abfc-fbcfc2d79f5f", + "metadata": { + "tags": [] + }, + "source": [ + "#### **Objektattribute - Instanzvariablen**\n", + "Um den Objekten einer Klasse eigene Attribute zuzuordnen, werden Variableninitialisierungen innerhalb einer Klassendefinition in die Definition des Klassen-Konstruktors ```__init__(self, ...)``` (vgl. Abschnitt zu Methoden) geschrieben:\n", + "```python\n", + "class ExampleClass:\n", + " def __init__(self, exampleValue): # Konstruktordefinition\n", + " self.exampleObjectAttribute = exampleValue # Objektattribut-Initialisierung\n", + "```\n", + "> Jedes Objekte der Klasse ```ExampleClass``` hat ein individuelles Objektattribute```exampleObjectAttribute```.<br>\n", + "> Objektattribute werden auch Instanzvariablen genannt. <br>\n", + "> Ein Objektattribut kann mittels der Punktnotation ```exampleObject.exampleObjectAttribute``` aufgerufen werden und so im Hauptprogramm oder auch dann innerhalb der Klasse mit self.exampleObjectAttribute verwendet werden." + ] + }, + { + "cell_type": "markdown", + "id": "cd73425a-507d-4c1f-8cb2-68b31a5a5540", + "metadata": { + "tags": [] + }, + "source": [ + "#### **Klassenattribute - statische Attribute**\n", + "Um einer gesamten Klasse Attribute zuzuordnen, werden Variableninitialisierungen innerhalb der Klassendefinition geschrieben:\n", + "```python\n", + "class ExampleClass:\n", + " exampleClassAttribute = 0 # Klassenattribut\n", + "```\n", + "> Das Klassenattribut ```exampleClassAttribute``` teilen sich alle Objekte der Klasse ```ExampleClass```.<br>\n", + "> Klassenattribute werden auch statische Attribute genannt. <br>\n", + "> Das Klassenattribute kann mittels ```ExampleClass.exampleClassAttribute``` aufgerufen werden und so dann innerhalb der Klasse oder auch im Hauptprogramm von allen Objekten der Klasse verwendet werden." + ] + }, + { + "cell_type": "markdown", + "id": "5b8aef64-e792-4cf5-a4f9-60f11af3d453", + "metadata": {}, + "source": [ + "#### **Methoden**\n", + "\n", + "Methoden sind Funktionen einer Klasse, die auf die Klassen- und Objektattribute zugreifen können. Sie werden genutzt, um mit der Klasse verbundene Operationen durchzuführen.\n", + "\n", + "Der Konstruktor ```__init__(self, ...)``` ist beispielsweise eine Methode seiner Klasse und wird bei der Initialisierung eines Objektes von diesem aufgerufen. \n", + "Es können jedoch auch eigene Methoden formuliert werden.\n", + "Dazu werden mit \"Funktionsdefinitionen\" innerhalb der Klassendefinition neue Methoden erzeugt.\n", + "Eine Funktion, deren Definition innerhalb einer Klassendefinition steht, wird somit Methode genannt und wird auch anders verwendet als eine reguläre Funktion:\n", + "```python\n", + "class ExampleClass:\n", + " exampleClassAttribute = 0 # Klassenattribut\n", + " \n", + " def __init__(self, exampleValue): # Konstruktordefinition\n", + " self.exampleObjectAttribute = exampleValue\n", + " \n", + " def exampleClassMethod(): # Klassenmethodendefinition\n", + " ExampleClass.exampleClassAttribute += 1\n", + " \n", + " def exampleObjectMethod(self):\n", + " self.exampleObjectAttribute = 10\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "4b39618d-5a2c-4310-b4d9-a67e05ecc4b0", + "metadata": {}, + "source": [ + "#### **Punktnotation: Methodenaufrufe und Attributzugriffe**\n", + "Methoden können von Objekten, oder manchmal auch Klassen, aufgerufen werden. \n", + "Dazu wird die \"dot-notation\" verwendet, also die Punktnotation. \n", + "Möchte man mit einem Objekt ```exampleObject``` der Klasse ```ExampleClass``` die Methode ```exampleObjectMethod()``` der Klasse ```ExampleClass``` aufrufen, geschieht das mit der Punktnotation: ```exampleObject.exampleObjectMethod()```. \n", + "Dabei wird eine Referenz, auf das aufrufende Objekt selber, lokal beim Methodenaufruf in ```self``` gespeichert. \n", + "Während nun die Methode ```exampleObjectMethod()``` ausgeführt wird, steht somit das Objekt ```exampleObject``` über ```self``` weiterhin zur Verfügung.\n", + "Es können somit weitere Methoden aufgerufen werden oder es kann auch auf Attribute zugegriffen werden.\n", + "Das passiert ohne, dass beim Schreiben der Methoden bekannt sein musste, welche Objekte später diese Methode aufrufen werden. \n", + "Da erst bei Ausführung der Methode die Referenz des aufrufenden Objektes in ```self``` lokal gespeichert wird.\\\n", + "Auch auf die Attribute eines Objektes wird mit der Punktnotation zugegriffen.\n", + "Entweder mit dem Objekt direkt selber ```exampleObject.exampleObjectAttribute``` oder über die lokale Referenz ```self.exampleObjectAttribute```." + ] + }, + { + "cell_type": "markdown", + "id": "e62551be-2e37-4a4f-9416-4d0f69eac24c", + "metadata": {}, + "source": [ + "#### **Klassenmethoden**\n", + "Ist der Inhalt einer Methode unabhängig von dem Objekt das sie aufruft, dann wird/muss kein ```(self...)``` in der Parameterliste übergeben werden. \n", + "Es handelt sich bei einer Methode um eine Klassenmethode, wenn kein ```(self...)``` in der Parameterliste vorhanden ist. \n", + "Bei Klassenmethoden werden keine Attribute eines aufrufenden Objektes verwendet oder bearbeitet, da die Information eines aufrufenden Objektes, also das ```self```, nicht vorhanden sind.\\\n", + "Klassenmethoden können über den Klassennamen aufgerufen werden: ```ExampleClass.exampleClassMethod()```.\n", + "Jedoch nicht über Objekte der Klasse: ~```exampleObject.exampleClassMethod()```~. Bei Ersterem war nie die Information eines aufrufenden Objektes von Interesse. Bei Letzterem findet die Information, über das aufrufende Objekt, keinen passenden Parameter in der Klassenmethodendefinition, wo diese Info gespeichert werden könnte, sodass die Methoden-Signatur nicht zum Methoden-Aufruf passt.\n", + "```python\n", + "class ExampleClass:\n", + " exampleClassAttribute = 0 # Klassenattribut\n", + " \n", + " def __init__(self, exampleValue): # Konstruktordefinition\n", + " self.exampleObjectAttribute = exampleValue\n", + " \n", + " def exampleClassMethod(): # Klassenmethodendefinition\n", + " ExampleClass.exampleClassAttribute += 1\n", + " \n", + " def exampleObjectMethod(self): # Objektmethodendefinition\n", + " self.exampleObjectAttribute = 10\n", + " \n", + "ExampleClass.exampleClassMethod() # Klassenmethodenaufruf mittels Klasse \n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "45900822-0657-41b7-8807-a42541c81043", + "metadata": {}, + "source": [ + "#### **Objektmethoden**\n", + "Objektmethoden müssen bei der Definition in ihrer Parameterliste immer als erstes Argument eine Referenz auf das Objekt selbst haben, um auf dessen Elemente zugreifen zu können. Diese Referenz ist ```self```. Bei Aufruf der Objektmethode, wird das ```self``` automatisch übergeben und wird daher nicht explizit in der Parameterliste angegeben. Die Methode ```exampleObjectMethof(self)``` dem Beispiel aus dem vorherigen Abschnitt würde also im Programm folgendermaßen aufgerufen:\n", + "```python\n", + "exampleObject = exampleClass()\n", + "exampleObject.exampleObjectMethod() \n", + "```\n", + "\n", + "Es ist übrigends nicht nötig, die Referenz auf das eigene Objekt ```self``` zu nennen. Es ist einfach immer der erste Parameter der Objektmethode. Die Benennung ist allerdings eine Konvention und es ist sinnvoll sich daran zu halten" + ] + }, + { + "cell_type": "markdown", + "id": "fd40aee3", + "metadata": {}, + "source": [ + "#### **Spezielle Methoden - Magic methods**\n", + "Klassen kann man sich wie einen selbst definierten Datentypen vorstellen. Datentypen, die wir bereits kennen, können oft mit Operatoren interagieren. Dabei hängt es vom Datentyp ab, was der Operator genau tut. Z.B. können zwei Listen durch ein + aneinandergehängt werden. Ein solches Verhalten kann man auch mit selbst definierten Klassen erreichen. Neben Operatoren gibt es auch verschiedene vordefinierte Funktionen, die ähnliches Verhalten zeigen. Z.B. ```len()``` oder ```print```.\\\n", + "Um die Verwendung von Operatoren zusammen mit eigenen Klassen zu ermöglichen müssen spezielle Objektmethoden programmiert werden, sogenannte \"magic methods\". Betrachten wir die Programmzeile\\\n", + "```a + b```\n", + "Falls a keine einfache Zahl ist (dort funktioniert der Mechanismus etwas anders) wird diese Zeile automatisch ersetzt durch:\n", + "```a.__add__(b)```\n", + "Also durch einen Methodenaufruf. Sofern die Klasse, von der a eine Instanz ist, diese Objektmethode implementiert, kann sie zusammen mit Operatoren verwendet werden. Das funktioniert nicht nur für das +. Eine Tabelle mit einigen magic methods\n", + "\n", + "|Operator | Methode| Anmerkung|\n", + "|---------|----------|----------|\n", + "|+ |__add__ | |\n", + "|- |__sub__ | |\n", + "|/ |__truediv__| |\n", + "|* |__mul__ | |\n", + "|//| __floordiv__| |\n", + "|% |__mod__| |\n", + "|** |__pow__| |\n", + "|>= | __ge__| |\n", + "|< | __lt__| |\n", + "|==| __eq__| |\n", + "| | __repr__| gibt die Zeichenkette zurück, die durch print ausgegeben wird|\n", + "| |__init__ | wird automatisch beim erzeugen eines Objekts aufgerufen |\n", + "| |__del__ | wird automatisch aufgerufen, wenn das Objekt gelöscht wird |\n", + "| [] | __getattr__(self,index),__setattr__(self,index,val) | wird durch den Indexoperator aufgerufen|\n", + "| | __len__| wird aufgerufen, um die Länge des Objektes mit len zu ermitteln|\n", + "\n", + "\n", + "Da die Methoden Objektmethoden sind muss ihr erster Parameter das angesprochene ```self``` sein. Weitere Parameter kommen je nach Operator hinzu. Alle Rechenoperatoren sind z.B. binäre Operatoren. Die magic methods haben einen zweiten Parameter, der das Objekt auf der rechten Seite des + enthält\n", + "\n", + "Die verfügbaren Magic methods sind fest bestimmt (siehe Liste ganz unten auf https://www.tutorialsteacher.com/python/magic-methods-in-python), und beginnen und enden immer mit zwei Unterstrichen ```__```. Die bereits bekannte Methode ```__init__()``` gehört demnach auch zu diesen Methoden. Im Fallbeispiel oben ist dies beispielhaft für die Verwendung in ```print( )``` gezeigt. Das ist die Methode ```__repr__(self)```.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "20a2b2ac-6118-46fd-ba80-771d9e10dc64", + "metadata": {}, + "source": [ + "> <font color='grey'>*Weiter Informationen zu Klassen können in der [offiziellen Dokumentation von Python](https://docs.python.org/3/tutorial/classes.html) nachgelesen werden*</font>" + ] + }, + { + "cell_type": "markdown", + "id": "97f327d5-f6f9-4c84-ab4a-c2627003cf60", + "metadata": {}, + "source": [ + "#### **Vererbung**\n", + "Vererbung ist ein Feature, das in Python nicht so häufig verwendet wird. Es ist möglich aus selbst definierten Klassen ganze Hierarchien aufzubauen. Um die Idee zu verdeutlichen konnen wir auf das Beispiel mit der Klasse Human zurück. Man könnte sagen ein Student ist auch ein Mensch, ein Mensch ist aber nicht zwingend ein Student. Ein Student teilt alle Merkmale eines Menschen, kann aber zusätzliche Attribute und Methoden besitzen. In Python kann diese Beziehung folgendermaßen ausgedrückt werden (Die Zelle funktioniert nur, wenn du die Zelle am Anfang des Notebooks ausführst, da die Klasse Human definiert sein muss)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "880f9feb-225f-4e98-ac22-5baa0039404c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Es gibt 5 Menschen\n", + "\n", + "Name: Jan, Alter: 21 Jahre\n", + "Ich habe gerade zu viel zu tun\n" + ] + } + ], + "source": [ + "class Student(Human):#Die runde Klammer bedeutet, dass die Klasse Student alle Attribute und Methoden von der Klasse Human erbt\n", + " def __init__(self, name, age, semester=None):#Einzelne Methoden können in der Klasse Student neu definiert werden. Z.B. der Konstruktor\n", + " super().__init__(name, age) #Damit die Klasse korrekt funktioniert muss der Original-Konstruktor von Human aufgerufen werden\n", + " if semester != None:\n", + " self.semester = semester\n", + " else: self.semester = 0\n", + " def marry(self, marriagePartner):\n", + " print (\"Ich habe gerade zu viel zu tun\")\n", + "#Einige Funktionalität dazu\n", + "\n", + "jan=Student(\"Jan\",21,3)\n", + "Human.getNumberOfPeople()#Auch der Student Jan zählt zu den Menschen\n", + "print(jan) #Alle Methoden die nicht überschrieben wurden von der Klasse Human übernommen\n", + "jan.marry(jenny) #Diese Methode wurde überschrieben und verhält sich anders (Das ist auch gut so, jenny ist ja schon mit Paul verheiratet)\n" + ] + }, + { + "cell_type": "markdown", + "id": "908d1c92-ed0b-4633-a6a1-f8475ec45b57", + "metadata": {}, + "source": [ + "Zusammengefasst erbt die neue Klasse (auch sub-Klasse) sämtliche Methoden von der Elternklasse (super-Klasse). Werden Methoden in der sub-Klasse neu definiert, dann werden diese Methoden sozusagen überschrieben. Das alleine würde wenig neue Funktionalität bieten. Die Klasse Student definiert z.B. die Methode ```__init__``` neu. Deshalb wird die Methode der Klasse Human auch nicht mehr aufgerufen, wenn die Klasse Student instanziiert wird. Gleiches gilt für die Methode ```mary```.\\\n", + "Es ist allerdings trotzdem möglich die Methoden gleichen Namens der super-Klasse aufzurufen. Das funktioniert mit ```super().Methode()```, wie in der ```__init``` Methode von Student gezeigt. Gerade wenn die ```__init__``` Methode in einer sub-Klasse neu definiert wird sollte genau diese Zeile an der ersten Stelle stehen, damit das Konzept der Vererbung wirklich funktioniert. Wird die ```__del``` Methode in einer sub-Klasse neu definiert, sollte ein ```super().__del__()``` als letzte Zeile dieser Methode eingeplant werden. Die meißten anderen Programmiersprachen machen genau das automatisch, bei Python muss man selbst daran denken. Praktisch gesehen ist Vererbung ein Konzept, dem ihr vermutlich in Python nicht so häufig begegnen werdet. Ihr könnt damit eigentlich nur bestehende Klassen nachträglich erweitern." + ] + } + ], + "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.8.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Uebung03/Uebung03.ipynb b/Uebung03/Uebung03.ipynb new file mode 100644 index 0000000..639d03a --- /dev/null +++ b/Uebung03/Uebung03.ipynb @@ -0,0 +1,218 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "757b9a6c-6599-4cd6-93c5-c4fb30ed5b53", + "metadata": {}, + "source": [ + "# <font color='blue'>**Übung 3 - Objektorientierte Programmierung**</font>" + ] + }, + { + "cell_type": "markdown", + "id": "d3a49027-9186-48a6-ba9f-332428e93bd9", + "metadata": {}, + "source": [ + "## <font color='blue'>**Die Grundlagen von Objektorientierter Programmierung**</font>\n", + "\n", + "In den vorherigen Übungen wurden die grundlegenden Elemente zur Ablaufsteuerung von Programmen behandelt. In dieser Übung führen wir ein wichtiges Konzept der Programmierung ein, die Objektorientierte Programmierung. Diese hilft sowohl bei der Strukturierung komplexer Projekte, der Verständlichkeit von Quellcode und dem gemeinsamen Arbeiten. Die Grundidee dahinter ist es, zusammengehörende Daten zusammen mit dazu passenden Operationen in (selbst) definierten Datentypen zusammenzufassen. \n", + "\n", + "### **Weitere Notebooks, die dir helfen könnten**\n", + "* Python Grundlagen Teil 1\n", + "* Python Grundlagen Teil 2\n", + "* OOP Grundlagen\n", + "\n", + "### **Vorkenntnisse**\n", + "* Übung 1\n", + "* Übung 2\n", + "\n", + "### **Lernziele**\n", + "* Klassen und Objekte\n", + "* Attribute und Methoden\n", + "* Spezielle Methoden" + ] + }, + { + "cell_type": "markdown", + "id": "b0e426c9-9a66-4bc6-a0be-fc8e08c18858", + "metadata": {}, + "source": [ + "# <font color='blue'>**Abschnitt 1 - Einfache Klasse**</font>\n", + "## <font color='blue'>*Aufgabe*</font>\n", + "\n", + "Für den ersten Kontakt mit Klassen und Objekten wollen wir mit einem einfachen Alltagsbeispiel beginnen.\n", + "\n", + "Erstelle eine Klasse namens Artikel, mit dem ein Supermarkt seine Artikel verwalten kann. Die Artikel sollen einen Namen, eine Menge und einen Preis pro Mengeneinheit haben. Dazu soll die Datenstruktur Methoden besitzen, mit denen der Supermarkt den Lagerbestand auffüllen kann, sowie eine bestimmte Menge eines Artikels (soweit vorhanden) verkaufen kann. Beim Verkaufen soll eine Ausgabe über die verkaufte Menge, den Preis und die verbleibende Menge gegeben werden. Außerdem soll ermittelbar sein, wieviele verschiedene Artikel es gibt.\n", + "\n", + "Teste das Programm anhand eines Supermarktes der zu Beginn 500 kg Zucker zu 1 Euro pro kg, und 1000 kg Mehl zu 1,50 Euro pro kg auf Lager hat. Er füllt das Lager um 600 kg Zucker auf, und ein Kunde kauft 4 kg Mehl. Nutze die erstellte Klasse, um die neuen Lagerbestände zu ermitteln, sowie den vom Kunden gezahlten Preis. " + ] + }, + { + "cell_type": "markdown", + "id": "b29c819a-aedd-4232-bcd7-eedcd810695c", + "metadata": {}, + "source": [ + "## <font color='blue'>*Lösung*</font>\n", + "\n", + "Klassendefinition und Instanziierung:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b0c8c9d-f3b6-47fc-9de7-04f557ed5511", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "d046ee6a", + "metadata": {}, + "source": [ + "Auffüll- und Verkaufsoperationen, sowie Testausgaben (beliebig oft wiederholbar):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7b68c5f0", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "c665968c", + "metadata": {}, + "source": [ + "## <font color='blue'>*Hinweise*</font>\n", + "\n", + "Es soll eine Klasse und ein Hauptprogramm erstellt werden. In dem Hauptprogramm sollen Objekte der Klasse verwendet werden, um die beispielhafte Testaufgabe zu erfüllen. Natürlich kannst du dich hier auch frei austoben und mehrere Verkäufe machen, oder testen, ob die Klasse beim Verkaufen korrekt erkennt, wenn nicht genug auf Lager ist. Es darf keine negativen Mengen geben.\n", + "\n", + "Wir machen folgende Vorschläge für die Namen der Klasse, Attribute und Methoden:\n", + "Klasse ```Artikel```,\n", + "Attribute ```anz_artikel```, ```menge```, ```preis```, ```name```\n", + "Methoden ```__init__()```, ```auffuellen()```, ```verkaufen()```\n", + "\n", + "Für die Syntax benötigst du Informationen aus dem Grunlagen OOP Notebook. Für diesen Abschnitt benötigst du Klassen und Objekte, Klassen- und Objektattribute, sowie Objektmethoden.\n" + ] + }, + { + "cell_type": "markdown", + "id": "46d21f3a-b37e-49d3-864f-587b09ba0b89", + "metadata": {}, + "source": [ + "# <font color='blue'>**Abschnitt 2 - Vektorrechnungen**</font>\n", + "\n", + "Nachdem du nun erste Erfahrungen mit der Objektorientierten Programmierung gemacht hast, wollen wir uns einem mathematischeren Thema widmen. Dabei wollen wir auch das Thema spezielle Methoden (auch magic method genannt) einführen. Diese erlauben es uns in dieser Aufgabe, Vektorrechnung mit den bekannten Operatoren wie mit \"normalen\" Variablen auch, durchzuführen." + ] + }, + { + "cell_type": "markdown", + "id": "6e25b06f", + "metadata": {}, + "source": [ + "## <font color='blue'>*Aufgabe*</font>\n", + "\n", + "Berechne den Betrag des Vektors c = a-b, mit den Vektoren a = (1,2,3) und b = (5,-4,3). Außerdem soll das Skalarprodukt mit a * b berechnet werden. Erstelle dazu eine Klasse ```Vektor3``` für die dreidimensionalen Vektoren so, dass die bereits gegebenen Codezeilen erfolgreich ausgeführt werden können." + ] + }, + { + "cell_type": "markdown", + "id": "e7333454-be6d-487d-a39e-ba509472aa30", + "metadata": { + "tags": [] + }, + "source": [ + "## <font color='blue'>*Lösung*</font>" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d5ce741-9f03-4e88-b10a-be8d223ef9e5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc85e62c-a188-46ab-b7c5-55fc44d8bbbf", + "metadata": {}, + "outputs": [], + "source": [ + "a = Vektor3([1,2,3])\n", + "b = Vektor3([5,-4,3])\n", + "\n", + "c = a-b\n", + "\n", + "print(\"Betrag des Vektors c: \" + str(c.get_betrag()))\n", + "print(\"Skalarprodukt a * b: \" + str(a*b))\n" + ] + }, + { + "cell_type": "markdown", + "id": "ac9ba52d", + "metadata": {}, + "source": [ + "## <font color='blue'>*Hinweise*</font>\n", + "\n", + "Nun benötigst du noch den Abschnitt über spezielle Methoden aus dem OOP-Grundlagen Notebook. Diese erlauben es, die Methoden so zu definieren, dass die Operationen wie a-b mit den selbst definierten Vektoren funktionieren.\n", + "\n", + "Es ist dir selbst überlassen, ob du die Einträge der Vektoren als eine Liste, oder als drei einzelne Werte speicherst.\n", + "\n", + "Das Ergebnis einer Summe oder Differenz ist ein neuer Vektor.\n" + ] + }, + { + "cell_type": "markdown", + "id": "595a83db-5a61-4048-84d3-e5f1ca14c263", + "metadata": {}, + "source": [ + "# <font color='blue'>**Aufgabe zum selbst probieren**</font>\n" + ] + }, + { + "cell_type": "markdown", + "id": "ca559a03-b79b-4f1a-a128-4e3e3e177017", + "metadata": {}, + "source": [ + "Erweitere die Vektorklasse um weitere Operationen, die dir sinnvoll erscheinen. Ebenso könnte es interessant sein, die Beschränkung auf 3 Dimensionen aufzuheben. Beachte dabei, dass die Operationen bestimmte Anforderungen haben. So funktioniert das Kreuzprodukt nur mit Vektoren mit drei Dimensionen, Addition und Substraktion nur für Vektoren gleicher Dimension etc. Die Funktionen müssen das dann überprüfen, ob sie selbst und auch der andere Operand die geforderte länge haben.\n", + "\n", + "\n", + "## <font color='blue'>**Lösung**</font>\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a4e935d-1468-41be-a175-71505b044a38", + "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.8.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- GitLab