No, hay (más de) dos formas de hacer objetos invocables. Uno es para def
una función, que obviamente es invocable. Otra es definir un método __call__
en una clase, lo que hará que las instancias puedan invocarse. Y las clases mismas son objetos invocables.
Un decorador no es más que un objeto invocable, que es previsto para aceptar una función como su único argumento y devolver algo invocable. La siguiente sintaxis:
@decorate
def some_function(...):
...
es sólo una manera un poco más bonitas de la escritura:
def some_function(...):
...
some_function = decorate(some_function)
El ejemplo basado en clases que da no es una función que toma una función y devuelve una función, que es el decorador de vainilla estándar de pantano, es una clase que se inicializa con una función cuyas instancias son invocables. Para mí, esto es un poco raro si en realidad no lo estás usando como clase (¿tiene otros métodos? ¿Su estado cambia? ¿Haces varias instancias de él que tengan un comportamiento común encapsulado por la clase?). Pero el uso normal de su función decorada no notará la diferencia (a menos que sea un decorador particularmente invasivo), así que haga lo que le parezca más natural.
¡Con las clases, puede hacer uso del protocolo descriptor! – phant0m
@ phant0m: En el lado negativo, con las clases que * tiene * para usar el protocolo de descriptores (de lo contrario, su decorador no funcionará exactamente en los métodos). –
@Rosh: Hmm sí, tienes un punto muy fuerte aquí :) – phant0m