PROJET AUTOBLOG


Sam et Max

source: Sam et Max

⇐ retour index

Les listes en intention VS map() en Python

jeudi 4 octobre 2012 à 15:26

Les 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 intention 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 ().