Browse Source

Add chapter 08.

master
paulusja 1 year ago
parent
commit
5474e49070
5 changed files with 1278 additions and 0 deletions
  1. 241
    0
      08kapitel/081 Begriffe.ipynb
  2. 661
    0
      08kapitel/082 Klassen.ipynb
  3. 217
    0
      08kapitel/083 Vererbung.ipynb
  4. 137
    0
      08kapitel/083a Uebung.ipynb
  5. 22
    0
      08kapitel/rise.css

+ 241
- 0
08kapitel/081 Begriffe.ipynb View File

@@ -0,0 +1,241 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Software Entwicklung \n",
"\n",
"## Kapitel 8: Objektorientierung\n",
"\n",
"### 8.1 Objekte\n",
"\n",
"Bisher haben wir *Daten* und *Funktionen* getrennt betrachtet.\n",
"Bei einem Objekt werden Daten (auch: *Attribute*) und Funktionen\n",
"(auch: *Methoden*) an einer Stelle zusammengefasst.\n",
"\n",
"Die Methoden eines Objekts können - neben lokalen Variablen, globalen Variablen\n",
"und Parametern - auch die Attribute des Objekts nutzen. So kann\n",
"z.B. ein Datumsobjekt die Attribute \"Jahr\", \"Monat\" und \"Tag\" besitzen\n",
"und die Methoden des Objekts auf Basis dieser Attribute den\n",
"Wochentag (0: Montag, ..., 6: Sonntag) ausrechnen oder eine standardisierte\n",
"Stringrepräsentation generieren.\n",
"\n",
"![Datum-Objekt](../img/object.png \"Datum-Objekt\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Datumsobjektsobjekte können mit Hilfe des Standardmoduls <code>datetime</code>\n",
"generiert werden. Die Methoden eines Objekts werden stets mit der Dot-Notation\n",
"aufgerufen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"import datetime\n",
"\n",
"d = datetime.date(1989, 11, 9)\n",
"print(d.weekday())\n",
"print(d.isoformat())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### 8.2 Klassen\n",
"\n",
"Der Bauplan für Datumsobjekte, der die Attribute und Methoden festlegt,\n",
"wird als *Klasse* bezeichnet. Das Standardmodul <code>datetime</code>\n",
"enthält einen Bauplan für Datumsobjekte in Form der Klasse <code>date</code>.\n",
"\n",
"Objekte, die gemäß eines solchen\n",
"Bauplans generiert wurden, haben die Klasse als Datentyp."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"print(type(d))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### 8.3 Instanzen\n",
"\n",
"Der Bauplan, den eine Klasse bereitstellt, kann *mehrfach* benutzt werden, um\n",
"mehrere Objekte zu erzeugen. Man spricht hier von *Instanzen* der Klasse."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"d1 = datetime.date(2000, 1, 1)\n",
"d2 = datetime.date(2010, 1, 1)\n",
"d3 = datetime.date(2020, 1, 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Attribute der Instanzen sind voneinander unabhängig, d.h.\n",
"anders als globale Variablen mehrfach vorhanden. Die Methoden, die\n",
"ja stets mit der Dot-Notation für eine spezifische Instanz aufgerufen\n",
"werden, nutzen die Attribute ihrer jeweiligen Instanz und liefern daher\n",
"ggf. unterschiedliche Werte."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"print(d1.weekday())\n",
"print(d2.weekday())\n",
"print(d3.weekday())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Welche Attribute und Methoden ein Objekt besitzt, ist normalerweise\n",
"der Dokumentation oder dem Programmcode der Klasse zu entnehmen.\n",
"Es gibt jedoch mit der Built-In-Funktion <code>dir</code> auch\n",
"eine Möglichkeit, diese Information programmatisch zu ermitteln."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"print(dir(d1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Beim betrachteten Datumsobjekt *beginnen und enden* einige der Methoden-\n",
"und Attributsnamen mit einem doppelten Unterstich <code>\\_\\_</code>, im\n",
"Python-Jargon auch *dunder methods* bzw. *dunder attributs* genannt.\n",
"Diese Methoden und Attribute werden vom Python-System verwendet und\n",
"dürfen nicht überschrieben werden! Ein bereits bekanntes Beispiel ist\n",
"die Variable <code>\\_\\_name\\_\\_</code>, die den aktuellen Modulnamen \n",
"oder den Wert <code>\\_\\_main\\_\\_</code> enthält."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"print(__name__)"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"Auch die Definition eigener\n",
"Funktionen und Variablen, die mit einem Doppel-Unterstich beginnen\n",
"und enden, sollte vermieden werden. Es könnte andere Entwickler\n",
"irritieren und System-Funktionen und -Variablen\n",
"künftiger Python-Versionen verdecken."
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"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.9"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

