:PROPERTIES:
:ID:       25d994fd-375b-429d-af38-6afba818159f
:mtime:    20220607075600
:ctime:    20220607074003
:END:
#+title: functools.singledispatch

* Introduction
Le module /functools/ permet la définition de /single dispatch methods/ :
 * Une sorte de méthode générique pour laquelle différentes implémentations sont écrites,
 * L'implémentation à exécuter est déterminée d'après le type du premier argument non /self/ ou non /cls/,
 * Peut être imbriqué (/nested/) avec d'autres décorateurs mais /singledispatchmethod/ doit être le plus englobant (cf. howto),
 * Depuis Python3.8 (3.9 pour les imbrications, cf. PCR 83860 en référence).

* Howto
** Usage de base
#+BEGIN_SRC python :results output
from functools import singledispatchmethod

class Negator:

    @singledispatchmethod
    def neg(self, arg):
        raise NotImplementedError("Cannot negate a")

    @neg.register
    def _(self, arg: int):
        return -arg

    @neg.register
    def _(self, arg: bool):
        return not arg

negator = Negator()
print(f'{negator.neg(5) = }')
print(f'{negator.neg(False) = }')
#+END_SRC

#+RESULTS:
: negator.neg(5) = -5
: negator.neg(False) = True
** Imbrication (/nested/) avec d'autres /decorator/
#+BEGIN_SRC python :results output
from functools import singledispatchmethod

class Negator:

    @singledispatchmethod
    @classmethod
    def neg(cls, arg):
        raise NotImplementedError("Cannot negate a")

    @neg.register
    @classmethod
    def _(cls, arg: int):
        return -arg

    @neg.register
    @classmethod
    def _(cls, arg: bool):
        return not arg

print(f'{Negator.neg(5) = }')
print(f'{Negator.neg(False) = }')
#+END_SRC

#+RESULTS:

* Références
 * [[https://medium.com/@sunilrana123/python-trick-functools-singledispatch-4cdf71843cd2][Python Trick : functools.singledispatch - Medium]]
 * [[https://docs.python.org/3/library/functools.html#functools.singledispatchmethod][functools.singledispatch - Python]]
 * [[https://github.com/python/cpython/issues/83860][functools: singledispatchmethod doesn't work with classmethod #83860 - CPython Github]]
