Re-implémentation détaillée d'un décorateur @timer pour mesurer le temps d'exécution d'une fonction. Compagnon utile en data science pour profiler.
def decorateur(func):
def wrapper(*args, **kwargs):
# avant
result = func(*args, **kwargs)
# après
return result
return wrapper*args et **kwargs permettent au wrapper d'accepter n'importe quels arguments et de les transmettre à func.
import timedef timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
# On pourrait print(f'{func.__name__} a pris {elapsed:.4f}s')
return result
return wrapperLignes clés
time.time() horloge système en secondes (float, précision ms)@timer
def process_data(n):
return sum(i ** 2 for i in range(n))result = process_data(100000)
print(f'Résultat: {result}')L'écriture @timer est équivalente à :
process_data = timer(process_data)Pour des mesures fines (sous-ms), préfère time.perf_counter() :
import time
start = time.perf_counter()
...
elapsed = time.perf_counter() - start # bien plus précisSans précaution, la fonction décorée "perd" son nom (devient 'wrapper'). Pour préserver :
from functools import wrapsdef timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
...
return wrapperMaintenant process_data.__name__ vaut bien 'process_data'.
Pour du profilage sérieux :
- %timeit dans Jupyter
- module cProfile (analyse appel par appel)
- lib externe : line_profiler (ligne par ligne)Un décorateur @timer collé sur quelques fonctions critiques permet de repérer rapidement les goulots d'étranglement d'un script.
Envie d'aller plus loin ? Découvrez nos formations certifiées Bac+2 à Bac+5 →