Duck Typing ist ein grundlegendes Prinzip in Python, bei dem ein Objekt nach seinem Verhalten und nicht nach seiner Klassenzugehörigkeit betrachtet wird.
Der Begriff stammt aus dem Sprichwort: "Wenn etwas wie eine Ente aussieht, wie eine Ente schwimmt und wie eine Ente quakt, dann ist es eine Ente." In Python ist das Verhalten eines Objekts (seines Interfaces) wichtiger als die Klasse, zu der es gehört. Dies verwirklicht das Prinzip des "Duck Typing" – die Typisierung nach Verhalten (strukturelle Typisierung).
Es scheint, dass Duck Typing maximale Flexibilität bietet. Aber es erhöht die Anzahl versteckter Bugs: Das Programm „bricht zusammen“, wenn zur Laufzeit festgestellt wird, dass ein Objekt das erforderliche Interface nicht unterstützt.
Anstatt den Typ (über isinstance oder type) zu überprüfen, schreiben Sie Funktionen, die versuchen, die erforderlichen Methoden des Objekts aufzurufen, in der Annahme, dass alles funktioniert, wenn es unterstützt wird. Im schlimmsten Fall fangen Sie AttributeError oder TypeError, um unerwartete Objekte zu behandeln.
Beispiel:
def quack_and_walk(duck): duck.quack() duck.walk() class Robot: def quack(self): print("Ich kann quaken!") def walk(self): print("Ich gehe") quack_and_walk(Robot()) # alles funktioniert!
Hauptmerkmale:
Kann man in Python den Typ mit isinstance überprüfen und sagen, dass das für Duck Typing korrekt ist?
Nein. Duck Typing steht gerade im Gegensatz zu einer strengen Typüberprüfung. Es ist genauer, sich mit dem Verhalten des Objekts und nicht mit seiner Abstammung zu befassen.
Kann man Duck Typing mit abstrakten Basisklassen (ABC) implementieren?
Teilweise. Abstrakte Klassen führen statische Struktur-Elemente ein. Duck Typing erfordert nicht, das Verwandtschaftsverhältnis zu deklarieren – Sie müssen einfach die erforderlichen Methoden implementieren. Aber mit Python 3.8 wurde das Modul typing.Protocol eingeführt, das uns der strukturellen Typisierung näher bringt.
Kann Duck Typing mit magischen Methoden (len, getitem usw.) funktionieren?
Ja. Wenn das Objekt die benötigte Methode (len) implementiert, kann es an Funktionen übergeben werden, beispielsweise len(obj), und das wird nach Duck Typing funktionieren.
Ein Entwickler schreibt eine Funktion, die alles mit der Methode run() akzeptiert, ohne zu überprüfen. Im Code erscheint ein Objekt ohne diese Methode – und der Fehler tritt nur zur Laufzeit auf.
Vorteile:
Nachteile:
Verwendung von Duck Typing, aber mit try/except und Dokumentation des Interfaces:
def run_task(obj): try: obj.run() except AttributeError: print("Das Objekt unterstützt das Ausführen der Aufgabe nicht!")
Vorteile:
Nachteile: