sábado, 6 de septiembre de 2014

Decorators en python


Supongamos que queremos logear cada vez que se llama una función. Es decir queremos saber cada vez que se llame una función. Para esta tarea podemos utilizar los decorators, no confundir con el patrón decorator.

Los decorators nos permiten agregar funcionalidad a una función (valga la redundancia)

Lo primero que debemos tener en cuenta es que vamos a trabaja con un closure. Este concepto hace referencia  a que una función puede ser evaluada en un contexto que puede, a su vez, uno o más componente dependiendo que otro entorno diferente. En nuestro caso, tendremos una función declarada dentro de otra, devolviendo la principal el resultado de la ejecución de la función contenida en la misma. Aunque parece un poco confuso, es mejor entenderlo echando un vistazo al siguiente código:

def principal(f) :
      def nueva():
          print("ini", f.__name__)
          f()
          print("fin", f.__name__)
      return nueva

El siguiente paso es definir una nueva función a la que llamaremos decorada. Será esta mueva función a la que aplicaremos como decorador la función principal:

@principal
def decorada():
     print("decorada")

Ahora llamamos la función y observamos la salida:

decorada()
ini decorada
decorada
fin decorada

De esta forma podemos utilizar decorators para agregar funcionalidad a funciones. Lo que sucede es que la función principal es llamada con la función decorada como parámetro, y principal devuelve la función nueva que internamente llama a decorada. :P

uff, mucho más fácil escribir el código que explicarlo...