Comment passer les paramètres d'une fonction en utilisant timeit.Minuterie()
voici les grandes lignes d'un programme simple
# some pre-defined constants
A = 1
B = 2
# function that does something critical
def foo(num1, num2):
# do something
# main program.... do something to A and B
for i in range(20):
# do something to A and B
# and update A and B during each iteration
import timeit
t = timeit.Timer(stmt="foo(num1,num2)")
print t.timeit(5)
- je continuer à recevoir "nom global foo n'est pas défini"..... Quelqu'un peut-il m'aider sur ce point? Merci!
10 réponses
les extraits de code doivent être indépendants-ils ne peuvent pas faire de références externes. Vous devez définir vos valeurs dans l'instruction-string ou setup-string:
import timeit
setup = """
A = 1
B = 2
def foo(num1, num2):
pass
def mainprog():
global A,B
for i in range(20):
# do something to A and B
foo(A, B)
"""
t = timeit.Timer(stmt="mainprog()" setup=setup)
print(t.timeit(5))
mieux encore, réécrivez votre code pour ne pas utiliser de valeurs globales.
les fonctions peuvent utiliser des arguments dans timeit
si ceux-ci sont créés en utilisant des fermetures, nous pouvons ajouter ces comportements en les enveloppant dans une autre fonction.
def foo(num1, num2):
def _foo():
# do something to num1 and num2
pass
return _foo
A = 1
B = 2
import timeit
t = timeit.Timer(foo(A,B))
print t.timeit(5)
ou plus court, nous pouvons utiliser functools.partie au lieu de la déclaration de fermeture explicite
def foo(num1, num2):
# do something to num1 and num2
pass
A = 1
B = 2
import timeit, functools
t = timeit.Timer(functools.partial(foo, A, B))
print t.timeit(5)
supposons que votre nom de fichier module soit test.py
# some pre-defined constants
A = 1
B = 2
# function that does something critical
def foo(n, m):
pass
# main program.... do something to A and B
for i in range(20):
pass
import timeit
t = timeit.Timer(stmt="test.foo(test.A, test.B)", setup="import test")
print t.timeit(5)
votre fonction doit être définie dans la chaîne de configuration. Une bonne façon de le faire est de configurer votre code dans un module, donc vous devez simplement faire
t = timeit.Timer("foo(num1, num2)", "from myfile import foo")
t.timeit(5)
sinon, vous devrez définir toute la configuration comme une chaîne à l'intérieur de la déclaration setup.
setup = """
# some pre-defined constants
A = 1
B = 2
# function that does something critical
def foo(num1, num2):
# do something
# main program.... do something to A and B
for i in range(20):
# do something to A and B
# and update A and B during each iteration
"""
t = timeit.Timer("foo(num1, num2)", setup)
t.timeit(5)
quelque chose de génial que je viens de découvrir est un raccourci pour iPython qui utilise cProfile.
def foo(x, y):
print x*y
%prun foo("foo", 100)
je crée habituellement une fonction supplémentaire:
def f(x,y):
return x*y
v1 = 10
v2 = 20
def f_test():
f(v1,v2)
print(timeit.timeit("f_test()", setup="from __main__ import f_test"))
voici un exemple pour compartimenter la routine temporelle, sans appeler les globals
def foo(a, b):
'''Do something to `a` and `b`'''
return a + b
def time_foo():
'''Create timer object simply without using global variables'''
import timeit
_foo = foo
a = 1
b = 2
# Get `Timer` oject, alternatively just get time with `timeit.timeit()`
t = timeit.Timer('_foo(a, b)', globals=locals())
return t
vous pouvez même généraliser cela si vous voulez utiliser la même fonction timeit
pour chronométrer d'autres fonctions. Voici un exemple avec votre exemple main()
routine:
def foo1(a, b):
'''Add `a` and `b`'''
return a + b
def foo2(a, b):
'''More math on `a` and `b`'''
return (a**2 * b)**2
def time_foo(func, **kwargs):
'''Create timer object simply without using global variables'''
import timeit
return timeit.timeit('func(**kwargs)', globals=locals())
def run():
'''Modify inputs to foo and see affect on execution time'''
a = 1
b = 2
for i in range(10):
# Update `a` and `b`
a += 1
b += 2
# Pass args to foo as **kwargs dict
print('foo1 time: ', time_foo(foo1, **{'a':a, 'b':b}))
print('foo2 time: ', time_foo(foo2, **{'a':a, 'b':b}))
return None
il y a une solution beaucoup plus simple (au moins pour Python 3), vous pouvez faire exécuter le code dans votre espace de noms global actuel:
t = timeit.Timer(stmt="foo(num1,num2)", globals=globals())
https://docs.python.org/3/library/timeit.html#examples Je sais que les globals ne sont pas préférés, mais si vous faites juste un script rapide pour vérifier quelque chose, je pense que c'est l'implémentation la plus facile.
je préfère créer une classe static
avec toutes les données prêtes à être récupérées avant d'exécuter le minuteur.
une autre note, il est préférable de faire des essais en fonction plutôt que dans l'espace global, car l'espace global ne profite pas de
FAST_LOAD
pourquoi le code Python s'exécute-t-il plus rapidement dans une fonction?
class Data(object):
"""Data Creation"""
x = [i for i in range(0, 10000)]
y = tuple([i for i in range(0, 10000)])
def __init__(self):
pass
import timeit
def testIterator(x):
for i in range(10000):
z = i
print timeit.timeit("testIterator(Data.x)", setup="from __main__ import testIterator, Data", number=50)
print timeit.timeit("testIterator(Data.y)", setup="from __main__ import testIterator, Data", number=50)
cela devrait fonctionner:
import timeit
def f(x,y):
return x*y
x = 5
y = 7
print(timeit.timeit(stmt='f(x,y)',
setup='from __main__ import f, x, y',
number=1000))
je jouais avec le timing en python 3.7 aujourd'hui et j'essayais de passer des fonctions et des variables dans la minuterie. C'est ce que je suis venu avec.
import re
text = "This is a test of the emergency broadcast system"
def regex(text):
return re.sub(r"(\s){1,}", r"", text)
def loop_while(text):
if " " in text:
while " " in text:
text = text.replace(" ", " ")
return text
if __name__ == "__main__":
import timeit
callable_functions = [item for item in locals().items() if callable(item[1])]
for func_name, func in callable_functions:
elapsed_time = timeit.timeit(f"{func_name}(text)", globals=globals(), number=100000)
print(f"{func_name}: {elapsed_time} \n{func(text)}\n")
Ce sorties:
regex: 1.378352418
Ceci est un test du système de diffusion d'urgenceloop_while: 0.1589502999997
151990920" Ceci est un test de l'urgence système de diffusion
tout ce qu'il faut pour tester une nouvelle version est l'ajout d'une nouvelle fonction. Quelque chose comme:
def split_join(text):
return " ".join(text.split())
Maintenant, c'sorties:
regex: 1.378352418
Ceci est un test du système de diffusion d'urgenceloop_while: 0.1589502999997
151990920" Ceci est un test du système de diffusion d'urgencesplit_join: 0.05700970800000005
Ceci est un test du système de diffusion d'urgence