La fonction partial est apparue dans la bibliothèque standard de Python (module functools), à partir de Python 2.5, pour mettre en œuvre le motif de currying et l'application partielle des arguments à une fonction. partialmethod a été introduit avec Python 3.4 pour une application similaire dans les méthodes de classe.
Dans de nombreux projets réels, il est souvent nécessaire de fixer une partie des arguments d'une fonction pour obtenir une nouvelle fonction avec des valeurs "mémorisées" de certains arguments. Cela est pratique pour les callbacks, les modèles de passage d'arguments, ou pour améliorer la lisibilité du code, en particulier dans la programmation fonctionnelle et lors de l'utilisation d'API qui attendent un certain style de fonctions.
La fonction partial retourne un nouvel objet-fonction dans lequel certaines des valeurs d'arguments ou d'arguments clés passés sont "fixées". partialmethod met en œuvre la même approche pour les méthodes de classe, en prenant correctement en charge la mécanique de transmission de self/cls.
Exemple de code :
from functools import partial, partialmethod def power(base, exponent): return base ** exponent # Fixons l'exposant = 2 square = partial(power, exponent=2) print(square(5)) # 25 class Math: def power(self, base, exponent): return base ** exponent square = partialmethod(power, exponent=2) m = Math() print(m.square(5)) # 25
Caractéristiques clés :
Peut-on utiliser partial pour les méthodes de classe afin d'obtenir un équivalent de partialmethod ?
Non, partial ne gère pas correctement self/cls, lorsqu'il est appliqué à une méthode de classe, il ne fonctionne pas comme prévu : self ne sera pas inséré automatiquement.
class C: def m(self, x, y): return x + y wrong = partial(m, y=2) # Incorrect !
Lors de l'appel c.wrong(5), une TypeError sera levée, car self ne sera pas transmis automatiquement.
L'objet créé par partial est-il une fonction ?
Oui, le résultat de partial est un objet qui se comporte comme une fonction, supporte l'appel, le nom, la docstring, etc., mais ce n'est pas une fonction ordinaire, c'est un objet de la classe partial, implémentant le protocole call.
from functools import partial f = partial(pow, 2) print(type(f)) # <class 'functools.partial'>
Partial fonctionne-t-il avec des arguments par défaut de la fonction ?
Oui, partial peut "réécrire" les valeurs par défaut dans la fonction interne ; si des arguments sont passés à partial, ceux-ci ont la priorité sur les valeurs par défaut de la fonction elle-même. Cependant, il est important de ne pas dupliquer les valeurs, sinon il y aura une erreur.
Un développeur utilise partial pour une méthode de classe au lieu de partialmethod :
class MyClass: def f(self, x, y): ... squared = partial(f, y=2) ... obj = MyClass() obj.squared(5) # TypeError: missing 1 required positional argument: 'self'
Avantages :
Inconvénients :
Au lieu de cela, on utilise partialmethod :
from functools import partialmethod class MyClass: def f(self, x, y): return x + y squared = partialmethod(f, y=2) obj = MyClass() print(obj.squared(5)) # 7
Avantages :
Inconvénients :