2010-11-24 22 views
56

Lequel est le plus pythonique?Plus de façons Python d'exécuter un processus X Times

While:

count = 0 
while count < 50: 
    print "Some thing" 
    count = count + 1 

boucle For:

for i in range(50): 
    print "Some thing" 

Edit: pas double emploi parce que cela a des réponses pour déterminer qui est plus claire, par rapport à la façon d'exécuter une gamme sans "je" - même si cela a fini par être le plus élégant

+7

Upvoting pour pour compenser les votes négatifs: si Lionel pose cette question, d'autres J'ai la même question, et les réponses ci-dessous seront utiles. – EOL

+2

Le terme "Pythonic" est en cours d'utilisation. C'est synonyme de "lisible" et "facilement compréhensible". En Python, au moins. – darioo

+0

Copie possible de [Est-il possible d'implémenter une boucle Python pour une plage sans une variable d'itérateur?] (Http://stackoverflow.com/questions/818828/is-it-possible-to-implement-a-python-for- range-loop-without-an-iterator-variable) –

Répondre

72

Personnellement:

for _ in range(50): 
    print "Some thing" 

si vous n'avez pas besoin i. Si vous utilisez Python < 3 et que vous voulez répéter la boucle plusieurs fois, utilisez xrange car il n'est pas nécessaire de générer la liste entière à l'avance.

+10

Attention cependant à _ étant mappé à la fonction de traduction gettext. –

+6

+1 pour la variable '_'. C'est ce que j'aurais suggéré. – EOL

+0

Merci pour cette réponse; c'était la principale raison pour laquelle je n'utilisais pas la boucle for parce que j'avais une variable inutilisée dans "i". – Lionel

1

Si vous êtes après le s Comme les effets qui se produisent dans la boucle, je vais personnellement pour l'approche range().

Si vous vous souciez du résultat de toutes les fonctions que vous appelez dans la boucle, j'opterais pour une approche de compréhension de liste ou map. Quelque chose comme ceci:

def f(n): 
    return n * n 

results = [f(i) for i in range(50)] 
# or using map: 
results = map(f, range(50)) 
+0

results = (f pour i dans la plage (50)) –

+1

results = itertools.imap (f, plage (50)) –

+0

@ralu, uniquement si vous n'en avez pas besoin accès répété ou aléatoire dans les résultats si. – aaronasterling

-6

Il n'y a pas vraiment de façon pythonique de répéter quelque chose. Cependant, il est une meilleure façon:

carte

(indice lambda: do_something(), xrange (10))

si vous devez passer l'index alors:

carte (indice lambda: do_something (index), xrange (10))

Considérer qu'il renvoie les résultats sous la forme d'une collection, donc si vous avez besoin de collecter les résultats, cela peut aider.

+0

Non seulement cela n'est pas vraiment meilleur (surcharge d'appel de fonction, expressions lambda moins connues, collecte des résultats inutilisés dans une liste), 10 n'est pas itérable. –

+0

Oui, xrange (10) pas 10. J'ai dit que c'est mieux parce que vous n'avez pas besoin d'écrire une fonction ou faire une boucle. Cependant, comme je l'ai dit, il n'y a pas vraiment de façon pythonique. J'ai changé le code, merci. –

1

La boucle for est définitivement plus pythonique, car elle utilise la fonctionnalité intégrée de niveau supérieur de Python pour transmettre ce que vous faites de façon plus claire et plus concise. La surcharge de range vs xrange et l'affectation d'une variable i non utilisée résultent de l'absence d'une instruction telle que l'instruction repeat de Verilog. La principale raison de s'en tenir à la solution for range est que les autres moyens sont plus complexes. Par exemple:

from itertools import repeat 

for unused in repeat(None, 10): 
    del unused # redundant and inefficient, the name is clear enough 
    print "This is run 10 times" 

au lieu de répétition Utiliser plage est moins claire ici parce qu'il est pas aussi bien connu d'une fonction, et plus complexe parce que vous devez l'importer. Les guides de style principaux si vous avez besoin d'une référence sont PEP 20 - The Zen of Python et PEP 8 - Style Guide for Python Code.

Nous notons également que la version pour la gamme est un exemple explicite utilisé dans les deux language reference et tutorial, bien que dans ce cas, la valeur est utilisée. Cela signifie que la forme est forcément plus familière que l'expansion while d'une boucle de type C.

+0

Ne vaudrait-il pas mieux utiliser la chose répétée directement, c'est-à-dire: 'pour s in repeat ('Ceci est exécuté 10 fois', 10): print s' ?? – F1Rumors

+0

Certainement! Mais l'impression dans l'exemple de code n'était qu'un exemple d'une section répétée de code, pour laquelle il n'y a peut-être pas d'objet central. –

-4

Pourquoi pas?

while BoolIter(N, default=True, falseIndex=N-1): 
    print 'some thing' 

ou d'une manière plus laid:

for _ in BoolIter(N): 
    print 'doing somthing' 

ou si vous voulez attraper la dernière fois par:

for lastIteration in BoolIter(N, default=False, trueIndex=N-1): 
    if not lastIteration: 
     print 'still going' 
    else: 
     print 'last time' 

où:

class BoolIter(object): 

    def __init__(self, n, default=False, falseIndex=None, trueIndex=None, falseIndexes=[], trueIndexes=[], emitObject=False): 
     self.n = n 
     self.i = None 
     self._default = default 
     self._falseIndexes=set(falseIndexes) 
     self._trueIndexes=set(trueIndexes) 
     if falseIndex is not None: 
      self._falseIndexes.add(falseIndex) 
     if trueIndex is not None: 
      self._trueIndexes.add(trueIndex) 
     self._emitObject = emitObject 


    def __iter__(self): 
     return self 

    def next(self): 
     if self.i is None: 
      self.i = 0 
     else: 
      self.i += 1 
     if self.i == self.n: 
      raise StopIteration 
     if self._emitObject: 
      return self 
     else: 
      return self.__nonzero__() 

    def __nonzero__(self): 
     i = self.i 
     if i in self._trueIndexes: 
      return True 
     if i in self._falseIndexes: 
      return False 
     return self._default 

    def __bool__(self): 
     return self.__nonzero__()