Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre un tema particular que ya vimos en un post anteriormente como un ejemplo.

Anuncios

Recuerdan cuando hablamos de la tecnica, ordenar-decorar-sin ordenar en este post, existe una posibilidad de poder usar solamente a decorar, este paradigma se volvio tan popular y con un uso tan amplio que python decidio implementarlo con una sintaxis propia, si bien no ahondaremos mucho en este tema y solo veremos tres situaciones posibles pero si quieren saber mas sobre como es su sintaxis completa les recomiendo visitar el siguiente link:

https://www.python.org/dev/peps/pep-0318/

Anuncios

Comencemos con el primer caso donde tenemos un solo decorador, primero veamos un ejemplo de funcion donde se implementa:

def funcion(arg1, arg2, ..., argN):
    pass
func = decorador(funcion)
Anuncios

Esta es una funcion basica que recibe N argumentos luego utilizamos un nuevo objeto donde por medio de decorator le asignamos la funcion anterior, la forma mas python de escribirlo es la siguiente:

@decorador
def funcion(arg1, arg2, ..., argN):
    pass
Anuncios

Como pueden ver es exactamente lo mismo pero de una forma mas corta y legible, pasemos a un caso donde tenemos dos decoradores:

def funcion(arg1, arg2, ..., argN):
    pass
func = deco1(deco2(funcion))
Anuncios

En este caso tenemos dos decoradores pero pueden ser todos los que necesitemos, en este caso primero trabajamos a la funcion con el deco2 y el resultado de esta con el deco1, una manera interesante de trabajar con este tema es recordar la siguiente frase:

Mas cerca esta el decorador de la funcion mas rapido se aplica

El Tinchicus
Anuncios

Al igual que en el caso anterior tiene una equivalencia que es la siguiente:

@deco1
@deco2
def funcion(arg1, arg2, ..., argN):
    pass
Anuncios

En este caso se debe respetar el orden de cual es la decoracion que debe trabajar mas rapido con nuestra funcion y el resto solo lo hara sobre el resultado o los distintos resultados en caso de haber mas decoradores, pasemos a ver el ultimo caso:

def funcion(arg1, arg2, ..., argN):
    pass
func = decoarg(arg_a, arg_b)(funcion)
Anuncios

En este caso vemos como un decorador puede recibir argumentos o valores, este es util en algunos casos pero no es algo que se utilice muy a menudo, como pueden ver tenemos al decorador seguido de los argumentos para finalmente pasar la funcion que decoramos, para entender el concepto vamos a analizar el siguiente ejemplo:

>>> from time import sleep, time
>>> def f():
...     sleep(.3)
... 
>>> def g():
...     sleep(.5)
... 
>>> def medicion(funcion):
...     t = time()
...     funcion()
...     print(funcion.__name__,'llevo:', time() -t)
... 
>>>
Anuncios
Anuncios

Primero importaremos dos funciones del modulo time, despues definiremos dos funciones que contendran distintos nombres pero seran iguales porque hara un retardo de una X cantidad de tiempo por medio de sleep, luego tendremos una funcion llamada medicion que recibe un valor que para nuestro ejemplo sera una funcion, luego crearemos una variable que almacenara el tiempo actual, llamaremos la funcion para generar el retardo luego mostrara el nombre de la funcion en cuestion y cuanto tiempo nos llevo por medio de la diferencia entre el tiempo y el tiempo almacenado anteriormente, con esto podemos pasar a probarlo:

>>> medicion(f)
f llevo: 0.3003075122833252
>>> medicion(g)
g llevo: 0.5007853507995605
>>>
Anuncios

En este caso vemos que la funcion medicion nos devolvio cual es la funcion que ejecutamos y cuanto tiempo le llevo ejecutarla pero debimos crear dos funciones para tener dos tiempos distintos lo cual va en contra de la filosofia de python, por lo tanto vamos a recrear el ejemplo de la siguiente manera:

>>> from time import sleep, time
>>> def f(descanso=0.1):
...     sleep(descanso)
... 
>>> def medicion(funcion, *args, **pcargs):
...     t = time()
...     funcion(*args, **pcargs)
...     print(funcion.__name__, 'llevo:', time() - t)
... 
>>>
Anuncios

En este caso eliminamos a la funcion g dejamos una sola que sera f, esta tendra un valor predeterminado y sera el que usaremos en sleep, luego modificaremos a medicion donde ahora recibira dos argumentos mas ademas de la funcion, volvemos a almacenar el valor de tiempo actual, luego llamamos a la funcion pero con los dos argumentos que recibimos, por ultimo volvemos a mostrar la funcion y cuanto tiempo llevo, veamos como funciona:

>>> medicion(f, descanso=0.3)
f llevo: 0.3006012439727783
>>> medicion(f, 0.2)
f llevo: 0.20050573348999023
>>>
Anuncios

Como vemos funciono como el caso anterior, el codigo quedo mas acorde al lenguaje y podemos pasar un tiempo cualquiera para trabajar pero ahora vamos a llevarlo un poco mas lejos al ejemplo para que nos devuelva directamente el valor de medicion sin necesidad de llamarlo, para ello primeroo modificaremos a la funcion medicion de la siguiente manera:

>>> def medicion(funcion):
...     def envoltorio(*args, **pcargs):
...             t = time()
...             funcion(*args, **pcargs)
...             print(funcion.__name__, "llevo:", time() -t)
...     return envoltorio
... 
>>>
Anuncios

Para este caso primero creamos una funcion llamada definicion que solamente recibe un valor, luego creamos otra funcion internamente llamada envoltorio que sera la encargada de recibir los argumentos de antes, dentro tenemos las mismas instrucciones a la funcion anterior pero la unica diferencia sera que una vez terminado la funcion superior se encargara de devolver el objeto creado por la funcion anterior, nuestro siguiente paso sera crear el punto de decoracion:

>>> f = medicion(f)
Anuncios

Tal como mencionamos al comienzo esto genera un decorador para nuestro ejemplo, si lo probamos veremos lo siguiente:

>>> f(0.2)
f llevo: 0.2005002498626709
>>> f(descanso=0.5)
f llevo: 0.5008797645568848
>>> print(f.__name__)
envoltorio
>>>
Anuncios

Observer como al usar las dos primeras acciones estas siguen trabajando como siempre pero al momento de verificar el verdadero nombre de f nos devuelve a envoltorio el lugar de su nombre, es decir que quedo con un error pero este lo solucionaremos en el proximo post.

Anuncios

En resumen, hoy hemos visto el concepto de decorador, hemos visto su concepto basico y otras formas que disponemos, de estas formas las tres mas utilizadas, despues fuimos mejorando un ejemplo poco a poco hasta mejora la forma de poder ejecutar nuestras acciones sin necesidad de mostrarlas, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.00