Dans le dernier article sur les lambdas, j’avais précisé que les lambdas étaient une question de style et qu’on pouvait faire sans. Voici différentes stratégies pour s’en passer.
Utiliser une inner function
En python on peut définir et exécuter à la volée une fonction dans une autre fonction/méthode ou une classe.
class Banane(object): def blougou(): # pas de self :-) print "Sens giratoir inversé" blougou() # on peut appeler une fonction en dehors d'une méthode def methode(self): # une vraie méthode print "Vive Edgar Morin" # on peut définir une fonction dans une méthode def moukrene(): print "A la glaviouse" moukrene() |
Et ça donne:
Sens giratoir inversé # affichage à l'import >>> Banane().methode() Vive Edgar Morin A la glaviouse |
Préremplissez des arguments
Le module functools
fournit tout un tas de goodies pour faire mumuse avec les fonctions, et notamment la fonction partial()
qui prend une fonction en argument, et des arguments à passer à la fonction qu’on lui a passé en argument. Vous suivez ?
On s’en sert quand on veut utiliser une fonction, mais qu’on sait d’avance quels arguments on va lui passer:
>>> from functools import partial >>> sum <built-in function sum> >>> sum([2, 2]) 4 >>> mini_sum = partial(sum, [2, 2]) >>> mini_sum() 4 |
On pas besoin de donner tous les arguments de la fonction à enrober: on peut passer les autres après.
Comme partial()
retourne une fonction prête à être appelée, on peut l’utiliser là où on utiliserait une lambda:
>>> from __future__ import print_function >>> def profit(etape1="On vol des caleçons", etape2=lambda: print('...')): ... print(etape1) ... etape2() ... >>> profit() On vol des caleçons ... |
Se tranforme en:
>>> def profit(etape1="On vol des caleçons", etape2=partial(print, '...')): ... print(etape1) ... etape2() ... >>> profit() On vol des caleçons ... |
Utiliser les fonctions derrières les opérations de base
Quand vous utilisez un +
ou un []
, il s’agit ni plus ni moins d’une syntaxe raccourcie pour l’appel d’une fonction. Et Python vous laisse accéder à ces fonctions à travers le module operator
.
>>> for operation in (lambda x: x[0], lambda x: x * 3): print(operation(ls)) ... a ['a', 3, 'a', 3, 'a', 3] |
>>> from operator import itemgetter, mul >>> for operation in (itemgetter(0), partial(mul, 3)): print(operation(ls)) ... a ['a', 3, 'a', 3, 'a', 3] |
Le module operator
est très riche: opérations logiques (incluant la négation), manipulation de slices, maths de base, set/get d’attributs/de clés/d’index… Il y a de quoi faire.
Mettez à la poubelle map
et filter
Map
permet d’appliquer une fonction a un itérable. Filter
permet de choisir les éléments d’un itérable selon un critère pour former un autre itérable.
>>> nombres = range(10) >>> paires = filter(lambda x: not x % 2, nombres) >>> paires [0, 2, 4, 6, 8] >>> paires_au_carres = map(lambda x: x * x, paires) >>> paires_au_carres [0, 4, 16, 36, 64] |
Les listes en intention remplacent avantageusement ces deux fonctions (je crois d’ailleurs qu’elles sont retirées des built-in en Python 3):
>>> [x * x for x in range(10) if not x % 2] [0, 4, 16, 36, 64] |
Je ne suis pas un allergique aux lambdas, et je les utilise assez souvent, mais il est bon de savoir qu’il existe des alternatives.
Juste en passant, c’est pas “je les utilisent assez souvent” dans la conclusion mais “je les utilise assez souvent”.
Hello,
est il préférable d’utiliser partial ou un lambda pour pré remplir des arguements ?
Je vais fouiller le net également.
J’ai utilisé des lambdas sans les maitriser dans des boutons de tkinter, parce que ceux ci ne peuvent prendre en commande que des fonctions sans arguments.
Merci d’avance si jamais j’ai une réponse,
Bonne soirée
Il n’y a pas de meilleure manière, c’est une question de style. Lambda est plus rapide, partial indique clairement l’intention de la ligne de code.
bonjour
En python 3.5, l’appel de Banane().methode() ne donne pas la même chose que dans cet article.
et c’est mieux comme ça, il y a aucune raison de lancer blougou quand on appelle une méthode de Banane()
‘Sens giratoir inversé’ apparait quand l’interpréteur parse la classe Banane
C’est une erreur dans l’article.