Grundlegendes zur Klassenvererbung in Python 3

Einführung

Objektorientierte Programmierung erstellt wiederverwendbare Codemuster, um die Redundanz in Entwicklungsprojekten zu verringern. Eine Möglichkeit für die objektorientierte Programmierung, wiederverwertbaren Code zu erhalten, besteht in der Vererbung, wenn eine Unterklasse Code von einer anderen Basisklasse nutzen kann.

In diesem Tutorial werden einige der wichtigsten Aspekte der Vererbung in Python behandelt, darunter die Funktionsweise von Eltern- und Kindklassen, das Überschreiben von Methoden und Attributen, die Verwendung der Funktion + super () + und die Verwendung von Mehrfachvererbung.

Was ist Vererbung?

  • Vererbung * ist, wenn eine Klasse Code verwendet, der in einer anderen Klasse erstellt wurde. Wenn wir an Vererbung im Sinne der Biologie denken, können wir uns vorstellen, dass ein Kind bestimmte Merkmale von seinem Elternteil erbt. Das heißt, ein Kind kann die Größe oder Augenfarbe eines Elternteils erben. Kinder können auch denselben Nachnamen mit ihren Eltern teilen.

Klassen mit dem Namen * child classes * oder * subclasses * erben Methoden und Variablen von * parent classes * oder * base classes *.

Wir können uns eine Elternklasse mit dem Namen "+ Parent " vorstellen, die https://www.digitalocean.com/community/tutorials/understanding-class-and-instance-variables-inpython-3#class-variables[class variables enthält ] für " last_name ", " height " und " eye_color ", die die untergeordnete Klasse " child " von " parent +" erbt.

Da die Unterklasse "+ Child " von der Basisklasse " Parent " erbt, kann die Klasse " Child " den Code von " Parent +" wiederverwenden, wodurch der Programmierer weniger Codezeilen verwenden und die Redundanz verringern kann.

Elternklassen

Übergeordnete oder Basisklassen erstellen ein Muster, auf dessen Grundlage untergeordnete oder Unterklassen erstellt werden können. Übergeordnete Klassen ermöglichen es uns, untergeordnete Klassen durch Vererbung zu erstellen, ohne dass derselbe Code jedes Mal neu geschrieben werden muss. Jede Klasse kann in eine übergeordnete Klasse umgewandelt werden, sodass es sich bei jeder Klasse um eine eigene, voll funktionsfähige Klasse handelt und nicht nur um eine Vorlage.

Angenommen, wir haben eine allgemeine übergeordnete Klasse "+ Bank_account " mit den untergeordneten Klassen " Personal_account " und " Business_account ". Viele der Methoden zwischen Privat- und Geschäftskonten sind ähnlich, z. B. das Abheben und Einzahlen von Geld, sodass diese zur übergeordneten Klasse von " Bank_account " gehören können. Die Unterklasse " Business_account " verfügt über spezifische Methoden, darunter möglicherweise eine Methode zum Sammeln von Geschäftsunterlagen und Formularen sowie eine Variable " employee_identification_number +".

In ähnlicher Weise kann eine "+ Animal " - Klasse " eating () " - und " sleeping () " - Methoden haben, und eine " Snake " - Unterklasse kann ihre eigenen spezifischen " hissing () " - und " slithering-Methoden enthalten () + `Methoden.

Erstellen wir eine übergeordnete Klasse "+ Fish +", mit der wir später Fischarten als Unterklassen konstruieren. Jeder dieser Fische hat zusätzlich zu den Merkmalen Vor- und Nachnamen.

Wir erstellen eine neue Datei mit dem Namen "+ fish.py " und beginnen mit der https://www.digitalocean.com/community/tutorials/how-to-construct-classes-and-define-objects-in-python- 3 # Die Konstruktormethode [` init () ` Konstruktormethode], die wir mit ` Vorname ` und ` Nachname ` Klassenvariablen für jedes ` Fisch +` Objekt oder jede Unterklasse füllen.

fish.py

class Fish:
   def __init__(self, first_name, last_name="Fish"):
       self.first_name = first_name
       self.last_name = last_name

Wir haben unsere Variable "+ last_name " mit der Zeichenfolge "" Fish "+" initialisiert, da wir wissen, dass die meisten Fische diesen Namen als Nachnamen haben.

