HEL LENGUAJE DE PROGRAMACIÓNPYTHONJuan Ignacio Rodríguez de Leónjileon en twittereuribates @ gmail.comProgramación orienta...
Objetos y Clases Las clases permiten que podamos definirnuestros propios tipos de datos Las Clases definen las propiedas...
Objetos Un objeto es una variable querepresenta un caso particular dentro delconjunto de posibles instancias de unaclase...
Creación de clases Palabra reservada class La clase más sencilla que podemospensar es:>>> class X:... pass>>>>>> class X...
La clase Point Inicializador: Método con el nombreespecial __init__ No es el constructor, pero casiclass Point:def __ini...
¿self? Se crea el objeto. Inmediatamente a continuación, comohemos visto, se llama al inicializador– los dos parámetros ...
Para programadores de C++ o Java Para programadores de C++ o Java es lavariable "magica" this. En Python se prefirió est...
Seguimos con self Empezemos por la segunda pregunta:self representa al propio objeto reciencreado Este primer parámetro ...
Quien pone self ahí Al definir métodos para una clase, hayque reservar el primer parámetro para elpropio objeto Al llama...
Herencia Para poder hablar de clases y objetoscon propidad es necesario que hayaalgún tipo de herencia La herencia nos p...
Herencia simple Si una clase A deriva o hereda de unaclase B (o también se dice que la clase Bes una superclase de A):– E...
Como declarar herencia en Python La forma de expresar esta herencia enpython es>>> class A(B):... pass>>> class A(B):... ...
Características de la herencia Como los objetos instanciados de A tienen losmismos atributos y métodos que B, debenpoder ...
Polimorfismo A puede sobreescribir un método f() de B Si tenemos una lista con objetos de tipo A yde tipo B mezclados, p...
Métodos o atributos privados No existen en Python Existe una convención de uso, por la cualsi un atributo o método empie...
Beneficios de usar clases/objetos Reducir el tamaño del código evitandorepeticiones– Si organizamos las herencias correct...
super ¿Que pasa si A sobreescribe un método de B, peroaun así ha de invocarlo? En realidad es un caso muy común, A quier...
Funciones auxiliares isinstance(objeto, clase)– nos devolverá verdadero si el objeto es unainstancia de una clase en part...
Sobrecarga de operadores Se puede, como en C++, sobreescribirlos operadores (operadores aritméticos,acceso por índices, e...
Sobrecarga de operadores: len Si en nuestra clase definimos un método__len__(), podemos hacer que lasinstancias de esa cl...
Sobrecarga de operadores: índices Si a una clase le añadimos los métodos__setitem__ y __getitem__ podemoshacer que se com...
class A:_Tabla = {0: ninguno, 1: uno, 2: dos,3: tres, 4: cuatro, 5: cinco,6: umm... seis,}def __len__(self):return 7 # por...
Sobrecarga de operadores: +/- Supongamos que queremos escribir un módulo deálgebra lineal y que definimos la clase Vector...
class Vector:def __init__(self, x, y):self.x = xself.y = ydef __str__(self):return Vector({}, {}).format(self.x, self.y)de...
Sobrecarga de operadores: +/- Para eso definimos los métodosespeciales __add__ y __sub__ paradefinir el comportamiento cu...
Excepciones Errores sintáctis y excepciones Información del error Las excepciones se producen durante laejecución– Pued...
Tipos de excepciones Según el error ZeroDivisionError, ValueError, etc... Como capturar excepciones: try/excepttry:a, b...
Tratamiento de excepciones Puede haber varias cláusulas except,para cada tipo de error Una cláusula puede gestionar vari...
else en clausulas try/except Similar al else del for/while El código del else se ejecuta si y solo si:– Se han ejecutado...
Argumento de la excepción La excepción se representa con un valor que tiene losdetalles del error Usando la palabra rese...
Legibilidad del códigocon excepciones Los programas en C suelen consistir enuna serie de llamadas a funcionesintercaladas...
Elevar excepciones Podemos elevar nosotros mismosexcepciones, usando la palabrareservada raise Podemos definir nuestras ...
Finally Cláusula final, que se ejecutará siempre Se hayan producido o no excepciones Uso habitual:– Liberación de recur...
Gestores de contexto: with with nos permite "envolver" un bloque decódigo con operaciones a ejecutar antes ydespués del m...
Más clarotry:f = open(fichero.datos, r)# proceso el ficheron = len(f.readlines())finally:f.close()try:f = open(fichero.dat...
Como funciona with (1) Usando Gestores de contexto Son objetos que saben lo que hay quehacer antes y después de usar otr...
Como funciona with (2)1) Evaluación y obtención del gestor decontexto2) Se carga __exit__()3) Se ejecuta __enter__() (si d...
Iteradores Nuestras clases y objetos pueden seriterables Como funciona for internamente:– Se llama a iter() pasándole lo...
Ejemplo>>> s = abc>>> it = iter(s)>>> it<iterator object at 0x00A1DB50>>>> it.next()a>>> it.next()b>>> it.next()c>>> it.ne...
Es fácil añadir “iterabilidad” Definir un método con el nombre__iter__() que devuelva un objeto Este objeto debe impleme...
Ejercicio Crear una clase CuentaAtras, que seaiterable y que, ejem, cuente hacia atráshasta llegar al cero.
Soluciónclass CuentaAtras:def __init__(self, tope):self.tope = topedef __iter__(self):self.counter = self.topereturn selfd...
Generadores Forma sencilla y potente de crear iteradores Como una función, pero devuelven resultados conyield, en vez de...
Cuenta Atras (como generador)>>> def cuenta_atras(n):... while n >= 0:... yield n... n -= 1...>>> for i in cuenta_atras(5)...
Ventajas Igual potencia que un iterador Solo por usar yield ya se sabe que esun generador Normalmente más fáciles de es...
Ejemplos degeneradores/iteradores El módulo os.path, como veremos másadelante, tiene una función walk, que esun generador...
Ejemplo de combinaciones Combinaciones tomando los cuatroelementos ABCD– De uno en uno:● A, B, C, D– De dos en dos:● AB, ...
La Fiscalia Anticorrupciónnos pide ayuda
Ajustar cuentas Estan investigando un casode un ex-tesorero y unadoble facturación Hay una serie de ingresospor un lado...
Los ingresos1910.00 €4090.20 €1945.45 €
Los pagos1404.93 €207.68 €297.39 €1816.42 €153.56 €1286.85 €322.90 €175.04 €335.43 €259.74 €301.28 €1384.43 €
¿Como podemos hacerlo? Empezar por uno de los ingresos– Tomar las combinaciones de pagos ytomarlas de una en una. Ver si ...
Herramientas Conseguir las combinaciones usandoitertoos.combinations. La función sum() nos suma loselementos de una secu...
facturacion_b.py (1)from decimal import Decimalimport itertoolsingresos = [Decimal(4090.20),Decimal(1910.00),Decimal(1945....
facturacion_b.py (2)for ingreso in ingresos:solucion = Nonefor size in range(1, len(pagos)+1):# Probando combinaciones de ...
Solución1816.42 + 153.56+ 1286.85 + 322.9+ 175.04 + 335.43 = 4090.201404.93 + 207.68 + 297.39 = 1910.00259.74 + 301.28 + 1...
Programación funcional Las funciones solo son otro tipo devariable Todo lo que se puede hacer con unavariable, se puede ...
Funciones Lambda λ Crear pequeñas funciones anónimas lambda <argumentos>: <expresion> Función que suma los dos parámetr...
filter Primer parámetro: una función Segundo parámetro: una secuencia Devuelve: otra secuencia en la que seestan sólo a...
EjemploCalcular los primeros 200números que son divisiblespor 5 y por 7
los primeros 200 númerosque son divisibles por 5 y por 7>>> def div57(x):... return x % 5 == 0 and x % 7 == 0...>>> for i ...
map Primer parámetro: una función Segundo parámetro: una secuencia Devuelve: otra secuencia, compuestapor los resultado...
cubos de los 10 primeros números>>> def cube(x): return x*x*x...>>> map(cube, range(1, 11))[1, 8, 27, 64, 125, 216, 343, 5...
map (2) Podemos pasar más de una secuencia La función pasada como parámetrodebe aceptar tantos parámetros comosecuencias...
media de los datos de dos listas>>> l1 = [123, 45, 923, 2, -23, 55]>>> l2 = [9, 35, 87, 75, 39, 7]>>> def media(a, b): ret...
reduce Primer parámetro: una función Segundo parámetro: una secuencia Devuelve: un único valor– la función que se pasa ...
Ejercicio: sumar los valoresde una lista
Ejercicio: sumar los valoresde una lista>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>>>>>>> def s...
Ejercicio: sumar los valoresde una lista>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>>>>>>> def s...
Ejercicio: sumar los valoresde una lista>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>>>>>>> def s...
Compresión de listas Forma muy expresiva de crear listas Usos comunes– Crear una lista cuyos elementos son resultadode a...
10 Números cuadrados Podemos crear una lista con loscuadrados de los 10 primeros númerosasí:>>> squares = []>>> for x in ...
10 Números cuadrados O así, con mapsquares = map(lambda x: x**2, range(10))squares = map(lambda x: x**2, range(10))
10 Números cuadrados Con comprensión de listas es aun másfácilsquares = [x**2 for x in range(11)]squares = [x**2 for x in...
Anatomía de una C.L. Corchete [ Expresión Cláusula for Cero, una o más cláusulas if Corchete ]
Ejercicio ¿Cuáles de los primeros 1500 númerosenteros cumplen la condición de que sucubo acaba en 272?– str() convierte u...
Respuesta[x for x in range(501) if str(x**3).endswith(272)][x for x in range(501) if str(x**3).endswith(272)][238, 488][23...
Expresiones generadoras Muy similar a una conprensión de lista Pero devuelve un generador, no una lista La sintaxis es ...
Ejemplo>>> s = [x**2 for x in range(11)]>>> s # es una lista[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]>>> s = (x**2 for x i...
Comprensión de diccionarios Crear diccionarios a partir de otrasfuentes de datos Sintaxis similar, pero cambiandocorchet...
Ejemplos>>> d = {x:x**2 for x in range(5)}>>> d{1: 1, 0: 0, 3: 9, 2: 4, 4: 16}>>> d = {x:x**2 for x in range(5) if x % 2 =...
Conprensión de conjuntos Definir un conjunto a partir de otrosvalores Igual que con los diccionarios, pero laexpresión n...
Ejemplo>>> s = {a, b, c}>>> sset([a, c, b])>>> s = {str(x**2) for x in range(7)}>>> type(s)<type set>>>> sset([25, 16, 36,...
Decoradores Funciones como objetos de primer nivel Las funciones se pueden almacenar,pasar como parámetros... … o ser d...
Suena raro...Una función …… puede devolver …… otra función
No es tan raro, veamos un ejemplo>>> def dame_una_funcion_incremento(inc):... def funcion_a_retornar(x):... return x + inc...
¿Qué es un decorador? Sabiendo que esto es posible, undecorador es:– Una función que acepta como parámetrouna función, y ...
Referencia friki totalmente gratuita
¿Para qué sirve un decorador? El uso de decoradores se enfoca aresolver el siguiente problema:– Tenemos un conjunto de fu...
Ejemplo de situación Supongamos que tenemos un conjuntode funciones a(), b(),..., z(), cada unade ellas con sus parámetro...
Opción A (de “A lo bruto”)Reescribir cada una de las funcionesdef a():# código de adef a():# código de aPasar de esto:def ...
Pegas de la opción A Sencillo, pero trabajoso Hay que reescribir mucho código El tamaño del código aumenta La lógica d...
Opción D (De “decoradores”) Intenta solucionar estos problemas Un decorador coge las función original,(a(), b(),..., z()...
Decorador “logged” Para el ejemplo de log, primero creamosuna función decoradora, que llamaramoslogged() Para simplifica...
Código de loggeddef logged(func):def inner(* args, **kwargs):print(Empieza la función {}.format(func.__name__))func(*args,...
Aplicación del decoradordef a(): print(Soy a())def b(): print(Soy b())b = logged(b)@loggeddef c(): print(Soy c())@loggedde...
Aplicación de decoradoresLa forma:@loggeddef c(): print(Soy c())@loggeddef c(): print(Soy c())Es azucar sintáctico para:de...
Ventaja de los decoradores Hay que tocar el código de cada función, si, pero elcambio es mínimo: añadir el decorador con ...
02 python Programación orientada a objetos y funcional
Upcoming SlideShare
Loading in …5
×

02 python Programación orientada a objetos y funcional

1,260 views

Published on

Taller Python IAC: Programación orientada a objetos y funcional con Python

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,260
On SlideShare
0
From Embeds
0
Number of Embeds
65
Actions
Shares
0
Downloads
77
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

02 python Programación orientada a objetos y funcional

  1. 1. HEL LENGUAJE DE PROGRAMACIÓNPYTHONJuan Ignacio Rodríguez de Leónjileon en twittereuribates @ gmail.comProgramación orientada a objetosProgramación funcional
  2. 2. Objetos y Clases Las clases permiten que podamos definirnuestros propios tipos de datos Las Clases definen las propiedases(atributos) y las capacidades ycomportamiento (métodos) general delos nuevos tipos Un objeto se crea o instancia a partir deuna clase
  3. 3. Objetos Un objeto es una variable querepresenta un caso particular dentro delconjunto de posibles instancias de unaclase De la misma forma que podemosconsiderar al número 7 como unainstancia particular de la clase NumerosEnteros
  4. 4. Creación de clases Palabra reservada class La clase más sencilla que podemospensar es:>>> class X:... pass>>>>>> class X:... pass>>> Instanciamos un objeto usando elnombre de la clase como si fuera unafunción:>>> x = X()>>> print(x)>>> x = X()>>> print(x)
  5. 5. La clase Point Inicializador: Método con el nombreespecial __init__ No es el constructor, pero casiclass Point:def __init__(self, lat, lng):self.latitud = latself.longitud = lngx = Point(28.4779, -16.3118)print(x.latitud, x.longitud)class Point:def __init__(self, lat, lng):self.latitud = latself.longitud = lngx = Point(28.4779, -16.3118)print(x.latitud, x.longitud)
  6. 6. ¿self? Se crea el objeto. Inmediatamente a continuación, comohemos visto, se llama al inicializador– los dos parámetros que usamos al crear alobjeto son los mismos valores que se pasanal método inicializador con los nombres laty lng Pero ¿De donde sale el primerparámetro, self? ¿Y qué representa?
  7. 7. Para programadores de C++ o Java Para programadores de C++ o Java es lavariable "magica" this. En Python se prefirió esta forma porconsiderarla más explicita. De igual manera, los atributos dentro dela función tienen que venir precedidospor el self., no hay alias mágicos paralos atributos de la instancia, para evitarla ambigüedad.
  8. 8. Seguimos con self Empezemos por la segunda pregunta:self representa al propio objeto reciencreado Este primer parámetro es lo quediferencia a las funciones que yaconociamos de los métodos:– un método siempre tienen como primerparámetro la instancia sobre la que estásiendo ejecutado.
  9. 9. Quien pone self ahí Al definir métodos para una clase, hayque reservar el primer parámetro para elpropio objeto Al llamar al método desde la instancia,Python ya se ocupa de poner el valorcorrecto como primer parámetro La tradición y la costumbre marcan queeste primer parámetro se llame self,pero en realidad no existe obligación dehacerlo (pero es conveniente hacerlo,por legibilidad)
  10. 10. Herencia Para poder hablar de clases y objetoscon propidad es necesario que hayaalgún tipo de herencia La herencia nos permite definir una clasea base de refinar o modificar otra(herencia simple) u otras (herenciamúltiple)
  11. 11. Herencia simple Si una clase A deriva o hereda de unaclase B (o también se dice que la clase Bes una superclase de A):– Entonces la clase A dispondrá, de entrada,de todos los atributos y métodos de B– Pero puede añadir más atributos y métodose incluso modificar o borrar los que haheredado.
  12. 12. Como declarar herencia en Python La forma de expresar esta herencia enpython es>>> class A(B):... pass>>> class A(B):... pass Si la clase modifique un método que haheredado, se dice que ha reescrito osobreescrito (override) el método.
  13. 13. Características de la herencia Como los objetos instanciados de A tienen losmismos atributos y métodos que B, debenpoder ser ser usados en cualquier sitio dondese use una instacia de B Entre A y B hay una relación es un tipo de– B es un caso general de A– O,si se prefiere, A es una especializacion de B
  14. 14. Polimorfismo A puede sobreescribir un método f() de B Si tenemos una lista con objetos de tipo A yde tipo B mezclados, podemos invocar sinmiedo el método f() en todos ellos, con laseguridad de que en cada caso se invocará almétodo adecuado. Esta capacidad se llama polimorfismo (delgriego Múltiples Formas)
  15. 15. Métodos o atributos privados No existen en Python Existe una convención de uso, por la cualsi un atributo o método empieza con elcarácter subrayado, ha de entenderseque:– Es de uso interno– No deberías jugar con él a no ser que sepasmuy bien lo que estás haciendo– Si en un futuro tu código deja de funcionarporque has usado ese atributo o método, nopuedes culpar a nadie más que a ti mismo
  16. 16. Beneficios de usar clases/objetos Reducir el tamaño del código evitandorepeticiones– Si organizamos las herencias correctamenteen jerarquias, de mas genéricas a másespecíficas, podemos compatibilizar elcódigo común de las primeras con el másespecífico de las últimas Encapsulamiento Polimorfismo Delegación de responsabilidades
  17. 17. super ¿Que pasa si A sobreescribe un método de B, peroaun así ha de invocarlo? En realidad es un caso muy común, A quiere hacerlo mismo que B, y un poquito más. Desde Python 2.2 hay una función super() quenos ayuda a invocar el código de la clase (o clases)de la que derivamos.class A(B):def f(self, arg):super(A, self).f(arg)...class A(B):def f(self, arg):super(A, self).f(arg)...class A(B):def f(self, arg):super().f(arg)class A(B):def f(self, arg):super().f(arg)Python 2.x Python 3.x
  18. 18. Funciones auxiliares isinstance(objeto, clase)– nos devolverá verdadero si el objeto es unainstancia de una clase en particular, o dealguna de sus subclases issubclass(objeto, clase)– nos devolverá verdadero si el objeto es unainstancia de una subclase de la claseindicada.
  19. 19. Sobrecarga de operadores Se puede, como en C++, sobreescribirlos operadores (operadores aritméticos,acceso por índices, etc...) mediante unasintaxis especial Los métodos y atributos que empiezan yacaban con un doble signo de subrayadotiene por lo general un significadoespecial.
  20. 20. Sobrecarga de operadores: len Si en nuestra clase definimos un método__len__(), podemos hacer que lasinstancias de esa clase puedan serusadas con la función len() Véase ejemplos/clases_02.py
  21. 21. Sobrecarga de operadores: índices Si a una clase le añadimos los métodos__setitem__ y __getitem__ podemoshacer que se comporte como si fuerauna contenedor accesible mediante lasoperaciones de índices
  22. 22. class A:_Tabla = {0: ninguno, 1: uno, 2: dos,3: tres, 4: cuatro, 5: cinco,6: umm... seis,}def __len__(self):return 7 # por la caradef __getitem__(self, index):if 0 <= index < 7:return self._Tabla[index]else:return Muchosdef __setitem__(self, index, value):passclass A:_Tabla = {0: ninguno, 1: uno, 2: dos,3: tres, 4: cuatro, 5: cinco,6: umm... seis,}def __len__(self):return 7 # por la caradef __getitem__(self, index):if 0 <= index < 7:return self._Tabla[index]else:return Muchosdef __setitem__(self, index, value):passEjemplos/clases_03.py
  23. 23. Sobrecarga de operadores: +/- Supongamos que queremos escribir un módulo deálgebra lineal y que definimos la clase Vector Podríamos crear una función independiente parasumar vectores:v1 = Vector(2, 3)v2 = Vector(-4, 2)v3 = suma_vector(v1, v2)v1 = Vector(2, 3)v2 = Vector(-4, 2)v3 = suma_vector(v1, v2)● Pero es claramente mejor, más legible y bonito, poderhacerv3 = v1 + v2v3 = v1 + v2
  24. 24. class Vector:def __init__(self, x, y):self.x = xself.y = ydef __str__(self):return Vector({}, {}).format(self.x, self.y)def __add__(self, other):return Vector(self.x + other.x,self.y + other.y)def __sub__(self, other):return Vector(self.x - other.x,self.y - other.y)class Vector:def __init__(self, x, y):self.x = xself.y = ydef __str__(self):return Vector({}, {}).format(self.x, self.y)def __add__(self, other):return Vector(self.x + other.x,self.y + other.y)def __sub__(self, other):return Vector(self.x - other.x,self.y - other.y)ejemplos/clases_04.py
  25. 25. Sobrecarga de operadores: +/- Para eso definimos los métodosespeciales __add__ y __sub__ paradefinir el comportamiento cuando sesumen o resten dos instancias de nuestaclase. Véase ejemplos/clases_04.py Existen muchos métodos especiales A Guide to Pythons Magic Methods:– http://www.rafekettler.com/magicmethods.html
  26. 26. Excepciones Errores sintáctis y excepciones Información del error Las excepciones se producen durante laejecución– Pueden ser tratadas: “capturadas”– Si no se capturan, el programa acaba
  27. 27. Tipos de excepciones Según el error ZeroDivisionError, ValueError, etc... Como capturar excepciones: try/excepttry:a, b = 7, 0c = a / bexcept ZeroDivisionError:print("No puedo dividir por cero")try:a, b = 7, 0c = a / bexcept ZeroDivisionError:print("No puedo dividir por cero")
  28. 28. Tratamiento de excepciones Puede haber varias cláusulas except,para cada tipo de error Una cláusula puede gestionar varioserrores Puede haber una clausula exceptgeneral (No recomendado) Podemos volver a “elevar” la excepcionque hemos capturado
  29. 29. else en clausulas try/except Similar al else del for/while El código del else se ejecuta si y solo si:– Se han ejecutado todas las líneas del try– No se ha producido ninguna excepción
  30. 30. Argumento de la excepción La excepción se representa con un valor que tiene losdetalles del error Usando la palabra reservada as podemos almacenareste valor Captura errores en las llamadas a funciones>>> def esto_falla():... x = 1/0...>>> try:... esto_falla()... except ZeroDivisionError as detail:... print(Detectado error, detail)...Detectado error: division by zero>>>>>> def esto_falla():... x = 1/0...>>> try:... esto_falla()... except ZeroDivisionError as detail:... print(Detectado error, detail)...Detectado error: division by zero>>>
  31. 31. Legibilidad del códigocon excepciones Los programas en C suelen consistir enuna serie de llamadas a funcionesintercaladas con comprobaciones deresultados Con excepciones:– La gestión de los errores no se entrometecon la función del algoritmo– Está centralizada y aparte
  32. 32. Elevar excepciones Podemos elevar nosotros mismosexcepciones, usando la palabrareservada raise Podemos definir nuestras propiasexcepciones– Derivadas de Exception– Jerarquía de excepciones
  33. 33. Finally Cláusula final, que se ejecutará siempre Se hayan producido o no excepciones Uso habitual:– Liberación de recursos– Operaciones de limpieza– Cualquier código que tenga que ejecutarse"si ó si"
  34. 34. Gestores de contexto: with with nos permite "envolver" un bloque decódigo con operaciones a ejecutar antes ydespués del mismo Simetría en las operaciones Garantía de ejecución Se pueden anidar Ejemplos– ficheros: open/close– memoria: malloc/free
  35. 35. Más clarotry:f = open(fichero.datos, r)# proceso el ficheron = len(f.readlines())finally:f.close()try:f = open(fichero.datos, r)# proceso el ficheron = len(f.readlines())finally:f.close()with open(fichero.datos, r) as f:... # proceso el fichero... n = len(f.readlines())with open(fichero.datos, r) as f:... # proceso el fichero... n = len(f.readlines())En vez de hacer esto:Hacemos esto:
  36. 36. Como funciona with (1) Usando Gestores de contexto Son objetos que saben lo que hay quehacer antes y después de usar otroobjeto El generador de contexto de file sabeque hay que cerrar el archivo Imposible olvidarse de cerrarlo
  37. 37. Como funciona with (2)1) Evaluación y obtención del gestor decontexto2) Se carga __exit__()3) Se ejecuta __enter__() (si devuelve unvalor y se ha usado as, se asigna a lavariable)4) Se ejecuta el bloque5) Se llama a __exit__() (con informaciónde errores, si hubiera)
  38. 38. Iteradores Nuestras clases y objetos pueden seriterables Como funciona for internamente:– Se llama a iter() pasándole lo que quieraque sea que vamos a iterar– Obtenemos un iterador, es decir, un objetocon un metodo next()– Llamamos a next() repetidas veces...– Hasta que termina: se eleva StopIteration
  39. 39. Ejemplo>>> s = abc>>> it = iter(s)>>> it<iterator object at 0x00A1DB50>>>> it.next()a>>> it.next()b>>> it.next()c>>> it.next()Traceback (most recent call last):File "<stdin>", line 1, in ?it.next()StopIteration>>> s = abc>>> it = iter(s)>>> it<iterator object at 0x00A1DB50>>>> it.next()a>>> it.next()b>>> it.next()c>>> it.next()Traceback (most recent call last):File "<stdin>", line 1, in ?it.next()StopIteration
  40. 40. Es fácil añadir “iterabilidad” Definir un método con el nombre__iter__() que devuelva un objeto Este objeto debe implementar un métodonext()– Cada vez que se llame a next(), este debedevolver el siguiente elemento– A no ser que no queden, entonces, elevaStopIteration Nuestra clase puede ser su propio iterador:basta con definir next() y en __iter__devolver self
  41. 41. Ejercicio Crear una clase CuentaAtras, que seaiterable y que, ejem, cuente hacia atráshasta llegar al cero.
  42. 42. Soluciónclass CuentaAtras:def __init__(self, tope):self.tope = topedef __iter__(self):self.counter = self.topereturn selfdef next(self): return self.__next__() # python 2.7def __next__(self):result = self.counterself.counter -= 1if result < 0:raise StopIterationreturn resultclass CuentaAtras:def __init__(self, tope):self.tope = topedef __iter__(self):self.counter = self.topereturn selfdef next(self): return self.__next__() # python 2.7def __next__(self):result = self.counterself.counter -= 1if result < 0:raise StopIterationreturn result
  43. 43. Generadores Forma sencilla y potente de crear iteradores Como una función, pero devuelven resultados conyield, en vez de return Cada vez que se llama a next(), el generadorcontinua a partir de donde se quedó Recuerda su estado: valores de las variables,última línea que se ejecutó, etc...
  44. 44. Cuenta Atras (como generador)>>> def cuenta_atras(n):... while n >= 0:... yield n... n -= 1...>>> for i in cuenta_atras(5): print(i)...543210>>>>>> def cuenta_atras(n):... while n >= 0:... yield n... n -= 1...>>> for i in cuenta_atras(5): print(i)...543210>>>
  45. 45. Ventajas Igual potencia que un iterador Solo por usar yield ya se sabe que esun generador Normalmente más fáciles de escribir Generación automática de next() y de__iter__() Eleva automáticamente StopIteration
  46. 46. Ejemplos degeneradores/iteradores El módulo os.path, como veremos másadelante, tiene una función walk, que esun generador que nos permite recorrerun árbol de directorios El módulo itertools define una funcioncombinations que nos da lascombinaciones de m elementostomandos de n en n
  47. 47. Ejemplo de combinaciones Combinaciones tomando los cuatroelementos ABCD– De uno en uno:● A, B, C, D– De dos en dos:● AB, AC, AD, CB, CD, BD– De tres en tres:● ACB, ACD, ABD, CBD– De cuatro en cuatro:● ABCD
  48. 48. La Fiscalia Anticorrupciónnos pide ayuda
  49. 49. Ajustar cuentas Estan investigando un casode un ex-tesorero y unadoble facturación Hay una serie de ingresospor un lado Y una serie de pagos por otro Demostrar que la serie depagos se corresponden,sumadas, con los ingresos.
  50. 50. Los ingresos1910.00 €4090.20 €1945.45 €
  51. 51. Los pagos1404.93 €207.68 €297.39 €1816.42 €153.56 €1286.85 €322.90 €175.04 €335.43 €259.74 €301.28 €1384.43 €
  52. 52. ¿Como podemos hacerlo? Empezar por uno de los ingresos– Tomar las combinaciones de pagos ytomarlas de una en una. Ver si sumadascoinciden con el ingreso– Tomar las combinaciones de pagos ytomarlas de dos en dos. Ver si sumadascoinciden con el ingreso– Seguir asi buscando combinaciones hastaque una coincida. Cuando se encuentra,retirar esos pagos de la lista de pagos yseguir con el siguiente ingreso
  53. 53. Herramientas Conseguir las combinaciones usandoitertoos.combinations. La función sum() nos suma loselementos de una secuencia Empezar con una versión minima delproblema: 2 ingresos, 4 pagos, porejemplo. Solución en:– ejemplos/facturacion_b.py
  54. 54. facturacion_b.py (1)from decimal import Decimalimport itertoolsingresos = [Decimal(4090.20),Decimal(1910.00),Decimal(1945.45),]pagos = [Decimal(1404.93), Decimal(207.68), Decimal(297.39),Decimal(1816.42), Decimal(153.56), Decimal(1286.85),Decimal(322.9), Decimal(175.04), Decimal(335.43),Decimal(259.74), Decimal(301.28), Decimal(1384.43),]from decimal import Decimalimport itertoolsingresos = [Decimal(4090.20),Decimal(1910.00),Decimal(1945.45),]pagos = [Decimal(1404.93), Decimal(207.68), Decimal(297.39),Decimal(1816.42), Decimal(153.56), Decimal(1286.85),Decimal(322.9), Decimal(175.04), Decimal(335.43),Decimal(259.74), Decimal(301.28), Decimal(1384.43),]
  55. 55. facturacion_b.py (2)for ingreso in ingresos:solucion = Nonefor size in range(1, len(pagos)+1):# Probando combinaciones de size elementosfor a_probar in itertools.combinations(pagos, size):if sum(a_probar) == ingreso:print(Encontrada una solución:)solucion = tuple(a_probar)print(*[{0:f}.format(d) for d in solucion],sep= + ,end= = )print(ingreso)breakif solucion:for pago in solucion:pagos.remove(pago)for ingreso in ingresos:solucion = Nonefor size in range(1, len(pagos)+1):# Probando combinaciones de size elementosfor a_probar in itertools.combinations(pagos, size):if sum(a_probar) == ingreso:print(Encontrada una solución:)solucion = tuple(a_probar)print(*[{0:f}.format(d) for d in solucion],sep= + ,end= = )print(ingreso)breakif solucion:for pago in solucion:pagos.remove(pago)
  56. 56. Solución1816.42 + 153.56+ 1286.85 + 322.9+ 175.04 + 335.43 = 4090.201404.93 + 207.68 + 297.39 = 1910.00259.74 + 301.28 + 1384.43 = 1945.45
  57. 57. Programación funcional Las funciones solo son otro tipo devariable Todo lo que se puede hacer con unavariable, se puede hacer con una función:– funciones como parámetros– funciones dentro de estructuras de datos– funciones como resultados “Las funciones son objetos de primeraclase”
  58. 58. Funciones Lambda λ Crear pequeñas funciones anónimas lambda <argumentos>: <expresion> Función que suma los dos parámetrosque se le pasan:– lambda(x,y): x+y No hace falta especificar return Azucar sintáctico para una definición defunción normal
  59. 59. filter Primer parámetro: una función Segundo parámetro: una secuencia Devuelve: otra secuencia en la que seestan sólo aquellos valores de lasecuencia original para los que elresultado de aplicarles la función esTrue
  60. 60. EjemploCalcular los primeros 200números que son divisiblespor 5 y por 7
  61. 61. los primeros 200 númerosque son divisibles por 5 y por 7>>> def div57(x):... return x % 5 == 0 and x % 7 == 0...>>> for i in filter(div57, range(1, 201)):... print(i)...3570105140175>>>>>> def div57(x):... return x % 5 == 0 and x % 7 == 0...>>> for i in filter(div57, range(1, 201)):... print(i)...3570105140175>>>
  62. 62. map Primer parámetro: una función Segundo parámetro: una secuencia Devuelve: otra secuencia, compuestapor los resultados de llamar a la funciónen cada uno de los elementos de lasecuencia original
  63. 63. cubos de los 10 primeros números>>> def cube(x): return x*x*x...>>> map(cube, range(1, 11))[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]>>>>>> def cube(x): return x*x*x...>>> map(cube, range(1, 11))[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]>>>
  64. 64. map (2) Podemos pasar más de una secuencia La función pasada como parámetrodebe aceptar tantos parámetros comosecuencias haya Ejercicio: media de los datos de otrasdos listas
  65. 65. media de los datos de dos listas>>> l1 = [123, 45, 923, 2, -23, 55]>>> l2 = [9, 35, 87, 75, 39, 7]>>> def media(a, b): return (a + b) / 2...>>> map(media, l1, l2)[66.0, 40.0, 505.0, 38.5, 8.0, 31.0]>>>>>> l1 = [123, 45, 923, 2, -23, 55]>>> l2 = [9, 35, 87, 75, 39, 7]>>> def media(a, b): return (a + b) / 2...>>> map(media, l1, l2)[66.0, 40.0, 505.0, 38.5, 8.0, 31.0]>>>
  66. 66. reduce Primer parámetro: una función Segundo parámetro: una secuencia Devuelve: un único valor– la función que se pasa como parámetro tieneque aceptar dos valores, y retornar uno– Se calcula el resultado de aplicar la función a losdos primeros valores de la secuencia– A continuación, se aplica de nuevo la función,usando como parámetros el dato anterior y altercer elemento de la secuencia– Así hasta acabar la secuencia original
  67. 67. Ejercicio: sumar los valoresde una lista
  68. 68. Ejercicio: sumar los valoresde una lista>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>
  69. 69. Ejercicio: sumar los valoresde una lista>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>Suma(1,2) = 3Suma(3,3) = 6Suma(6,4) = 10Suma(10,5) = 15Suma(15,6) = 21Suma(21,7) = 28Suma(28,8) = 36Suma(36,9) = 45Suma(45,10) = 55
  70. 70. Ejercicio: sumar los valoresde una lista>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>>>>>>> def suma(x,y): return x+y...>>> reduce(suma, range(1, 11))55>>>No se debe usar este modo de realizar sumas,porque esta es una necesidad tan común que yaexiste una función incorporada para ello:sum(seq), que funciona exactamente igual, peromás rápido al estár implementada en C.
  71. 71. Compresión de listas Forma muy expresiva de crear listas Usos comunes– Crear una lista cuyos elementos son resultadode aplicar una serie de operaciones a otrasecuencia– Crear una sebsecuencia de aquellos elementosque cumplan una determinada condición En resumen, nos permiten hacer lo mismoque map o filter, pero de forma máslegible.
  72. 72. 10 Números cuadrados Podemos crear una lista con loscuadrados de los 10 primeros númerosasí:>>> squares = []>>> for x in range(11):... squares.append(x**2)...>>> squares[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]>>>>>> squares = []>>> for x in range(11):... squares.append(x**2)...>>> squares[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]>>>
  73. 73. 10 Números cuadrados O así, con mapsquares = map(lambda x: x**2, range(10))squares = map(lambda x: x**2, range(10))
  74. 74. 10 Números cuadrados Con comprensión de listas es aun másfácilsquares = [x**2 for x in range(11)]squares = [x**2 for x in range(11)]
  75. 75. Anatomía de una C.L. Corchete [ Expresión Cláusula for Cero, una o más cláusulas if Corchete ]
  76. 76. Ejercicio ¿Cuáles de los primeros 1500 númerosenteros cumplen la condición de que sucubo acaba en 272?– str() convierte un número en texto– endswith() es un metodo de los textos quedevuelve True si la cadena de texto sobre laque se aplica acaba en el texto indicadocomo parámetro:● hola.endswith(a) → True
  77. 77. Respuesta[x for x in range(501) if str(x**3).endswith(272)][x for x in range(501) if str(x**3).endswith(272)][238, 488][238, 488]
  78. 78. Expresiones generadoras Muy similar a una conprensión de lista Pero devuelve un generador, no una lista La sintaxis es idéntica, sustituyendo loscorchetes por paréntesis– con la lista obtenemos todos los elementosya generados (y, por tanto, consumiendomemoria)– El generador nos irá dando los valores deuno en uno (lazy evaluation)
  79. 79. Ejemplo>>> s = [x**2 for x in range(11)]>>> s # es una lista[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]>>> s = (x**2 for x in range(11))>>> s # es un generador<generator object <genexpr> at 0xb74588ec>>>> s.next()0>>> for i in s: print(i)...14[...]81100>>>>>> s = [x**2 for x in range(11)]>>> s # es una lista[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]>>> s = (x**2 for x in range(11))>>> s # es un generador<generator object <genexpr> at 0xb74588ec>>>> s.next()0>>> for i in s: print(i)...14[...]81100>>>
  80. 80. Comprensión de diccionarios Crear diccionarios a partir de otrasfuentes de datos Sintaxis similar, pero cambiandocorchetes/paréntesis por llaves: {} La expresión tienen que tener laforma <clave>:<valor>
  81. 81. Ejemplos>>> d = {x:x**2 for x in range(5)}>>> d{1: 1, 0: 0, 3: 9, 2: 4, 4: 16}>>> d = {x:x**2 for x in range(5) if x % 2 == 0}>>> d{0: 0, 2: 4, 4: 16}>>> print({i : chr(65+i) for i in range(4)}){0 : A, 1 : B, 2 : C, 3 : D}>>>>>> d = {x:x**2 for x in range(5)}>>> d{1: 1, 0: 0, 3: 9, 2: 4, 4: 16}>>> d = {x:x**2 for x in range(5) if x % 2 == 0}>>> d{0: 0, 2: 4, 4: 16}>>> print({i : chr(65+i) for i in range(4)}){0 : A, 1 : B, 2 : C, 3 : D}>>>
  82. 82. Conprensión de conjuntos Definir un conjunto a partir de otrosvalores Igual que con los diccionarios, pero laexpresión no va en la forma<clave>:<valor>, sino como unaexpresión simple NO se puede crear así un diccionariovacio (Crearía un diccionario)
  83. 83. Ejemplo>>> s = {a, b, c}>>> sset([a, c, b])>>> s = {str(x**2) for x in range(7)}>>> type(s)<type set>>>> sset([25, 16, 36, 1, 0, 4, 9])>>>>>> s = {a, b, c}>>> sset([a, c, b])>>> s = {str(x**2) for x in range(7)}>>> type(s)<type set>>>> sset([25, 16, 36, 1, 0, 4, 9])>>>
  84. 84. Decoradores Funciones como objetos de primer nivel Las funciones se pueden almacenar,pasar como parámetros... … o ser devueltas como resultado deuna función Una función puede devolver otra función
  85. 85. Suena raro...Una función …… puede devolver …… otra función
  86. 86. No es tan raro, veamos un ejemplo>>> def dame_una_funcion_incremento(inc):... def funcion_a_retornar(x):... return x + inc... return funcion_a_retornar...>>> inc3 = dame_una_funcion_incremento(3)>>> inc3(6)9>>> inc47 = dame_una_funcion_incremento(47)>>> inc47(3)50>>> def dame_una_funcion_incremento(inc):... def funcion_a_retornar(x):... return x + inc... return funcion_a_retornar...>>> inc3 = dame_una_funcion_incremento(3)>>> inc3(6)9>>> inc47 = dame_una_funcion_incremento(47)>>> inc47(3)50
  87. 87. ¿Qué es un decorador? Sabiendo que esto es posible, undecorador es:– Una función que acepta como parámetrouna función, y devuelve otra función, quenormalmente sustituirá a la original.– Es decir, un decorador nos permitemodificar una función (Normalmentehaciendo algo antes, o después, o ambascosas)
  88. 88. Referencia friki totalmente gratuita
  89. 89. ¿Para qué sirve un decorador? El uso de decoradores se enfoca aresolver el siguiente problema:– Tenemos un conjunto de funciones– Queremos que todas ellas hagan una nuevacosa, algo por lo general ajeno al propiocomportamiento de la función, y que todaslo hagan por igual.– En otras palabras, queremos añadir unafuncionalidad horizontal.
  90. 90. Ejemplo de situación Supongamos que tenemos un conjuntode funciones a(), b(),..., z(), cada unade ellas con sus parámetros,particularidades, etc... Queremos ahora, con el mínimo trabajoposible, que cada función escriba en unfichero log cuando empieza a trabajar ycuanto termina.
  91. 91. Opción A (de “A lo bruto”)Reescribir cada una de las funcionesdef a():# código de adef a():# código de aPasar de esto:def a():with open(/tmp/log.txt, a) as log:log.write(Empieza la función an)# codigo de awith open(/tmp/log.txt, a) as log:log.write(Acaba la función an)def a():with open(/tmp/log.txt, a) as log:log.write(Empieza la función an)# codigo de awith open(/tmp/log.txt, a) as log:log.write(Acaba la función an)A esto:
  92. 92. Pegas de la opción A Sencillo, pero trabajoso Hay que reescribir mucho código El tamaño del código aumenta La lógica de las funciones quedadifuminada con todas esas llamadas aescribir el log Si queremos cambiar la información dellog, (incluir fecha y hora, p.e.) hay quevolver a modificar todas las funciones
  93. 93. Opción D (De “decoradores”) Intenta solucionar estos problemas Un decorador coge las función original,(a(), b(),..., z() en nuestro caso), lamodifica y la reemplaza Ahora, cuando se llama a a(), se invocaen realidad a nuestra versión modificada(que a su vez invocará a la a() original)
  94. 94. Decorador “logged” Para el ejemplo de log, primero creamosuna función decoradora, que llamaramoslogged() Para simplificar, en vez de escribir a unfichero log nos limitaremos a hacer dosprints, uno antes de que empieze lafunción y otro después
  95. 95. Código de loggeddef logged(func):def inner(* args, **kwargs):print(Empieza la función {}.format(func.__name__))func(*args, **kwargs)print(Termina la función {}.format(func.__name__))return innerdef logged(func):def inner(* args, **kwargs):print(Empieza la función {}.format(func.__name__))func(*args, **kwargs)print(Termina la función {}.format(func.__name__))return inner
  96. 96. Aplicación del decoradordef a(): print(Soy a())def b(): print(Soy b())b = logged(b)@loggeddef c(): print(Soy c())@loggeddef d(msg):print(Soy d y digo: {}.format(msg))a()b()c()d(Hola, mundo)def a(): print(Soy a())def b(): print(Soy b())b = logged(b)@loggeddef c(): print(Soy c())@loggeddef d(msg):print(Soy d y digo: {}.format(msg))a()b()c()d(Hola, mundo)
  97. 97. Aplicación de decoradoresLa forma:@loggeddef c(): print(Soy c())@loggeddef c(): print(Soy c())Es azucar sintáctico para:def c(): print(Soy c())c = logged(c)def c(): print(Soy c())c = logged(c)La forma más cómoda de aplicar eldecorador es poner el símbolo @ y elnombre del decorador antes de la definiciónde la función
  98. 98. Ventaja de los decoradores Hay que tocar el código de cada función, si, pero elcambio es mínimo: añadir el decorador con elsimbolo @ El código no se repite. No hay aumento apreciablede tamaño del mismo El código interno de las funciones decoradas no seve perturbado por la nueva funcionalidad. Podemos añadir nuevas características a lasfunciones "logeadas" modificando solo una cosa: eldecorador

×