Apprenez en lisant dans l'ordre

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.

Comment marche map()
[1, 2, 3, 4, 5]lambda x: x ** 2<map object>(itérateur)[1, 4, 9, 16, 25]alimente chaque élémentmap()récupère avec list()
Chaque élément du second argument est passé dans la fonction du premier argument, et les résultats reviennent sous forme d'objet 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.

Construis une liste de prix TTC (10 %) à partir d'une liste prices de prix de produits.

① Déclare prices = [100, 250, 480, 1200].

② Multiplie chaque élément par 1.1, convertis en int, construis la liste résultante, et affecte-la à tax_included.

③ Affiche le résultat avec print(tax_included).

(Lorsque la réponse est correcte, l'explication apparaîtra.)

Éditeur Python

Exécuter le code pour voir le résultat

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]
Passer deux listes à map()
lambda a, b: a * bA = [1, 2, 3]B = [10, 20, 30](1, 10)(2, 20)(3, 30)104090premier1*102*203*30
Les éléments de 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.

À partir d'une liste de noms de produits et d'une liste de quantités, construis une liste de chaînes "nom × quantité" en utilisant map().

① Déclare items = ["pomme", "orange", "raisin"] et counts = [3, 5, 2].

② Enveloppe map(lambda name, n: f"{name} × {n}", items, counts) dans list(...) et affecte à labels.

③ Affiche chacun sur sa propre ligne avec for label in labels: print(label).

Éditeur Python

Exécuter le code pour voir le résultat

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.

ObjectifAvec 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 intlist(map(int, str_nums))[int(s) for s in str_nums]
Deux listes à la foislist(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.

Convertis une liste de chaînes en entrée en liste d'entiers de deux façons : avec map() et avec une compréhension.

① Déclare inputs = ["10", "20", "30", "40"].

② Enveloppe map(int, inputs) dans list(...), affecte-le à via_map, et print(via_map).

③ Construis le même résultat avec [int(s) for s in inputs], affecte-le à via_comp, et print(via_comp).

④ Enfin, exécute print(via_map == via_comp) pour confirmer que les deux valeurs sont égales.

Éditeur Python

Exécuter le code pour voir le résultat
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Qu'affiche ce code ?
nums = [1, 2, 3]
print(list(map(lambda x: x + 10, nums)))

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 ?