Fügen wir noch einige andere Methoden hinzu:

fish.py

class Fish:
   def __init__(self, first_name, last_name="Fish"):
       self.first_name = first_name
       self.last_name = last_name

Wir haben die Methoden + swim () + und + swim backwards () + zur Klasse + Fish hinzugefügt, damit auch jede Unterklasse diese Methoden verwenden kann.

Da die meisten Fische, die wir erstellen werden, als bony fish (wie sie ein Knochengerüst haben) und nicht als https: // en angesehen werden .wikipedia.org / wiki / Chondrichthyes [Knorpelfische] (da sie ein Skelett aus Knorpel haben), können wir der Methode + init () + ein paar weitere Attribute hinzufügen:

fish.py

class Fish:
   def __init__(self, first_name, last_name="Fish",
                ):
       self.first_name = first_name
       self.last_name = last_name



   def swim(self):
       print("The fish is swimming.")

   def swim_backwards(self):
       print("The fish can swim backwards.")

Das Erstellen einer übergeordneten Klasse folgt der gleichen Methodik wie das Erstellen einer anderen Klasse, mit der Ausnahme, dass wir uns überlegen, welche Methoden die untergeordneten Klassen verwenden können, sobald wir diese erstellen.

Kinderklassen

Untergeordnete oder Unterklassen sind Klassen, die von der übergeordneten Klasse erben. Das bedeutet, dass jede untergeordnete Klasse die Methoden und Variablen der übergeordneten Klasse verwenden kann.

Beispielsweise kann eine untergeordnete Klasse "+ Goldfish ", die die Klasse " Fish " unterordnet, die in " Fish " deklarierte Methode " swim () +" verwenden, ohne dass diese deklariert werden muss.

Wir können uns jede Kinderklasse als eine Klasse der Elternklasse vorstellen. Das heißt, wenn wir eine untergeordnete Klasse mit dem Namen "+ Rhombus " und eine übergeordnete Klasse mit dem Namen " Parallelogram " haben, können wir sagen, dass ein " Rhombus " * ein " Parallelogram " ist, genau wie ein " Goldfish " *. ist ein * ` Fisch +`.

Die erste Zeile einer untergeordneten Klasse unterscheidet sich geringfügig von Klassen, die keine untergeordneten Klassen sind, da Sie die übergeordnete Klasse als Parameter an die untergeordnete Klasse übergeben müssen:

class Trout(Fish):

Die Klasse "+ Forelle" ist ein Kind der Klasse "+ Fisch". Wir wissen das, weil das Wort "+ Fisch +" in Klammern steht.

Bei untergeordneten Klassen können Sie wählen, ob Sie weitere Methoden hinzufügen, vorhandene übergeordnete Methoden überschreiben oder einfach die standardmäßigen übergeordneten Methoden mit dem Schlüsselwort "+ pass +" akzeptieren möchten. In diesem Fall gehen Sie folgendermaßen vor:

fish.py

...
class Trout(Fish):
   pass

Wir können jetzt ein "+ Trout +" - Objekt erstellen, ohne zusätzliche Methoden definieren zu müssen.

fish.py

...
class Trout(Fish):
   pass

terry = Trout("Terry")
print(terry.first_name + " " + terry.last_name)
print(terry.skeleton)
print(terry.eyelids)
terry.swim()
terry.swim_backwards()

Wir haben ein "+ Trout " -Objekt " terry " erstellt, das alle Methoden der Klasse " Fish " verwendet, obwohl wir diese Methoden nicht in der untergeordneten Klasse " Trout " definiert haben. Wir mussten nur den Wert "" Terry "" an die Variable " first_name +" übergeben, da alle anderen Variablen initialisiert wurden.

Wenn wir das Programm ausführen, erhalten wir die folgende Ausgabe:

OutputTerry Fish
bone
False
The fish is swimming.
The fish can swim backwards.

Als Nächstes erstellen wir eine weitere untergeordnete Klasse, die eine eigene Methode enthält. Wir nennen diese Klasse "+ Clownfish +" und ihre spezielle Methode ermöglicht es ihr, mit Seeanemonen zu leben:

fish.py

