J'utilise principalement des fonctions lambda mais j'utilise parfois des fonctions imbriquées qui semblent fournir le même comportement.
Voici quelques exemples triviaux où ils font fonctionnellement la même chose si l'un ou l'autre était trouvé dans une autre fonction:
Fonction Lambda
>>> a = lambda x : 1 + x
>>> a(5)
6
Fonction imbriquée
>>> def b(x): return 1 + x
>>> b(5)
6
Y a-t-il des avantages à utiliser l'un par rapport à l'autre? (Performances? Lisibilité? Limitations? Cohérence? Etc.)
Cela a-t-il même une importance? Si ce n'est pas le cas, cela viole le principe pythonique:
Il devrait y avoir une - et de préférence une seule - façon évidente de le faire .
lambda
, mais je ne suis pas d'accord pour dire que c'est "très rare", c'est courant pour les fonctions clés àsorted
ouitertools.groupby
etc., par exemplesorted(['a1', 'b0'], key= lambda x: int(x[1]))
En pratique, pour moi, il y a deux différences:
Le premier concerne ce qu'ils font et ce qu'ils retournent:
def est un mot-clé qui ne renvoie rien et crée un 'nom' dans l'espace de noms local.
lambda est un mot-clé qui renvoie un objet fonction et ne crée pas de «nom» dans l'espace de noms local.
Par conséquent, si vous devez appeler une fonction qui prend un objet fonction, la seule façon de le faire dans une ligne de code python est d'utiliser un lambda. Il n'y a pas d'équivalent avec def.
Dans certains cadres, c'est en fait assez courant; par exemple, j'utilise beaucoup Twisted , et je fais donc quelque chose comme
est assez courant, et plus concis avec les lambdas.
La deuxième différence concerne ce que la fonction réelle est autorisée à faire.
Par exemple,
fonctionne comme prévu, tandis que
est une SyntaxError.
Bien sûr, il existe des solutions de contournement: remplacez-les
print
parsys.stdout.write
ouimport
par__import__
. Mais généralement, il vaut mieux utiliser une fonction dans ce cas.la source
Dans cette interview, Guido van Rossum dit qu'il souhaite ne pas avoir laissé `` lambda '' entrer en Python:
À mon humble avis, les Iambdas peuvent parfois être pratiques, mais sont généralement pratiques au détriment de la lisibilité. Pouvez-vous me dire ce que cela fait:
Je l'ai écrit et il m'a fallu une minute pour le comprendre. Cela vient du projet Euler - je ne dirai pas quel problème parce que je déteste les spoilers, mais cela fonctionne en 0,124 seconde :)
la source
lambda
ne pas être supprimé dans la 3.0 était une chose proche, et que Guido ne se battait pas pour le garder.Pour n = 1000, voici le temps d'appeler une fonction par rapport à un lambda:
la source
Performance:
Créer une fonction avec
lambda
est légèrement plus rapide que la créer avecdef
. La différence est due à ladef
création d'une entrée de nom dans la table locale. La fonction résultante a la même vitesse d'exécution.Lisibilité:
Les fonctions Lambda sont un peu moins lisibles pour la plupart des utilisateurs de Python, mais aussi beaucoup plus concises dans certaines circonstances. Envisagez de passer d'une routine non fonctionnelle à une routine fonctionnelle:
Comme vous pouvez le voir, la
lambda
version est plus courte et "plus facile" dans le sens où il suffit d'ajouterlambda v:
à la version non fonctionnelle d'origine pour passer à la version fonctionnelle. C'est aussi beaucoup plus concis. Mais rappelez-vous que beaucoup d'utilisateurs de Python seront confus par la syntaxe lambda, donc ce que vous perdez en longueur et en complexité réelle pourrait être récupéré dans la confusion des autres codeurs.Limites:
lambda
les fonctions ne peuvent être utilisées qu'une seule fois, sauf si elles sont affectées à un nom de variable.lambda
les fonctions affectées aux noms de variables n'ont aucun avantage sur lesdef
fonctions.lambda
les fonctions peuvent être difficiles ou impossibles à décaper.def
Les noms des fonctions doivent être soigneusement choisis pour être raisonnablement descriptifs et uniques ou du moins autrement inutilisés dans leur portée.Cohérence:
Python évite principalement les conventions de programmation fonctionnelle au profit d'une sémantique objective procédurale et plus simple. L'
lambda
opérateur s'oppose directement à ce biais. De plus, comme alternative au déjà répandudef
, lalambda
fonction ajoute de la diversité à votre syntaxe. Certains jugeraient cela moins cohérent.Fonctions préexistantes:
Comme indiqué par d'autres, de nombreuses utilisations de
lambda
sur le terrain peuvent être remplacées par des membres duoperator
ou d'autres modules. Par exemple:L'utilisation de la fonction préexistante peut rendre le code plus lisible dans de nombreux cas.
Le principe pythonique: «Il devrait y avoir une - et de préférence une seule - façon évidente de le faire»
C'est similaire à la source unique de la doctrine de la vérité . Malheureusement, le principe de la manière simple et évidente de le faire a toujours été plus une aspiration mélancolique pour Python, plutôt qu'un véritable principe directeur. Considérez les très puissantes compréhensions de tableaux en Python. Ils sont fonctionnellement équivalents aux fonctions
map
etfilter
:lambda
etdef
sont les mêmes.C'est une question d'opinion, mais je dirais que tout ce qui dans le langage Python destiné à un usage général qui ne casse évidemment rien est assez "pythonique".
la source
Il y a un avantage à utiliser un lambda par rapport à une fonction régulière: ils sont créés dans une expression.
Il y a plusieurs inconvénients:
'<lambda>'
)Ils sont également tous deux du même type d'objet. Pour ces raisons, je préfère généralement créer des fonctions avec le
def
mot - clé plutôt qu'avec lambdas.Premier point - ils sont du même type d'objet
Un lambda donne le même type d'objet qu'une fonction régulière
Puisque les lambdas sont des fonctions, ce sont des objets de première classe.
Les lambdas et les fonctions:
Mais les lambdas manquent, par défaut, de certaines choses que les fonctions obtiennent via la syntaxe de définition de fonction complète.
Un lamba
__name__
est'<lambda>'
Les lambdas sont des fonctions anonymes, après tout, donc ils ne connaissent pas leur propre nom.
Ainsi, les lambda ne peuvent pas être recherchés par programme dans leur espace de noms.
Cela limite certaines choses. Par exemple,
foo
peut être recherché avec un code sérialisé, alors quel
ne peut pas:Nous pouvons très bien chercher
foo
- car il connaît son propre nom:Les lambdas n'ont pas d'annotations et pas de docstring
Fondamentalement, les lambdas ne sont pas documentés. Réécrivons
foo
pour être mieux documenté:Maintenant, foo a de la documentation:
Alors que nous n'avons pas le même mécanisme pour donner les mêmes informations aux lambdas:
Mais nous pouvons les pirater sur:
Mais il y a probablement une erreur qui gâche la sortie de l'aide, cependant.
Lambdas ne peut renvoyer qu'une expression
Lambdas ne peut pas renvoyer d'instructions complexes, uniquement des expressions.
Les expressions peuvent certes être assez complexes, et si vous essayez très dur, vous pouvez probablement accomplir la même chose avec un lambda, mais la complexité supplémentaire est plus un inconvénient à l'écriture de code clair.
Nous utilisons Python pour plus de clarté et de maintenabilité. La surutilisation des lambdas peut agir contre cela.
Le seul avantage pour les lambdas: peut être créé en une seule expression
C'est le seul avantage possible. Puisque vous pouvez créer un lambda avec une expression, vous pouvez le créer à l'intérieur d'un appel de fonction.
La création d'une fonction à l'intérieur d'un appel de fonction évite la recherche de nom (peu coûteuse) par rapport à celle créée ailleurs.
Cependant, étant donné que Python est strictement évalué, il n'y a pas d'autre gain de performances que d'éviter la recherche de nom.
Pour une expression très simple, je pourrais choisir un lambda.
J'ai également tendance à utiliser des lambdas lorsque je fais du Python interactif, pour éviter plusieurs lignes quand on fera l'affaire. J'utilise le type de format de code suivant lorsque je veux passer un argument à un constructeur lors de l'appel
timeit.repeat
:Et maintenant:
Je crois que la légère différence de temps ci-dessus peut être attribuée à la recherche de nom dans
return_nullary_function
- notez que c'est très négligeable.Conclusion
Les lambdas sont parfaits pour les situations informelles où vous souhaitez minimiser les lignes de code en faveur de la création d'un point singulier.
Les lambdas sont mauvais pour les situations plus formelles où vous avez besoin de clarté pour les éditeurs de code qui viendront plus tard, en particulier dans les cas où ils ne sont pas triviaux.
Nous savons que nous sommes censés donner de bons noms à nos objets. Comment pouvons-nous le faire quand l'objet n'a pas nom?
Pour toutes ces raisons, je préfère généralement créer des fonctions avec
def
plutôt qu'aveclambda
.la source
Je suis d'accord avec le conseil de nosklo: si vous devez donner un nom à la fonction, utilisez
def
. Je réserve deslambda
fonctions pour les cas où je ne fais que passer un bref extrait de code à une autre fonction, par exemple:la source
Tout en étant d'accord avec les autres réponses, c'est parfois plus lisible. Voici un exemple où
lambda
est très pratique, dans un cas d'utilisation je continue à rencontrer d'une N dimensionsdefaultdict
.Voici un exemple:
Je le trouve plus lisible que de créer un
def
pour la deuxième dimension. Ceci est encore plus significatif pour les dimensions supérieures.la source
from functools import partial; defaultdict(partial(defaultdict, list))
. Attribuez le partiel à un nom si vous souhaitez l'utiliser plusieurs fois. Mais, si vous continuez à rencontrer cette construction, cela signifie que vous n'êtes pas SEC. Factorisez-le dans une bibliothèque utilitaire. Vous pouvez utiliser cette construction pour créer un defaultdict arbitraire à n dimensions en utilisant d'autres functools (ou une boucle ou une récursivité).La principale utilisation de lambda a toujours été pour les fonctions de rappel simples et pour map, reduction, filter, qui nécessitent une fonction comme argument. Avec les compréhensions de liste devenant la norme, et l'ajout autorisé si comme dans:
il est difficile d'imaginer un cas réel pour l'utilisation de lambda dans un usage quotidien. En conséquence, je dirais, évitez lambda et créez des fonctions imbriquées.
la source
Une limitation importante des lambdas est qu'ils ne peuvent contenir rien d'autre qu'une expression. Il est presque impossible pour une expression lambda de produire autre chose que des effets secondaires triviaux, car elle ne peut pas avoir un corps aussi riche qu'une fonction
def
'ed.Cela étant dit, Lua a influencé mon style de programmation vers l'utilisation intensive de fonctions anonymes, et j'en jette mon code. En plus de cela, j'ai tendance à penser à mapper / réduire comme des opérateurs abstraits d'une manière que je ne considère pas comme des compréhensions de listes ou des générateurs, presque comme si je reportais explicitement une décision d'implémentation en utilisant ces opérateurs.
Edit: C'est une question assez ancienne, et mes opinions sur la question ont quelque peu changé.
Tout d'abord, je suis fortement contre l'attribution d'une
lambda
expression à une variable; car python a une syntaxe spéciale juste pour cela (indice,def
). En plus de cela, de nombreuses utilisations de lambda, même lorsqu'elles n'obtiennent pas de nom, ont des implémentations prédéfinies (et plus efficaces). Par exemple, l'exemple en question peut être abrégé en juste(1).__add__
, sans qu'il soit nécessaire de l'envelopper dans unlambda
oudef
. De nombreux autres usages communs peuvent être satisfaits d' une combinaison desoperator
,itertools
et desfunctools
modules.la source
(1).__add__
- L'appel direct des méthodes dunder ne devrait presque jamais se produire. Millelambda
s pour chaque appel direct dunder.(1).__add__
sont quelque peu rares, mais je n'irais nulle part près de "devrait". sans aucun doute, je trouve que le premier est beaucoup plus lisiblelambda x: 1 + x
. Si nous avions quelque chose de plus proche de la notation par tranches de haskells,(1+)
ce serait génial, mais nous devons nous contenter de ce qui est sémantiquement exactement cette chose, le nom de la méthode dunder.Considérant un exemple simple,
la source
Si vous allez simplement assigner le lambda à une variable dans la portée locale, vous pouvez également utiliser def car il est plus lisible et peut être développé plus facilement à l'avenir:
ou
la source
from operator import pow;map(pow, someList)
et(a**b for a,b in someList)
sont encore plus lisibles.Une utilisation des lambdas que j'ai trouvée ... est dans les messages de débogage.
Puisque les lambdas peuvent être évalués paresseusement, vous pouvez avoir un code comme celui-ci:
au lieu de peut-être cher:
qui traite la chaîne de format même si l'appel de débogage ne produit pas de sortie en raison du niveau de journalisation actuel.
Bien sûr, pour que cela fonctionne comme décrit, le module de journalisation utilisé doit prendre en charge les lambdas en tant que "paramètres paresseux" (comme le fait mon module de journalisation).
La même idée peut être appliquée à tout autre cas d'évaluation paresseuse pour la création de valeur de contenu à la demande.
Par exemple, cet opérateur ternaire personnalisé:
au lieu de:
avec lambdas, seule l'expression sélectionnée par la condition sera évaluée, sans lambdas les deux seront évaluées.
Bien sûr, vous pouvez simplement utiliser des fonctions au lieu de lambdas, mais pour les expressions courtes, les lambdas sont (c) plus maigres.
la source
logging
déjà un formatage paresseux:log.debug("this is my message: %r", some_data)
ne formatera que lorsque / si le message est demandé.some_data
pourrait être une expression coûteuse ou un appel de fonction / méthode.Je suis d'accord avec nosklo. Au fait, même avec une utilisation une fois, jetez plupart du temps, vous voulez simplement utiliser quelque chose du module opérateur.
PAR EXEMPLE :
Vous avez une fonction avec cette signature: maFonction (données, fonction de rappel).
Vous voulez passer une fonction qui ajoute 2 éléments.
Utilisation de lambda:
La voie pythonique:
Ou bien sûr, c'est un exemple simple, mais il y a beaucoup de choses que le module opérateur fournit, y compris les éléments setters / getters pour list et dict. Vraiment cool.
la source
Une différence majeure est que vous ne pouvez pas utiliser les
def
fonctions en ligne, ce qui est à mon avis le cas d'utilisation le plus pratique pour unelambda
fonction. Par exemple lors du tri d'une liste d'objets:Je suggérerais donc de conserver l'utilisation des lambdas à ce genre d'opérations triviales, qui ne bénéficient pas non plus vraiment de la documentation automatique fournie par la dénomination de la fonction.
la source
lambda est utile pour générer de nouvelles fonctions:
la source