+ 661
- 0
08kapitel/082 Klassen.ipynb View File

@@ -0,0 +1,661 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Software Entwicklung \n",
"\n",
"## Kapitel 8: Objektorientierung\n",
"\n",
"### 8.4 Eigene Klassen\n",
"\n",
"Bislang war die einzige Möglichkeit der Strukturierung\n",
"größerer Programme die Zerlegung in Funktionen und Module.\n",
"Durch die Programmierung *eigener Klassen* kommt ein\n",
"weiteres mächtiges Strukturierungswerkzeug hinzu.\n",
"\n",
"Eingeleitet wird die Definiton einer Klasse durch\n",
"das Schlüsselwort <code>class</code>, gefolgt vom Klassennamen,\n",
"einem Klammernpaar (dazu später mehr) und einem Doppelpunkt.\n",
"Danach folgen eingerückt in gewohnter Weise die Definitionen,\n",
"die den Bauplan ausmachen. Klassennamen beginnen nach Konvention mit\n",
"einem Großbuchstaben (Ausnahme: Klassen der Standardbibliothek sind\n",
"oft kleingeschrieben, um sie wie \"normale\" Datentypen aussehen zu lassen)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Hinweis: das Schlüsselwort <code>pass</code> ist die leere Anweisung\n",
"(\"Tue nichts\") und kann verwendet werden, wenn die Python-Syntax\n",
"eine Anweisung erfordert, man aber (noch) keine Anweisung angeben will.\n",
"\n",
"Somit ist die oben skizzierte Klasse eine minimale Klassendefinition. Sie\n",
"kann aber bereits benutzt werden, um Instanzen zu erzeugen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"s1 = Student()\n",
"s2 = Student()\n",
"print(type(s1))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Innerhalb der Klassendefinition können nun Methoden definiert werden.\n",
"Die Definition gleicht der Definition von Funktionen, jedoch\n",
"muss in der Parameterliste immer als erstes der Parameter\n",
"<code>self</code> aufgeführt werden, der dann im Methodenrumpf\n",
"das eigene Objekt repräsentiert. Es gibt also keine\n",
"Methodendefinitionen mit leerer Parameterliste!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
" def print_my_type(self):\n",
" print(type(self))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Beim Aufruf der Methode wird der erste Parameter weggelassen. Er\n",
"wird von Python selbständig gesetzt, indem das Objekt eingesetzt wird,\n",
"das links vom Punkt beim Aufruf über die Dot-Notation steht."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"s = Student()\n",
"s.print_my_type()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Alternativ ist auch eine Langform möglich, die aber kaum genutzt wird."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"s = Student()\n",
"Student.print_my_type(s)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Der Bezeichner <code>self</code> kann auch genutzt werden,\n",
"um innerhalb einer Methode auf Attribute der Instanz zuzugriffen\n",
"oder sie erstmalig zu definieren."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def set_name(self, name):\n",
" self.name = name\n",
"\n",
" def get_name(self):\n",
" return self.name\n",
"\n",
"s1 = Student()\n",
"s1.set_name(\"Hans\")\n",
"s2 = Student()\n",
"s2.set_name(\"Hilde\")\n",
"print(s1.get_name())\n",
"print(s2.get_name())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Im Beispiel wird auf das Attribut <code>name</code> mit Hilfe\n",
"einer Methode <code>get_name</code> zugegriffen. Es ist guter\n",
"Stil und absolut üblich, lediglich die Methoden eines Objekts\n",
"direkt auf die Attribute zugreifen zu lassen, und\n",
"Zugriffe \"von außen\" über sog. *Getter-Funktionen*\n",
"abzuwickeln.\n",
"\n",
"Grundsätzlich möglich wäre es aber:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"print(s2.name)\n",
"s1.name = \"Hubert\"\n",
"print(s1.name)"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### 8.5 Zugriffsschutz\n",
"\n",
"Attribute (und Methoden) sind also in Python *öffentlich*,\n",
"d.h. von außen zugreifbar und nutzbar. Um das\n",
"unkontrollierte Ändern von Attributen zu unterbinden,\n",
"haben sich aber einige Konventionen durchgesetzt:\n",
"\n",
"Attribute, die mit einem einfachen Unterstrich <code>\\_</code>\n",
"beginnen, sind vom Entwickler als geschützt gekennzeichnet\n",
"und sollten nicht direkt genutzt werden. Möglich ist es aber weiterhin!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def set_name(self, name):\n",
" self._name = name\n",
"\n",
" def get_name(self):\n",
" return self._name\n",
"\n",
"s = Student()\n",
"s._name = \"Horst\"\n",
"print(s.get_name())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Beginnt der Attributname mit zwei Unterstrichen (bitte nicht zusätzlich mit\n",
"zwei Unterstrichen beenden, s.o.), so ist der Zugriff auf das Attribut nur\n",
"noch aus Methoden der Klasse möglich.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def set_name(self, name):\n",
" self.__name = name\n",
"\n",
" def get_name(self):\n",
" return self.__name\n",
"\n",
"s = Student()\n",
"s.set_name(\"Hans\")\n",
"print(s.get_name())\n",
"s.__name = \"Horst\"\n",
"print(s.get_name())"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### 8.6 Magic Methods\n",
"\n",
"Einige besondere Methodennamen, die sog. *Magic Methods* sind reserviert.\n",
"Die sind alle *dunder methods*, d.h. ihr Name\n",
"beginnt und endet mit zwei Unterstichen. Sie werden bei\n",
"bestimmten Ereignissen vom Python-Laufzeitsystem ausgeführt, d.h.\n",
"als Entwickler ruft man sie i.d.R. nicht direkt auf.\n",
"\n",
"Es ist nicht zwingend erforderlich, diese Methoden zu definieren\n",
"und zu implementieren; mit ihrer Implementierung kann aber\n",
"das Verhalten der Klasse beeinflusst werden.\n",
"\n",
"#### 8.6.1 Konstruktor\n",
"\n",
"Es kann je Klasse ein Konstruktor implementiert werden. Das ist\n",
"eine Methode, die unmittelbar beim Generieren einer neuen\n",
"Instanz aufgerufen wird. Der Konstruktor hat den Methodennamen\n",
"<code>\\_\\_init\\_\\_</code>."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def __init__(self):\n",
" print(\"Im Konstruktor\")\n",
"\n",
"s = Student()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Häufig wird der Konstruktor genutzt, um die Attribute der neuen\n",
"Instanz vorzubelegen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def __init__(self):\n",
" self.__name = None\n",
"\n",
" def set_name(self, name):\n",
" self.__name = name\n",
"\n",
" def get_name(self):\n",
" return \"N.N.\" if self.__name is None else self.__name\n",
"\n",
"s = Student()\n",
"print(s.get_name())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Der Konstruktor kann auch Parameter besitzen, die dann bei der\n",
"Neuanlage eines Objekts versorgt werden müssen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def __init__(self, name):\n",
" self.__name = name\n",
"\n",
" def set_name(self, name):\n",
" self.__name = name\n",
"\n",
" def get_name(self):\n",
" return \"N.N.\" if self.__name is None else self.__name\n",
"\n",
"s = Student(\"Hilde\")\n",
"print(s.get_name())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Attribute können auch direkt in der Klasse vorbelegt werden. Bei Erstellung des Objekts exisitiert das Attribut mit dem entsprechenden Wert bereits. Die bietet sich z.B. für konstante Werte einer Klasse an."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class Student():\n",
" __DEFAULT_NAME = 'N.N.'\n",
"\n",
" def __init__(self, name=None):\n",
" self.__name = name\n",
"\n",
" def set_name(self, name):\n",
" self.__name = name\n",
"\n",
" def get_name(self):\n",
" return self.__DEFAULT_NAME if self.__name is None else self.__name\n",
" \n",
"s = Student()\n",
"print(s.get_name())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#### 8.6.2 Umwandlung in einen String\n",
"\n",
"Viele Built-In-Funktions rufen eine *magic Method* auf, so\n",
"auch <code>str</code>, die ihren Parameter bekanntlich in einen\n",
"String umwandelt. In diesem Fall wird <code>\\_\\_str\\_\\_</code> aufgerufen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def __init__(self, name):\n",
" self.__name = name\n",
"\n",
" def __str__(self):\n",
" return \"<\" + self.__name + \">\"\n",
"\n",
"s = Student(\"Horst\")\n",
"print(str(s))"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### 8.7 Identität\n",
"\n",
"Wie bei jedem neuen Datentyp steht die Frage im Raum, ob es sich\n",
"um einen veränderlichen oder unveränderlichen Datentyp handelt. In Python\n",
"bedeutet unveränderlich, dass bei Änderungen ein neues Objekt\n",
"mit einer veränderten Identität erzeugt wird."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def __init__(self, name):\n",
" self.__name = name\n",
"\n",
" def set_name(self, name):\n",
" self.__name = name\n",
"\n",
" def get_name(self):\n",
" return \"N.N.\" if self.__name is None else self.__name\n",
"\n",
"s = Student(\"Hilde\")\n",
"print(id(s))\n",
"s.set_name(\"Herta\")\n",
"print(id(s))"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Da die Identität des Objekts gleich bleibt, handelt es sich bei\n",
"Python-Objekten um einen *veränderlichen* Datentyp (wie Listen und Mengen).\n",
"Allerdings können Python-Objekte Schlüssel für Dictionaries\n",
"sein, da in diesem Fall die Identität als Schlüssel verwendet wird.\n",
"\n",
"Obwohl Objekte veränderlich sind, entspricht trotzdem (zunächst)\n",
"die Gleichheit der Identität bei Objekten.\n",
"Anders als bei Listen oder Mengen findet also kein elementweiser\n",
"Vergleich auf Basis der Attribute statt."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"s1 = Student(\"Hilde\")\n",
"s2 = Student(\"Hilde\")\n",
"\n",
"if id(s1) == id(s2):\n",
" print(\"Identisch\")\n",
"\n",
"if s1 == s2:\n",
" print(\"Gleich\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Das Verhalten bei der Betrachtung der Gleichheit kann jedoch\n",
"durch Implementierung der *magic Method* <code>\\_\\_eq\\_\\_</code>\n",
"verändert werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def __init__(self, name):\n",
" self.__name = name\n",
"\n",
" def __eq__(self, other):\n",
" return self.__name == other.__name\n",
"\n",
"s1 = Student(\"Hilde\")\n",
"s2 = Student(\"Hilde\")\n",
"\n",
"if id(s1) == id(s2):\n",
" print(\"Identisch\")\n",
"\n",
"if s1 == s2:\n",
" print(\"Gleich\")\n",
"\n",
"\n"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"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.9"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

