================= Python avanzado ================= :Autor: Alberto Bertogli (albertito@gmail.com) :Fecha: Sábado 7/Octubre/2006 .. footer:: Día de lenguajes · 7/Oct/2006 El plan! ======== - Mostrar los elementos avanzados del lenguaje. - Concentrarnos principalmente en su uso, no en sus mañas. - Ver las cosas locas que se pueden hacer, y la magia que hay detrás. - ¿Porque? - A todos les gustan las cosas locas. - Las fieras en su hábitat: control de complejidad. - Incrementar la calidad del código. ¿Como? ====== - Agregados sintácticos: - Operadores básicos. - Listas por comprensión. - Decorators. - Propiedades mágicas del lenguaje: - Introspección - Métodos especiales. - Interfaz de iteración. - Generators. - with statement. - Metaclases. - Mucha imaginación. Operadores básicos I ==================== - Por si no lo vieron a la mañana. - Todos los métodos mágicos se nombran de la forma *__metodo__*. - Las operaciones básicas se pueden sobrecargar: - \+ \- \* / // \*\* % - ^ \| & << >> ~ - Equivalentes in-place: \+= \-= ... - Igualdades y desigualdades varias - Nos permiten proveer sintaxis amistosa y legible para nuestros objetos. Operadores básicos II ===================== - Podemos abusarnos de la sintaxis clara. - Tener cuidado de no dar sorpresas. - Ejemplos: - Se usan mucho en las clases built-in. - Si extrañamos C++: **<<** y **>>** para I/O. - **\|** para paso de mensajes entre objetos onda Erlang. Listas por comprensión ====================== - Símil a expresar conjuntos por comprensión - Ejemplos:: [ x + 1 for x in l ] [ (x, y) for x in l1 for y in l2 ] [ f(x) for x in l] == map(f, l) [ x for x in l if f(x) ] == filter(f, l) [ f(x, y) for x in l1 for y in l2 if p1(x) and p2(x) ] Introspección I: Mirándose el ombligo ===================================== - Es poder obtener información en tiempo de ejecución acerca de los objetos. - Ejemplo clásico: preguntar por los parámetros de una función, la lista de atributos de un objeto, a que clase pertenece, etc. - Muy útil para aprender y debuggear. - Mas útil aún para meter mano de forma combinada con las otras cosas que vamos a ver. - Módulo inspect Introspección II: Un montón de espejos ====================================== - Ejemplos simples:: dir(thread) => [... 'stack_size', 'start_new', 'start_new_thread' ... ] isinstance(1, int) => True f.func_code.co_argcount => Cant. de args de f - Ejemplos clásicos: - Módulo pickle - Serialización de objetos para RPC - Ejemplos mas divertidos: - Módulo traceback - Módulo dis Métodos especiales I ==================== - Gran parte de la sintaxis normal termina en la invocación de métodos especiales. - Son como los operadores, solo que reflejan la sintaxis. - Los mas simples (usados para tipos onda *containers*): - **getitem**, **setitem** y **delitem** para *obj[key]* (*key* puede ser un objeto cualquiera, con sintaxis para slices). - **__contains__** para *if key in obj*. Métodos especiales II ===================== Emulando funciones ------------------ - La invocación es también un método! - *f(x) == f.__call__(x)* - Nos permite armar objetos que se puedan llamar como una función. - Podemos armar "wrappers" a funciones. - Ejemplo interesante: aplicación parcial (*functools.partial*) Métodos especiales III (a) ========================== Acceso a atributos I -------------------- - El acceso a los atributos también se hace a través de métodos. - El camino es un poco mas largo que con la ejecución de funciones, y no es el mismo para el get, set y delete. - Dibujin de get en la otra filmina. - Símil para set y del. Métodos especiales III (b) ========================== Acceso a atributos II --------------------- .. image:: attraccess.png Métodos especiales III (c) ========================== Acceso a atributos III ---------------------- - No es tan engorroso como parece, y solo lo usamos para cosas locas. - Ejemplos built-in: - Descriptors con property(). - staticmethod y classmethod (mas adelante). - Ejemplos: - Loguear todos los accesos a los métodos para debugging. - Restringir acceso a instancias de ciertas clases. - RPC transparente. Interfaz de iteración ===================== - Hay magia detrás del *for i in obj*. - Primero se le pide a *obj* que devuelva un *"objeto iterador"* usando el atributo *__iter__()*. - Después se va llamando al método *next()* del iterador. - Cuando no quedan mas items, se levanta una excepción *StopIteration* y el *for* termina de iterar. Generators I ============ - Se lo robamos a Ricky (aunque el les dice iterators). - La idea es la misma, tiramos cosas con *yield* hasta que cuando se agota levantamos *StopIteration* (o sale sola con *return*). - "Encajan" en la interfaz de iteración de forma natural - Generator expressions: *( (x, t(x)) for x in l if p(x) )* - Podemos "pasarle" cosas al generator con *.send()* y mandarle excepciones con *.throw()* - Ejemplos aparte Decorators I: ¿Que son? ======================= - Un decorator es una función normal. - Toma una función como parámetro, devuelve una función. - Se usa así:: def f(x): return x + 1 f = decorate(f) - Horrible, demasiado explicito, poco practico, difícil de leer. Decorators II: Belleza ====================== - Sintaxis linda para lo anterior:: @decorate def f(x): return x + 1 - Podemos apilarlos y pasarle parámetros (ojo con la evaluación):: @debug @dtag('minor') def f(...): ... - ¿Pero de que nos sirven? Decorators III: Aplicación ========================== - Son **muy** útiles. - Nos permiten todo tipo de triquiñuelas con una sintaxis agradable, combinando las otras cosas que vimos. - Algunos ejemplos clásicos: - staticmethod y classmethod (built-in). - Logueo y tracing de ejecución. - Checkeo de permisos de ejecución. - Algunos ejemplos apenas mas originales: - Ejecución condicional. - Ejecución asincronica con paso de mensajes. - Funciones lazy y "onda dataflow". with statement ============== - Nuevo en Python 2.5 - Permite cosas como:: with db.transaction() as trans: ... - Llama a *__enter__()* al entrar y a *__exit__()* al salir - Útil para transacciones, locks, y bloques donde se quiera efectuar un conjunto de acciones con algún objeto que deba ser notificado. Metaclases ========== - No vamos a llegar con tiempo para esto. - El 99% de los programadores de Python no lo usa nunca (de forma consciente). - Son las clases de las clases. Sirven para tener control acerca de como se crea una **clase**, y manipularla. - Ejemplos de uso simples: - Registrar una clase en un diccionario común. - Modificar los métodos y atributos. - Ejemplos de uso avanzados - SQLObject y SQLAlchemy Chau ==== .. class:: huge *¡Fin!* ¿Que sigue? ¡La noche de los museos!