Home
Navigation
Impressum
Coder Welten - Programmierung und Optimierung
Coder Welten
 
 

 

 

OOP Python: Vererbung und Sichtbarkeit

Objektorientierte Programmierung mit Python 3

Die Vererbung spielt in der objektorientierten Programmierung eine bedeutende Rolle. Ohne Vererbung müsste zuerst eine übergeordnete Klasse instanziiert wer­den, um z.B. auf die öffentlichen Eigenschaften (Attribute) dieser überge­ordneten Klasse zugreifen und in einer nachfolgenden Klasse mit diesen arbeiten zu können. Ebenso verhält es sich mit den Funktionalitäten von Methoden.
Zuerst ein Beispiel ohne Vererbung. Um mit den Attributen der Klasse "Säuger" in der Klasse "Mensch" arbeiten zu können, wird zuerst die Klasse Säuger instanziiert, danach die Klasse Mensch und dabei der Klasse Mensch die Werte der Attribute aus der Instanz "Säuger" übergeben.

Beispiel 1 (ohne Vererbung):

class Saeuger:

    def __init__(self):
        self.ordnung = "Primaten"
        self.familie = "Menschenaffen"
        self.spezies = "Mensch"

class Mensch:

    def __init__(self, ordnung, familie, spezies):
        self.ordnung = ordnung
        self.familie = familie
        self.spezies = spezies

    def get_spezies(self):
        art_spezies = "Der {0} gehört im Tierreich ".format(self.spezies)
        art_ordnung = "zur Ordnung der {0} ".format(self.ordnung)
        art_familie = "und zur Familie der {0}.\n".format(self.familie)
        return "{0}{1}{2}".format(art_spezies, art_ordnung, art_familie)

erste_instanz = Saeuger()
zweite_instanz = Mensch(erste_instanz.ordnung, erste_instanz.familie,
                        erste_instanz.spezies)

print(zweite_instanz.get_spezies())

Eine andere Möglichkeit bestünde darin, eine Klasse in einer anderen zu instan­ziieren. Von dieser Möglichkeit wird häufiger Gebrauch gemacht, als von der hier aufgezeigten Variante.

Nun drei Beispiele mit Vererbung. Damit eine abgeleitete Kinderklasse von einer über­geordneten Elternklasse erben kann, muss der Bezeichner von der Eltern­klasse in Klammern hinter der Definition einer Kinderklasse notiert werden.

Beispiel 2 (mit Vererbung):

class Saeuger:

    def __init__(self):
        self.ordnung = "Primaten"
        self.familie = "Menschenaffen"
        self.spezies = "Mensch"

class Mensch(Saeuger):

    def get_spezies(self):
        art_spezies = "Der {0} gehört im Tierreich ".format(self.spezies)
        art_ordnung = "zur Ordnung der {0} ".format(self.ordnung)
        art_familie = "und zur Familie der {0}.\n".format(self.familie)
        return "{0}{1}{2}".format(art_spezies, art_ordnung, art_familie)

instanz = Mensch()
print(instanz.get_spezies())

Das dritte Beispiel unterscheidet sich vom zweiten Beispiel lediglich dadurch, dass beim Instanziieren der Kinderklasse "Mensch" ein Wert für die Attribute-Eigenschaft "spezies" der Elternklasse "Saeuger" übergeben wird.

Beispiel 3 (mit Werteübergabe):

class Saeuger:

    def __init__(self,  spezies_value = None):
        self.ordnung = "Primaten"
        self.familie = "Menschenaffen"
        self.spezies = spezies_value

class Mensch(Saeuger):

    def get_spezies(self):
        art_spezies = "Der {0} gehört im Tierreich ".format(self.spezies)
        art_ordnung = "zur Ordnung der {0} ".format(self.ordnung)
        art_familie = "und zur Familie der {0}.\n".format(self.familie)
        return "{0}{1}{2}".format(art_spezies, art_ordnung, art_familie)

instanz = Mensch("Mensch")
print(instanz.get_spezies())

Beim vierten Beispiel wurde die Methode get_spezies() in die Elternklasse ver­scho­ben. Um in der erbenden Klasse Mensch auf diese Methode beim Instan­ziieren zugreifen zu können, wird diese mit der Methode get_art() in der Kinder­klasse auf­gerufen.

Beispiel 4 (mit Vererbung einer Methode):

class Saeuger:

    def __init__(self,  spezies_value = None):
        self.ordnung = "Primaten"
        self.familie = "Menschenaffen"
        self.spezies = spezies_value

    def get_spezies(self):
        art_spezies = "Der {0} gehört im Tierreich ".format(self.spezies)
        art_ordnung = "zur Ordnung der {0} ".format(self.ordnung)
        art_familie = "und zur Familie der {0}.\n".format(self.familie)
        return "{0}{1}{2}".format(art_spezies, art_ordnung, art_familie)

class Mensch(Saeuger):

    def get_art(self):
        return self.get_spezies()

instanz = Mensch("Mensch")
print(instanz.get_art())

Bei der Vererbung muss bedacht werden, dass die Vergabe von gleichnamigen Bezeichnern beim Definieren von Methoden in einer vererbenden und in einer er­benden Klasse eine Überschreibung der geerbten Methoden in der erbenden Klasse bewirkt. Von dieser Überschreibung in der erbenden Klasse ist auch die __init__ Methode nicht ausgeschlossen, insofern beide Klassen eine __init__ Methode be­sitzen. Um einer Überschreibung entgegenzuwirken muss die __init__ Methode aus der Elternklasse in einer erbenden Klasse mit Parametern aufge­rufen werden, selbst wenn diese Parameter wie im ersten Beispiel nur als Platz­halter für die eigentlichen Argumente dienen.
Nebenbei sei erwähnt, Parameter dienen der Übergabe von Werten, erst inner­halb einer Funktion oder Methode werden Parameter und deren Werte als Argu­mente benutzt.

Beispiel 5 (mit Platzhaltern für Parameter):

class Saeuger:

    def __init__(self, ordnung, familie):
        self.ordnung = "Primaten"
        self.familie = "Menschenaffen"

class Mensch(Saeuger):

    def __init__(self):
        self.spezies = "Mensch"
        Saeuger.__init__(self, "?", "?")

    def get_art(self):
        art_spezies = "Der {0} gehört im Tierreich ".format(self.spezies)
        art_ordnung = "zur Ordnung der {0} ".format(self.ordnung)
        art_familie = "und zur Familie der {0}.\n".format(self.familie)
        return "{0}{1}{2}".format(art_spezies, art_ordnung, art_familie)

instanz = Mensch()
print(instanz.get_art())

Beispiel 6 (mit der Übergabe von Werten):

class Saeuger:

    def __init__(self, value_ordnung, value_familie):
        self.ordnung = value_ordnung
        self.familie = value_familie

    def get_spezies(self):
        art_spezies = "Der {0} gehört im Tierreich ".format(self.spezies)
        art_ordnung = "zur Ordnung der {0} ".format(self.ordnung)
        art_familie = "und zur Familie der {0}.\n".format(self.familie)
        return "{0}{1}{2}".format(art_spezies, art_ordnung, art_familie)

class Mensch(Saeuger):

    def __init__(self):
        self.spezies = "Mensch"
        Saeuger.__init__(self, "Primaten", "Menschenaffen")

    def get_art(self):
        return self.get_spezies()

instanz = Mensch()
print(instanz.get_art())

Alle vorausgehenden Beispiele bewirken eine sich gleichende Ausgabe, da es sich lediglich um unterschiedliche Varianten handelt, die letztendlich alle zum gleichen Ergebnis führen.

Ausgabe:

Der Mensch gehört im Tierreich zur Ordnung der Primaten und zur Familie der Menschenaffen.

Etwas anders sieht die Ausgabe vom folgenden Beispiel aus.

Dabei sollte beachtet werden, Variablen, denen ein Sternchen vorangestellt wur­de, dienen der Speicherung von Werten für Argumente in Tupeln. Mit zwei Stern­chen versehende Variablen speichern hingegen Parameter und die Werte für Argumente in Dictionaries. Diese Variante kann benutzt werden, wenn beim Er­stellen von Klassen nicht von einer stetig gleichbleibenden Anzahl von zu übergebenen Parametern bzw. von Parameter-Wertepaaren ausgegangen werden kann.

Beispiel 7:

class Saeuger:

    def __init__(self, *args, **kwargs):
        self.ordnung = "Primaten"
        self.familie = "Menschenaffen"

    def get_argumente(self, *args):
        return "Antwort von der Klasse Saeuger: {}".format(args)

class Mensch(Saeuger):

    def __init__(self, *args, **kwargs):
        Saeuger.__init__(self, *args, **kwargs)
        self.spezies = "Mensch"

    def get_keyword_argumente (self, **kwargs):
        return "Antwort von der Klasse Mensch: {}".format(kwargs)

instanz = Mensch()
print(instanz.get_argumente("Doe", "John"))
print(instanz.get_keyword_argumente(Nachname = "Doe", Vornahme = "Jane"))

Ausgabe:

Antwort von der Klasse Saeuger: ('Doe', 'John')
Antwort von der Klasse Mensch: {'Nachname': 'Doe', 'Vornahme': 'Jane'}

Sichtbarkeit von Attributen

Die Sichtbarkeit von Attributen wird zuweilen mit der Sichtbarkeit in anderen Script- und Programmiersprachen verglichen, wobei dann die Schlüsselwörter public, protected und private aus diesen Sprachen benutzt werden, doch hinken diese Vergleiche. Ein Grund für dieses Hinken, protected gibt es in Python praktisch nicht.
Attribute und Methoden können mit Hilfe eines vorangestellten Präfixes, beste­hend aus zwei __Unterstrichen, vor einem Zugriff von außerhalb oder von einer erbenden Klasse aus geschützt werden, ein einzelner vorangestellter Unterstrich hat hingegen für Python keine Bedeutung. Wird ein einzelner Unterstrich dennoch verwendet, dann nur um anderen Programmierern, die ein Script weiterent­wickeln möchten, mitzuteilen, dass dieses Attribut nicht unbedingt geändert wer­den sollte.

Beispiel 8 (öffentliche Attribute):

class Saeuger:

    def __init__(self):
        self.variable01   = "öffentlich 01"
        self._variable02  = "öffentlich 02"
        self.__variable03 = "privat"

class Mensch(Saeuger):

    def get_sichtbarkeitstest(self):
        test = "# Ausgabe get_sichtbarkeitstest(): {0:s}, {1:s}".format(
                self.variable01, self._variable02)
        return test

instanz = Mensch()
print(instanz.get_sichtbarkeitstest())

instanz = Saeuger()
print("# Ausgabe Saeuger(): {}".format(instanz.variable01))
print("# Ausgabe Saeuger(): {}".format(instanz._variable02))

# Ausgabe get_sichtbarkeitstest(): öffentlich 01, öffentlich 02
# Ausgabe Saeuger(): öffentlich 01
# Ausgabe Saeuger(): öffentlich 02

Die Ausgaben von beiden Code-Listings wurden jeweils als Kommentare mit ein­gefügt, wobei es sich im nächsten Beispiel nicht um eine Print-Ausgabe handelt, sondern um die erhaltene Fehlermeldung beim Versuch auf ein mit zwei voran­gestellten Unterstrichen versehendes Attribut zuzugreifen.

Beispiel 9 (mit geschütztem Attribut):

class Saeuger:

    def __init__(self):
        self.__geheimnis = "private"

class Mensch(Saeuger):

    def get_sichtbarkeitstest(self):
        test = "# Ausgabe: {0:s}".format( self.__geheimnis)
        return test

instanz = Mensch()
print(instanz.get_sichtbarkeitstest())

# AttributeError: 'Mensch' object has no attribute '_Mensch__geheimnis'

Beispiel 10 (mit öffentlichem Attribut aber geschützter Methode):

class Saeuger:

    def __init__(self):
        self.oeffentlich = "öffentlich 01"

class Mensch(Saeuger):

    def __get_sichtbarkeitstest(self):
        test = "# Ausgabe: {0:s}".format( self.oeffentlich)
        return test

instanz = Mensch()
print(instanz.__get_sichtbarkeitstest())

# AttributeError: 'Mensch' object has no attribute '__get_sichtbarkeitstest'
 
Navigation

Einstieg in Python

 


OOP mit Python

  • Vererbung und Sicht­barkeit

 


Codes & Tutorials

 

Weitere Themen

Kleines Projekt

 


Copyright © Verlag Horst Müller - Stendal - 2006 - Impressum - Datenschutz - Nutzungsbedingungen