...
class Clownfish(Fish):

   def live_with_anemone(self):
       print("The clownfish is coexisting with sea anemone.")

Als nächstes erstellen wir ein "+ Clownfish +" - Objekt, um zu sehen, wie dies funktioniert:

fish.py

...
casey = Clownfish("Casey")
print(casey.first_name + " " + casey.last_name)
casey.swim()
casey.live_with_anemone()

Wenn wir das Programm ausführen, erhalten wir die folgende Ausgabe:

OutputCasey Fish
The fish is swimming.
The clownfish is coexisting with sea anemone.

Die Ausgabe zeigt, dass das + Clownfish + Objekt + casey + die + Fish + Methoden + init () + und + swim () + sowie die untergeordnete Klassenmethode von `+ live_with_anemone verwenden kann () + `.

Wenn wir versuchen, die Methode "+ live_with_anemone () " in einem " Trout +" - Objekt zu verwenden, erhalten wir eine Fehlermeldung:

Outputterry.live_with_anemone()
AttributeError: 'Trout' object has no attribute 'live_with_anemone'

Dies liegt daran, dass die Methode "+ live_with_anemone () " nur zur Klasse " Clownfish " gehört und nicht zur Klasse " Fish +".

Untergeordnete Klassen erben die Methoden der übergeordneten Klasse, zu der sie gehören, sodass jede untergeordnete Klasse diese Methoden in Programmen verwenden kann.

Übergeordnete Methoden überschreiben

Bisher haben wir uns die untergeordnete Klasse "+ Trout " angesehen, die das Schlüsselwort " pass " verwendet, um alle Verhaltensweisen der übergeordneten Klasse " Fish " zu erben, und eine andere untergeordnete Klasse " Clownfish ", die alle Eigenschaften von " Trout +" geerbt hat Verhalten der übergeordneten Klasse und erstellte außerdem eine eigene eindeutige Methode, die für die untergeordnete Klasse spezifisch ist. Manchmal möchten wir jedoch einige der Verhaltensweisen der übergeordneten Klasse nutzen, jedoch nicht alle. Wenn wir übergeordnete Klassenmethoden ändern, * überschreiben * wir sie.

Beim Erstellen von über- und untergeordneten Klassen ist es wichtig, das Programmdesign im Auge zu behalten, damit beim Überschreiben kein unnötiger oder redundanter Code erzeugt wird.

Wir erstellen eine untergeordnete Klasse "+ Shark " für die übergeordnete Klasse " Fish ". Da wir die Klasse " Fish " mit der Idee erstellt haben, dass hauptsächlich knöcherne Fische erstellt werden, müssen wir Anpassungen für die Klasse " Shark +" vornehmen, die stattdessen ein knorpeliger Fisch ist. Wenn wir mehr als einen nicht knöchernen Fisch hätten, würden wir höchstwahrscheinlich getrennte Klassen für jede dieser beiden Arten von Fischen erstellen wollen.

Haie haben im Gegensatz zu knöchernen Fischen Skelette aus Knorpel anstelle von Knochen. Sie haben auch Augenlider und können nicht rückwärts schwimmen. Haie können sich jedoch durch Sinken rückwärts bewegen.

Vor diesem Hintergrund werden wir die Konstruktormethode "+ init () " und die Methode " swim_backwards () " überschreiben. Die Methode " swim () +" muss nicht geändert werden, da Haie schwimmfähige Fische sind. Werfen wir einen Blick auf diese Kinderklasse:

fish.py

...
class Shark(Fish):
   def __init__(self, first_name, last_name="Shark",
                skeleton="cartilage", eyelids=True):
       self.first_name = first_name
       self.last_name = last_name
       self.skeleton = skeleton
       self.eyelids = eyelids

   def swim_backwards(self):
       print("The shark cannot swim backwards, but can sink backwards.")

Wir haben die initialisierten Parameter in der Methode "+ init () " überschrieben, so dass die Variable " last_name " jetzt gleich der Zeichenfolge "" Shark "" und die Variable " skeleton " gleich gesetzt wird auf die Zeichenfolge "" Knorpel "" und die Variable " Augenlider " wird jetzt auf den Booleschen Wert " True +" gesetzt. Jede Instanz der Klasse kann diese Parameter auch überschreiben.

