Comment utiliser les fonctions Lambda Python

Comment utiliser les fonctions Lambda Python

Python et d'autres langages comme Java, C # et même C ++ ont ajouté des fonctions lambda à leur syntaxe, tandis que des langages comme LISP ou la famille de langages ML, Haskell, OCaml et F #, utilisent des lambdas comme concept de base.

Les lambdas Python sont de petites fonctions anonymes, soumises à une syntaxe plus restrictive mais plus concise que les fonctions Python normales.

À la fin de cet article, vous saurez:

  • Comment les lambdas en Python ont vu le jour

  • Comparaison des lambdas avec les objets de fonction réguliers

  • Comment écrire des fonctions lambda

  • Les fonctions de la bibliothèque standard Python exploitent les lambdas

  • Quand utiliser ou éviter les fonctions lambda Python

Notes: vous verrez quelques exemples de code utilisantlambda qui semblent ignorer de manière flagrante les meilleures pratiques de style Python. Ceci est uniquement destiné à illustrer les concepts de calcul lambda ou à mettre en évidence les capacités de Pythonlambda.

Ces exemples douteux seront mis en contraste avec de meilleures approches ou alternatives au fur et à mesure de votre progression dans l'article.

Ce tutoriel est principalement destiné aux programmeurs Python intermédiaires à expérimentés, mais il est accessible à tous les esprits curieux intéressés par la programmation et le calcul lambda.

Tous les exemples inclus dans ce tutoriel ont été testés avec Python 3.7.

__ Take the Quiz: Testez vos connaissances avec notre quiz interactif «Fonctions Python Lambda». À la fin, vous recevrez un score afin que vous puissiez suivre vos progrès d'apprentissage au fil du temps:

Free Bonus:Click here to get access to a chapter from Python Tricks: The Book qui vous montre les meilleures pratiques de Python avec des exemples simples que vous pouvez appliquer instantanément pour écrire du code + Pythonic plus beau.

Lambda Calculus

Les expressions lambda en Python et dans d'autres langages de programmation ont leurs racines dans le calcul lambda, un modèle de calcul inventé par Alonzo Church. Vous découvrirez quand le lambda calcul a été introduit et pourquoi c'est un concept fondamental qui s'est retrouvé dans l'écosystème Python.

Histoire

Alonzo Church a formalisélambda calculus, un langage basé sur l'abstraction pure, dans les années 1930. Les fonctions lambda sont également appelées abstractions lambda, une référence directe au modèle d'abstraction de la création originale d'Alonzo Church.

Le calcul lambda peut coder n'importe quel calcul. C'estTuring complete, mais contrairement au concept d'unTuring machine, il est pur et ne garde aucun état.

Les langages fonctionnels trouvent leur origine dans la logique mathématique et le calcul lambda, tandis que les langages de programmation impératifs embrassent le modèle de calcul basé sur l'état inventé par Alan Turing. Les deux modèles de calcul, lambda calcul etTuring machines, peuvent être traduits l'un dans l'autre. Cette équivalence est connue sous le nom deChurch-Turing hypothesis.

Les langages fonctionnels héritent directement de la philosophie du calcul lambda, adoptant une approche déclarative de la programmation qui met l'accent sur l'abstraction, la transformation des données, la composition et la pureté (aucun état et aucun effet secondaire). Des exemples de langages fonctionnels incluentHaskell,Lisp ouErlang.

En revanche, la machine de Turing a conduit à une programmation impérative trouvée dans des langages commeFortran,C ouPython.

Le style impératif consiste à programmer avec des instructions, conduisant le déroulement du programme étape par étape avec des instructions détaillées. Cette approche favorise la mutation et nécessite la gestion de l'état.

La séparation dans les deux familles présente quelques nuances, car certains langages fonctionnels intègrent des caractéristiques impératives, commeOCaml, tandis que des caractéristiques fonctionnelles ont imprégné la famille impérative de langages en particulier avec l'introduction de fonctions lambda dansJava, ou Python.

Python n'est pas intrinsèquement un langage fonctionnel, mais il a adopté très tôt certains concepts fonctionnels. En janvier 1994,map(),filter(),reduce() et l'opérateurlambda ont été ajoutés à la langue.

Premier exemple

Voici quelques exemples pour vous donner un appétit pour du code Python, style fonctionnel.

Leidentity function, une fonction qui renvoie son argument, est exprimé avec une définition de fonction Python standard en utilisant le mot-clédef comme suit:

>>>

>>> def identity(x):
...     return x

identity() prend un argumentx et le renvoie lors de l'appel.

En revanche, si vous utilisez une construction lambda Python, vous obtenez les éléments suivants:

>>>

>>> lambda x: x

Dans l'exemple ci-dessus, l'expression est composée de:

  • Le mot clé: lambda

  • Une variable liée: x

  • Un corps: x

Note: dans le contexte de cet article, unbound variable est un argument d'une fonction lambda.

En revanche, unfree variable n'est pas lié et peut être référencé dans le corps de l'expression. Une variable libre peut être une constante ou une variable définie dans la portée englobante de la fonction.

Vous pouvez écrire un exemple un peu plus élaboré, une fonction qui ajoute1 à un argument, comme suit:

>>>

>>> lambda x: x + 1

Vous pouvez appliquer la fonction ci-dessus à un argument en entourant la fonction et son argument de parenthèses:

>>>

>>> (lambda x: x + 1)(2)
3

Reduction est une stratégie de calcul lambda pour calculer la valeur de l'expression. Il consiste à remplacer l'argument2 parx:

(lambda x: x + 1)(2) = lambda 2: 2 + 1
                     = 2 + 1
                     = 3

Une fonction lambda étant une expression, elle peut être nommée. Par conséquent, vous pouvez écrire le code précédent comme suit:

>>>

>>> add_one = lambda x: x + 1
>>> add_one(2)
3

La fonction lambda ci-dessus équivaut à écrire ceci:

def add_one(x):
    return x + 1