+ 217
- 0
08kapitel/083 Vererbung.ipynb View File

@@ -0,0 +1,217 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Software Entwicklung \n",
"\n",
"## Kapitel 8: Objektorientierung\n",
"\n",
"### 8.8 Vererbung\n",
"\n",
"Neue Klassen können auch bestehende Klassen erweitern.\n",
"Die neue Klasse wird von einer oder mehreren *Oberklassen*\n",
"abgeleitet und ist in dieser Beziehnung die *Unterklasse*.\n",
"Die Oberklassen werden bei der Klassendefinition\n",
"zwischen den Klammern angegeben.\n",
"\n",
"<code> class Unterklasse(Oberklasse1, Oberklasse2, ...): </code>"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Die *Unterklasse* erbt alle Attribute und Methoden\n",
"der *Oberklassen*."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Student():\n",
"\n",
" def __init__(self, name):\n",
" self.__name = name\n",
"\n",
" def __str__(self):\n",
" return self.__name\n",
"\n",
"\n",
"class BMEDStudent(Student):\n",
"\n",
" def get_major_subject(self):\n",
" return None\n",
"\n",
"\n",
"s = BMEDStudent(\"Herbert\")\n",
"print(str(s))\n",
"print(s.get_major_subject())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"In einer Unterklasse können neue Methoden und\n",
"Attribute ergänzt sowie geerbte Methoden überschrieben werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class BMMFStudent(BMEDStudent):\n",
"\n",
" def get_favorite_lecture(self):\n",
" return \"Software Entwicklung\"\n",
"\n",
" def get_major_subject(self):\n",
" return \"MF\"\n",
"\n",
"s = BMMFStudent(\"Helga\")\n",
"print(str(s))\n",
"print(s.get_major_subject())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Gelegentlich benötigt man in einer Unterklasse Zugriff auf Methoden der Oberklassen\n",
"in dem Zustand, *bevor* sie überschrieben wurden. Dies kann mit der\n",
"Built-In Funktion *super* erreicht werden, die das aktuelle Objekt im Gewand der\n",
"Oberklasse zurückgibt, so dass die Methoden der Oberklasse aufgerufen werden können."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class BMEIStudent(BMEDStudent):\n",
"\n",
" def get_major_subject(self):\n",
" return \"EI\"\n",
"\n",
" def __str__(self):\n",
" return super().__str__() + \" \" + self.get_major_subject()\n",
"\n",
"s = BMEIStudent(\"Henning\")\n",
"print(str(s))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### 8.9 Polymorphie\n",
"\n",
"Der Begriff *Polymorphie* stammt aus dem Griechischen und setzt sich zusammen aus\n",
"\n",
"* πολύς (polýs) = \"viel\"\n",
"* μορφή (morphé) = \"Gestalt\"\n",
"\n",
"Beschrieben wird damit der Umstand, dass der Aufrufer einer Methode nicht genau wissen muss,\n",
"welches Objekt er vor sich hat, und dennoch die richtige Methode ausgeführt wird."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"from random import random\n",
"\n",
"if random() < 0.5:\n",
" s = BMMFStudent(\"Hans\")\n",
"else:\n",
" s = BMEIStudent(\"Hannelore\")\n",
"\n",
"print(s.get_major_subject())"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"Die Methode <code>get_major_subject</code> ist im obigen Beispiel *polymorph*.\n",
"\n",
"\n"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"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.9"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

