Duck typing is een fundamenteel principe van Python, waarbij een object wordt beoordeeld op zijn gedrag en niet op zijn plaats in de klassenhiërarchie.
De term komt van de uitdrukking: "Als iets eruitziet als een eend, zwemt als een eend en kwakt als een eend, dan is het een eend". In Python is het gedrag van een object (de interface) belangrijker dan de klasse waartoe het behoort. Dit belichaamt het principe van "duck typing" - typisering op basis van gedrag (structurele typisering).
Het lijkt erop dat duck typing maximale flexibiliteit biedt. Maar dit vergroot het aantal verborgen fouten: een programma "breekt" pas tijdens uitvoering als een object de vereiste interface niet ondersteunt.
Schrijf in plaats van typecontroles (via isinstance of type) functies die proberen de vereiste methoden op het object aan te roepen, ervan uitgaand dat als het deze ondersteunt, alles zal werken. In het uiterste geval vang je AttributeError of TypeError op om onverwachte objecten te verwerken.
Voorbeeld:
def quack_and_walk(duck): duck.quack() duck.walk() class Robot: def quack(self): print("Ik kan kwaken!") def walk(self): print("Ik loop") quack_and_walk(Robot()) # alles werkt!
Belangrijkste kenmerken:
Kan je in Python het type controleren via isinstance en zeggen dat het correct is voor duck typing?
Nee. Duck typing staat juist tegenover strikte typecontrole. Het is correcter om met het gedrag van het object te werken, in plaats van met zijn stamboom.
Kan duck typing worden gerealiseerd met behulp van abstracte basisklassen (ABC)?
Deels. Abstracte klassen introduceren elementen van statische structuur. Duck typing vereist niet dat je verwantschap declareert - je moet gewoon de vereiste methoden implementeren. Maar sinds Python 3.8 is er de typing.Protocol module, die ons dichter bij structurele typisering brengt.
Kan duck typing werken met magische methoden (len, getitem enz.)?
Ja. Als een object de vereiste methode (len) implementeert, kan het worden doorgegeven aan functies, bijvoorbeeld len(obj), en dit zal werken volgens duck typing.
Een ontwikkelaar schrijft een functie die alles accepteert met een run() methode, zonder controle. In de code verschijnt een object zonder deze methode - en de fout ontstaat pas tijdens runtime.
Voordelen:
Nadelen:
Gebruik van duck typing, maar met try/except en documentatie van de interface:
def run_task(obj): try: obj.run() except AttributeError: print("Het object ondersteunt het uitvoeren van de taak niet!")
Voordelen:
Nadelen: