Pensez à une fonction que j'appelle pour ses effets secondaires, pas pour ses valeurs de retour (comme l'impression à l'écran, la mise à jour de l'interface graphique, l'impression dans un fichier, etc.).
def fun_with_side_effects(x):
...side effects...
return y
Maintenant, est-ce Pythonic d'utiliser les compréhensions de liste pour appeler cette fonction:
[fun_with_side_effects(x) for x in y if (...conditions...)]
Notez que je ne sauvegarde la liste nulle part
Ou devrais-je appeler cette func comme ceci:
for x in y:
if (...conditions...):
fun_with_side_effects(x)
Quel est le meilleur et pourquoi?
for ... in
est utilisé dans les deux cas - ce qui conduit à des questions comme celle-ci!Réponses:
C'est très anti-pythonique de le faire, et tout Pythonista chevronné vous en donnera l'enfer. La liste intermédiaire est jetée après sa création et elle peut être potentiellement très, très volumineuse et donc coûteuse à créer.
la source
for
avant, pour me débarrasser de laif
).Vous ne devriez pas utiliser une compréhension de liste , car comme les gens l'ont dit, cela créera une longue liste temporaire dont vous n'avez pas besoin. Les deux méthodes suivantes sont équivalentes:
avec la définition de
consume
depuis laitertools
page de manuel:Bien sûr, ce dernier est plus clair et plus facile à comprendre.
la source
map
cela ne soit pas aussi intuitif si vous n'avez pas encore fait de programmation fonctionnelle.consume = collections.deque(maxlen=0).extend
Les compréhensions de listes servent à créer des listes. Et à moins que vous ne créiez réellement une liste, vous ne devez pas utiliser de compréhension de liste.
Donc, j'aurais pour la deuxième option, juste itérer sur la liste, puis appeler la fonction lorsque les conditions s'appliquent.
la source
Le deuxième est meilleur.
Pensez à la personne qui aurait besoin de comprendre votre code. Vous pouvez facilement obtenir un mauvais karma avec le premier :)
Vous pouvez aller au milieu entre les deux en utilisant filter (). Prenons l'exemple:
la source
lambda x : x > 3
.for el in (x for x in y if x > 3):
.el
etx
peut avoir le même nom, mais cela pourrait dérouter les gens.Cela dépend de votre objectif.
Si vous essayez d'effectuer une opération sur chaque objet d'une liste, la deuxième approche doit être adoptée.
Si vous essayez de générer une liste à partir d'une autre liste, vous pouvez utiliser la compréhension de liste.
la source
Tu peux faire
mais ce n'est pas très joli.
la source
Utiliser une compréhension de liste pour ses effets secondaires est moche, non pythonique, inefficace et je ne le ferais pas. J'utiliserais
for
plutôt une boucle, car unefor
boucle signale un style procédural dans lequel les effets secondaires sont importants.Mais, si vous insistez absolument pour utiliser une compréhension de liste pour ses effets secondaires, vous devez éviter l'inefficacité en utilisant plutôt une expression de générateur. Si vous insistez absolument sur ce style, faites l'un de ces deux:
ou:
Ce sont des expressions génératrices et elles ne génèrent pas de liste aléatoire qui est jetée. Je pense que le
all
formulaire est peut-être un peu plus clair, même si je pense que les deux sont déroutants et ne devraient pas être utilisés.Je pense que c'est moche et je ne le ferais pas réellement dans le code. Mais si vous insistez pour implémenter vos boucles de cette façon, c'est comme ça que je le ferais.
J'ai tendance à penser que les compréhensions de listes et leurs semblables devraient signaler une tentative d'utiliser quelque chose qui ressemble au moins légèrement à un style fonctionnel. Mettre des choses avec des effets secondaires qui cassent cette hypothèse obligera les gens à lire votre code plus attentivement, et je pense que c'est une mauvaise chose.
la source
fun_with_side_effects
renvoie Vrai?itertools.consume
n'existe plus, probablement parce qu'utiliser des compréhensions avec des effets secondaires est moche.