Anuncios

Bienvenidos sean a este post, hoy continuaremos con lo visto en el post anterior.

Anuncios

Anteriormente vimos la teoria de que es un decorador y como asignarlo pero nos quedamos con este ultimo ejemplo:

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

Primero importamos las funciones sleep, time para despues crear la funcion f para usar a sleep, despues tenemos la funcion medicion que es la encargada de medir la demora generada por sleep y lo hacia por medio de una funcion llamada envoltorio para finalmente crear el punto de decoracion y cuando lo probamos obtuvimos lo siguiente:

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

La decoracion funciona exitosamente pero al momento de querer obtener el nombre de la funcion en lugar de devolvernos el nombre de la funcion nos devuelve la funcion que genera el «envoltorio», para solucionar esto debemos hacer unas modificaciones a nuestro codigo anterior, tanto en la funcion f como en medicion veamos el nuevo codigo:

>>> from time import sleep, time
>>> from functools import wraps
>>> 
>>> def medicion(funcion):
...     @wraps(funcion)
...     def envoltorio(*args, **pcargs):
...             t = time()
...             funcion(*args, **pcargs)
...             print(funcion.__name__, "llevo:", time() - t)
...     return envoltorio
... 
>>> @medicion
... def f(descanso=0.1):
...     """ Tinchicus.com el mejor lugar para aprender """
...     sleep(descanso)
... 
>>>
Anuncios
Anuncios

En este caso la primera modificacion sera importar la funcion wraps del modulo functools, la siguiente modificacion sera en medicion donde implimentaremos a wraps para la funcion que recibiremos, esto impedira que la funcion original sea reemplazada por la funcion que la decora, el resto sigue siendo al caso anterior pero aqui viene otro cambio de lo mencionado en el post anterior, en lugar de definir la funcion y luego usar el decorador, pasamos primero el decorador con la arroba (@) y luego definimos a la funcion, en este caso la unica diferencia con respecto al anterior es que le agregamos un docstring para probar una cosa mas adelante, el resto es exactamente igual a la funcion como trabajaba antes, vamos a probarlo para ver como trabaja:

>>> f(0.2)
f llevo: 0.20052742958068848
>>> f(descanso=0.5)
f llevo: 0.5013518333435059
>>> print(f.__name__, f.__doc__)
f  Tinchicus.com el mejor lugar para aprender 
>>>
Anuncios

Ahora podemos ver que no solamente funciona correctamente sino que a su vez seguimos manteniendo el nombre de la funcion original gracias a wraps, tambien vemos que nos trajo la documentacion de la funcion, con esto pudimos solucionar el inconveniente del post anterior y pudimos ver como utilizar la declaracion de un decorador por medio de arroba, tomemos otro ejemplo.

Anuncios

En este caso crearemos un decorador multiple para no solamente seguir haciendo la medicion anterior sino que estableceremos un limite de valor de maximo para calcular el cubo de una funcion, primero vamos a crear la nueva funcion de medicion:

>>> def medicion(funcion):
...     @wraps(funcion)
...     def envoltorio(*args, **pcargs):
...             t = time()
...             resultado = funcion(*args, **pcargs)
...             print(funcion.__name__, "llevo:", time() - t)
...             return resultado
...     return envoltorio
... 
>>>
Anuncios
Nota: 
Recuerden importar las funcion sleep y time del modulo time y wraps del modulo functools
Anuncios

Esta funcion es muy parecida a la anterior pero su unica diferencia va a estar en que el resultado de la llamada a la funcion con los argumentos lo almacenaremos en una variable llamado resultado y antes de salir no solamente mostraremos el valor de la demora sino que devolveremos el objeto en resultado, y por ultimo devolvemos a envoltorio, agreguemos la siguiente funcion:

>>> def resultado_max(funcion):
...     @wraps(funcion)
...     def envoltorio(*args, **pcargs):
...             resultado = funcion(*args, **pcargs)
...             if resultado > 100:
...                     print('Resultado demasiado grande ({0})'
...                             .format(resultado),
...                             'Maximo permitido es 100.'
...                     )
...             return resultado
...     return envoltorio
... 
>>>
Anuncios
Anuncios

Este determinara un valor maximo, primero recibiremos la funcion como hasta ahora, volvemos a usar a wraps, despues creamos otra funcion envoltorio donde recibiremos los datos, volvemos a crear una variable llamada resultado donde almacenaremos el objeto creado por la funcion y los valores recibidos, en este tenemos un condicional donde verifica que resultado sea mayor a 100, en caso de ser verdadero nos muestra un mensaje que el valor maximo es de 100, lo siguiente es devolver el objeto en resultado y despues el objeto de envoltorio, con esto tenemos una funcion que nos hara la medicion del tiempo y otra que nos establece un valor maximo, ahora nos toca implementar la decoracion:

>>> @medicion
... @resultado_max
... def cubo(n):
...     return n ** 3
... 
>>>
Anuncios

Volvemos a implementar la definicion de decoradores por medio de la arroba, en este caso primero pasaremos a medicion y luego resultado_max porque para este caso nos interesa que la funcion trabaje sobre la funcion en si, nuestra funcion sera para calcular el cubo del valor informado, y unicamente devuelve ese valor, pero si lo ejecutamos veremos lo siguiente:

>>> cubo(3)
cubo llevo: 2.0503997802734375e-05
27
>>> cubo(5)
Resultado demasiado grande (125) Maximo permitido es 100
cubo llevo: 9.632110595703125e-05
125
>>>
Anuncios
Anuncios

Como pueden ver si hacemos el cubo del valor 3 nos devuelve el tiempo y luego el valor, despues volvemos a hacer el cubo pero esta vez del valor 5, en este caso como es mayor a 100 nos muestra el mensaje en pantalla y despues nos muestra lo que demoro y el valor, observen como resultado_max verifica lo devuelto por la funcion y en caso de cumplirse la condicion devuelve el mensaje de lo contrario no hace nada, con el objeto creado lo pasamos por medicion, aca unicamente recibimos el valor del objeto anterior, hacemos la medicion que haciamos anteriormente y mostramos el valor de resultado, por esta razon vemos el valor del cubo en todos los casos.

Anuncios

En resumen, hoy hemos completado decoradores, hemos visto cual es la herramienta que nos permite envolver a las funciones de nuestros decoradores, hemos visto un ejemplo de como trabaja y como trabaja unos decoradores multiples, espero les haya sido de utilidad 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
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.00