¿Por qué los dos guiones siguientes no son equivalentes?¿Por qué los decoradores de Python no pueden encadenarse entre las definiciones?
(tomado de otra pregunta: Understanding Python Decorators)
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makebold
@makeitalic
def hello():
return "hello world"
print hello() ## returns <b><i>hello world</i></b>
y decorada con un decorador:
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
@makebold
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makeitalic
def hello():
return "hello world"
print hello() ## TypeError: wrapped() takes no arguments (1 given)
¿Por qué quiero saber? He escrito un decorador retry
para capturar las excepciones de MySQLdb: si la excepción es transitoria (por ejemplo, tiempo de espera) volverá a llamar a la función después de dormir un poco.
También tengo un decorador modifies_db
que se encarga de algunas tareas de limpieza relacionadas con la caché. modifies_db
está decorado con retry
, por lo que supuse que todas las funciones decoradas con modifies_db
también volverían a intentarse implícitamente. ¿Qué hice mal?
Buena pregunta. Me encontré con el mismo escenario hace unos meses mientras hacía mi propio decorador de reintentos. Requirió un recuento de reintentos, por lo que el problema se presentó un poco diferente al suyo, pero tenía las mismas soluciones que se muestran a continuación. –