Decora tu código (Python decorators)

Los decoradores de Python ofrecen una forma elegante de aplicar wrappers a clases, métodos y propiedades.

La sintaxis es la siguiente:

>>> @decorador>>> def funcion_decorada():>>>     return 'resultado'>>>>>> print funcion_decorada()resultado>>>

y básicamente, significa lo mismo que el siguiente trozo de código:

>>> def funcion():>>>     return 'resultado'>>>>>> funcion_decorada = decorador(funcion)>>>>>> print funcion_decorada()resultado>>>

Un decorador es una función que:

  • - recibe una función como parámetro y
  • - devuelve otra función como resultado.

Completando nuestro primer ejemplo, el siguiente decorador:

>>> def decorador(funcion):>>>>>>    def nuevaFuncion(*args, **kwargs):>>>        print 'pamplinas'>>>        return funcion(*args, **kwargs)>>>>>>    return nuevaFuncion>>>

modifica el comportamiento de nuestra función de la siguiente manera:

>>> print funcion_decorada()pamplinasresultado>>>  

Un aplicación típica de los decoradores es en la definición de métodos de clase. Tradicionalmente se ha utilizado esta sintáxis:

>>> def metodo(self):>>>     return 'resultado'>>>>>> metodo_de_clase = classmethod(metodo)>>>

Si el cuerpo del método es muy largo, puede quedarnos poco legible el código. Los decoradores nos permiten abreviar bastante:

>>> @classmethod>>> def metodo_de_clase(self):>>>     return 'resultado'

Los decoradores tienen numerosas aplicaciones, por ejemplo, podemos implementar una política de “Dreprecation Warnings” de la siguiente manera:

>>> import warnings>>>>>> def deprecated(funcion):>>> >>>     def nuevaFuncion(*args, **kwargs):>>>         warnings.warn(funcion.__name__, DeprecationWarning, stacklevel=2)>>>         return funcion(*args, **kwargs)>>> >>>     nuevaFuncion.__name__ = funcion.__name__>>>     nuevaFuncion.__doc__ = funcion.__doc__>>>     nuevaFuncion.__dict__.update(funcion.__dict__)>>>     return nuevaFuncion>>> >>> >>> class MiClase:>>> >>>      @deprecated>>>      def metodo_anticuado(self):>>>          return 'resultado'>>> >>> miClase = MiClase()>>>>>> r = miClase.metodo_anticuado()DeprecationWarning: metodo_anticuado>>>

Referencias:

2 Responses to “Decora tu código (Python decorators)”

  1. NcTrun says:

    Qué grandes son. Cuando estuve viendo la librería de decoradores [1] fue como :-o Vienen al pelo para logging u otros elementos rollo aspectos, o para expresar de manera clara restricciones a funciones, o incluso para transformar parámetros de un tipo a otro (rollo “de verdad recibo usuario y passwd de una BD” y las funciones que tengo las implemento como que recibo cursores diréctamente).Es lo que dices, nada que no se pudiese hacer antes en plan:def micodigo(bla): ble blemicodigo = decorador(micodigo)pero de una forma más elegante.[1] http://wiki.python.org/moin/PythonDecoratorLibrary

  2. nando says:

    Aupi NcTrun,Buena referencia! No conozco mucho sobre ‘aspectos’, a ver si nos escribes algo sobre ello! ;-DAgur,Nando.

Leave a Reply