Vous êtes ici : Accueil Actualités Le canard tapant

Le canard tapant

Explication humoristique de ce qu'est le concept de "Duck typing"

Contexte

Il y a un peu plus d'un mois, mes pérégrinations sur internet à la recherche de nouveautés Pythoniques (il faut bien se faire un carnet d'adresses web important pour faire une veille efficace) m'ont fait découvrir un magnifique blog (que je ne citerais pas) qui parlait de Python dans les grandes lignes, mais d'une manière sinon fausse du moins incompréhensible. Des articles aux titres alléchants, mais très courts et aux phrases trop longues, parfois sans queues ni tête. C'est au détour de l'une d'entre elles que j'ai découvert avec horreur le canard tapant, ce que je n'ai pas tout de suite compris, tellement les phrases étaient emberlificotées.

Au bout de la troisième relecture de la phrase, j'ai compris que "canard tapant" était une sublime traduction de "duck typing". Le tout dans un article qui se prend vraiment au sérieux. Du coup, pour que cela passe mieux, je m'engage à militer pour que l'expression entre à l'académie française en lui trouvant une vraie définition.

Définition (humoristique, vraiment ...)

Le canard normal est un animal bien connu. Il en existe deux espèces : le canard interfacé et le canard tapant.

Le premier a signé un contrat avec mère nature qui stipule :

  • le canard interfacé doit s'exprimer en caquetant ;
  • le canard interfacé doit se déplacer en dandinant ;

Du coup, si l'on se promène dans la nature, on peut demander à tout animal que l'on croiserait de nous montrer son contrat. C'est ainsi que l'on peut savoir qu'un animal est un canard et que par conséquent, il caquette et dandine.

Au contraire, un canard tapant est un canard libre de tout contrat. Celui qui se promène dans la nature doit donc observer cet animal et s'il voit qu'il se déplace en se dandinant et s'exprime en caquetant, alors il peut en déduire qu'il s'agit d'un canard tapant.

Quel est l'intérêt, me demanderez-vous ?

  • cela évite la paperasse : on est pas obligé de signer un contrat pour chaque canard... il faut penser à préserver nos forêts et éviter ce gâchis inutile de papier ;
  • cela oblige le promeneur à se montrer attentif à ce qui l'entoure et non pas de marcher comme un bourrin vers son but en ayant bien ajusté ses œillères  au préalable ;
  • cela renverse la responsabilité : C'est celui qui veut utiliser le canard qui doit s'assurer qu'il a bien affaire à un canard et non pas au canard de fournir son contrat ;

En conclusion, le canard tapant est plus libre, plus léger, plus insouciant que le canard interfacé, ce qui a ses avantages et ses inconvénients.

Application à l'informatique

De la théorie (absurde) à la pratique

Voyons ce qu'il en est pour le canard interfacé :

Le promeneur est une classe qui doit s’agréger une classe canard. La première solution est de poser un contrat. J'ai besoin que tu te déplaces en dandinant et que tu t'exprimes en caquetant, je t'impose donc d'avoir une certification, c'est à dire remplir un contrat, autrement dit d'implémenter une interface.

Autrement formulé, la classe promeneur agrège la classe canard et utilise sa méthode __len__, par exemple. Elle va donc exiger que canard implémente une interface qui contienne __len__, par exemple une interface Countable.

Et voici pour le canard tapant :

Le promeneur est une classe qui doit s'agréger une classe canard. La solution ici retenue est de tester si canard fait bien les choses correctement, soit s'il se déplace en dandinant et s'exprime en caquetant. Une sorte d'entretien d'embauche, en fait, au lieu d'une certification.

Autrement formulé, la classe promeneur agrège la classe canard et utilise sa méthode __len__. Elle va donc tester que la méthode existe et est correcte, ce qui va plus loin que la simple interface.

Un petit exemple vaut mieux qu'un long discours (surtout s'il est absurde)

Voici un petit scénario :

>>> class A:
...     pass
...
>>> a = A()
>>> len(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'A' has no len()
>>> class B:
...     def __len__(self):
...             return '1'
...
>>> b = B()
>>> len(b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer
>>> class C:
...     def __len__(self):
...             return 1
...
>>> c = C()
>>> len(c)
1

A ne possède pas la méthode __len__ : la primitive len ne peut donc pas fonctionner.

B possède la méthode __len__, mais celle-ci ne renvoie pas le bon type : la primitive len ne peut donc pas fonctionner non plus.

On peut aller encore plus loin : par exemple, un itérable au sens de Python est un objet qui possède la méthode __iter__ et cette dernière doit renvoyer un objet nommé itérateur qui possède la méthode __next__.

Conclusion

La traduction, c'est surfait. En fait, canard tapant, çà se comprend bien, sinon c'est que vous êtes trop citadins. Alors arrêtez de coder un peu, sortez de chez vous et aller dans des parcs pour observer les canards tapants et demander leurs contrats aux canard interfacés. C'est çà la vraie vie !

Sinon, le duck typing, c'est juste un des principes fondateurs du langage Python, qui vise à régir la relation entre objets. Mais si vous avez un gros second degré, vous l'aviez compris (et très probablement, vous le saviez déjà).

Spinner