web-dev-qa-db-fra.com

Python idiomatique: boucle "fois"

Disons que j'ai une fonction foo que je veux appeler n fois. En Ruby, j'écrirais:

n.times { foo }

En Python, je pourrais écrire:

for _ in xrange(n): foo()

Mais cela semble être une manière hacky de faire les choses.

Ma question: existe-t-il une façon idiomatique de le faire en Python?

47
perimosocordiae

La question présuppose que l'appel de foo () n fois est une chose a priori nécessaire. D'où vient-il? Est-ce la longueur de quelque chose d'itérable? Ensuite, parcourez l'itérable. Comme je prends Python, je trouve que j'utilise peu ou pas de valeurs arbitraires; il y a un sens plus saillant derrière votre n qui s'est perdu quand il est devenu un entier.

Plus tôt dans la journée, je suis tombé sur l'article provocateur de Nicklaus Wirth pour IEEE Computer intitulé Bonnes idées - à travers le miroir (archivé version pour les futurs lecteurs) . Dans la section 4, il apporte une perspective différente sur les constructions de programmation que tout le monde (y compris lui-même) a prises pour acquis mais qui contiennent des défauts expressifs:

"La généralité de la déclaration for d'ALGOL aurait dû être un signal d'avertissement pour tous les futurs concepteurs afin de toujours garder à l'esprit l'objectif principal d'une construction et de se lasser d'une généralité et d'une complexité exagérées, qui peuvent facilement devenir productif."

ALGOL for est équivalent au C/Java for, il en fait juste trop. Ce document est utile à lire, ne serait-ce que parce qu'il fait que l'on ne tient pas tant pour acquis que nous le faisons si facilement. Alors peut-être une meilleure question est "Pourquoi auriez-vous besoin d'une boucle qui s'exécute un nombre arbitraire de fois?"

8
msw

Vous avez déjà montré la voie idiomatique:

for _ in range(n): # or xrange if you are on 2.X
    foo()

Je ne sais pas ce qui est "hackish" à ce sujet. Si vous avez un cas d'utilisation plus spécifique à l'esprit, veuillez fournir plus de détails et il pourrait y avoir quelque chose de mieux adapté à ce que vous faites.

42
TM.

Si vous voulez la méthode times et que vous devez l'utiliser sur vos propres fonctions, essayez ceci:

def times(self, n, *args, **kwargs):
    for _ in range(n):
        self.__call__(*args, **kwargs)

import new
def repeatable(func):
    func.times = new.instancemethod(times, func, func.__class__)
    return func

ajoutez maintenant un @repeatable décorateur pour toute méthode sur laquelle vous avez besoin d'une méthode times sur:

@repeatable
def foo(bar):
    print bar

foo.times(4, "baz") #outputs 4 lines of "baz"
17
Carson Myers

Le plus rapide et le plus propre est itertools.repeat :

import itertools

for _ in itertools.repeat(None, n):
    foo()
16
Alex Martelli