Die Methode + swim_backwards () + gibt jetzt eine andere Zeichenkette aus als die der Elternklasse + Fish +, da Haie nicht so rückwärts schwimmen können, wie es Knochenfische können.

Wir können jetzt eine Instanz der untergeordneten Klasse "+ Shark " erstellen, die weiterhin die Methode " swim () " der übergeordneten Klasse " Fish +" verwendet:

fish.py

...
sammy = Shark("Sammy")
print(sammy.first_name + " " + sammy.last_name)
sammy.swim()
sammy.swim_backwards()
print(sammy.eyelids)
print(sammy.skeleton)

Wenn wir diesen Code ausführen, erhalten wir die folgende Ausgabe:

OutputSammy Shark
The fish is swimming.
The shark cannot swim backwards, but can sink backwards.
True
cartilage

Die untergeordnete Klasse "+ Shark In" überschreibt erfolgreich die Methoden "+ init () " und " swim backwards () " der übergeordneten Klasse " Fish " und übernimmt gleichzeitig die Methode " swim () +" von die Elternklasse.

Wenn es eine begrenzte Anzahl von Kindklassen gibt, die eindeutiger sind als andere, kann sich das Überschreiben von Elternklassenmethoden als nützlich erweisen.

Die Funktion + super () +

Mit der Funktion + super () + erhalten Sie Zugriff auf geerbte Methoden, die in einem Klassenobjekt überschrieben wurden.

Wenn wir die Funktion + super () + verwenden, rufen wir eine übergeordnete Methode in eine untergeordnete Methode auf, um sie zu verwenden. Beispielsweise möchten wir möglicherweise einen Aspekt der übergeordneten Methode mit bestimmten Funktionen überschreiben, aber dann den Rest der ursprünglichen übergeordneten Methode aufrufen, um die Methode zu beenden.

In einem Programm, das Schüler benotet, möchten wir möglicherweise eine untergeordnete Klasse für "+ Weighted_grade ", die von der übergeordneten Klasse " Grade " erbt. In der untergeordneten Klasse " Weighted_grade " möchten wir möglicherweise die Methode " calculator_grade () " der übergeordneten Klasse überschreiben, um Funktionen zum Berechnen einer gewichteten Note einzuschließen, aber den Rest der Funktionen der ursprünglichen Klasse beizubehalten . Durch Aufrufen der Funktion " super () +" können wir dies erreichen.

Die Funktion + super () + wird am häufigsten in der Methode + init () + verwendet, da Sie dort höchstwahrscheinlich der untergeordneten Klasse eine Eindeutigkeit hinzufügen und dann die Initialisierung vom übergeordneten Element durchführen müssen.

Um zu sehen, wie dies funktioniert, ändern wir unsere untergeordnete Klasse "+ Trout ". Da Forellen normalerweise Süßwasserfische sind, fügen wir der Methode " init () " eine Variable " water " hinzu und setzen sie gleich der Zeichenfolge "" freshwater "+", behalten dann aber die restlichen Variablen der Elternklasse bei und Parameter:

fish.py

...
class Trout(Fish):
   def __init__(self, water = "freshwater"):
       self.water = water
       super().__init__(self)
...

Wir haben die Methode "+ init () " in der untergeordneten Klasse " Trout " überschrieben und eine andere Implementierung der " init () " bereitgestellt, die bereits durch die übergeordnete Klasse " Fish " definiert ist. Innerhalb der Methode " init () " unserer Klasse " Trout " haben wir die Methode " init () " der Klasse " Fish +" explizit aufgerufen.

Da wir die Methode überschrieben haben, müssen wir "+ first_name " nicht mehr als Parameter an " Trout " übergeben, und wenn wir einen Parameter übergeben würden, würden wir stattdessen " freshwater " zurücksetzen. Wir werden daher das ` first_name +` initialisieren, indem wir die Variable in unserer Objektinstanz aufrufen.

Jetzt können wir die initialisierten Variablen der übergeordneten Klasse aufrufen und auch die eindeutige untergeordnete Variable verwenden. Verwenden wir dies in einer Instanz von "+ Trout +":

fish.py

...
terry = Trout()

# Initialize first name
terry.first_name = "Terry"

# Use parent __init__() through super()
print(terry.first_name + " " + terry.last_name)
print(terry.eyelids)

