12. Unterrichtsblock
Python Vererbung
Durch Vererbung kann eine Klasse definiert werden, die alle Methoden und Eigenschaften einer anderen Klasse erbt. Die übergeordnete Klasse ist die Klasse, von der geerbt wird, auch Basisklasse genannt.
Eine untergeordnete Klasse ist die Klasse, die von einer anderen Klasse erbt, auch abgeleitete Klasse genannt.
Die erbende Klasse übernimmt alle Eigenschaften und Methoden der beerbten Klasse!
Verwendungsmöglichkeiten der Vererbung
- Da eine untergeordnete Klasse alle Funktionalitäten der übergeordneten Klasse erben kann, ermöglicht dies die Wiederverwendbarkeit von Code.
- Sobald eine Funktionalität entwickelt ist, kann man diese einfach erben. Das Rad muss nicht neu erfunden werden. Dies ermöglicht einen saubereren Code und eine einfachere Wartung.
- Da man in der untergeordneten Klasse auch eigene Funktionalitäten hinzufügen kann, können diese nur die nützlichen Funktionalitäten erben und andere erforderliche Funktionen definieren.
Syntax
Hier ist die Syntax der Vererbung in Python:
# Definition einer Elternklasse
class eltern_klasse:
# Attribute und Methoden definieren
# Vererbung
class kind_klasse(eltern_klasse):
# Attribute und Methoden der eltern_klasse
# Attribute und Methoden der kind_klasse
Hier erben wir die Klasse kind_klasse
aus der Klasse eltern_klasse
.
Beispiel einer Vererbung von Attributen und Methoden
class tier:
# Attribute und Methoden der Elternklasse
name = ""
fellfarbe = "schwarz"
def futter(self):
print("Ich liebe Knochen")
# Vererbung von Elternklasse "tier" an neue Kindklasse "hund"
class hund(tier):
# Neue Methode in Kindklasse
def anzeige(self):
# Zugriff auf Namen-Attribut der Kindklasse mit dem "self" Keyword
print("Mein Name ist", self.name, "und mein Fell ist", self.fellfarbe)
# Erstellung eines Objekts der Kindklasse
labrador = hund()
# Zugriff auf Elternklassen-Attribut und Zuteilung eines Attributwerts
labrador.name = "Bello"
# Aufruf der Methode aus der Kindklasse
labrador.anzeige()
# Aufruf der Methode aus der Elternklasse
labrador.futter()
Im obigen Beispiel haben wir eine Kindklasse hund
von einer Elternklasse tier
abgeleitet.
Hier verwenden wir labrador
(Objekt von hund
), um auf den Namen und die Methode futter()
der tier
Elternklasse zuzugreifen. Dies ist möglich, weil die Kindklasse alle Attribute und Methoden der Elternklasse erbt.
Außerdem wurde mithilfe von self
auf das name
-Attribut innerhalb einer Methode der hund
–Klasse zugegriffen.
Schauen wir uns ein weiteres Beispiel für die Vererbung in Python an:
Ein Polygon ist eine geschlossene Figur mit mindestens drei oder mehr Seiten. Folgendes Beispiel zeigt eine Klasse namens Polygon
wie folgt definiert:
class Polygon:
def __init__(self, seitenzahl):
self.n = seitenzahl
self.seiten = [0 for i in range(seitenzahl)]
def eingabeSeiten(self):
self.seiten = [float(input("Gibt die Länge der "+str(i+1)+". Seite ein: ")) for i in range(self.n)]
def anzeigeSeiten(self):
for i in range(self.n):
print("Seite",i+1,"is",self.seiten[i])
Diese Klasse verfügt über Datenattribute zum Speichern der Anzahl der Seiten n
und der Größe jeder Seite als Liste bezeichnet seiten
.
- Die
eingabeSeiten()
Methode berücksichtigt die Größe jeder Seite - Die
anzeigeSeiten()
Methode zeigt diese Seitenlängen an
Ein Dreieck ist ein Polygon mit 3 Seiten. Wir können nun also eine Klasse namens Dreieck
erstellen, die von Polygon
erbt. Dies macht alle Attribute der Polygon
-Klasse für die Dreieck
-Klasse verfügbar.
Wir müssen sie also nicht erneut definieren (Wiederverwendbarkeit des Codes). Unsere Dreieck
kann wie folgt definiert werden:
class Dreieck(Polygon):
def __init__(self):
Polygon.__init__(self,3)
def ermittleFlaeche(self):
a, b, c = self.seiten
# Semiperimeter (Halbmesser) berechnen
s = (a + b + c) / 2
# Flächenberechnung mit der Heron-Formel
flaeche = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('Die Fläche des Dreiecks ist ', flaeche, 'cm²')
Die Klasse Dreieck
erbt alle Attribute und Methoden der Elternklasse Polygon
. Allerdings hat die Dreieck
-Klasse die neue Methode ermittleFlaeche()
um die Fläche des Dreiecks zu ermitteln und auszugeben.
Sehen wir uns nun den vollständigen Arbeitscode des obigen Beispiels an, einschließlich der Erstellung eines Objekts.
# Elternklasse Polygon
class Polygon:
# Initialisierung der Seitenzahl
def __init__(self, seitenzahl):
self.n = seitenzahl
self.seiten = [0 for i in range(seitenzahl)]
def eingabeSeiten(self):
self.seiten = [float(input("Gibt die Länge der "+str(i+1)+". Seite ein: ")) for i in range(self.n)]
# Methode zur Anzeige einer jeder Seitenlänge des Polygons
def anzeigeSeiten(self):
for i in range(self.n):
print("Seite",i+1,"is",self.seiten[i])
# Kindklasse Dreieck
class Dreieck(Polygon):
# Initialisierung der Seitenzahl des Dreiecks auf 3 durch
# Aufruf der __init__ Methode aus der Polygon Klasse
def __init__(self):
Polygon.__init__(self,3)
def ermittleFlaeche(self):
a, b, c = self.seiten
# Semiperimeter (Halbmesser) berechnen
s = (a + b + c) / 2
# Flächenberechnung mit der Heron-Formel
flaeche = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('Die Fläche des Dreiecks ist ', flaeche, 'cm²')
# Erstellung eines Objekts der Dreieck-Klasse
d = Dreieck()
# Anweisung des Nutzers zur Eingabe der Seitenlängen des Dreiecks
d.eingabeSeiten()
# Anzeige der Seiten des Dreiecks
d.anzeigeSeiten()
# Berechnung und Ausgabe der Fläche des Dreiecks
d.ermittleFlaeche()
Hier kann man sehen, dass obwohl in der Klasse Dreieck
keine Methoden wie eingabeSeiten()
oder anzeigeSeiten()
definiert wurde, diese für die Aufgabe in der Klasse Dreieck
dennoch genutzt werden konnten.
Wenn ein Attribut oder eine Methode in der Klasse selbst nicht gefunden wird, wird die Suche in der Elternklasse fortgesetzt. Dies wiederholt sich rekursiv, wenn die Elternklasse selbst von anderen Klassen abgeleitet ist.
Aufgabe
Finde eine Methode, um bei der Flächenberechnung im Ergebnis nur zwei Ziffern hinter dem Komma ausgeben zu lassen und implementiere die Lösung in o.g. Aufbau.
Erstelle eine Kindklasse „Quadrat“ und eine Kindklasse „Hexagon“ und erstelle innerhalb der Kindklassen Methoden zur Flächenberechnung.
Rufe die Methoden über ein Objekt der Kindklassen auf.
Methodenüberschreibung in der Python-Vererbung
Im vorherigen Beispiel ist zu sehen, dass das Objekt der Kindklasse auf die Methode der Elternklasse zugreifen kann.
Was aber, wenn dieselbe Methode sowohl in der Elternklasse als auch in der Kindklasse vorhanden ist?
In diesem Fall überschreibt die Methode in der Kindklasse die Methode in der Elternklasse. Dieses Konzept wird in Python als Methodenüberschreibung bezeichnet und ähnelt dem Kaskadensystem in CSS.
class tier:
# Attribute und Methoden der Elternklasse
name = ""
fellfarbe = "schwarz"
def futter(self):
print("Ich liebe Knochen")
# Vererbung von Elternklasse "tier" an neue Kindklasse "hund"
class hund(tier):
# Überschreiben der futter() Methode
def futter(self):
print("Ich liebe Hausschuhe")
# Erstellung eines Objekts der Kindklasse
labrador = hund()
# Aufruf der Methode aus der Kindklasse (Nicht mehr aus der Elternklasse)
labrador.futter()
Aufgabe
Schreibe o.g. Aufbau so um, dass über ein Objekt auch noch die futter()
-Methode der Klasse tier
aufgerufen wird.
Die super()-Methode in der Python-Vererbung
Zuvor haben wir gesehen, dass dieselbe Methode in der Unterklasse die Methode in der Oberklasse überschreibt.
Wenn man jedoch von der Unterklasse aus auf die Methode der Oberklasse zugreifen muss, verwendet man die super()
-Methode. Zum Beispiel:
class tier:
# Attribute und Methoden der Elternklasse
name = ""
fellfarbe = "schwarz"
def futter(self):
print("Ich liebe Knochen")
# Vererbung von Elternklasse "tier" an neue Kindklasse "hund"
class hund(tier):
# Überschreiben der futter() Methode
def futter(self):
# Ruft zusätzlich die futter()-Methode der Elternklasse auf
super().futter()
print("Ich liebe Hausschuhe")
# Erstellung eines Objekts der Kindklasse
labrador = hund()
# Aufruf der Methode aus der Kindklasse & Elternklasse
labrador.futter()
Aufgabe
Die Klasse hund
soll neben der Elternklasse tier
auch noch die Eigeschaften einer weiteren Elternklasse familienmitglied
erben. Baue eine Klasse familienmitglied
mit eigenen Attributen und Methoden und rufe diese über das Objekt labrador
auf.
Python JSON
JSON ist eine Syntax zum Speichern und Austauschen von Daten. JSON ist Text, geschrieben mit JavaScript-Objektnotation.
Python verfügt über ein integriertes Paket namens json
, das für die Arbeit mit JSON-Daten verwendet werden kann.
Importiert das JSON-Modul:
import json
JSON analysieren – Konvertieren von JSON nach Python
Wenn man über einen JSON-String verfügt, kann man diesen mithilfe der json.loads()
-Methode analysieren. Das Ergebnis wird ein Dictionary
sein.
Konvertieren von JSON nach Python:
import json
# Ein JSON String:
x = '{ "name":"Peter", "alter":30, "stadt":"Rosenheim"}'
# x Parsen:
y = json.loads(x)
# Das Ergebnis ist ein Python Dictionary:
print(y["alter"])
INFO: Ein Parser ist ein Computerprogramm, das in der Informatik für die Zerlegung und Umwandlung einer Eingabe in ein für die Weiterverarbeitung geeigneteres Format zuständig ist (Übersetzer).
Konvertieren von Python nach JSON
Wenn man über ein Python-Objekt verfügt, kann man dieses mithilfe der json.dumps()
Methode in einen JSON-String konvertieren.
Konvertieren von Python nach JSON:
import json
# Ein Python-Objekt (Dictionary):
x = {
"name": "Peter",
"alter": 30,
"stadt": "Rosenheim"
}
# Konvertierung zu JSON:
y = json.dumps(x)
# Das Ergebnis ist ein JSON-String:
print(y)
Man kann Python-Objekte der folgenden Typen in JSON-Strings konvertieren:
Python | JSON |
---|---|
dict | Object |
list | Array |
tuple | Array |
str | String |
int | Number |
float | Number |
True | true |
False | false |
None | null |
Beispiel
Konvertierung von Python-Objekten in JSON-Strings und die Ausgabe der Werte:
import json
print(json.dumps({"name": "Peter", "alter": 30}))
print(json.dumps(["Apfel", "Banane"]))
print(json.dumps(("Apfel", "Banane")))
print(json.dumps("Hallo"))
print(json.dumps(42))
print(json.dumps(31.76))
print(json.dumps(True))
print(json.dumps(False))
print(json.dumps(None))
Wenn man von Python nach JSON konvertiert, werden Python-Objekte in das JSON-Äquivalent (JavaScript) konvertiert.
Beispielhaftes Konvertieren eines Python-Objekts, das alle zulässigen Datentypen enthält:
import json
x = {
"name": "Peter",
"alter": 30,
"verheiratet": True,
"geschieden": False,
"kinder": ("Anna","Maxi"),
"tiere": None,
"autos": [
{"model": "BMW 320", "ps": 220},
{"model": "VW Golf", "ps": 150}
]
}
print(json.dumps(x))
Formatieren des Ergebnisses
Das obige Beispiel gibt einen JSON-String aus, der jedoch nicht sehr einfach zu lesen ist, da es keine Einrückungen und Zeilenumbrüche gibt.
Die json.dumps()
-Methode verfügt über Parameter, die das Ablesen des Ergebnisses erleichtern:
Hierfür wird der indent
-Parameter verwendet, um die Anzahl der Einrückungen zu definieren:
json.dumps(x, indent=4)
Man kann auch Trennzeichen definieren. Der Standardwert ist („, „, „:“)
Das bedeutet, dass man ein Komma und ein Leerzeichen verwenden muss, um jedes Objekt zu trennen,
und einen Doppelpunkt und ein Leerzeichen, um Schlüssel von Werten zu trennen.
Verwendung des separators
-Parameter, um das Standardtrennzeichen zu ändern:
json.dumps(x, indent=4, separators=(". ", " = "))
Ordnen des Ergebnisses & Ausgabe von Zeichen
Die json.dumps()
Methode verfügt über Parameter zum Ordnen der Schlüssel im Ergebnis:
Verwendung des sort_keys
-Parameter, um anzugeben, ob das Ergebnis sortiert werden soll oder nicht:
json.dumps(x, indent=4, sort_keys=True)
Die ensure_ascii
-Parameter werden verwendet, um Sonderzeichen auch als solche abzuspeichern. Der Standardwert ist „True“, was dazu führt, dass Nicht-ASCII-Zeichen mit einem Escape-Zeichen (\) versehen.
Beispiel:
json.dumps(x, ensure_ascii=True)
# Ergebnis bei der Ausgabe von "Müller" = "M\u00fcller"
json.dumps(x, ensure_ascii=False)
# Ergebnis bei der Ausgabe von "Müller" = "Müller"
Aufgabe
- Baue eine Klasse, welche die Eingaben von „Name“, „Beruf“, „E-Mail-Adresse“ in einem JSON-String speichert und um weitere Einträge geränzt, wenn man eine neue Eingabe starten möchte
- Baue eine weitere Klasse, welche die Daten aus dem zuvor erzeugten JSON-String ausliest und in einer Python-Ausgabe darstellt.
Machinelle Lernanwendungen
Aufbau neuronales Netz: https://ad-research.cs.uni-freiburg.de/nn-demo-1/
Übungen Objekte und Klassen
- Einfache Klasse erstellen Erstelle eine Klasse namens
Person
, die zwei Attribute hat:name
undalter
. Die Klasse sollte auch eine Methode namensvorstellen
haben, die den Namen und das Alter der Person ausgibt. - Konstruktor verwenden Erweitern Sie die
Person
-Klasse um einen Konstruktor, der den Namen und das Alter der Person beim Erstellen eines neuen Objekts initialisiert. - Klasse Tier Erstelle eine Klasse namens
Tier
mit den Attributenart
undlaut
. Die Klasse sollte eine Methode namensmachenLaut
haben, die den Laut des Tieres ausgibt. - Vererbung Erstelle eine Klasse namens
Student
, die von derPerson
-Klasse erbt und ein zusätzliches Attribut namensmatrikelnummer
hat. - Überschreiben von Methoden Überschreibe die
vorstellen
-Methode in derStudent
-Klasse, sodass sie auch die Matrikelnummer des Studenten ausgibt. - Klasse Auto Erstelle eine Klasse namens
Auto
mit den Attributenmarke
,modell
undkilometerstand
. Füge Methoden hinzu, um den Kilometerstand zu erhöhen und den aktuellen Kilometerstand auszugeben. - Private Attribute Ändere die
Auto
-Klasse, sodass derkilometerstand
ein privates Attribut ist. Füge Methoden hinzu, um den Kilometerstand sicher zu setzen und zu erhalten. - Klasse Buch Erstelle eine Klasse namens
Buch
mit den Attributentitel
,autor
undseitenzahl
. Füge eine Methode hinzu, die das Buch vorstellt. - Klassenmethoden und statische Methoden Füge der
Person
-Klasse eine Klassenmethode hinzu, die die Anzahl der erstellten Personenobjekte zählt. Füge auch eine statische Methode hinzu, die einen beliebigen Gruß ausgibt. - Zusammensetzung Erstelle eine Klasse namens
Bibliothek
, die eine Liste vonBuch
-Objekten enthält. Füge Methoden hinzu, um Bücher hinzuzufügen und zu entfernen.
Übungen Vererbung
- Mehrstufige Vererbung Erstelle eine Klasse
Dozent
, die von der KlassePerson
erbt. Füge dieser Klasse ein Attributfachgebiet
hinzu. Erstelle dann eine KlasseProfessor
, die von der KlasseDozent
erbt und ein zusätzliches Attributpublikationen
(eine Liste von Publikationstiteln) hat. - Überschreiben und Erweitern von Methoden Erweitere die Klasse
Student
um eine Methodestudieren
, die einen Text wie „Ich studiere gerade…“ ausgibt. Überschreibe diese Methode in einer neuen KlasseDoktorand
, die vonStudent
erbt, sodass sie „Ich forsche gerade…“ ausgibt. Füge demDoktorand
auch ein Attributforschungsgebiet
hinzu. - Verwendung von
super()
In der KlasseProfessor
(aus Aufgabe 11) überschreibe die Methodevorstellen
, sodass sie zusätzlich zu den Informationen der Elternklassen auch die Anzahl der Publikationen ausgibt. Verwende diesuper()
-Funktion, um den Code der Elternklasse nicht zu duplizieren. - Mehrere Vererbung Erstelle zwei Klassen:
Forscher
mit einem Attributforschungsfeld
undSchriftsteller
mit einem AttributveroeffentlichteBuecher
. Erstelle dann eine KlasseWissenschaftsautor
, die von beiden Klassen erbt und beide Attribute kombiniert. - Abstrakte Klassen und Methoden Erstelle eine abstrakte Klasse
Fahrzeug
mit einer abstrakten Methodefahren
. Leite zwei Klassen davon ab:Auto
undFahrrad
. Implementiere die Methodefahren
in beiden Klassen, sodass sie jeweils einen passenden Text ausgeben, z.B. „Das Auto fährt“ und „Das Fahrrad fährt“.
Weitere Übungen Objektorientierte Programmierung: https://informatik.bildung-rp.de/fileadmin/user_upload/informatik.bildung-rp.de/Fortbildung/pdf/PY-110831-Savoric-OOP.pdf