Ces fonctions prennent toutes un seul argument. Vous avez peut-être remarqué que, dans la définition des lambdas, les arguments n'ont pas de parenthèses autour d'eux. Les fonctions multi-arguments (fonctions qui prennent plus d'un argument) sont exprimées en lambdas Python en listant les arguments et en les séparant par une virgule (,) mais sans les entourer de parenthèses:

>>>

>>> full_name = lambda first, last: f'Full name: {first.title()} {last.title()}'
>>> full_name('guido', 'van rossum')
'Full name: Guido Van Rossum'

La fonction lambda affectée àfull_name prend deux arguments et renvoie une chaîne interpolant les deux paramètresfirst etlast. Comme prévu, la définition du lambda répertorie les arguments sans parenthèses, tandis que l'appel de la fonction se fait exactement comme une fonction Python normale, avec des parenthèses entourant les arguments.

Fonctions anonymes

Les termes suivants peuvent être utilisés de manière interchangeable selon le type et la culture du langage de programmation:

  • Fonctions anonymes

  • Fonctions lambda

  • Expressions lambda

  • Abstractions lambda

  • Forme lambda

  • Littéraux de fonction

Pour le reste de cet article après cette section, vous verrez principalement le termelambda function.

Pris littéralement, une fonction anonyme est une fonction sans nom. En Python, une fonction anonyme est créée avec le mot-clélambda. Plus lâchement, il peut être ou non attribué un nom. Considérons une fonction anonyme à deux arguments définie aveclambda mais non liée à une variable. Le lambda ne reçoit pas de nom:

>>>

>>> lambda x, y: x + y

La fonction ci-dessus définit une expression lambda qui prend deux arguments et retourne leur somme.

En plus de vous informer que Python est parfaitement adapté à ce formulaire, il ne conduit à aucune utilisation pratique. Vous pouvez invoquer la fonction dans l'interpréteur Python:

>>>

>>> _(1, 2)
3

L'exemple ci-dessus tire parti de la fonctionnalité d'interprétation interactive uniquement fournie via le trait de soulignement (_). Voir la note ci-dessous pour plus de détails.

Vous ne pouviez pas écrire de code similaire dans un module Python. Considérez les_ dans l'interpréteur comme un effet secondaire dont vous avez profité. Dans un module Python, vous attribueriez un nom au lambda, ou vous transmettriez le lambda à une fonction. Vous utiliserez ces deux approches plus loin dans cet article.

Note: dans l'interpréteur interactif, le trait de soulignement unique (_) est lié à la dernière expression évaluée.

Dans l'exemple ci-dessus, le_ pointe vers la fonction lambda. Pour plus de détails sur l'utilisation de ce caractère spécial en Python, consultezThe Meaning of Underscores in Python.

Un autre modèle utilisé dans d'autres langages comme JavaScript est d'exécuter immédiatement une fonction lambda Python. Ceci est connu sous le nom deImmediately Invoked Function Expression (IIFE, prononcez «iffy»). Voici un exemple:

>>>

>>> (lambda x, y: x + y)(2, 3)
5

La fonction lambda ci-dessus est définie puis immédiatement appelée avec deux arguments (2 et3). Il renvoie la valeur5, qui est la somme des arguments.

Plusieurs exemples de ce didacticiel utilisent ce format pour mettre en évidence l'aspect anonyme d'une fonction lambda et éviter de se concentrer surlambda en Python comme moyen plus court de définir une fonction.

Python n'encourage pas l'utilisation d'expressions lambda immédiatement appelées. Il résulte simplement d'une expression lambda pouvant être appelée, contrairement au corps d'une fonction normale.

Les fonctions Lambda sont fréquemment utilisées avechigher-order functions, qui prennent une ou plusieurs fonctions comme arguments ou renvoient une ou plusieurs fonctions.

Une fonction lambda peut être une fonction d'ordre supérieur en prenant une fonction (normale ou lambda) comme argument comme dans l'exemple artificiel suivant:

>>>

>>> high_ord_func = lambda x, func: x + func(x)
>>> high_ord_func(2, lambda x: x * x)
6
>>> high_ord_func(2, lambda x: x + 3)
7

Python expose les fonctions d'ordre supérieur en tant que fonctions intégrées ou dans la bibliothèque standard. Les exemples incluentmap(),filter(),functools.reduce(), ainsi que des fonctions clés telles quesort(),sorted(),min() etmax() . Vous utiliserez des fonctions lambda avec des fonctions Python d'ordre supérieur dansAppropriate Uses of Lambda Expressions.

Python Lambda et fonctions régulières

Cette citation desPython Design and History FAQ semble donner le ton sur l'attente globale concernant l'utilisation des fonctions lambda en Python:

Contrairement aux formulaires lambda dans d'autres langages, où ils ajoutent des fonctionnalités, les lambdas Python ne sont qu'une notation abrégée si vous êtes trop paresseux pour définir une fonction. (Source)

Néanmoins, ne laissez pas cette instruction vous dissuader d’utiliser leslambda de Python. À première vue, vous pouvez accepter qu'une fonction lambda est une fonction avec dessyntactic sugarraccourcissant le code pour définir ou appeler une fonction. Les sections suivantes mettent en évidence les points communs et les différences subtiles entre les fonctions Python normales et les fonctions lambda.

Les fonctions

À ce stade, vous pouvez vous demander ce qui distingue fondamentalement une fonction lambda liée à une variable d'une fonction régulière avec une seule lignereturn: sous la surface, presque rien. Vérifions comment Python voit une fonction construite avec une seule instruction return par rapport à une fonction construite comme une expression (lambda).

Le moduledis expose des fonctions pour analyser le bytecode Python généré par le compilateur Python:

>>>

>>> import dis
>>> add = lambda x, y: x + y
>>> type(add)

>>> dis.dis(add)
  1           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 RETURN_VALUE
>>> add
 at 0x7f30c6ce9ea0>

Vous pouvez voir quedis() expose une version lisible du bytecode Python permettant l'inspection des instructions de bas niveau que l'interpréteur Python utilisera lors de l'exécution du programme.

Maintenant, voyez-le avec un objet de fonction régulière:

>>>

>>> import dis
>>> def add(x, y): return x + y
>>> type(add)

>>> dis.dis(add)
  1           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 RETURN_VALUE
>>> add

Le bytecode interprété par Python est le même pour les deux fonctions. Mais vous remarquerez peut-être que la dénomination est différente: le nom de la fonction estadd pour une fonction définie avecdef, alors que la fonction lambda Python est considérée commelambda.

Traceback

Vous avez vu dans la section précédente que, dans le contexte de la fonction lambda, Python n'a pas fourni le nom de la fonction, mais seulement<lambda>. Cela peut être une limitation à prendre en compte lorsqu'une exception se produit et qu'une traceback ne montre que<lambda>:

>>>

>>> div_zero = lambda x: x / 0
>>> div_zero(2)
Traceback (most recent call last):
    File "", line 1, in 
    File "", line 1, in 
ZeroDivisionError: division by zero

Le traçage d'une exception déclenchée lors de l'exécution d'une fonction lambda identifie uniquement la fonction à l'origine de l'exception en tant que<lambda>.

Voici la même exception déclenchée par une fonction normale:

>>>

>>> def div_zero(x): return x / 0
>>> div_zero(2)
Traceback (most recent call last):
    File "", line 1, in 
    File "", line 1, in div_zero
ZeroDivisionError: division by zero

La fonction normale provoque une erreur similaire mais entraîne un suivi plus précis car elle donne le nom de la fonction,div_zero.

Syntaxe

Comme vous l'avez vu dans les sections précédentes, un formulaire lambda présente des distinctions syntaxiques par rapport à une fonction normale. En particulier, une fonction lambda présente les caractéristiques suivantes:

  • Il ne peut contenir que des expressions et ne peut pas inclure d'instructions dans son corps.

  • Il est écrit comme une seule ligne d'exécution.

  • Il ne prend pas en charge les annotations de type.

  • Il peut être immédiatement invoqué (IIFE).

Aucune déclaration

Une fonction lambda ne peut contenir aucune instruction. Dans une fonction lambda, des instructions telles quereturn,pass,assert ouraise lèveront une exceptionSyntaxError. Voici un exemple d'ajout deassert au corps d'un lambda:

>>>

>>> (lambda x: assert x == 2)(2)
  File "", line 1
    (lambda x: assert x == 2)(2)
                    ^
SyntaxError: invalid syntax

Cet exemple artificiel destiné àassert que le paramètrex avait une valeur de2. Mais, l'interpréteur identifie unSyntaxError tout en analysant le code qui implique l'instructionassert dans le corps deslambda.

Expression unique

Contrairement à une fonction normale, une fonction lambda Python est une expression unique. Bien que, dans le corps d'unlambda, vous puissiez étaler l'expression sur plusieurs lignes en utilisant des parenthèses ou une chaîne multiligne, il reste une seule expression:

>>>

>>> (lambda x:
... (x % 2 and 'odd' or 'even'))(3)
'odd'

L'exemple ci-dessus renvoie la chaîne'odd' lorsque l'argument lambda est impair, et'even' lorsque l'argument est pair. Il s'étend sur deux lignes car il est contenu dans un ensemble de parenthèses, mais il reste une seule expression.

Type d'annotations

Si vous avez commencé à adopter l'indication de type, qui est désormais disponible en Python, vous avez une autre bonne raison de préférer les fonctions normales aux fonctions lambda Python. ConsultezPython Type Checking (Guide) pour en savoir plus sur les indicateurs de type Python et la vérification de type. Dans une fonction lambda, il n'y a pas d'équivalent pour ce qui suit:

def full_name(first: str, last: str) -> str:
    return f'{first.title()} {last.title()}'

Toute erreur de type avecfull_name() peut être interceptée par des outils commemypy oupyre, alors qu'unSyntaxError avec la fonction lambda équivalente est déclenché à l'exécution:

>>>

>>> lambda first: str, last: str: first.title() + " " + last.title() -> str
  File "", line 1
    lambda first: str, last: str: first.title() + " " + last.title() -> str

SyntaxError: invalid syntax

Comme pour essayer d'inclure une instruction dans un lambda, l'ajout d'une annotation de type entraîne immédiatement unSyntaxError à l'exécution.

IIFE

Vous avez déjà vu plusieurs exemples deimmediately invoked function execution:

>>>

>>> (lambda x: x * x)(3)
9

En dehors de l'interpréteur Python, cette fonctionnalité n'est probablement pas utilisée dans la pratique. C’est une conséquence directe de l’appel d’une fonction lambda telle qu’elle est définie. Par exemple, cela vous permet de transmettre la définition d'une expression lambda Python à une fonction d'ordre supérieur commemap(),filter() oufunctools.reduce(), ou à une fonction clé.

Arguments

Comme un objet fonction normal défini avecdef, les expressions lambda Python prennent en charge toutes les différentes façons de passer des arguments. Ceci comprend:

  • Arguments positionnels

  • Arguments nommés (parfois appelés arguments de mots clés)

  • Liste variable d'arguments (souvent appeléevarargs)

  • Liste variable d'arguments de mots clés

  • Arguments contenant uniquement des mots clés

Les exemples suivants illustrent les options qui s'offrent à vous pour passer des arguments aux expressions lambda:

>>>

>>> (lambda x, y, z: x + y + z)(1, 2, 3)
6
>>> (lambda x, y, z=3: x + y + z)(1, 2)
6
>>> (lambda x, y, z=3: x + y + z)(1, y=2)
6
>>> (lambda *args: sum(args))(1,2,3)
6
>>> (lambda **kwargs: sum(kwargs.values()))(one=1, two=2, three=3)
6
>>> (lambda x, *, y=0, z=0: x + y + z)(1, y=2, z=3)
6

Décorateurs

En Python, undecorator est l'implémentation d'un modèle qui permet d'ajouter un comportement à une fonction ou à une classe. Il est généralement exprimé avec la syntaxe@decorator préfixant une fonction. Voici un exemple artificiel:

def some_decorator(f):
    def wraps(*args):
        print(f"Calling function '{f.__name__}'")
        return f(args)
    return wraps

@some_decorator
def decorated_function(x):
    print(f"With argument '{x}'")

Dans l'exemple ci-dessus,some_decorator() est une fonction qui ajoute un comportement àdecorated_function(), de sorte que l'appel dedecorated_function("Python") entraîne la sortie suivante:

Calling function 'decorated_function'
With argument 'Python'

decorated_function() n'imprime queWith argument 'Python', mais le décorateur ajoute un comportement supplémentaire qui imprime égalementCalling function 'decorated_function'.

Un décorateur peut être appliqué à un lambda. Bien qu'il ne soit pas possible de décorer un lambda avec la syntaxe@decorator, un décorateur n'est qu'une fonction, il peut donc appeler la fonction lambda:

 1 # Defining a decorator
 2 def trace(f):
 3     def wrap(*args, **kwargs):
 4         print(f"[TRACE] func: {f.__name__}, args: {args}, kwargs: {kwargs}")
 5         return f(*args, **kwargs)
 6
 7     return wrap
 8
 9 # Applying decorator to a function
10 @trace
11 def add_two(x):
12     return x + 2
13
14 # Calling the decorated function
15 add_two(3)
16
17 # Applying decorator to a lambda
18 print((trace(lambda x: x ** 2))(3))

add_two(), décoré avec@trace à la ligne 11, est invoqué avec l'argument3 à la ligne 15. En revanche, à la ligne 18, une fonction lambda est immédiatement impliquée et intégrée dans un appel àtrace(), le décorateur. Lorsque vous exécutez le code ci-dessus, vous obtenez les éléments suivants:

[TRACE] func: add_two, args: (3,), kwargs: {}
[TRACE] func: , args: (3,), kwargs: {}
9

Voyez comment, comme vous l’avez déjà vu, le nom de la fonction lambda apparaît sous la forme<lambda>, alors queadd_two est clairement identifié pour la fonction normale.

Décorer la fonction lambda de cette façon pourrait être utile à des fins de débogage, éventuellement pour déboguer le comportement d'une fonction lambda utilisée dans le contexte d'une fonction d'ordre supérieur ou d'une fonction clé. Voyons un exemple avecmap():

list(map(trace(lambda x: x*2), range(3)))

Le premier argument demap() est un lambda qui multiplie son argument par2. Ce lambda est décoré detrace(). Une fois exécuté, l'exemple ci-dessus génère les informations suivantes:

[TRACE] Calling  with args (0,) and kwargs {}
[TRACE] Calling  with args (1,) and kwargs {}
[TRACE] Calling  with args (2,) and kwargs {}
[0, 2, 4]

Le résultat[0, 2, 4] est une liste obtenue en multipliant chaque élément derange(3). Pour l'instant, considérezrange(3) équivalent à la liste[0, 1, 2].

Vous serez exposé àmap() plus en détail dansMap.

Un lambda peut aussi être décorateur, mais ce n'est pas recommandé. Si vous avez besoin de faire cela, consultezPEP 8, Programming Recommendations.

Pour en savoir plus sur les décorateurs Python, consultezPrimer on Python Decorators.

Fermeture

Unclosure est une fonction où chaque variable libre, tout sauf les paramètres, utilisée dans cette fonction est liée à une valeur spécifique définie dans la portée englobante de cette fonction. En effet, les fermetures définissent l'environnement dans lequel elles s'exécutent et peuvent donc être appelées de n'importe où.

Les concepts de lambdas et de fermetures ne sont pas nécessairement liés, bien que les fonctions lambda puissent être des fermetures de la même manière que les fonctions normales peuvent également être des fermetures. Certains langages ont des constructions spéciales pour la fermeture ou lambda (par exemple, Groovy avec un bloc de code anonyme comme objet Closure), ou une expression lambda (par exemple, l'expression Java Lambda avec une option limitée pour la fermeture).

Voici une fermeture construite avec une fonction Python normale:

 1 def outer_func(x):
 2     y = 4
 3     def inner_func(z):
 4         print(f"x = {x}, y = {y}, z = {z}")
 5         return x + y + z
 6     return inner_func
 7
 8 for i in range(3):
 9     closure = outer_func(i)
10     print(f"closure({i+5}) = {closure(i+5)}")

outer_func() renvoieinner_func(), une fonction imbriquée qui calcule la somme de trois arguments:

  • x est passé en argument àouter_func().

  • y est une variable locale àouter_func().

  • z est un argument passé àinner_func().

Pour tester le comportement deouter_func() etinner_func(),outer_func() est appelé trois fois dans une bouclefor qui imprime ce qui suit:

x = 0, y = 4, z = 5
closure(5) = 9
x = 1, y = 4, z = 6
closure(6) = 11
x = 2, y = 4, z = 7
closure(7) = 13

À la ligne 9 du code,inner_func() renvoyé par l'invocation deouter_func() est lié au nomclosure. Sur la ligne 5,inner_func() capturex ety car il a accès à son environnement d'intégration, de sorte qu'à l'invocation de la fermeture, il est capable d'opérer sur les deux variables libresx ety.

De même, unlambda peut également être une fermeture. Voici le même exemple avec une fonction lambda Python:

 1 def outer_func(x):
 2     y = 4
 3     return lambda z: x + y + z
 4
 5 for i in range(3):
 6     closure = outer_func(i)
 7     print(f"closure({i+5}) = {closure(i+5)}")

Lorsque vous exécutez le code ci-dessus, vous obtenez la sortie suivante:

closure(5) = 9
closure(6) = 11
closure(7) = 13

À la ligne 6,outer_func() renvoie un lambda et l'affecte à la variableclosure. Sur la ligne 3, le corps de la fonction lambda fait référence àx ety. La variabley est disponible au moment de la définition, tandis quex est défini à l'exécution lorsqueouter_func() est appelé.

Dans cette situation, la fonction normale et le lambda se comportent de la même manière. Dans la section suivante, vous verrez une situation où le comportement d'un lambda peut être trompeur en raison de son temps d'évaluation (temps de définition vs temps d'exécution).

Temps d'évaluation

Dans certaines situations impliquantloops, le comportement d'une fonction lambda Python en tant que fermeture peut être contre-intuitif. Il faut comprendre quand les variables libres sont liées dans le contexte d'un lambda. Les exemples suivants montrent la différence lors de l'utilisation d'une fonction régulière par rapport à l'utilisation d'un lambda Python.

Testez d'abord le scénario à l'aide d'une fonction régulière:

>>>

 1 >>> def wrap(n):
 2 ...     def f():
 3 ...         print(n)
 4 ...     return f
 5 ...
 6 >>> numbers = 'one', 'two', 'three'
 7 >>> funcs = []
 8 >>> for n in numbers:
 9 ...     funcs.append(wrap(n))
10 ...
11 >>> for f in funcs:
12 ...     f()
13 ...
14 one
15 two
16 three

Dans une fonction normale,n est évalué au moment de la définition, à la ligne 9, lorsque la fonction est ajoutée à la liste:funcs.append(wrap(n)).

Maintenant, avec l'implémentation de la même logique avec une fonction lambda, observez le comportement inattendu:

>>>

 1 >>> numbers = 'one', 'two', 'three'
 2 >>> funcs = []
 3 >>> for n in numbers:
 4 ...     funcs.append(lambda: print(n))
 5 ...
 6 >>> for f in funcs:
 7 ...     f()
 8 ...
 9 three
10 three
11 three

Le résultat inattendu se produit car la variable libren, telle qu'implémentée, est liée au moment de l'exécution de l'expression lambda. La fonction lambda Python sur la ligne 4 est une fermeture qui capturen, une variable libre liée à l'exécution. Lors de l'exécution, lors de l'appel de la fonctionf sur la ligne 7, la valeur den estthree.

Pour résoudre ce problème, vous pouvez affecter la variable libre au moment de la définition comme suit:

>>>

 1 >>> numbers = 'one', 'two', 'three'
 2 >>> funcs = []
 3 >>> for n in numbers:
 4 ...     funcs.append(lambda n=n: print(n))
 5 ...
 6 >>> for f in funcs:
 7 ...     f()
 8 ...
 9 one
10 two
11 three

Une fonction lambda Python se comporte comme une fonction normale en ce qui concerne les arguments. Par conséquent, un paramètre lambda peut être initialisé avec une valeur par défaut: le paramètren prend lesn externes comme valeur par défaut. La fonction lambda Python aurait pu être écrite sous la formelambda x=n: print(x) et avoir le même résultat.

La fonction lambda Python est appelée sans aucun argument à la ligne 7 et utilise la valeur par défautn définie au moment de la définition.

Test des Lambdas

Les lambdas Python peuvent être testés de la même manière que les fonctions régulières. Il est possible d’utiliser à la foisunittest etdoctest.

unittest

Le moduleunittest gère les fonctions lambda Python de la même manière que les fonctions régulières:

import unittest

addtwo = lambda x: x + 2

class LambdaTest(unittest.TestCase):
    def test_add_two(self):
        self.assertEqual(addtwo(2), 4)

    def test_add_two_point_two(self):
        self.assertEqual(addtwo(2.2), 4.2)

    def test_add_three(self):
        # Should fail
        self.assertEqual(addtwo(3), 6)

if __name__ == '__main__':
    unittest.main(verbosity=2)

LambdaTest définit un cas de test avec trois méthodes de test, chacune d'entre elles exécutant un scénario de test pouraddtwo() implémenté en tant que fonction lambda. L'exécution du fichier Pythonlambda_unittest.py qui contientLambdaTest produit les éléments suivants:

$ python lambda_unittest.py
test_add_three (__main__.LambdaTest) ... FAIL
test_add_two (__main__.LambdaTest) ... ok
test_add_two_point_two (__main__.LambdaTest) ... ok

======================================================================
FAIL: test_add_three (__main__.LambdaTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lambda_unittest.py", line 18, in test_add_three
    self.assertEqual(addtwo(3), 6)
AssertionError: 5 != 6

----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (failures=1)

Comme prévu, nous avons deux cas de test réussis et un échec pourtest_add_three: le résultat est5, mais le résultat attendu était6. Cet échec est dû à une erreur intentionnelle dans le cas de test. Changer le résultat attendu de6 à5 satisfera tous les tests pourLambdaTest.

doctest

Le moduledoctest extrait le code Python interactif dedocstring pour exécuter des tests. Bien que la syntaxe des fonctions lambda Python ne prenne pas en charge undocstring typique, il est possible d'attribuer une chaîne à l'élément__doc__ d'un lambda nommé:

addtwo = lambda x: x + 2
addtwo.__doc__ = """Add 2 to a number.
    >>> addtwo(2)
    4
    >>> addtwo(2.2)
    4.2
    >>> addtwo(3) # Should fail
    6
    """

if __name__ == '__main__':
    import doctest
    doctest.testmod(verbose=True)

Ledoctest dans le commentaire doc de lambdaaddtwo() décrit les mêmes cas de test que dans la section précédente.

Lorsque vous exécutez les tests viadoctest.testmod(), vous obtenez ce qui suit:

$ python lambda_doctest.py
Trying:
    addtwo(2)
Expecting:
    4
ok
Trying:
    addtwo(2.2)
Expecting:
    4.2
ok
Trying:
    addtwo(3) # Should fail
Expecting:
    6
**********************************************************************
File "lambda_doctest.py", line 16, in __main__.addtwo
Failed example:
    addtwo(3) # Should fail
Expected:
    6
Got:
    5
1 items had no tests:
    __main__
**********************************************************************
1 items had failures:
   1 of   3 in __main__.addtwo
3 tests in 2 items.
2 passed and 1 failed.
***Test Failed*** 1 failures.

Les tests échoués résultent de la même panne expliquée dans l'exécution des tests unitaires dans la section précédente.

Vous pouvez ajouter undocstring à un lambda Python via une affectation à__doc__ pour documenter une fonction lambda. Bien que possible, la syntaxe Python accepte mieux lesdocstring pour les fonctions normales que les fonctions lambda.

Pour un aperçu complet des tests unitaires en Python, vous pouvez vous référer àGetting Started With Testing in Python.

Abus d'expression de Lambda

Plusieurs exemples dans cet article, s'ils sont écrits dans le contexte d'un code Python professionnel, pourraient être considérés comme des abus.

Si vous essayez de surmonter quelque chose qu'une expression lambda ne prend pas en charge, c'est probablement le signe qu'une fonction normale serait mieux adaptée. Ledocstring pour une expression lambda dans la section précédente est un bon exemple. Tenter de surmonter le fait qu'une fonction lambda Python ne prend pas en charge les instructions est un autre drapeau rouge.

Les sections suivantes illustrent quelques exemples d'utilisations lambda à éviter. Ces exemples peuvent être des situations où, dans le contexte de Python lambda, le code présente le modèle suivant:

  • Il ne suit pas le guide de style Python (PEP 8)

  • C'est lourd et difficile à lire.

  • Il est inutilement intelligent au prix d’une lisibilité difficile.

Levée d'une exception

Essayer de lever une exception dans un lambda Python devrait vous faire réfléchir à deux fois. Il existe des moyens intelligents de le faire, mais même quelque chose comme ce qui suit est préférable d'éviter:

>>>

>>> def throw(ex): raise ex
>>> (lambda: throw(Exception('Something bad happened')))()
Traceback (most recent call last):
    File "", line 1, in 
    File "", line 1, in 
    File "", line 1, in throw
Exception: Something bad happened

Étant donné qu'une instruction n'est pas syntaxiquement correcte dans un corps lambda Python, la solution de contournement dans l'exemple ci-dessus consiste à résumer l'appel d'instruction avec une fonction dédiéethrow(). L'utilisation de ce type de solution de contournement doit être évitée. Si vous rencontrez ce type de code, vous devriez envisager de refactoriser le code pour utiliser une fonction régulière.

Style cryptique

Comme dans tous les langages de programmation, vous trouverez du code Python qui peut être difficile à lire en raison du style utilisé. Les fonctions lambda, en raison de leur concision, peuvent être propices à l'écriture de code difficile à lire.

L'exemple lambda suivant contient plusieurs choix de style incorrects:

>>>

>>> (lambda _: list(map(lambda _: _ // 2, _)))([1,2,3,4,5,6,7,8,9,10])
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

Le trait de soulignement (_) fait référence à une variable à laquelle vous n’avez pas besoin de vous référer explicitement. Mais dans cet exemple, trois_ font référence à des variables différentes. Une mise à niveau initiale de ce code lambda pourrait être de nommer les variables:

>>>

>>> (lambda some_list: list(map(lambda n: n // 2,
                                some_list)))([1,2,3,4,5,6,7,8,9,10])
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

Certes, c'est encore difficile à lire. En profitant toujours d'unlambda, une fonction régulière contribuerait grandement à rendre ce code plus lisible, en répartissant la logique sur quelques lignes et les appels de fonction:

>>>

>>> def div_items(some_list):
      div_by_two = lambda n: n // 2
      return map(div_by_two, some_list)
>>> list(div_items([1,2,3,4,5,6,7,8,9,10])))
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

Ce n'est pas encore optimal mais vous montre un chemin possible pour rendre le code, et les fonctions lambda Python en particulier, plus lisibles. DansAlternatives to Lambdas, vous apprendrez à remplacermap() etlambda par des compréhensions de liste ou des expressions génératrices. Cela améliorera considérablement la lisibilité du code.

Classes Python

Vous pouvez mais ne devez pas écrire des méthodes de classe en tant que fonctions lambda Python. L'exemple suivant est un code Python parfaitement légal, mais présente un code Python non conventionnel reposant surlambda. Par exemple, au lieu d'implémenter__str__ en tant que fonction régulière, il utilise unlambda. De même,brand etyear sont desproperties également implémentés avec des fonctions lambda, au lieu des fonctions régulières ou des décorateurs:

class Car:
    """Car with methods as lambda functions."""
    def __init__(self, brand, year):
        self.brand = brand
        self.year = year

    brand = property(lambda self: getattr(self, '_brand'),
                     lambda self, value: setattr(self, '_brand', value))

    year = property(lambda self: getattr(self, '_year'),
                    lambda self, value: setattr(self, '_year', value))

    __str__ = lambda self: f'{self.brand} {self.year}'  # 1: error E731

    honk = lambda self: print('Honk!')     # 2: error E731

L'exécution d'un outil tel queflake8, un outil d'application du guide de style, affichera les erreurs suivantes pour__str__ ethonk:

E731 do not assign a lambda expression, use a def

Bien queflake8 ne signale pas de problème d'utilisation des fonctions lambda Python dans les propriétés, elles sont difficiles à lire et sujettes à des erreurs en raison de l'utilisation de plusieurs chaînes comme'_brand' et'_year'.

La mise en œuvre correcte de__str__ devrait être la suivante:

def __str__(self):
    return f'{self.brand} {self.year}'

brand s'écrirait comme suit:

@property
def brand(self):
    return self._brand

@brand.setter
def brand(self, value):
    self._brand = value

En règle générale, dans le contexte du code écrit en Python, préférez les fonctions régulières aux expressions lambda. Néanmoins, il existe des cas qui bénéficient de la syntaxe lambda, comme vous le verrez dans la section suivante.

Utilisations appropriées des expressions Lambda

Les lambdas en Python ont tendance à faire l'objet de controverses. Certains des arguments contre lambdas en Python sont:

  • Problèmes de lisibilité

  • L'imposition d'un mode de pensée fonctionnel

  • Syntaxe lourde avec le mot-clélambda

Malgré les débats houleux qui remettent en question la simple existence de cette fonctionnalité en Python, les fonctions lambda ont des propriétés qui fournissent parfois de la valeur au langage Python et aux développeurs.

Les exemples suivants illustrent des scénarios où l'utilisation des fonctions lambda est non seulement appropriée, mais encouragée dans le code Python.

Constructions fonctionnelles classiques

Les fonctions Lambda sont régulièrement utilisées avec les fonctions intégréesmap() etfilter(), ainsi quefunctools.reduce(), exposées dans le modulefunctools. Les trois exemples suivants sont des illustrations respectives de l'utilisation de ces fonctions avec des expressions lambda comme compagnons:

>>>

>>> list(map(lambda x: x.upper(), ['cat', 'dog', 'cow']))
['CAT', 'DOG', 'COW']
>>> list(filter(lambda x: 'o' in x, ['cat', 'dog', 'cow']))
['dog', 'cow']
>>> from functools import reduce
>>> reduce(lambda acc, x: f'{acc} | {x}', ['cat', 'dog', 'cow'])
'cat | dog | cow'

Vous devrez peut-être lire du code ressemblant aux exemples ci-dessus, mais avec des données plus pertinentes. Pour cette raison, il est important de reconnaître ces constructions. Néanmoins, ces constructions ont des alternatives équivalentes qui sont considérées comme plus Pythonic. DansAlternatives to Lambdas, vous apprendrez à convertir des fonctions d'ordre supérieur et leurs lambdas associées en d'autres formes plus idiomatiques.

Fonctions clés

Les fonctions clés en Python sont des fonctions d'ordre supérieur qui prennent un paramètrekey comme argument nommé. key reçoit une fonction qui peut être unlambda. Cette fonction influence directement l'algorithme piloté par la fonction clé elle-même. Voici quelques fonctions clés:

  • Méthode de liste desort():

  • Fonctions intégrées desorted(), min(), max():

  • nlargest() and nsmallest(): dans le module d'algorithme de file d'attente du tasheapq

Imaginez que vous souhaitiez trier une liste d'ID représentés sous forme de chaînes. Chaque ID est leconcatenation de la chaîneid et un nombre. Le tri de cette liste avec la fonction intégréesorted(), par défaut, utilise un ordre lexicographique car les éléments de la liste sont des chaînes.

Pour influencer l'exécution du tri, vous pouvez attribuer un lambda à l'argument nommékey, de sorte que le tri utilisera le numéro associé à l'ID:

>>>

>>> ids = ['id1', 'id2', 'id30', 'id3', 'id22', 'id100']
>>> print(sorted(ids)) # Lexicographic sort
['id1', 'id2', 'id30', 'id3', 'id22', 'id100']
>>> sorted_ids = sorted(ids, key=lambda x: int(x[2:])) # Integer sort
>>> print(sorted_ids)
['id1', 'id2', 'id3', 'id22', 'id30', 'id100']

Cadres d'interface utilisateur

Les infrastructures d'interface utilisateur telles queTkinter,wxPython ou .NET Windows Forms avecIronPython tirent parti des fonctions lambda pour mapper des actions en réponse aux événements d'interface utilisateur.

Le programme naïf Tkinter ci-dessous démontre l'utilisation d'unlambda affecté à la commande du boutonReverse:

import tkinter as tk
import sys

window = tk.Tk()
window.grid_columnconfigure(0, weight=1)
window.title("Lambda")
window.geometry("300x100")
label = tk.Label(window, text="Lambda Calculus")
label.grid(column=0, row=0)
button = tk.Button(
    window,
    text="Reverse",
    command=lambda: label.configure(text=label.cget("text")[::-1]),
)
button.grid(column=0, row=1)
window.mainloop()

Cliquer sur le boutonReverse déclenche un événement qui déclenche la fonction lambda, changeant le libellé deLambda Calculus àsuluclaC adbmaL *:

Animated TkInter Windows demonstrating the action of the button to the text

WxPython et IronPython sur la plate-forme .NET partagent une approche similaire pour la gestion des événements. Notez quelambda est une façon de gérer les événements de déclenchement, mais une fonction peut être utilisée dans le même but. Il finit par être autonome et moins verbeux d'utiliser unlambda lorsque la quantité de code nécessaire est très courte.

Pour explorer wxPython, consultezHow to Build a Python GUI Application With wxPython.

Interpréteur Python

Lorsque vous jouez avec du code Python dans l'interpréteur interactif, les fonctions lambda Python sont souvent une bénédiction. Il est facile de créer une fonction rapide à une ligne pour explorer des extraits de code qui ne verront jamais la lumière du jour en dehors de l'interpréteur. Les lambdas écrites dans l'interprète, pour une découverte rapide, sont comme du papier brouillon que vous pouvez jeter après usage.

timeit

Dans le même esprit que l'expérimentation de l'interpréteur Python, le moduletimeit fournit des fonctions pour chronométrer de petits fragments de code. Lestimeit.timeit() en particulier peuvent être appelés directement, en passant du code Python dans une chaîne. Voici un exemple:

>>>

>>> from timeit import timeit
>>> timeit("factorial(999)", "from math import factorial", number=10)
0.0013087529951008037

Lorsque l'instruction est passée sous forme de chaîne,timeit() a besoin du contexte complet. Dans l'exemple ci-dessus, cela est fourni par le deuxième argument qui configure l'environnement dont la fonction principale doit être chronométrée. Ne pas le faire déclencherait une exceptionNameError.

Une autre approche consiste à utiliser unlambda:

>>>

>>> from math import factorial
>>> timeit(lambda: factorial(999), number=10)
0.0012704220062005334

Cette solution est plus propre, plus lisible et plus rapide à taper dans l'interpréteur. Bien que le temps d'exécution ait été légèrement inférieur pour la versionlambda, une nouvelle exécution des fonctions peut présenter un léger avantage pour la versionstring. Le temps d’exécution dessetup est exclu du temps d’exécution global et ne devrait avoir aucun impact sur le résultat.

Patch de singe

Pour les tests, il est parfois nécessaire de s'appuyer sur des résultats reproductibles, même si lors de l'exécution normale d'un logiciel donné, les résultats correspondants devraient différer, voire être totalement aléatoires.

Supposons que vous souhaitiez tester une fonction qui, lors de l'exécution, gère des valeurs aléatoires. Mais, au cours de l'exécution du test, vous devez effectuer une vérification par rapport aux valeurs prévisibles de manière répétable. L'exemple suivant montre comment, avec une fonctionlambda, le monkey patching peut vous aider:

from contextlib import contextmanager
import secrets

def gen_token():
    """Generate a random token."""
    return f'TOKEN_{secrets.token_hex(8)}'

@contextmanager
def mock_token():
    """Context manager to monkey patch the secrets.token_hex
    function during testing.
    """
    default_token_hex = secrets.token_hex
    secrets.token_hex = lambda _: 'feedfacecafebeef'
    yield
    secrets.token_hex = default_token_hex

def test_gen_key():
    """Test the random token."""
    with mock_token():
        assert gen_token() == f"TOKEN_{'feedfacecafebeef'}"

test_gen_key()

Un gestionnaire de contexte aide à isoler l'opération de patching singe d'une fonction de la bibliothèque standard (secrets, dans cet exemple). La fonction lambda affectée àsecrets.token_hex() remplace le comportement par défaut en renvoyant une valeur statique.

Cela permet de tester toute fonction dépendant detoken_hex() de manière prévisible. Avant de quitter le gestionnaire de contexte, le comportement par défaut detoken_hex() est rétabli pour éliminer tout effet secondaire inattendu qui affecterait d'autres zones du test pouvant dépendre du comportement par défaut detoken_hex().

Les frameworks de tests unitaires commeunittest etpytest portent ce concept à un niveau de sophistication supérieur.

Avecpytest, toujours en utilisant une fonctionlambda, le même exemple devient plus élégant et concis:

import secrets

def gen_token():
    return f'TOKEN_{secrets.token_hex(8)}'

def test_gen_key(monkeypatch):
    monkeypatch.setattr('secrets.token_hex', lambda _: 'feedfacecafebeef')
    assert gen_token() == f"TOKEN_{'feedfacecafebeef'}"

Avec lespytest monkeypatch fixture,secrets.token_hex() est écrasé par un lambda qui renverra une valeur déterministe,feedfacecafebeef, permettant de valider le test. L'appareil pytestmonkeypatch vous permet de contrôler la portée du remplacement. Dans l'exemple ci-dessus, invoquersecrets.token_hex() dans les tests suivants, sans utiliser le patch monkey, exécuterait l'implémentation normale de cette fonction.

L'exécution du testpytest donne le résultat suivant:

$ pytest test_token.py -v
============================= test session starts ==============================
platform linux -- Python 3.7.2, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
cachedir: .pytest_cache
rootdir: /home/andre/AB/tools/bpython, inifile:
collected 1 item

test_token.py::test_gen_key PASSED                                       [100%]

=========================== 1 passed in 0.01 seconds ===========================

Le test réussit car nous avons validé que legen_token() a été exercé, et les résultats étaient ceux attendus dans le contexte du test.

Alternatives à Lambdas

Bien qu'il existe de bonnes raisons d'utiliserlambda, il existe des cas où son utilisation est mal vue. Alors quelles sont les alternatives?

Les fonctions d'ordre supérieur commemap(),filter() etfunctools.reduce() peuvent être converties en des formes plus élégantes avec de légères torsions de créativité, en particulier avec des compréhensions de liste ou des expressions génératrices.

RegardezUsing List Comprehensions Effectively pour en savoir plus sur les compréhensions de listes.

Map

La fonction intégréemap() prend une fonction comme premier argument et l'applique à chacun des éléments de son deuxième argument, uniterable. Des exemples d'itérables sont des chaînes, des listes et des tuples. Pour plus d'informations sur les itérateurs et les itérateurs, consultezIterables and Iterators.

map() renvoie un itérateur correspondant à la collection transformée. Par exemple, si vous souhaitez transformer une liste de chaînes en une nouvelle liste avec chaque chaîne en majuscule, vous pouvez utilisermap(), comme suit:

>>>

>>> list(map(lambda x: x.capitalize(), ['cat', 'dog', 'cow']))
['Cat', 'Dog', 'Cow']

Vous devez appelerlist() pour convertir l'itérateur renvoyé parmap() en une liste développée qui peut être affichée dans l'interpréteur de shell Python.

L'utilisation d'une compréhension de liste élimine le besoin de définir et d'appeler la fonction lambda:

>>>

>>> [x.capitalize() for x in ['cat', 'dog', 'cow']]
['Cat', 'Dog', 'Cow']

Filtre

La fonction intégréefilter(), une autre construction fonctionnelle classique, peut être convertie en une compréhension de liste. Il prend unpredicate comme premier argument et un itérable comme second argument. Il construit un itérateur contenant tous les éléments de la collection initiale qui satisfait la fonction de prédicat. Voici un exemple qui filtre tous les nombres pairs dans une liste d'entiers donnée:

>>>

>>> even = lambda x: x%2 == 0
>>> list(filter(even, range(11)))
[0, 2, 4, 6, 8, 10]

Notez quefilter() renvoie un itérateur, d'où la nécessité d'invoquer le type intégrélist qui construit une liste à partir d'un itérateur.

L'implémentation utilisant la construction de compréhension de liste donne les éléments suivants:

>>>

>>> [x for x in range(11) if x%2 == 0]
[0, 2, 4, 6, 8, 10]

Réduire

Depuis Python 3,reduce() est passé d'une fonction intégrée à une fonction de modulefunctools. Commemap() etfilter(), ses deux premiers arguments sont respectivement une fonction et un itérable. Il peut également prendre un initialiseur comme troisième argument utilisé comme valeur initiale de l'accumulateur résultant. Pour chaque élément de l'itérable,reduce() applique la fonction et accumule le résultat qui est renvoyé lorsque l'itérable est épuisé.

Pour appliquerreduce() à une liste de paires et calculer la somme du premier élément de chaque paire, vous pouvez écrire ceci:

>>>

>>> import functools
>>> pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
>>> functools.reduce(lambda acc, pair: acc + pair[0], pairs, 0)
6

Une approche plus idiomatique utilisant ungenerator expression, comme argument desum() dans l'exemple, est la suivante:

>>>

>>> pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
>>> sum(x[0] for x in pairs)
6

Une solution légèrement différente et peut-être plus propre supprime la nécessité d'accéder explicitement au premier élément de la paire et d'utiliser à la place le déballage:

>>>

>>> pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
>>> sum(x for x, _ in pairs)
6

L'utilisation du trait de soulignement (_) est une convention Python indiquant que vous pouvez ignorer la deuxième valeur de la paire.

sum() prend un argument unique, donc l'expression du générateur n'a pas besoin d'être entre parenthèses.

Les Lambdas sont-ils pythoniques ou non?

PEP 8, qui est le guide de style pour le code Python, lit:

Utilisez toujours une instruction def au lieu d'une instruction d'affectation qui lie directement une expression lambda à un identifiant. (Source)

Cela décourage fortement l'utilisation de lambda lié à un identifiant, principalement lorsque les fonctions doivent être utilisées et présentent plus d'avantages. PEP 8 ne mentionne pas d'autres utilisations delambda. Comme vous l'avez vu dans les sections précédentes, les fonctions lambda peuvent certainement avoir de bonnes utilisations, bien qu'elles soient limitées.

Une façon possible de répondre à la question est que les fonctions lambda sont parfaitement Pythonic s'il n'y a rien de plus Pythonic disponible. Je m'abstiens de définir ce que signifie «Pythonic», vous laissant la définition qui convient le mieux à votre état d'esprit, ainsi qu'à votre style de codage personnel ou à celui de votre équipe.

Au-delà de la portée étroite de Pythonlambda,How to Write Beautiful Python Code With PEP 8 est une excellente ressource que vous voudrez peut-être consulter concernant le style de code en Python.

Conclusion

Vous savez maintenant utiliser les fonctions de Pythonlambda et pouvez:

  • Écrire des lambdas Python et utiliser des fonctions anonymes

  • Choisissez judicieusement entre les fonctions lambdas ou Python normales

  • Évitez l'utilisation excessive de lambdas

  • Utiliser des lambdas avec des fonctions d'ordre supérieur ou des fonctions de touches Python

Si vous avez un penchant pour les mathématiques, vous pouvez vous amuser à explorer le monde fascinant delambda calculus.

Les lambdas en python sont comme du sel. Une pincée de spam, de jambon et d'œufs rehaussera les saveurs, mais trop gâtera le plat.

__ Take the Quiz: Testez vos connaissances avec notre quiz interactif «Fonctions Python Lambda». À la fin, vous recevrez un score afin que vous puissiez suivre vos progrès d'apprentissage au fil du temps:

Note: Le langage de programmation Python, nommé d'après Monty Python, préfère utiliserspam,ham eteggs comme variables métasyntaxiques, au lieu des traditionnelsfoo, bar etbaz.