ProgrammationData Engineer

Décrivez le fonctionnement de la fonction map() en Python. En quoi est-elle différente des expressions génératrices et des expressions de liste, dans quels cas map est-elle préférable, et quand ne l'est-elle pas ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question

La fonction map() vient de la programmation fonctionnelle (déjà présente dans Lisp), son but est d'appliquer une fonction à chaque élément d'une séquence tout en renvoyant un nouvel objet itérable avec les résultats. En Python, elle est apparue bien avant l'arrivée des expressions génératrices et des expressions de liste, mais elle est toujours largement utilisée, en particulier dans les grands pipelines de traitement de données.

Problème

Lorsque vous devez modifier chaque élément d'une collection selon certaines règles, les solutions de type for deviennent rapidement encombrantes et moins lisibles. Les expressions de liste et map() permettent d'exprimer l'intention de manière compacte. Il est important de comprendre les différences entre ces approches pour choisir le bon outil.

Solution

  • map(func, iterable) crée un itérateur paresseux où les éléments de la séquence d'origine sont transformés par la fonction func
  • En Python 3, l'objet map ne calcule pas immédiatement les éléments, il fonctionne de manière paresseuse
def square(x): return x * x squares = map(square, [1, 2, 3]) print(list(squares)) # [1, 4, 9]

L'expression de liste [square(x) for x in [1, 2, 3]] fait la même chose, mais renvoie immédiatement une liste, tandis que l'expression génératrice (square(x) for x in [1, 2, 3]) est un générateur paresseux.

Caractéristiques clés :

  • map() renvoie toujours un itérateur paresseux
  • Pratique pour travailler avec plusieurs collections (avec plusieurs arguments) — map(f, a, b)
  • Ne prend pas en charge les conditions de filtrage par syntaxe directe (contrairement aux expressions de liste)

Questions pièges.

Map() renvoie-t-il une liste en Python 3 ?

Non, à partir de Python 3, map() ne renvoie pas une liste mais un itérateur paresseux. Pour obtenir une liste, il faut envelopper le résultat dans list().

res = map(str.upper, ['a', 'b']) print(res) # <map object ...> print(list(res)) # ['A', 'B']

Peut-on utiliser map() pour ajouter une condition de filtrage dans la fonction ?

Non, map() ne filtre pas les éléments, il ne fait que les transformer. Pour le filtrage, utilisez filter() ou une expression de liste :

result = map(str.upper, ['a', 'b', None]) # Si None est passé, map lèvera une erreur d'appel str.upper(None) # filter aidera à supprimer None avant map

Peut-on parcourir deux séquences en même temps avec map() ?

Oui, map() peut accepter un nombre arbitraire de séquences, et la fonction de transformation doit accepter autant d'arguments :

x = [1, 2, 3] y = [10, 20, 30] result = map(lambda a, b: a + b, x, y) print(list(result)) # [11, 22, 33]

Erreurs typiques et anti-modèles

  • Attendre que map() renvoie une liste en Python 3
  • Essayer de filtrer à l'intérieur de map() — map ne fait que transformer
  • Passer des séquences de longueurs inégales — les lignes sont tronquées à la longueur minimale

Exemple dans la vie

Cas négatif

Le développeur s'attend à obtenir une liste immédiatement :

mapped = map(abs, [-1, -2, -3]) print(mapped[1]) # TypeError: 'map' object is not subscriptable

Avantages :

  • Économise de la mémoire

Inconvénients :

  • Erreur lors de la tentative d'accès par indice
  • Nécessite une conversion en list()

Cas positif

Utilisation d'une expression génératrice pour le filtrage et de map() pour la transformation :

nums = range(-5, 6) positives = (x for x in nums if x > 0) sq = map(lambda n: n * n, positives) print(list(sq)) # [1, 4, 9, 16, 25, 36]

Avantages :

  • Facile à combiner avec des filtres
  • Consommation de mémoire minimale

Inconvénients :

  • Lisibilité réduite pour les débutants
  • Pas de support syntaxique pour la condition