Les listes en intension VS map() en Python


sLes adeptes de la programmation fonctionnelle connaissent bien le principe de la fonction map() et sont souvent plus à l’aise avec elle qu’avec les listes en intension en Python.

Les deux font pourtant la même chose, tant et si bien que Python 3 voit map() retiré de ses built-in. Ouuuups. Dérapage un-con-trollé de Sam.

C’est plutôt une nouvelle chose car dans un language orienté objet comme Python, il y a une subtile différence entre map() et les comprehension lists. Quand on utilise une méthode plutôt qu’une fonction, map() tue le duck tuping:

>>> l = [u'      Le choix dans la date     ', '     Les nouilles cuisent au jus de canne     ']
>>> map(str.strip, l)
Traceback (most recent call last):
  File "<ipython-input-14-41df8a735feb>", line 1, in <module>
    map(str.strip, l)
TypeError: descriptor 'strip' requires a 'str' object but received a 'unicode'
 
>>> map(unicode.strip, l)
Traceback (most recent call last):
  File "<ipython-input-15-fc0fc8fef32d>", line 1, in <module>
    map(unicode.strip, l)
TypeError: descriptor 'strip' requires a 'unicode' object but received a 'str'
 
>>> [x.strip() for x in l]
[u'Le choix dans la date', 'Les nouilles cuisent au jus de canne']

Notez que je vous recomande d’éviter à tout prix de mélanger des chaînes encodées, et des chaînes unicode, de toute façon. J’utilise ceci uniquement parce que c’est un cas simple à comprendre.

Mais ici, le problème peut être résumé ainsi: nous avons une collection hétérogène d’objets (qui pourraient être de n’importe quels autres types, il y a des cas beaucoup plus légitimes), et nous appliquons la méthode de l’objet. Qui ne correspond pas forcément à son type.

Avoir des types différents avec la même interface est courant en Python pour profiter du duck typing, donc ce genre de chose n’est pas un edge case.

La solution est bien entendu de wrapper l’appel dans une fonction anonyme:

>>> map(lambda x: x.strip(), l)
[u'Le choix dans la date', 'Les nouilles cuisent au jus de canne']

Mais à ce stade, [x.strip() for x in l] est beaucoup plus lisible et rapide. Sans compter qu’il peut être transformé en générateur juste en changeant les [] en ().

4 thoughts on “Les listes en intension VS map() en Python

  • JeromeJ

    Bonjour,

    D’où est-ce que Python3 n’aurait plus map dans ses built-ins ?! C’est faux ! C’est prévu pour une prochaine version ? Où ça ?

    Car, ouais non, y a quand même une légère différence dans le code *chicane*.

    Ah et en Python 3 map renvoit un générateur aussi hein :)

    Et par exemple, perso je préfère écrire
    "".join(map(str, range(10)))
    que
    "".join(str(n) for n in range(10))
    mais bon ça c’est peut-être moi. Ça va dépendre des cas aussi surtout.

  • Sam Post author

    Effectivement, mea culpa, j’en étais intimement persuadé, et j’avais tord. Seul reduce() a été retiré des built-in.

  • jolanouille

    Les listes en intension VS map() en Python -> Les listes en intention VS map() en Python

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.