Booklet A4/A5 - PET: Python Entre Todos - Python Argentina
Booklet A4/A5 - PET: Python Entre Todos - Python Argentina
Booklet A4/A5 - PET: Python Entre Todos - Python Argentina
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Funciones decoradoras sin argumentos 49<br />
b. Con argumentos.<br />
2. Clases decoradoras<br />
a. Sin argumentos.<br />
b. Con argumentos.<br />
La llamada del callable en un decorador debe ser explícita, un decorador podría por<br />
ejemplo hacer que no se ejecute la función decorada.<br />
Ejemplo:<br />
def disable(callable):<br />
"""Decorates callable and prevents executing it."""<br />
def wrap(*args, **kwargs):<br />
logging.debug("{0} called but its execution "\<br />
"has been prevented".format(<br />
callable.__name__)<br />
)<br />
return wrap<br />
@disable<br />
def yes(string='y', end='\n'):<br />
[...]<br />
Funciones decoradoras sin argumentos<br />
En una función decoradora que no recibe argumentos su primer y único parámetro es<br />
el callable decorado en cuestión. Ya en la función anidada es dónde se reciben los<br />
argumentos posicionales y de palabra clave que se utilizaron para llamar al callable<br />
decorado.<br />
Esto puede verse en cualquiera de los decoradores mostrados anteriormente.<br />
Funciones decoradoras con argumentos<br />
Veremos ahora un ejemplo de función decoradora que recibe argumentos propios.<br />
Vamos a trabajar en un equivalente de log_callable que permita especificar si queremos<br />
contar o no el número de llamadas.<br />
<strong>Python</strong> <strong>Entre</strong> <strong>Todos</strong> (número 1, Agosto 2010) — http://revista.python.org.ar<br />
20 Concurrencia Indolora: el módulo multiprocessing<br />
# Esperamos un ratito, o hasta que termine el hilo,<br />
# lo que sea más corto.<br />
hilo.join(.3)<br />
print "Termina el programa"<br />
# Importante: los módulos no deberían ejecutar<br />
# código al ser importados<br />
if __name__ == '__main__':<br />
main()<br />
Sí, lo único que cambia es import threading por import multiprocessing y<br />
Process en vez de Thread. Ahora la función trabajador se ejecuta en un intérprete<br />
python separado. Como son procesos separados, usa tantos cores como procesos<br />
tengas, haciendo que el programa pueda ser mucho más rápido en una máquina<br />
moderna.<br />
Antes mencioné deadlocks. Tal vez creas que tener un poco de cuidado y poner locks<br />
alrededor de variables te evita esos problemas. Bueno, no. Veamos dos funciones f1 y<br />
f2 que necesitan usar dos variables x y y protegidas por locks lockx y locky:<br />
# -*- coding: utf-8 -*-<br />
import threading<br />
import time<br />
x = 4<br />
y = 6<br />
lock_x = threading.Lock()<br />
lock_y = threading.Lock()<br />
def f1():<br />
lock_x.acquire()<br />
time.sleep(2)<br />
lock_y.acquire()<br />
time.sleep(2)<br />
lock_x.release()<br />
lock_y.release()<br />
def f2():<br />
lock_y.acquire()<br />
time.sleep(2)<br />
<strong>Python</strong> <strong>Entre</strong> <strong>Todos</strong> (número 1, Agosto 2010) — http://revista.python.org.ar