13.01.2015 Views

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

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Clases decoradoras con argumentos 53<br />

[...]<br />

Clases decoradoras con argumentos<br />

Entendiendo bien los 3 casos de decoradores anteriores es posible inferir cómo sería<br />

una clase decoradora que recibe argumentos.<br />

Ejemplo de LogCallable con parámetro:<br />

class LogCallable(object):<br />

"""Decorates callable and logs information about it.<br />

Logs how many times the callable was called and the params it had.<br />

"""<br />

def __init__(self, do_count):<br />

self.do_count = do_count<br />

if not getattr(LogCallable, 'count_dict', None) and do_count:<br />

LogCallable.count_dict = {}<br />

def __call__(self, callable):<br />

def wrap(*args, **kwargs):<br />

callable(*args, **kwargs)<br />

message = []<br />

if self.do_count:<br />

LogCallable.count_dict.setdefault(<br />

callable.__name__, 0<br />

)<br />

LogCallable.count_dict[callable.__name__] += 1<br />

message.append(<br />

u"""called: '{0}' '{1} times'""".format(<br />

callable.__name__,<br />

LogCallable.count_dict[callable.__name__],<br />

)<br />

)<br />

<strong>Python</strong> <strong>Entre</strong> <strong>Todos</strong> (número 1, Agosto 2010) — http://revista.python.org.ar<br />

16 Administradores de contexto<br />

Nota: Sucede que todas las excepciones tienen una referencia a las variables locales de<br />

donde se produjo la excepción, pues es útil para los depuradores, y eso puede mantener<br />

vivas instancias, o resucitarlas.<br />

Así que C<strong>Python</strong>, muy al tanto de este problema, ignora las excepciones que intentan<br />

escapar de un destructor. Si el destructor no atrapa una excepción, no se elevará al<br />

código que “llamó” al destructor. Lo cual tiene sentido, porque el código que llamó al<br />

destructor lo hizo implícitamente, de casualidad, rara vez sabría atrapar la excepción.<br />

Otra forma de dejar escapar referencias a self que suele pasar desapercibida es al<br />

usar closures. Expresiones lambda como lambda x : self.atributo + x, tienen<br />

implícita una referencia a self, y si escapa esa expresión lambda también escapa self.<br />

Administradores de contexto<br />

Concluyendo, los destructores son útiles, cómodos, y difíciles de predecir. Hay que<br />

usarlos con cuidado, y siempre que asumamos que los destructores se llaman inmediatamente<br />

al dereferenciar una instancia, estaremos creando código que sólo funcionará<br />

correctamente en C<strong>Python</strong>.<br />

Para cerrar archivos, <strong>Python</strong> nos provee de una herramienta más predecible, y con<br />

soporte uniforme en todas las implementaciones del lenguaje: la sentencia with:<br />

>>> with open("archivito.txt", "r") as f:<br />

... # hacer algo<br />

... # no hace falta llamar a f.close(),<br />

... # se llama al salir del bloque 'with'<br />

No veremos los detalles de la sentencia with, pero cabe mencionar que no reemplaza<br />

a los destructores. Sólo reemplaza al uso que le dimos a los destructores en este<br />

artículo, o sea, para cerrar archivos. La sentencia tiene muchos otros usos, los invito<br />

a investigarla.<br />

<strong>Python</strong> <strong>Entre</strong> <strong>Todos</strong> (número 1, Agosto 2010) — http://revista.python.org.ar

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!