HOWTO · Python
Methodenüberladung in Python
Dieses Tutorial stellt das Überladen von Methoden in Python und seine Vorteile mit Beispielen vor.
Auf dieser Seite
Python wählt keine Methode oder Funktion aus, indem es die Anzahl oder Typen der Argumente mit mehreren Definitionen desselben Namens abgleicht. Eine spätere Definition ersetzt die frühere Namensbindung. Für unterschiedliche Aufrufe können Sie eine Funktion mit optionalen Parametern verwenden, anhand der Eingabetypen ausdrücklich verzweigen oder ein Drittanbieterpaket für Multiple Dispatch einsetzen. Das sind unterschiedliche Techniken; nur die letzte wählt anhand der Argumenttypen zwischen registrierten Implementierungen aus.
Unterstützt Python Methodenüberladung?
Python bietet standardmäßig keine signaturbasierte Methodenüberladung. Definiert eine Klasse denselben Methodennamen mehrmals, bleibt unter diesem Namen die letzte Definition erhalten. Das unterscheidet sich von der Operatorüberladung, bei der eine Klasse mit speziellen Methoden wie __add__ das Verhalten eines Operators anpassen kann. Es unterscheidet sich auch von einer einzelnen Methode mit einem optionalen Argument: Diese Methode hat weiterhin nur eine Implementierung und entscheidet selbst, was sie mit den übergebenen Werten macht.
Eine Begrüßungsmethode kann beispielsweise einen Namen entgegennehmen, wenn einer verfügbar ist, und andernfalls einen Standardwert verwenden. Das ist Verhalten mit einem optionalen Argument, keine Überladung mit zwei Varianten.
Standardargumente für optionale Parameter verwenden
Verwenden Sie einen Standardwert, wenn eine Eingabe tatsächlich optional ist und derselbe Vorgang mit beiden Aufrufformen funktioniert. Das Beispiel definiert eine Methode und ruft sie sowohl mit als auch ohne Namen auf.
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
class Greeter:
def greet(self, name="there"):
print(f"Hello, {name}!")
Greeter().greet()
Greeter().greet("Ada")
Bei der bereitgestellten Ausführung wurden diese Aufrufe ausgeführt und Folgendes ausgegeben:
Hello, there!
Hello, Ada!
Das Standardargument setzt "there" ein, wenn der Aufrufer name weglässt; wird ein Name übergeben, wird stattdessen dieser Wert verwendet. Verwenden Sie bei veränderlichen Standardwerten wie Listen oder Dictionaries None und erzeugen Sie innerhalb der Methode einen neuen Wert. So teilen sich mehrere Aufrufe nicht dasselbe veränderliche Objekt.
Typprüfungen für unterschiedliches Verhalten verwenden
Wenn eine kleine Anzahl von Eingabetypen unterschiedliches Verhalten auslösen soll, kann eine Funktion ihre Eingaben prüfen und ausdrücklich verzweigen. Die folgende Funktion akzeptiert entweder zwei Ganzzahlen oder zwei Zeichenfolgen. Andere Kombinationen weist sie mit einem aussagekräftigen TypeError zurück, statt sich auf ein zufälliges Verhalten des +-Operators in Python zu verlassen.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
def combine(left, right):
if type(left) is int and type(right) is int:
return left + right
if type(left) is str and type(right) is str:
return left + right
raise TypeError("combine expects two integers or two strings")
print(combine(7, 11))
print(combine("Hello, ", "Python"))
Bei der bereitgestellten Ausführung wurde das Beispiel ausgeführt und Folgendes ausgegeben:
18
Hello, Python
Dies ist eine ausdrückliche Typprüfung innerhalb einer Funktion, keine automatische Methodenüberladung. Exakte Prüfungen mit type(...) is ... schließen Unterklassen wie bool aus, das eine Unterklasse von int ist. Verwenden Sie stattdessen isinstance, wenn Unterklassen akzeptiert werden sollen. Die Funktion akzeptiert absichtlich auch keine gemischten Paare, etwa eine Ganzzahl und eine Zeichenfolge. Erweitern Sie die Verzweigungen nur dann um solche Kombinationen, wenn sie in Ihrer Anwendung eine klar definierte Bedeutung haben.
Multiple Dispatch für die Auswahl nach Typ verwenden
Für die Auswahl anhand mehrerer Argumenttypen registriert das Drittanbieterpaket multipledispatch Implementierungen für bestimmte Signaturen. Installieren Sie es mit pip install multipledispatch in der Umgebung, in der das Programm ausgeführt werden soll. Das folgende Beispiel definiert Funktionen, keine Klassenmethoden, und registriert eine Signatur für drei Ganzzahlen und eine weitere für drei Fließkommazahlen:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
try:
from multipledispatch import dispatch
except ImportError:
print("Install multipledispatch to run this example.")
else:
@dispatch(int, int, int)
def multiply(first, second, third):
return first * second * third
@dispatch(float, float, float)
def multiply(first, second, third):
return first * second * third
print(multiply(3, 7, 8))
print(multiply(3.6, 5.9, 9.9))
Bei der bereitgestellten Ausführung wurde der Rückfall mit der Installationsmeldung durchgespielt und Folgendes ausgegeben:
Install multipledispatch to run this example.
Erfolgreiche Aufrufe der registrierten Dispatch-Funktionen mit installierter Abhängigkeit wurden nicht ausgeführt. Ist das Paket installiert, wählen Aufrufe, die einer registrierten Signatur entsprechen, die zugehörige Funktionsimplementierung aus. Hier sind nur diese Signaturen registriert; für eine gemischte Kombination aus Ganzzahlen und Fließkommazahlen gibt es keine passende Registrierung. Fügen Sie Registrierungen für die Kombinationen hinzu, die Ihr Programm unterstützen soll, und prüfen Sie, ob die zusätzliche Abhängigkeit für Ihr Projekt geeignet ist.
Den Ansatz anhand der Aufrufsignatur auswählen
Wählen Sie ein Standardargument, wenn Aufrufer eine Eingabe weglassen können und eine Implementierung beide Aufrufformen behandeln kann. Verwenden Sie ausdrückliche Typprüfungen, wenn es nur wenige beabsichtigte Verhaltensweisen gibt und die Regel in einer Funktion leicht verständlich bleibt. Nutzen Sie Multiple Dispatch, wenn die Auswahl anhand von Argumenttypkombinationen für den Entwurf zentral ist und die zusätzliche Abhängigkeit akzeptabel ist.
Keine dieser Möglichkeiten macht ein Programm automatisch schneller oder einfacher. Legen Sie die unterstützten Aufrufe ausdrücklich fest: Dokumentieren Sie Standardwerte, definieren Sie das Verhalten für jede akzeptierte Typkombination und registrieren Sie jede Signatur, die der Dispatch-Ansatz abdecken muss. Pythons gewöhnliche Namensbindung bleibt bei allen diesen Mustern unverändert.