Les fonctions anonymes lambda en Python : print, expressions conditionnelles et récursivité
Si Python n’est pas un langage de programmation fonctionnelle, il possède cependant des fonctions anonymes lambda qui sont typiques de cette famille de langages. Ces fonctions sont réputées peu puissantes en Python car elle ont été volontairement limitées syntaxiquement à une expression, sans possibilité d’utiliser des instructions. Pourtant, nous allons voir qu’elles ont dans ce langage quelques particularités intéressantes.
L’instruction print
est devenue une fonction print()
- et donc une expression - dans Python 3 suite à la PEP 3105. Ainsi, si vous utilisez print
dans une fonction lambda, Python 2 lèvera une exception SyntaxError: invalid syntax
alors que Python 3 l'acceptera :
>>> pr = lambda x : print(x)
>>> pr('OK en Python 3')
OK en Python 3
Expressions conditionnelles
Introduites (tardivement) dans Python 2.5 suite à la PEP 308, les expressions conditionnelles sont une manière simplifiée de réaliser grâce à l’opérateur ternaire true_value if condition else false_value
la suite d'instructions suivante :
if condition:
x = true_value
else:
x = false_value
Comme leur nom l’indique, les expressions conditionnelles sont bien des expressions et elles permettent donc de mettre de la logique dans les fonctions lambda. Cela était déjà possible précédemment, en abusant un peu les opérateurs logiques classiques avec condition and true_value or false_value
, mais c'est une méthode que je déconseille car elle n'est pas totalement fiable pour certaines valeurs de condition
.
Dans l’exemple suivant, j’utilise une expression conditionnelle avec la fonction print()
et donc Python 3, ce dernier me permettant d'utiliser un nom de variable avec le caractère non-ASCII é
(PEP 3131) :
>>> majorité = lambda x : print("mineur") if x < 18 else print("majeur")
>>> majorité(15)
mineur
>>> majorité(25)
majeur
Récursivité
Le principe des fonctions anonymes étant de ne pas être nommées, il est donc logiquement difficile de les appeler. Ainsi, les fonctions anonymes de certains langages fonctionnels ne peuvent pas s’appeler, et donc ne peuvent pas être récursives. En Python, les lambda sont un sucre syntaxique limité des fonctions normales mais elles leur sont sémantiquement équivalentes, et elles peuvent donc parfaitement s’appeler récursivement.
En utilisant une expression conditionnelle et la récursivité on peut ainsi facilement implémenter l’algorithme récursif naïf de la très classique suite de Fibonacci :
>>> fib = lambda x : x if x < 2 else fib(x - 1) + fib(x - 2)
>>> fib(1)
1
>>> fib(10)
55
>>> fib(25)
75025
Vous n’arriverez pas à atteindre la limite de récursivité de l’interpréteur Python avec cet algorithme de complexité exponentielle, mais vous pourrez le faire aisément avec un algorithme à récursion terminale :
>>> fib2 = lambda n, a, b: fib2(n-1, b, a+b) if n > 0 else a
>>> fib2(200, 0, 1)
280571172992510140037611932413038677189525
>>> fib2(1000, 0, 1)
RuntimeError: maximum recursion depth exceeded
Compréhension de liste
On peut enfin ajouter que l’usage de compréhension de liste permet aisément de faire une boucle dans une fonction lambda :
>>> incr = lambda liste : [i + 1 for i in liste]
>>> incr([1, 45, 340])
[2, 46, 341]
Mise à jour du 21 mars 2019 : Ajout du Fibonacci à récursion terminale.