Existe-t-il un moyen rapide d'appeler une fonction deux fois ou plus consécutivement en Python? Par exemple:
do()
do()
do()
peut-être comme:
3*do()
Je voudrais:
for _ in range(3):
do()
Le _
Est la convention pour une variable dont vous ne vous souciez pas de la valeur.
Vous pourriez également voir certaines personnes écrire:
[do() for _ in range(3)]
cependant, c'est un peu plus cher car il crée une liste contenant les valeurs de retour de chaque appel de do()
(même si c'est None
), puis jette la liste résultante. Je ne suggérerais pas d'utiliser ceci à moins que vous soyez en utilisant la liste des valeurs de retour.
Vous pouvez définir une fonction qui répète la fonction passée N fois.
def repeat_fun(times, f):
for i in range(times): f()
Si vous voulez le rendre encore plus flexible, vous pouvez même passer des arguments à la fonction en cours de répétition:
def repeat_fun(times, f, *args):
for i in range(times): f(*args)
Usage:
>>> def do():
... print 'Doing'
...
>>> def say(s):
... print s
...
>>> repeat_fun(3, do)
Doing
Doing
Doing
>>> repeat_fun(4, say, 'Hello!')
Hello!
Hello!
Hello!
Hello!
Trois autres façons de le faire:
(I) Je pense que l'utilisation de map
peut également être une option, bien que cela nécessite la génération d'une liste supplémentaire avec None
s dans certains cas et nécessite toujours une liste d'arguments:
def do():
print 'hello world'
l=map(lambda x: do(), range(10))
(II) itertools
contient des fonctions qui peuvent également être utilisées pour parcourir d'autres fonctions https://docs.python.org/2/library/itertools.html
(III) L'utilisation de listes de fonctions n'était pas mentionnée jusqu'à présent je pense (et c'est en fait la syntaxe la plus proche de celle discutée à l'origine):
it=[do]*10
[f() for f in it]
Ou en tant que doublure:
[f() for f in [do]*10]
Une boucle simple pour?
for i in range(3):
do()
Ou, si vous êtes intéressé par les résultats et que vous souhaitez les collecter, avec le bonus d'être un liner:
vals = [do() for _ in range(3)]
Mes deux centimes:
from itertools import repeat
list(repeat(f(), x)) # for pure f
[f() for f in repeat(f, x)] # for impure f
Voici une approche qui ne nécessite pas l'utilisation d'une boucle for
ou la définition d'une fonction intermédiaire ou d'une fonction lambda (et est également une ligne). La méthode combine les deux idées suivantes:
appeler la fonction intégrée iter()
avec l'argument sentinelle facultatif, et
en utilisant la itertools
recette pour faire avancer un itérateur n
étapes (voir la recette de consume()
).
Ensemble, nous obtenons:
next(islice(iter(do, object()), 3, 3), None)
(L'idée de passer object()
comme sentinelle vient de this réponse Stack Overflow acceptée.)
Et voici à quoi cela ressemble dans l'invite interactive:
>>> def do():
... print("called")
...
>>> next(itertools.islice(iter(do, object()), 3, 3), None)
called
called
called
from itertools import repeat, starmap
results = list(starmap(do, repeat((), 3)))
Voir la recette repeatfunc du module itertools qui est en fait beaucoup plus puissante. Si vous devez simplement appeler la méthode mais ne vous souciez pas des valeurs de retour, vous pouvez l'utiliser dans une boucle for:
for _ in starmap(do, repeat((), 3)): pass
mais ça devient moche.
Vous pouvez essayer la boucle while comme indiqué ci-dessous;
def do1():
# Do something
def do2(x):
while x > 0:
do1()
x -= 1
do2(5)
Faites donc appeler la fonction do1 5 fois.
Vous pouvez utiliser itertools.repeat
avec operator.methodcaller
pour appeler le __call__
méthode de la fonction [~ # ~] n [~ # ~] fois. Voici un exemple d'une fonction générateur qui le fait:
from itertools import repeat
from operator import methodcaller
def call_n_times(function, n):
yield from map(methodcaller('__call__'), repeat(function, n))
Exemple d'utilisation:
import random
from functools import partial
throw_dice = partial(random.randint, 1, 6)
result = call_n_times(throw_dice, 10)
print(list(result))
# [6, 3, 1, 2, 4, 6, 4, 1, 4, 6]