El Decorador solo funciona cuando un método está decorado, pero no cuando el decorador se llama con el método pasado como argumento.
Escucha desde hace mucho tiempo; primera vez que llama, así que por favor no me critiques si no he seguido perfectamente las pautas.
Estoy intentando crear un decorador que aplique una barra de progreso a un método generador. Mi decorador funciona perfectamente cuando se usa la sintaxis @decorator. Sin embargo, cuando llamo al decorador y paso un método como argumento, el decorador no hace nada en absoluto. Me gustaría llamar a la función decoradora como cualquier otra función en lugar de usar @status_bar porque quiero una forma simple de usar opcionalmente el generador.
Aquí está el código funcionando:
import time
from alive_progress import alive_bar
def status_bar(func):
def wrapper(self):
with alive_bar() as bar:
for x in func(self):
bar()
return wrapper
class TestClass:
def __init__(self):
pass
@status_bar
def iter_range(self):
for x in range(10000):
time.sleep(0.01)
yield x
TestClass().iter_range()
Esto devuelve una barra de progreso en la consola como se esperaba.
| ▶▶▶▶▶▶▶▶▶▶▶▶▶ | ▂▂▄ 326 en 3s (98.2/s)
Pero al ejecutar el código sin el azúcar sintáctico, no hace nada.
def status_bar(func):
def wrapper(self):
with alive_bar() as bar:
for x in func(self):
bar()
return wrapper
class TestClass:
def __init__(self):
pass
def iter_range(self):
for x in range(10000):
time.sleep(0.01)
yield x
status_bar(TestClass().iter_range)
En cambio, el código se ejecuta como si no se hubiera llamado a ninguna función.
Proceso finalizado con el código de salida 0
Siempre obtengo la misma salida y sé que hay una explicación sencilla aquí, por eso me molesta tanto no poder hacer que funcione. Cualquier ayuda es muy apreciada. Gracias.
davy.ai
La razón por la que el segundo fragmento de código no funciona es que
status_bar(TestClass().iter_range)
solo devuelve la función envoltorio, no la ejecuta. Para que funcione, debes ejecutar la función envoltorio devuelta por el decorador. Puedes hacerlo asignando la función decorada a una variable y luego llamando a esa variable:Alternativamente, puedes modificar el decorador para que devuelva directamente la función decorada:
Con este cambio, puedes llamar a la función decorada de la siguiente manera: