Question 1Qu'affiche ce code ?nums = [1, 2, 3]
print(list(map(lambda x: x + 10, nums)))
map() — appliquer une fonction à chaque élément d'une liste d'un coup
Apprends à utiliser map() en Python pour appliquer une fonction à chaque élément d'un iterable d'un seul coup.
Dans l'article précédent sur les décorateurs, tu as vu comment envelopper du comportement supplémentaire autour d'une fonction. Cette fois, tu changes de registre et tu regardes la fonction intégrée map() — l'outil que tu prends quand tu veux appliquer la même fonction à chaque élément d'une liste d'un coup.
map() s'associe naturellement aux lambdas, et le mécanisme sous-jacent est similaire à une compréhension de liste. De nos jours, les compréhensions sont généralement le choix recommandé plutôt que map().
Ce qu'est map() — une fonction d'ordre supérieur qui touche chaque élément
map(function, iterable) applique la fonction du premier argument à chaque élément du second argument (une liste, un tuple, etc.) et retourne un objet map qui te permet de récupérer les résultats un à un. Tu peux soit l'itérer avec for, soit l'envelopper dans list() pour matérialiser le tout en liste.
Comme son premier argument est une fonction, map() est lui-même une fonction d'ordre supérieur.
map. Enveloppe-le dans list() pour matérialiser le contenu.numbers = [1, 2, 3, 4, 5]
squared = map(lambda x: x ** 2, numbers)
print(type(squared)) # <class 'map'>
print(squared) # <map object at 0x...>
# Récupère les valeurs avec list()
print(list(squared)) # [1, 4, 9, 16, 25]
# Les fonctions intégrées marchent aussi (convertit une liste de chaînes en int)
str_nums = ["10", "20", "30"]
print(list(map(int, str_nums))) # [10, 20, 30]
Un objet map est à usage unique
La valeur de retour de map() est un itérateur — du même genre que celui que tu obtiens d'un générateur — et une fois que tu l'as parcouru, il est vide. Appelle list(squared) une seconde fois et tu obtiendras []. Si tu as besoin de réutiliser les résultats plusieurs fois, fais list(map(...)) d'avance et travaille avec la liste.
Passer plusieurs iterables à la fois
À partir du second argument, map() accepte plusieurs iterables. Dans ce cas, la fonction du premier argument doit accepter un élément de chaque à la position correspondante. Écris map(function, A, B) et la fonction est appliquée à la paire A[0] et B[0], puis A[1] et B[1], et ainsi de suite.
Par exemple, pour multiplier deux listes numériques élément par élément, map(lambda a, b: a * b, A, B) te donne une liste de produits par paires.
A = [1, 2, 3]
B = [10, 20, 30]
# Multiplie les éléments au même index
print(list(map(lambda a, b: a * b, A, B))) # [10, 40, 90]
# Pareil avec trois iterables
def calculate(x, y, op):
return x + y if op == "plus" else x - y
xs = [10, 20, 30]
ys = [3, 3, 3]
ops = ["plus", "minus", "plus"]
print(list(map(calculate, xs, ys, ops))) # [13, 17, 33]
A et B au même index sont appariés et passés au lambda lambda a, b: a * b.Des longueurs différentes s'arrêtent à la plus courte
Quand les iterables que tu passes ont des longueurs différentes, map() s'arrête au plus court. Par exemple, map(f, [1, 2, 3, 4], [10, 20]) ne s'exécute que deux fois. Si tu veux un alignement explicite, vérifie les longueurs à l'avance, ou associe map() à `zip()` selon tes besoins.
map() vs compréhension de liste — laquelle utiliser ?
Presque tout ce que map() peut faire, une compréhension de liste peut le faire aussi. La doc officielle de Python et des livres comme Fluent Python recommandent de préférer les compréhensions dans le nouveau code, et en Python moderne, les compréhensions sont la forme standard.
map() était la forme par défaut dans l'ancien code, mais son rôle s'est réduit aux cas où tu peux passer un nom de fonction existant sans écrire de lambda (pense à map(int, str_nums)). Mettons les différences côte à côte.
| Objectif | Avec map() | Avec compréhension |
|---|---|---|
| Élever chaque élément au carré | list(map(lambda x: x ** 2, nums)) | [x ** 2 for x in nums] |
| Convertir str en int | list(map(int, str_nums)) | [int(s) for s in str_nums] |
| Deux listes à la fois | list(map(f, A, B)) | [f(a, b) for a, b in zip(A, B)] |
nums = [1, 2, 3, 4, 5]
# Version map()
print(list(map(lambda x: x ** 2, nums))) # [1, 4, 9, 16, 25]
# Version compréhension (préférée)
print([x ** 2 for x in nums]) # [1, 4, 9, 16, 25]
# Quand tu peux passer un nom de fonction directement, map() est plus propre
str_nums = ["10", "20", "30"]
print(list(map(int, str_nums))) # [10, 20, 30]
print([int(s) for s in str_nums]) # [10, 20, 30]
# Pour filtrer, les compréhensions sont bien plus concises
print([x for x in nums if x % 2 == 0]) # [2, 4]
Dans le doute, prends une compréhension
Que tu veuilles transformer, filtrer, ou les deux, une compréhension te permet d'écrire le tout naturellement à l'intérieur des mêmes crochets. Si tu t'engages à n'utiliser map() que quand tu passes un nom de fonction existant tel quel, ton code reste cohérent. C'est plus léger pour celui qui écrit comme pour celui qui lit, donc préfère les compréhensions dans le nouveau code.
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Quelle compréhension produit le même résultat que list(map(int, ["1", "2", "3"])) ?
Question 3Quelle affirmation sur la valeur de retour de map() est correcte ?