12. Unterrichtsblock

Kursinhalte

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

  1. Da eine untergeordnete Klasse alle Funktionalitäten der übergeordneten Klasse erben kann, ermöglicht dies die Wiederverwendbarkeit von Code.
  2. 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.
  3. 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 hundKlasse 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:

PythonJSON
dictObject
listArray
tupleArray
strString
intNumber
floatNumber
Truetrue
Falsefalse
Nonenull

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

  1. Einfache Klasse erstellen Erstelle eine Klasse namens Person, die zwei Attribute hat: name und alter. Die Klasse sollte auch eine Methode namens vorstellen haben, die den Namen und das Alter der Person ausgibt.
  2. Konstruktor verwenden Erweitern Sie die Person-Klasse um einen Konstruktor, der den Namen und das Alter der Person beim Erstellen eines neuen Objekts initialisiert.
  3. Klasse Tier Erstelle eine Klasse namens Tier mit den Attributen art und laut. Die Klasse sollte eine Methode namens machenLaut haben, die den Laut des Tieres ausgibt.
  4. Vererbung Erstelle eine Klasse namens Student, die von der Person-Klasse erbt und ein zusätzliches Attribut namens matrikelnummer hat.
  5. Überschreiben von Methoden Überschreibe die vorstellen-Methode in der Student-Klasse, sodass sie auch die Matrikelnummer des Studenten ausgibt.
  6. Klasse Auto Erstelle eine Klasse namens Auto mit den Attributen marke, modell und kilometerstand. Füge Methoden hinzu, um den Kilometerstand zu erhöhen und den aktuellen Kilometerstand auszugeben.
  7. Private Attribute Ändere die Auto-Klasse, sodass der kilometerstand ein privates Attribut ist. Füge Methoden hinzu, um den Kilometerstand sicher zu setzen und zu erhalten.
  8. Klasse Buch Erstelle eine Klasse namens Buch mit den Attributen titel, autor und seitenzahl. Füge eine Methode hinzu, die das Buch vorstellt.
  9. 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.
  10. Zusammensetzung Erstelle eine Klasse namens Bibliothek, die eine Liste von Buch-Objekten enthält. Füge Methoden hinzu, um Bücher hinzuzufügen und zu entfernen.

Übungen Vererbung

  1. Mehrstufige Vererbung Erstelle eine Klasse Dozent, die von der Klasse Person erbt. Füge dieser Klasse ein Attribut fachgebiet hinzu. Erstelle dann eine Klasse Professor, die von der Klasse Dozent erbt und ein zusätzliches Attribut publikationen (eine Liste von Publikationstiteln) hat.
  2. Überschreiben und Erweitern von Methoden Erweitere die Klasse Student um eine Methode studieren, die einen Text wie „Ich studiere gerade…“ ausgibt. Überschreibe diese Methode in einer neuen Klasse Doktorand, die von Student erbt, sodass sie „Ich forsche gerade…“ ausgibt. Füge dem Doktorand auch ein Attribut forschungsgebiet hinzu.
  3. Verwendung von super() In der Klasse Professor (aus Aufgabe 11) überschreibe die Methode vorstellen, sodass sie zusätzlich zu den Informationen der Elternklassen auch die Anzahl der Publikationen ausgibt. Verwende die super()-Funktion, um den Code der Elternklasse nicht zu duplizieren.
  4. Mehrere Vererbung Erstelle zwei Klassen: Forscher mit einem Attribut forschungsfeld und Schriftsteller mit einem Attribut veroeffentlichteBuecher. Erstelle dann eine Klasse Wissenschaftsautor, die von beiden Klassen erbt und beide Attribute kombiniert.
  5. Abstrakte Klassen und Methoden Erstelle eine abstrakte Klasse Fahrzeug mit einer abstrakten Methode fahren. Leite zwei Klassen davon ab: Auto und Fahrrad. Implementiere die Methode fahren 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