+ 137
- 0
08kapitel/083a Uebung.ipynb View File

@@ -0,0 +1,137 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"_Aufgabe 1_\n",
"\n",
"Sie entwickeln im Team ein CAD-Programm,\n",
"das das Zusammenstellen komplexer Zeichnungen aus einfachen 2D-Elementen erlaubt.\n",
"Gegeben ist bereits eine Klasse *Element*."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class Element():\n",
"\n",
" def get_bezeichnung(self):\n",
" return \"N.N.\"\n",
"\n",
" def umfang(self):\n",
" raise NotImplementedError()\n",
"\n",
" def __str__(self):\n",
" return self.get_bezeichnung() + f\" Umfang: {self.umfang()}\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ihr Teamleiter beauftragt Sie, für die Elemente *Kreis* und *Rechteck* Unterklassen\n",
"zur Oberklasse *Element* so zu implementieren,\n",
"dass anschließend die Aufrufe\n",
"\n",
"<code>k = Kreis(radius=3)</code>\n",
"\n",
"<code>r = Rechteck(breite=10, hoehe=5)</code>\n",
"\n",
"möglich sind.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"import math\n",
"\n",
"\n",
"k = Kreis(radius=3)\n",
"print(k)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"\n",
"r = Rechteck(breite=10, hoehe=5)\n",
"print(r)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_Aufgabe 2_\n",
"\n",
"Fügen Sie jetzt noch eine weitere Klasse *Quadrat* hinzu. Welche Oberklasse besitzt diese neue Klasse?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"\n",
"q = Quadrat(seite=4)\n",
"print(q)\n",
"\n",
"\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.2"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

+ 22
- 0
08kapitel/rise.css View File

@@ -0,0 +1,22 @@
body.rise-enabled div.inner_cell>div.input_area {
font-size: 150%;
}

body.rise-enabled div.output_subarea.output_text.output_result {
font-size: 150%;
}
body.rise-enabled div.output_subarea.output_text.output_stream.output_stdout {
font-size: 150%;
}

body.rise-enabled div.output_subarea.output_html.rendered_html.output_result {
font-size: 150%;
}

body.rise-enabled td {
font-size: 120%;
}

body.rise-enabled th {
font-size: 120%;
}

Loading…
Cancel
Save