Cela est lié aux éléments suivants: (In Python Code)
for i in object:
doSomething(i)
versus
map(doSomething, object)
Les deux sont faciles à comprendre et courts, mais y a-t-il une différence de vitesse? Maintenant, si doSomething avait une valeur de retour que nous devions vérifier, il serait renvoyé sous forme de liste à partir de la carte, et dans la boucle for, nous pourrions soit créer notre propre liste, soit en vérifier une à la fois.
for i in object:
returnValue = doSomething(i)
doSomethingWithReturnValue(returnValue)
versus
returnValue = map(doSomething, object)
map(doSomethingWithReturnValue, returnValue)
Maintenant, je sens que les deux divergent un peu. Les deux fonctions doSomethingWithReturnValue peuvent être différentes selon que si elles sont vérifiées à la volée au fur et à mesure que nous parcourons la boucle ou si toutes les vérifications à la fois à la fin produisent des résultats différents. Il semble également que la boucle for fonctionnerait toujours, peut-être plus lentement, où la carte ne fonctionnerait que dans certains scénarios. Bien sûr, nous pourrions faire des contorsions pour faire fonctionner l'une ou l'autre, mais le but est d'éviter ce type de travail.
Ce que je recherche, c'est un scénario où la fonction de mappage brille vraiment par rapport à une boucle bien réalisée pour les performances, la lisibilité, la maintenabilité ou la vitesse de mise en œuvre. Si la réponse est qu'il n'y a vraiment pas de grande différence, j'aimerais savoir quand dans la pratique les gens utilisent l'un ou l'autre ou si c'est vraiment complètement arbitraire et défini par des normes de codage en fonction de votre institution.
Merci!
map
est utile lorsque vous souhaitez appliquer la fonction à chaque élément d'un itérable et renvoyer une liste des résultats. C'est plus simple et plus concis que d'utiliser une boucle for et de construire une liste.
for
est souvent plus lisible pour d'autres situations, et dans LISP, il y avait beaucoup de constructions d'itérations qui ont été écrites essentiellement à l'aide de macros et de cartes. Donc, dans les cas où map
ne convient pas, utilisez une boucle for
.
En théorie, si nous avions un compilateur/interprète suffisamment intelligent pour utiliser plusieurs processeurs/processeurs, map
pourrait être implémenté plus rapidement car les différentes opérations sur chaque élément pourraient être effectuées en parallèle. Cependant, je ne pense pas que ce soit le cas actuellement.
Connaissez-vous le module timeit? Voici quelques horaires. -s effectue une configuration unique, puis la commande est bouclée et le meilleur temps enregistré.
1> python -m timeit -s "L=[]; M=range(1000)" "for m in M: L.append(m*2)"
1000 loops, best of 3: 432 usec per loop
2> python -m timeit -s "M=range(1000);f=lambda x: x*2" "L=map(f,M)"
1000 loops, best of 3: 449 usec per loop
3> python -m timeit -s "M=range(1000);f=lambda x:x*2" "L=[f(m) for m in M]"
1000 loops, best of 3: 483 usec per loop
4> python -m timeit -s "L=[]; A=L.append; M=range(1000)" "for m in M: A(m*2)"
1000 loops, best of 3: 287 usec per loop
5> python -m timeit -s "M=range(1000)" "L=[m*2 for m in M]"
1000 loops, best of 3: 174 usec per loop
Notez qu'ils sont tous similaires à l'exception des deux derniers. Ce sont les appels de fonction (L.append ou f(x)) qui affectent gravement le timing. Dans # 4, la recherche L.append a été effectuée une fois dans la configuration. Dans # 5 a list comp sans appel de fonction est utilisé.
utilisez simplement des listes de compréhension: elles sont plus Pythonic. Ils ont également une syntaxe similaire aux expressions de générateur, ce qui facilite le passage de l'une à l'autre. Vous n'avez rien à changer lors de la conversion de votre code en py3k: map
renvoie un itérable dans py3k et vous devrez ajuster votre code.
si vous ne vous souciez pas des valeurs de retour, ne nommez pas la nouvelle liste, vous devez utiliser les valeurs de retour une fois dans votre code, vous pouvez basculer vers des expressions de générateur et une seule compréhension de liste à la fin.