Obtener el nombre de la función cuando se utiliza ContextDecorator como decorador.
Tengo el siguiente gestor de contexto y decorador para medir el tiempo de cualquier función o bloque de código:
import time
from contextlib import ContextDecorator
class timer(ContextDecorator):
def <strong>init</strong>(self, label: str):
self.label = label
<pre><code>def __enter__(self):
self.start_time = time.perf_counter()
return self
def __exit__(self, *exc):
net_time = time.perf_counter() - self.start_time
print(f"{self.label} tomó {net_time:.1f} segundos")
return False
</code></pre>
Se puede usar como gestor de contexto:
with timer("mi bloque de código"):
time.sleep(2)
<h1>mi bloque de código tomó 2.0 segundos</h1>
También se puede usar como decorador:
@timer("mi<em>func")
def mi</em>func():
time.sleep(3)
mi_func()
<h1>mi_func tomó 3.0 segundos</h1>
Lo único que no me gusta es tener que pasar manualmente el nombre de la función como la etiqueta
cuando se usa como decorador. Me encantaría que el decorador use automáticamente el nombre de la función si no se pasa una etiqueta:
@timer()
def mi_func():
time.sleep(3)
mi_func()
<h1>mi_func tomó 3.0 segundos</h1>
¿Hay alguna manera de hacer esto?
davy.ai
Sí, es posible modificar el decorador
timer
para utilizar automáticamente el nombre de la función como etiqueta si no se pasa ninguna etiqueta. Esto se puede hacer modificando el método__init__
de la clasetimer
para comprobar si se pasa una etiqueta, y si no, utilizar el nombre de la función decorada en su lugar:En esta versión modificada de la clase
timer
, el método__init__
ahora recibe un argumentolabel
opcional, que por defecto esNone
. Si no se pasa etiqueta, se utiliza el atributo__class__.__name__
para obtener el nombre de la función decorada. Este es el nombre de la clase a la que se ha adjuntado el decorador, que en este caso debería ser la función decorada.Con esta modificación, ahora es posible utilizar el decorador
timer
sin pasar una etiqueta, y se utilizará automáticamente el nombre de la función decorada: