Fonctions Python Lambda : Syntaxe, utilisations réelles et quand ne pas les utiliser
Un lambda est une petite fonction que vous pouvez écrire sur une seule ligne, là où vous en avez besoin. Apprenez la syntaxe, les endroits où les lambdas aident réellement, le piège qui attrape les développeurs expérimentés et quand une fonction normale est tout simplement meilleure.
- Un lambda est une fonction anonyme limitée à une seule expression.
- Sa meilleure utilisation est comme argument court, en particulier le
keypoursorted,minetmax. - La compréhension d’une liste est généralement plus claire que
mapoufilteravec un lambda. - Si vous attribuez un lambda à un nom, écrivez plutôt un
def.
Vous devez trier les produits par prix. Écrire une fonction nommée distincte juste pour dire « utiliser le prix » ressemble à beaucoup de cérémonie. Les fonctions Python lambda vous permettent de définir ce petit élément de logique en ligne, exactement là où vous l’utilisez.
Les lambdas sont pratiques, mais ils sont également faciles à abuser. Ce guide montre où ils aident vraiment et où ils rendent le code plus difficile à lire. Nous avons exécuté chaque exemple sur Python 3.13 et le résultat affiché provient de cette exécution.
Qu’est-ce qu’un lambda ?
Un lambda est une fonction sans nom, écrite avec le mot clé lambda :
lambda arguments: expression
Il prend n’importe quel nombre d’arguments et renvoie automatiquement la valeur d’une seule expression. Il n’y a pas de mot-clé return ni de corps d’instructions.
square = lambda x: x * x
print(square(4)) # 16
print((lambda a, b=10: a + b)(5)) # 15
La deuxième ligne définit un lambda avec un argument par défaut et l’appelle immédiatement. Vous écririez rarement cela dans du code réel, mais cela montre qu’un lambda est un objet fonction ordinaire.
lambda contre déf
Ces deux produits produisent des fonctions qui se comportent de la même manière :
square = lambda x: x * x
def square_def(x):
return x * x
print(square(4), square_def(4)) # 16 16
print(square.__name__, square_def.__name__) # <lambda> square_def
Regardez les noms. Chaque lambda est simplement appelé <lambda>, donc les messages d’erreur et les journaux ne peuvent pas vous dire lequel a échoué. C’est la principale raison pour laquelle les guides de style tels que PEP 8 recommandent un def chaque fois que vous souhaitez donner un nom à une fonction.
| Caractéristique | lambda |
déf |
|---|---|---|
| Nom | Anonyme | Nommé |
| Corps | Une expression | N’importe quel nombre de déclarations |
| Retour | Implicite | Explicite return |
| Docstring et astuces de type | Non pris en charge | Pris en charge |
| Tracebacks lisibles | Spectacles <lambda> |
Affiche le nom |
| Idéal pour | Arguments courts et jetables | Tout le reste |
Tri avec clé : la meilleure utilisation
Les fonctions telles que sorted, min et max acceptent une fonction key qui décide quoi comparer. C’est là que les lambdas brillent :
products = [("pen", 10), ("bag", 900), ("book", 250)]
sorted(products, key=lambda p: p[1])
# [('pen', 10), ('book', 250), ('bag', 900)]
max(products, key=lambda p: p[1])
# ('bag', 900)
Pour trier selon plusieurs éléments, renvoyez un tuple. Ici, les gens sont triés par âge, les plus âgés d’abord, puis par nom :
people = [{"name": "Asha", "age": 31}, {"name": "Ben", "age": 25},
{"name": "Dev", "age": 31}]
[p["name"] for p in sorted(people, key=lambda p: (-p["age"], p["name"]))]
# ['Asha', 'Dev', 'Ben']
Le signe moins inverse l’ordre du nombre uniquement. Parfois, vous n’avez pas du tout besoin d’un lambda, car une fonction existante fait déjà le travail. Comparez le tri par défaut avec un tri insensible à la casse :
names = ["Asha", "ben", "Chitra", "dev"]
sorted(names) # ['Asha', 'Chitra', 'ben', 'dev']
sorted(names, key=str.lower) # ['Asha', 'ben', 'Chitra', 'dev']
La valeur par défaut place tous les mots en majuscules en premier. Passer str.lower corrige cela sans aucun lambda. Le module operator propose des aides similaires, telles que itemgetter(1) pour lambda p: p[1].
cartographier et filtrer
map applique une fonction à chaque élément et filter conserve les éléments pour lesquels il renvoie vrai. Les deux fonctionnent avec des lambdas, mais comparez chacun avec une compréhension de liste :
nums = [1, 2, 3, 4, 5, 6]
list(map(lambda n: n * 10, nums)) # [10, 20, 30, 40, 50, 60]
[n * 10 for n in nums] # [10, 20, 30, 40, 50, 60]
list(filter(lambda n: n % 2 == 0, nums)) # [2, 4, 6]
[n for n in nums if n % 2 == 0] # [2, 4, 6]
Les résultats sont identiques et la plupart des développeurs Python trouvent les compréhensions plus faciles à lire. Notez également que map et filter renvoient des itérateurs paresseux, vous avez donc besoin de list() pour voir les valeurs. Notre guide de Compréhension des listes Python couvre ce style en profondeur. map se lit toujours bien avec une fonction nommée existante, comme dans map(str.strip, lines).
réduire
functools.reduce combine les éléments en une seule valeur, portant un résultat courant :
from functools import reduce
reduce(lambda acc, n: acc + n, nums, 0) # 21
sum(nums) # 21
Pour les tâches courantes, telles que les totaux, utilisez un élément intégré tel que sum, max ou any. Gardez reduce pour les cas plus rares et envisagez une boucle simple si le lambda commence à paraître compliqué.
Conditions dans un lambda
Vous ne pouvez pas utiliser une instruction if dans un lambda, mais vous pouvez utiliser une expression conditionnelle :
label = lambda total: "large" if total >= 1000 else "small"
label(1200), label(300)
# ('large', 'small')
Une condition est bonne. Une fois que vous commencez à les imbriquer, les lecteurs doivent travailler dur, ce qui est un signe clair pour passer à un def avec des instructions if ordinaires.
Lambdas qui renvoient des fonctions
Une fonction peut créer et renvoyer un lambda qui mémorise une valeur de son environnement :
def multiplier(n):
return lambda x: x * n
double = multiplier(2)
double(7) # 14
Cela fonctionne grâce aux fermetures, que notre article sur les Fermetures JavaScript explique dans un langage différent. Python functools.partial propose une autre façon de pré-remplir les arguments.
Le piège de la liaison tardive
Cela finit par attraper presque tout le monde. Nous avons créé trois lambdas dans une boucle, en attendant que chacun renvoie son propre numéro :
funcs = [lambda: i for i in range(3)]
[f() for f in funcs]
# [2, 2, 2]
Tous les trois renvoient 2. Un lambda ne capture pas la valeur de i lors de sa création. Il recherche la variable lorsqu’elle est appelée, et la boucle est alors terminée, laissant i à 2. La solution habituelle consiste à capturer la valeur comme argument par défaut, puisque les valeurs par défaut sont évaluées au moment de la définition :
funcs = [lambda i=i: i for i in range(3)]
[f() for f in funcs]
# [0, 1, 2]
Ceci n’est pas propre aux lambdas, car un def à l’intérieur d’une boucle se comporte de la même manière. Il apparaît simplement plus souvent avec les lambdas, car ils sont si souvent créés dans des boucles, par exemple lors de l’attachement de rappels de boutons.
Conseil : Si vous avez besoin d’une fonction par élément, demandez-vous si vous avez besoin de plusieurs fonctions. Souvent, une seule fonction qui prend l’élément comme argument est plus claire et évite complètement le piège.
Tables de recherche de petites fonctions
Les lambdas s’intègrent parfaitement dans un dictionnaire qui mappe les noms à de petites opérations :
ops = {
"add": lambda a, b: a + b,
"sub": lambda a, b: a - b,
}
ops["sub"](10, 3) # 7
Cela peut remplacer une longue chaîne de if et elif. Le guide Dictionnaire Python couvre davantage de modèles de dictionnaire, et le module operator fournit déjà operator.add et operator.sub.
Limites des lambdas
- Une seule expression. Aucune affectation avec
=, pas de boucles et pas de blocstry. - Aucune déclaration. L’écriture de
lambda x: return xéchoue avec unSyntaxError, comme notre test l’a confirmé. - Pas d’indications de docstring ou de type. Les outils et les lecteurs reçoivent moins d’aide.
- Débogage plus difficile. Les erreurs pointent vers
<lambda>plutôt que vers un nom utile.
Bien entendu, les Lambdas peuvent toujours déclencher des exceptions. Leur gestion fonctionne de la même manière que pour n’importe quelle fonction, comme expliqué dans Gestion des exceptions Python.
Quand ne pas utiliser un lambda
| Situation | Meilleur choix |
|---|---|
| Lui attribuer un nom | déf |
| La logique a besoin de plus d’une ligne | déf |
| Transformer ou filtrer une liste | Une compréhension de liste |
| Additionner ou trouver un maximum | sum, max, min |
| Obtenir un élément ou un attribut | operator.itemgetter ou attrgetter |
| Le même lambda apparaît à plusieurs endroits | Une fonction nommée que vous pouvez tester |
Ce dernier point est important. Une logique qui mérite d’être réutilisée vaut la peine d’être testée, et une fonction nommée est beaucoup plus facile à tester, comme le montre notre tutoriel pytest.
Pour conclure
Un bon lambda est suffisamment court pour être lu d’un seul coup d’œil et utilisé une seule fois, généralement comme argument. Les clés de tri sont l’exemple classique. Pour vérifier votre propre code, recherchez = lambda et transformez-le en fonctions nommées. Ensuite, regardez n’importe quel map ou filter avec un lambda et voyez si une compréhension se lit mieux.
Questions fréquentes
Qu’est-ce qu’une fonction lambda en Python ?
C’est une petite fonction anonyme créée avec le mot-clé lambda. Il prend des arguments et renvoie la valeur d’une seule expression, sans nom ni instruction de retour.
Un Python lambda peut-il avoir plusieurs lignes ?
Non. Un lambda est limité à une seule expression. Vous pouvez le diviser en lignes entre parenthèses, mais il ne peut toujours pas contenir d’instructions, utilisez donc def pour une logique plus complexe.
Puis-je utiliser if else dans un lambda ?
Vous pouvez utiliser une expression conditionnelle, telle que lambda x : “big” si x > 10 sinon “small”. Une instruction if avec un bloc n’est pas autorisée.
Les lambdas sont-ils plus rapides que les fonctions normales ?
Pas de manière significative. Les deux créent le même type d’objet fonction. Choisissez entre eux pour la lisibilité et non pour les performances.
Dois-je utiliser une carte avec lambda ou une compréhension de liste ?
La plupart des développeurs Python préfèrent une compréhension de liste pour plus de lisibilité. map est raisonnable lorsque vous avez déjà une fonction nommée, telle que map(str.strip, lines).
Continuez à apprendre
Besoin d’aide pour les tests, WordPress ou le référencement ?
Nous aidons les équipes à proposer de meilleurs logiciels et à développer leurs sites. Dites-nous sur quoi vous travaillez et nous vous proposerons une prochaine étape claire.
Plus de guides sur tests, IA et développement moderne
Vous avez apprécié cet article ? Choisissez un sujet et accédez directement à nos nouveaux didacticiels.
Les hallucinations de l'IA expliquées : pourquoi les modèles de langage inventent les choses et comment les réduire
Les hallucinations de l'IA ont expliqué : ce qu'elles sont, pourquoi les modèles de langage les produisent, les types courants, comment les réduire …
Lire l'article →DevOpsVariables d'environnement expliquées : fichiers .env, secrets et configuration correctement effectués
Variables d'environnement expliquées avec des exemples Python que nous avons exécutés : lecture et définition, pourquoi chaque valeur est une chaîne…
Lire l'article →Développement logicielLimitation du débit de l'API expliquée : algorithmes, en-têtes et gestion des erreurs 429
Limitation du débit de l'API expliquée avec une simulation que nous avons exécutée : compartiment de jetons, fenêtre fixe, fenêtre glissante, 429 ré…
Lire l'article →Automatisation des testsSe moquer en Python : unittest.mock, patch et les erreurs qui font mentir les tests
Moquerie en Python avec unittest.mock, testée : Mock et return_value, side_effect, correctifs où un nom est utilisé, spec et autospec, dates moqueus…
Lire l'article →Tests logicielsCouverture du code expliquée : couverture des lignes par rapport aux branches et ce que signifie réellement 100 %
Couverture du code expliquée avec une véritable exécution de cover.py : couverture des lignes, des branches et des conditions, lecture d'un rapport,…
Lire l'article →Bases de données et SQLDELETE vs TRUNCATE vs DROP dans SQL : différences, restauration et quand les utiliser
DELETE vs TRUNCATE vs DROP expliqué avec SQL testé : ce que chacun supprime, restauration, déclencheurs, réinitialisation d'identité, vitesse et en …
Lire l'article →Bases de données et SQLVues SQL expliquées : créez, utilisez et évitez les pièges, avec des exemples
Vues SQL expliquées avec les requêtes que nous avons exécutées : création d'une vue, résultats en direct, masquage des colonnes, performances, vues …
Lire l'article →Développement logicielInterface TypeScript vs Type : différences réelles, testées avec le compilateur
Interface TypeScript vs type, vérifiée avec le vrai compilateur : ce que les deux peuvent faire, ce qu'un seul peut faire, la fusion des déclaration…
Lire l'article →Développement logicielPython *args et **kwargs expliqués : fonctions flexibles avec des exemples clairs
Python *args et **kwargs expliqués avec le code que nous avons exécuté : emballage et déballage, ordre des paramètres, arguments de mot-clé uniqueme…
Lire l'article →Développement logicielFonctions Python Lambda : syntaxe, utilisations réelles et quand ne pas les utiliser
Fonctions Python lambda expliquées avec le code que nous avons exécuté : syntaxe, tri avec clé, carte et filtre, fermetures, piège de liaison tardiv…
Lire l'article →Intelligence artificielleQue sont les agents IA ? Comment ils fonctionnent, avec une simple boucle d'agent que vous pouvez exécuter
Que sont les agents IA ? Un guide simple sur la boucle d'agent, les outils, la mémoire et les garde-fous, avec une petite boucle Python que nous avo…
Lire l'article →DevOpsSurveillance vs observabilité : la vraie différence, avec les journaux, les métriques et les traces
Surveillance et observabilité expliquées : échecs connus et inconnus, journaux, métriques et traces, présentation pas à pas des incidents de paiemen…
Lire l'article →DevOpsVolumes Docker vs montages Bind : conserver les données du conteneur de la bonne manière
Volumes Docker et montages de liaison expliqués : pourquoi les données du conteneur disparaissent, volumes nommés, montages de liaison, tmpfs, exemp…
Lire l'article →Automatisation des testsTDD vs BDD : principales différences, une fonctionnalité conçue dans les deux sens et quand les utiliser
TDD vs BDD expliqué avec une fonctionnalité de remise construite dans les deux sens : refactor rouge-vert avec le code que nous avons exécuté, scéna…
Lire l'article →Développement logicielGit merge vs rebase : différences, exemples et quand utiliser chacun
Git merge vs rebase expliqué avec de vraies sorties de log, un tableau comparatif, la règle d'or du rebase et un flux de travail sûr pour les équipes.
Lire l'article →Développement logicielList comprehension Python : syntaxe, exemples et cas à éviter
La list comprehension Python expliquée : syntaxe, filtres, if-else, boucles imbriquées, temps mesurés et cas où une boucle for classique est préféra…
Lire l'article →Bases de données et SQLJointures SQL expliquées avec exemples (Inner, Left, Right, Full)
Comprenez les jointures SQL pas à pas avec des tables et requêtes d'exemple : INNER, LEFT, RIGHT, FULL, CROSS et SELF, plus erreurs courantes et con…
Lire l'article →