# Use child __init__() override
print(terry.water)

# Use parent swim() method
terry.swim()
OutputTerry Fish
False
freshwater
The fish is swimming.

Die Ausgabe zeigt, dass das Objekt "+ terry " der untergeordneten Klasse " Trout " sowohl die kinderspezifische Variable " init () " " water " verwenden kann, als auch das "" aufrufen kann Fisch + Eltern + init () + Variablen von + Vorname + , + Nachname + und + Augenlider + `.

Die eingebaute Python-Funktion "+ super () +" ermöglicht es uns, übergeordnete Klassenmethoden zu verwenden, selbst wenn bestimmte Aspekte dieser Methoden in unseren untergeordneten Klassen überschrieben werden.

Mehrfachvererbung

  • Mehrfachvererbung * ist, wenn eine Klasse Attribute und Methoden von mehr als einer Elternklasse erben kann. Dies kann es Programmen ermöglichen, die Redundanz zu reduzieren, es kann jedoch auch ein gewisses Maß an Komplexität und Mehrdeutigkeit mit sich bringen. Daher sollte das gesamte Programmdesign berücksichtigt werden.

Um zu zeigen, wie die Mehrfachvererbung funktioniert, erstellen wir eine untergeordnete Klasse "+ Coral_reef " als Erbe einer Klasse " Coral " und einer Klasse " Sea_anemone ". Wir können in jedem eine Methode erstellen und dann das Schlüsselwort " pass " in der untergeordneten Klasse " Coral_reef +" verwenden:

coral_reef.py

class Coral:

   def community(self):
       print("Coral lives in a community.")


class Anemone:

   def protect_clownfish(self):
       print("The anemone is protecting the clownfish.")


class CoralReef(Coral, Anemone):
   pass

Die Klasse "+ Coral " hat eine Methode mit dem Namen " community () ", die eine Zeile druckt, und die Klasse " Anemone " hat eine Methode mit dem Namen " protect_clownfish () ", die eine weitere Zeile druckt. Dann rufen wir beide Klassen in der Vererbung https://www.digitalocean.com/community/tutorials/understanding-tuples-in-python-3[tuple] auf. Dies bedeutet, dass " Coral +" von zwei übergeordneten Klassen erbt.

Instanziieren wir nun ein "+ Coral +" - Objekt:

coral_reef.py

...
great_barrier = CoralReef()
great_barrier.community()
great_barrier.protect_clownfish()

Das Objekt "+ great_barrier " wird als " CoralReef +" - Objekt festgelegt und kann die Methoden in beiden übergeordneten Klassen verwenden. Wenn wir das Programm ausführen, wird die folgende Ausgabe angezeigt:

OutputCoral lives in a community.
The anemone is protecting the clownfish.

Die Ausgabe zeigt, dass Methoden aus beiden übergeordneten Klassen effektiv in der untergeordneten Klasse verwendet wurden.

Durch Mehrfachvererbung können wir den Code von mehr als einer übergeordneten Klasse in einer untergeordneten Klasse verwenden. Wenn dieselbe Methode in mehreren übergeordneten Methoden definiert ist, verwendet die untergeordnete Klasse die Methode des ersten übergeordneten Elements, das in der Tupelliste deklariert ist.

Obwohl es effektiv genutzt werden kann, sollte die Mehrfachvererbung mit Sorgfalt durchgeführt werden, damit unsere Programme nicht mehrdeutig und für andere Programmierer schwer zu verstehen sind.

Fazit

In diesem Lernprogramm wurden über- und untergeordnete Klassen erstellt, übergeordnete Methoden und Attribute in untergeordneten Klassen mit der Funktion "+ super () +" überschrieben und untergeordneten Klassen ermöglicht, von mehreren übergeordneten Klassen zu erben.

Durch die Vererbung in der objektorientierten Codierung kann das DRY-Prinzip (Don’t Repeat Yourself) der Softwareentwicklung eingehalten werden, sodass mit weniger Code und Wiederholungen mehr erreicht werden kann. Vererbung zwingt Programmierer auch dazu, darüber nachzudenken, wie sie die von ihnen erstellten Programme entwerfen, um sicherzustellen, dass der Code effektiv und klar ist.