SlideShare una empresa de Scribd logo
H
EL LENGUAJE DE PROGRAMACIÓN
PYTHON
Juan Ignacio Rodríguez de León
jileon en twitter
euribates @ gmail.com
Programación orientada a objetos
Programación funcional
Objetos y Clases
 Las clases permiten que podamos definir
nuestros propios tipos de datos
 Las Clases definen las propiedases
(atributos) y las capacidades y
comportamiento (métodos) general de
los nuevos tipos
 Un objeto se crea o instancia a partir de
una clase
Objetos
 Un objeto es una variable que
representa un caso particular dentro del
conjunto de posibles instancias de una
clase
 De la misma forma que podemos
considerar al número 7 como una
instancia particular de la clase Numeros
Enteros
Creación de clases
 Palabra reservada class
 La clase más sencilla que podemos
pensar es:
>>> class X:
... pass
>>>
>>> class X:
... pass
>>>
 Instanciamos un objeto usando el
nombre de la clase como si fuera una
función:
>>> x = X()
>>> print(x)
>>> x = X()
>>> print(x)
La clase Point
 Inicializador: Método con el nombre
especial __init__
 No es el constructor, pero casi
class Point:
def __init__(self, lat, lng):
self.latitud = lat
self.longitud = lng
x = Point(28.4779, -16.3118)
print(x.latitud, x.longitud)
class Point:
def __init__(self, lat, lng):
self.latitud = lat
self.longitud = lng
x = Point(28.4779, -16.3118)
print(x.latitud, x.longitud)
¿self?
 Se crea el objeto.
 Inmediatamente a continuación, como
hemos visto, se llama al inicializador
– los dos parámetros que usamos al crear al
objeto son los mismos valores que se pasan
al método inicializador con los nombres lat
y lng
 Pero ¿De donde sale el primer
parámetro, self? ¿Y qué representa?
Para programadores de C++ o Java
 Para programadores de C++ o Java es la
variable "magica" this.
 En Python se prefirió esta forma por
considerarla más explicita.
 De igual manera, los atributos dentro de
la función tienen que venir precedidos
por el self., no hay alias mágicos para
los atributos de la instancia, para evitar
la ambigüedad.
Seguimos con self
 Empezemos por la segunda pregunta:
self representa al propio objeto recien
creado
 Este primer parámetro es lo que
diferencia a las funciones que ya
conociamos de los métodos:
– un método siempre tienen como primer
parámetro la instancia sobre la que está
siendo ejecutado.
Quien pone self ahí
 Al definir métodos para una clase, hay
que reservar el primer parámetro para el
propio objeto
 Al llamar al método desde la instancia,
Python ya se ocupa de poner el valor
correcto como primer parámetro
 La tradición y la costumbre marcan que
este primer parámetro se llame self,
pero en realidad no existe obligación de
hacerlo (pero es conveniente hacerlo,
por legibilidad)
Herencia
 Para poder hablar de clases y objetos
con propidad es necesario que haya
algún tipo de herencia
 La herencia nos permite definir una clase
a base de refinar o modificar otra
(herencia simple) u otras (herencia
múltiple)
Herencia simple
 Si una clase A deriva o hereda de una
clase B (o también se dice que la clase B
es 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étodos
e incluso modificar o borrar los que ha
heredado.
Como declarar herencia en Python
 La forma de expresar esta herencia en
python es
>>> class A(B):
... pass
>>> class A(B):
... pass
 Si la clase modifique un método que ha
heredado, se dice que ha reescrito o
sobreescrito (override) el método.
Características de la herencia
 Como los objetos instanciados de A tienen los
mismos atributos y métodos que B, deben
poder ser ser usados en cualquier sitio donde
se 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
Polimorfismo
 A puede sobreescribir un método f() de B
 Si tenemos una lista con objetos de tipo A y
de tipo B mezclados, podemos invocar sin
miedo el método f() en todos ellos, con la
seguridad de que en cada caso se invocará al
método adecuado.
 Esta capacidad se llama polimorfismo (del
griego Múltiples Formas)
Métodos o atributos privados
 No existen en Python
 Existe una convención de uso, por la cual
si un atributo o método empieza con el
carácter subrayado, ha de entenderse
que:
– Es de uso interno
– No deberías jugar con él a no ser que sepas
muy bien lo que estás haciendo
– Si en un futuro tu código deja de funcionar
porque has usado ese atributo o método, no
puedes culpar a nadie más que a ti mismo
Beneficios de usar clases/objetos
 Reducir el tamaño del código evitando
repeticiones
– Si organizamos las herencias correctamente
en jerarquias, de mas genéricas a más
específicas, podemos compatibilizar el
código común de las primeras con el más
específico de las últimas
 Encapsulamiento
 Polimorfismo
 Delegación de responsabilidades
super
 ¿Que pasa si A sobreescribe un método de B, pero
aun así ha de invocarlo?
 En realidad es un caso muy común, A quiere hacer
lo mismo que B, y un poquito más.
 Desde Python 2.2 hay una función super() que
nos 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
Funciones auxiliares
 isinstance(objeto, clase)
– nos devolverá verdadero si el objeto es una
instancia de una clase en particular, o de
alguna de sus subclases
 issubclass(objeto, clase)
– nos devolverá verdadero si el objeto es una
instancia de una subclase de la clase
indicada.
Sobrecarga de operadores
 Se puede, como en C++, sobreescribir
los operadores (operadores aritméticos,
acceso por índices, etc...) mediante una
sintaxis especial
 Los métodos y atributos que empiezan y
acaban con un doble signo de subrayado
tiene por lo general un significado
especial.
Sobrecarga de operadores: len
 Si en nuestra clase definimos un método
__len__(), podemos hacer que las
instancias de esa clase puedan ser
usadas con la función len()
 Véase ejemplos/clases_02.py
Sobrecarga de operadores: índices
 Si a una clase le añadimos los métodos
__setitem__ y __getitem__ podemos
hacer que se comporte como si fuera
una contenedor accesible mediante las
operaciones de índices
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 cara
def __getitem__(self, index):
if 0 <= index < 7:
return self._Tabla[index]
else:
return 'Muchos'
def __setitem__(self, index, value):
pass
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 cara
def __getitem__(self, index):
if 0 <= index < 7:
return self._Tabla[index]
else:
return 'Muchos'
def __setitem__(self, index, value):
pass
Ejemplos/clases_03.py
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 para
sumar 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, poder
hacer
v3 = v1 + v2v3 = v1 + v2
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __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 = x
self.y = y
def __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
Sobrecarga de operadores: +/-
 Para eso definimos los métodos
especiales __add__ y __sub__ para
definir el comportamiento cuando se
sumen o resten dos instancias de nuesta
clase.
 Véase ejemplos/clases_04.py
 Existen muchos métodos especiales
 A Guide to Python's Magic Methods:
– http://www.rafekettler.com/magicmethods.html
Excepciones
 Errores sintáctis y excepciones
 Información del error
 Las excepciones se producen durante la
ejecución
– Pueden ser tratadas: “capturadas”
– Si no se capturan, el programa acaba
Tipos de excepciones
 Según el error
 ZeroDivisionError, ValueError, etc...
 Como capturar excepciones: try/except
try:
a, b = 7, 0
c = a / b
except ZeroDivisionError:
print("No puedo dividir por cero")
try:
a, b = 7, 0
c = a / b
except ZeroDivisionError:
print("No puedo dividir por cero")
Tratamiento de excepciones
 Puede haber varias cláusulas except,
para cada tipo de error
 Una cláusula puede gestionar varios
errores
 Puede haber una clausula except
general (No recomendado)
 Podemos volver a “elevar” la excepcion
que hemos capturado
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
Argumento de la excepción
 La excepción se representa con un valor que tiene los
detalles del error
 Usando la palabra reservada as podemos almacenar
este 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
>>>
Legibilidad del código
con excepciones
 Los programas en C suelen consistir en
una serie de llamadas a funciones
intercaladas con comprobaciones de
resultados
 Con excepciones:
– La gestión de los errores no se entromete
con la función del algoritmo
– Está centralizada y aparte
Elevar excepciones
 Podemos elevar nosotros mismos
excepciones, usando la palabra
reservada raise
 Podemos definir nuestras propias
excepciones
– Derivadas de Exception
– Jerarquía de excepciones
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"
Gestores de contexto: with
 with nos permite "envolver" un bloque de
código con operaciones a ejecutar antes y
después del mismo
 Simetría en las operaciones
 Garantía de ejecución
 Se pueden anidar
 Ejemplos
– ficheros: open/close
– memoria: malloc/free
Más claro
try:
f = open('fichero.datos', 'r')
# proceso el fichero
n = len(f.readlines())
finally:
f.close()
try:
f = open('fichero.datos', 'r')
# proceso el fichero
n = 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:
Como funciona with (1)
 Usando Gestores de contexto
 Son objetos que saben lo que hay que
hacer antes y después de usar otro
objeto
 El generador de contexto de file sabe
que hay que cerrar el archivo
 Imposible olvidarse de cerrarlo
Como funciona with (2)
1) Evaluación y obtención del gestor de
contexto
2) Se carga __exit__()
3) Se ejecuta __enter__() (si devuelve un
valor y se ha usado as, se asigna a la
variable)
4) Se ejecuta el bloque
5) Se llama a __exit__() (con información
de errores, si hubiera)
Iteradores
 Nuestras clases y objetos pueden ser
iterables
 Como funciona for internamente:
– Se llama a iter() pasándole lo que quiera
que sea que vamos a iterar
– Obtenemos un iterador, es decir, un objeto
con un metodo next()
– Llamamos a next() repetidas veces...
– Hasta que termina: se eleva StopIteration
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
Es fácil añadir “iterabilidad”
 Definir un método con el nombre
__iter__() que devuelva un objeto
 Este objeto debe implementar un método
next()
– Cada vez que se llame a next(), este debe
devolver el siguiente elemento
– A no ser que no queden, entonces, eleva
StopIteration
 Nuestra clase puede ser su propio iterador:
basta con definir next() y en __iter__
devolver self
Ejercicio
 Crear una clase CuentaAtras, que sea
iterable y que, ejem, cuente hacia atrás
hasta llegar al cero.
Solución
class CuentaAtras:
def __init__(self, tope):
self.tope = tope
def __iter__(self):
self.counter = self.tope
return self
def next(self): return self.__next__() # python 2.7
def __next__(self):
result = self.counter
self.counter -= 1
if result < 0:
raise StopIteration
return result
class CuentaAtras:
def __init__(self, tope):
self.tope = tope
def __iter__(self):
self.counter = self.tope
return self
def next(self): return self.__next__() # python 2.7
def __next__(self):
result = self.counter
self.counter -= 1
if result < 0:
raise StopIteration
return result
Generadores
 Forma sencilla y potente de crear iteradores
 Como una función, pero devuelven resultados con
yield, en vez de return
 Cada vez que se llama a next(), el generador
continua a partir de donde se quedó
 Recuerda su estado: valores de las variables,
última línea que se ejecutó, etc...
Cuenta Atras (como generador)
>>> def cuenta_atras(n):
... while n >= 0:
... yield n
... n -= 1
...
>>> for i in cuenta_atras(5): print(i)
...
5
4
3
2
1
0
>>>
>>> def cuenta_atras(n):
... while n >= 0:
... yield n
... n -= 1
...
>>> for i in cuenta_atras(5): print(i)
...
5
4
3
2
1
0
>>>
Ventajas
 Igual potencia que un iterador
 Solo por usar yield ya se sabe que es
un generador
 Normalmente más fáciles de escribir
 Generación automática de next() y de
__iter__()
 Eleva automáticamente StopIteration
Ejemplos de
generadores/iteradores
 El módulo os.path, como veremos más
adelante, tiene una función walk, que es
un generador que nos permite recorrer
un árbol de directorios
 El módulo itertools define una funcion
combinations que nos da las
combinaciones de m elementos
tomandos de n en n
Ejemplo de combinaciones
 Combinaciones tomando los cuatro
elementos 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
La Fiscalia Anticorrupción
nos pide ayuda
Ajustar cuentas
 Estan investigando un caso
de un ex-tesorero y una
doble facturación
 Hay una serie de ingresos
por un lado
 Y una serie de pagos por otro
 Demostrar que la serie de
pagos se corresponden,
sumadas, con los ingresos.
Los ingresos
1910.00 €
4090.20 €
1945.45 €
Los pagos
1404.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 y
tomarlas de una en una. Ver si sumadas
coinciden con el ingreso
– Tomar las combinaciones de pagos y
tomarlas de dos en dos. Ver si sumadas
coinciden con el ingreso
– Seguir asi buscando combinaciones hasta
que una coincida. Cuando se encuentra,
retirar esos pagos de la lista de pagos y
seguir con el siguiente ingreso
Herramientas
 Conseguir las combinaciones usando
itertoos.combinations.
 La función sum() nos suma los
elementos de una secuencia
 Empezar con una versión minima del
problema: 2 ingresos, 4 pagos, por
ejemplo.
 Solución en:
– ejemplos/facturacion_b.py
facturacion_b.py (1)
from decimal import Decimal
import itertools
ingresos = [
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 Decimal
import itertools
ingresos = [
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'),
]
facturacion_b.py (2)
for ingreso in ingresos:
solucion = None
for size in range(1, len(pagos)+1):
# Probando combinaciones de size elementos
for 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)
break
if solucion:
for pago in solucion:
pagos.remove(pago)
for ingreso in ingresos:
solucion = None
for size in range(1, len(pagos)+1):
# Probando combinaciones de size elementos
for 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)
break
if solucion:
for pago in solucion:
pagos.remove(pago)
Solución
1816.42 + 153.56
+ 1286.85 + 322.9
+ 175.04 + 335.43 = 4090.20
1404.93 + 207.68 + 297.39 = 1910.00
259.74 + 301.28 + 1384.43 = 1945.45
Programación funcional
 Las funciones solo son otro tipo de
variable
 Todo lo que se puede hacer con una
variable, 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 primera
clase”
Funciones Lambda λ
 Crear pequeñas funciones anónimas
 lambda <argumentos>: <expresion>
 Función que suma los dos parámetros
que se le pasan:
– lambda(x,y): x+y
 No hace falta especificar return
 Azucar sintáctico para una definición de
función normal
filter
 Primer parámetro: una función
 Segundo parámetro: una secuencia
 Devuelve: otra secuencia en la que se
estan sólo aquellos valores de la
secuencia original para los que el
resultado de aplicarles la función es
True
Ejemplo
Calcular los primeros 200
números que son divisibles
por 5 y por 7
los primeros 200 números
que 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)
...
35
70
105
140
175
>>>
>>> def div57(x):
... return x % 5 == 0 and x % 7 == 0
...
>>> for i in filter(div57, range(1, 201)):
... print(i)
...
35
70
105
140
175
>>>
map
 Primer parámetro: una función
 Segundo parámetro: una secuencia
 Devuelve: otra secuencia, compuesta
por los resultados de llamar a la función
en cada uno de los elementos de la
secuencia original
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]
>>>
map (2)
 Podemos pasar más de una secuencia
 La función pasada como parámetro
debe aceptar tantos parámetros como
secuencias haya
 Ejercicio: media de los datos de otras
dos listas
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]
>>>
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 tiene
que aceptar dos valores, y retornar uno
– Se calcula el resultado de aplicar la función a los
dos primeros valores de la secuencia
– A continuación, se aplica de nuevo la función,
usando como parámetros el dato anterior y al
tercer elemento de la secuencia
– Así hasta acabar la secuencia original
Ejercicio: sumar los valores
de una lista
Ejercicio: sumar los valores
de 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
>>>
Ejercicio: sumar los valores
de 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) = 3
Suma(3,3) = 6
Suma(6,4) = 10
Suma(10,5) = 15
Suma(15,6) = 21
Suma(21,7) = 28
Suma(28,8) = 36
Suma(36,9) = 45
Suma(45,10) = 55
Ejercicio: sumar los valores
de 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 ya
existe una función incorporada para ello:
sum(seq), que funciona exactamente igual, pero
más rápido al estár implementada en C.
Compresión de listas
 Forma muy expresiva de crear listas
 Usos comunes
– Crear una lista cuyos elementos son resultado
de aplicar una serie de operaciones a otra
secuencia
– Crear una sebsecuencia de aquellos elementos
que cumplan una determinada condición
 En resumen, nos permiten hacer lo mismo
que map o filter, pero de forma más
legible.
10 Números cuadrados
 Podemos crear una lista con los
cuadrados de los 10 primeros números
así:
>>> 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]
>>>
10 Números cuadrados
 O así, con map
squares = 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ás
fácil
squares = [x**2 for x in range(11)]squares = [x**2 for x in range(11)]
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úmeros
enteros cumplen la condición de que su
cubo acaba en 272?
– str() convierte un número en texto
– endswith() es un metodo de los textos que
devuelve True si la cadena de texto sobre la
que se aplica acaba en el texto indicado
como parámetro:
● 'hola'.endswith('a') → True
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]
Expresiones generadoras
 Muy similar a una conprensión de lista
 Pero devuelve un generador, no una lista
 La sintaxis es idéntica, sustituyendo los
corchetes por paréntesis
– con la lista obtenemos todos los elementos
ya generados (y, por tanto, consumiendo
memoria)
– El generador nos irá dando los valores de
uno en uno (lazy evaluation)
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)
...
1
4
[...]
81
100
>>>
>>> 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)
...
1
4
[...]
81
100
>>>
Comprensión de diccionarios
 Crear diccionarios a partir de otras
fuentes de datos
 Sintaxis similar, pero cambiando
corchetes/paréntesis por llaves: {}
 La expresión tienen que tener la
forma <clave>:<valor>
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'}
>>>
Conprensión de conjuntos
 Definir un conjunto a partir de otros
valores
 Igual que con los diccionarios, pero la
expresión no va en la forma
<clave>:<valor>, sino como una
expresión simple
 NO se puede crear así un diccionario
vacio (Crearía un diccionario)
Ejemplo
>>> s = {'a', 'b', 'c'}
>>> s
set(['a', 'c', 'b'])
>>> s = {str(x**2) for x in range(7)}
>>> type(s)
<type 'set'>
>>> s
set(['25', '16', '36', '1', '0', '4', '9'])
>>>
>>> s = {'a', 'b', 'c'}
>>> s
set(['a', 'c', 'b'])
>>> s = {str(x**2) for x in range(7)}
>>> type(s)
<type 'set'>
>>> s
set(['25', '16', '36', '1', '0', '4', '9'])
>>>
Decoradores
 Funciones como objetos de primer nivel
 Las funciones se pueden almacenar,
pasar como parámetros...
 … o ser devueltas como resultado de
una función
 Una función puede devolver otra función
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
... 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
¿Qué es un decorador?
 Sabiendo que esto es posible, un
decorador es:
– Una función que acepta como parámetro
una función, y devuelve otra función, que
normalmente sustituirá a la original.
– Es decir, un decorador nos permite
modificar una función (Normalmente
haciendo algo antes, o después, o ambas
cosas)
Referencia friki totalmente gratuita
¿Para qué sirve un decorador?
 El uso de decoradores se enfoca a
resolver el siguiente problema:
– Tenemos un conjunto de funciones
– Queremos que todas ellas hagan una nueva
cosa, algo por lo general ajeno al propio
comportamiento de la función, y que todas
lo hagan por igual.
– En otras palabras, queremos añadir una
funcionalidad horizontal.
Ejemplo de situación
 Supongamos que tenemos un conjunto
de funciones a(), b(),..., z(), cada una
de ellas con sus parámetros,
particularidades, etc...
 Queremos ahora, con el mínimo trabajo
posible, que cada función escriba en un
fichero log cuando empieza a trabajar y
cuanto termina.
Opción A (de “A lo bruto”)
Reescribir cada una de las funciones
def a():
# código de a
def a():
# código de a
Pasar de esto:
def a():
with open('/tmp/log.txt', 'a') as log:
log.write('Empieza la función an')
# codigo de a
with 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 a
with open('/tmp/log.txt', 'a') as log:
log.write('Acaba la función an')
A esto:
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 queda
difuminada con todas esas llamadas a
escribir el log
 Si queremos cambiar la información del
log, (incluir fecha y hora, p.e.) hay que
volver a modificar todas las funciones
Opción D (De “decoradores”)
 Intenta solucionar estos problemas
 Un decorador coge las función original,
(a(), b(),..., z() en nuestro caso), la
modifica y la reemplaza
 Ahora, cuando se llama a a(), se invoca
en realidad a nuestra versión modificada
(que a su vez invocará a la a() original)
Decorador “logged”
 Para el ejemplo de log, primero creamos
una función decoradora, que llamaramos
logged()
 Para simplificar, en vez de escribir a un
fichero log nos limitaremos a hacer dos
prints, uno antes de que empieze la
función y otro después
Código de logged
def 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
def 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
Aplicación del decorador
def a(): print('Soy a()')
def b(): print('Soy b()')
b = logged(b)
@logged
def c(): print('Soy c()')
@logged
def 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)
@logged
def c(): print('Soy c()')
@logged
def d(msg):
print('Soy d y digo: {}'.format(msg))
a()
b()
c()
d('Hola, mundo')
Aplicación de decoradores
La forma:
@logged
def c(): print('Soy c()')
@logged
def 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 el
decorador es poner el símbolo @ y el
nombre del decorador antes de la definición
de la función
Ventaja de los decoradores
 Hay que tocar el código de cada función, si, pero el
cambio es mínimo: añadir el decorador con el
simbolo @
 El código no se repite. No hay aumento apreciable
de tamaño del mismo
 El código interno de las funciones decoradas no se
ve perturbado por la nueva funcionalidad.
 Podemos añadir nuevas características a las
funciones "logeadas" modificando solo una cosa: el
decorador

Más contenido relacionado

La actualidad más candente

Presentacion Java
Presentacion JavaPresentacion Java
Presentacion Java
maeusogo
 
Seguridad y proteccion en Sistemas Operativos
Seguridad y proteccion en Sistemas OperativosSeguridad y proteccion en Sistemas Operativos
Seguridad y proteccion en Sistemas Operativos
Danianny Verónica Senju
 
PSW Unidad 1 PROCESO DE SOFTWARE
PSW Unidad 1 PROCESO DE SOFTWAREPSW Unidad 1 PROCESO DE SOFTWARE
PSW Unidad 1 PROCESO DE SOFTWARE
Franklin Parrales Bravo
 
Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)programadorjavablog
 
Fundamentos de POO
Fundamentos de POOFundamentos de POO
Fundamentos de POO
gueritamala
 
Modelo relacional
Modelo relacionalModelo relacional
Modelo relacional
Victor Quintero
 
Clases Genéricas en Java
Clases Genéricas en JavaClases Genéricas en Java
Clases Genéricas en Java
Alejandro Colomer Everett
 
Protección y Seguridad de los sistemas operativos
Protección y Seguridad de los sistemas operativosProtección y Seguridad de los sistemas operativos
Protección y Seguridad de los sistemas operativos
Aquiles Guzman
 
Introduccion bases de datos
Introduccion bases de datosIntroduccion bases de datos
Introduccion bases de datos
UTN
 
Análisis estructurado
Análisis estructuradoAnálisis estructurado
Análisis estructurado
MSc Aldo Valdez Alvarado
 
Metodologiasad 1
Metodologiasad 1Metodologiasad 1
Metodologiasad 1
innovalabcun
 
Programación orientada a objetos (POO) [JAVA]
Programación orientada a objetos (POO) [JAVA]Programación orientada a objetos (POO) [JAVA]
Programación orientada a objetos (POO) [JAVA]Hack '
 
Clase I Estructura de Datos
Clase I Estructura de Datos Clase I Estructura de Datos
Clase I Estructura de Datos guestc906c2
 
Hilos En Java
Hilos En JavaHilos En Java
Uml clase 04_uml_clases
Uml clase 04_uml_clasesUml clase 04_uml_clases
Uml clase 04_uml_clases
Universidad Fermín Toro
 
TABLA DE SÍMBOLOS
TABLA DE SÍMBOLOSTABLA DE SÍMBOLOS
TABLA DE SÍMBOLOS
Infomania pro
 
Conceptos de POO (Programacion Orientada a Objetos)
Conceptos de POO (Programacion Orientada a Objetos)Conceptos de POO (Programacion Orientada a Objetos)
Conceptos de POO (Programacion Orientada a Objetos)
Josue Lara Reyes
 
Diagramas clases presentacion
Diagramas clases presentacionDiagramas clases presentacion
Diagramas clases presentacion
josebrandon24
 
Hacking ético
Hacking éticoHacking ético
Hacking ético
Paulo Colomés
 

La actualidad más candente (20)

Presentacion Java
Presentacion JavaPresentacion Java
Presentacion Java
 
Seguridad y proteccion en Sistemas Operativos
Seguridad y proteccion en Sistemas OperativosSeguridad y proteccion en Sistemas Operativos
Seguridad y proteccion en Sistemas Operativos
 
PSW Unidad 1 PROCESO DE SOFTWARE
PSW Unidad 1 PROCESO DE SOFTWAREPSW Unidad 1 PROCESO DE SOFTWARE
PSW Unidad 1 PROCESO DE SOFTWARE
 
Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)Patrones de diseño(presentación 7)
Patrones de diseño(presentación 7)
 
Fundamentos de POO
Fundamentos de POOFundamentos de POO
Fundamentos de POO
 
Modelo relacional
Modelo relacionalModelo relacional
Modelo relacional
 
Clases Genéricas en Java
Clases Genéricas en JavaClases Genéricas en Java
Clases Genéricas en Java
 
Protección y Seguridad de los sistemas operativos
Protección y Seguridad de los sistemas operativosProtección y Seguridad de los sistemas operativos
Protección y Seguridad de los sistemas operativos
 
Introduccion bases de datos
Introduccion bases de datosIntroduccion bases de datos
Introduccion bases de datos
 
Herencia Y Polimorfismo
Herencia Y PolimorfismoHerencia Y Polimorfismo
Herencia Y Polimorfismo
 
Análisis estructurado
Análisis estructuradoAnálisis estructurado
Análisis estructurado
 
Metodologiasad 1
Metodologiasad 1Metodologiasad 1
Metodologiasad 1
 
Programación orientada a objetos (POO) [JAVA]
Programación orientada a objetos (POO) [JAVA]Programación orientada a objetos (POO) [JAVA]
Programación orientada a objetos (POO) [JAVA]
 
Clase I Estructura de Datos
Clase I Estructura de Datos Clase I Estructura de Datos
Clase I Estructura de Datos
 
Hilos En Java
Hilos En JavaHilos En Java
Hilos En Java
 
Uml clase 04_uml_clases
Uml clase 04_uml_clasesUml clase 04_uml_clases
Uml clase 04_uml_clases
 
TABLA DE SÍMBOLOS
TABLA DE SÍMBOLOSTABLA DE SÍMBOLOS
TABLA DE SÍMBOLOS
 
Conceptos de POO (Programacion Orientada a Objetos)
Conceptos de POO (Programacion Orientada a Objetos)Conceptos de POO (Programacion Orientada a Objetos)
Conceptos de POO (Programacion Orientada a Objetos)
 
Diagramas clases presentacion
Diagramas clases presentacionDiagramas clases presentacion
Diagramas clases presentacion
 
Hacking ético
Hacking éticoHacking ético
Hacking ético
 

Similar a 02 python Programación orientada a objetos y funcional

U8.- Programacion Orientada a objetos II (2).pdf
U8.- Programacion Orientada a objetos II (2).pdfU8.- Programacion Orientada a objetos II (2).pdf
U8.- Programacion Orientada a objetos II (2).pdf
JCarlosCrespo
 
programacion orientada a objetos
programacion orientada a objetosprogramacion orientada a objetos
programacion orientada a objetosjent46
 
Guia poo php
Guia poo phpGuia poo php
Guia poo php
lissette_torrealba
 
Programación ii presentación tema 5
Programación ii presentación tema 5Programación ii presentación tema 5
Programación ii presentación tema 5
Joel Mieses
 
PROGRAMACIÓN ORIENTADA A OBJETOS
PROGRAMACIÓN ORIENTADA A OBJETOSPROGRAMACIÓN ORIENTADA A OBJETOS
PROGRAMACIÓN ORIENTADA A OBJETOS
PEDRO OSWALDO BELTRAN CANESSA
 
Cuarta sesion herencia y polimorfismo-explicacion anibal
Cuarta sesion herencia y polimorfismo-explicacion anibalCuarta sesion herencia y polimorfismo-explicacion anibal
Cuarta sesion herencia y polimorfismo-explicacion anibal
Carlos Anibal Riascos Hurtado
 
Net1 oop vbnet
Net1 oop vbnetNet1 oop vbnet
Net1 oop vbnet
jhordy2000
 
Explicacion de interface
Explicacion de interfaceExplicacion de interface
Explicacion de interfaceBoris Salleg
 
Programacion
ProgramacionProgramacion
Programacion
jalfonso9971
 
Herencia en java
Herencia en javaHerencia en java
Herencia en javajbersosa
 
Php orientado a_objetos
Php orientado a_objetosPhp orientado a_objetos
Php orientado a_objetosJose Ney Quil
 
Java morld cap2 [CURSO JAVA]
Java morld cap2 [CURSO JAVA]Java morld cap2 [CURSO JAVA]
Java morld cap2 [CURSO JAVA]Hack '
 
Presentacion de clases en c#
Presentacion de clases en c#Presentacion de clases en c#
Presentacion de clases en c#
Sterling Rafael Santana Vargas
 
03 java poo_parte_2
03 java poo_parte_203 java poo_parte_2
03 java poo_parte_2
Renny Batista
 

Similar a 02 python Programación orientada a objetos y funcional (20)

U8.- Programacion Orientada a objetos II (2).pdf
U8.- Programacion Orientada a objetos II (2).pdfU8.- Programacion Orientada a objetos II (2).pdf
U8.- Programacion Orientada a objetos II (2).pdf
 
Java
JavaJava
Java
 
programacion orientada a objetos
programacion orientada a objetosprogramacion orientada a objetos
programacion orientada a objetos
 
Guia poo
Guia pooGuia poo
Guia poo
 
Guia poo
Guia pooGuia poo
Guia poo
 
Guia poo php
Guia poo phpGuia poo php
Guia poo php
 
C2 clases en java
C2 clases en javaC2 clases en java
C2 clases en java
 
Programación ii presentación tema 5
Programación ii presentación tema 5Programación ii presentación tema 5
Programación ii presentación tema 5
 
PROGRAMACIÓN ORIENTADA A OBJETOS
PROGRAMACIÓN ORIENTADA A OBJETOSPROGRAMACIÓN ORIENTADA A OBJETOS
PROGRAMACIÓN ORIENTADA A OBJETOS
 
Cuarta sesion herencia y polimorfismo-explicacion anibal
Cuarta sesion herencia y polimorfismo-explicacion anibalCuarta sesion herencia y polimorfismo-explicacion anibal
Cuarta sesion herencia y polimorfismo-explicacion anibal
 
Poo
PooPoo
Poo
 
Net1 oop vbnet
Net1 oop vbnetNet1 oop vbnet
Net1 oop vbnet
 
Explicacion de interface
Explicacion de interfaceExplicacion de interface
Explicacion de interface
 
Programacion
ProgramacionProgramacion
Programacion
 
Herencia en java
Herencia en javaHerencia en java
Herencia en java
 
Php orientado a_objetos
Php orientado a_objetosPhp orientado a_objetos
Php orientado a_objetos
 
Java morld cap2 [CURSO JAVA]
Java morld cap2 [CURSO JAVA]Java morld cap2 [CURSO JAVA]
Java morld cap2 [CURSO JAVA]
 
Semana9b Vbr
Semana9b VbrSemana9b Vbr
Semana9b Vbr
 
Presentacion de clases en c#
Presentacion de clases en c#Presentacion de clases en c#
Presentacion de clases en c#
 
03 java poo_parte_2
03 java poo_parte_203 java poo_parte_2
03 java poo_parte_2
 

Más de Juan Rodríguez

Estados imposibles y como evitarlos
Estados imposibles y como evitarlosEstados imposibles y como evitarlos
Estados imposibles y como evitarlos
Juan Rodríguez
 
Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)
Juan Rodríguez
 
Vue.js: El framework javascript para muggles
Vue.js: El framework javascript para mugglesVue.js: El framework javascript para muggles
Vue.js: El framework javascript para muggles
Juan Rodríguez
 
Introducción a jupyter (antes i python notebook)
Introducción a jupyter (antes i python notebook)Introducción a jupyter (antes i python notebook)
Introducción a jupyter (antes i python notebook)
Juan Rodríguez
 
Acceder a C desde Python (O viceversa)
Acceder a C desde Python (O viceversa)Acceder a C desde Python (O viceversa)
Acceder a C desde Python (O viceversa)
Juan Rodríguez
 
Viaje al centro de la locura con Javascript
Viaje al centro de la locura con JavascriptViaje al centro de la locura con Javascript
Viaje al centro de la locura con Javascript
Juan Rodríguez
 
Una imagen vale más que mil mentiras
Una imagen vale más que mil mentirasUna imagen vale más que mil mentiras
Una imagen vale más que mil mentiras
Juan Rodríguez
 
Introducción a DSL (Lenguajes Específicos de Dominios) con Python
Introducción a DSL (Lenguajes Específicos de Dominios) con PythonIntroducción a DSL (Lenguajes Específicos de Dominios) con Python
Introducción a DSL (Lenguajes Específicos de Dominios) con Python
Juan Rodríguez
 
Presentación estetoscopio
Presentación estetoscopioPresentación estetoscopio
Presentación estetoscopio
Juan Rodríguez
 
Charla introducción a RaspberryPI
Charla introducción a RaspberryPICharla introducción a RaspberryPI
Charla introducción a RaspberryPI
Juan Rodríguez
 
Guia (breve) de supervivencia a python 3
Guia (breve) de supervivencia a python 3Guia (breve) de supervivencia a python 3
Guia (breve) de supervivencia a python 3
Juan Rodríguez
 
¡A todo Kanban! ~ Introducción a kanban
¡A todo Kanban! ~ Introducción a kanban¡A todo Kanban! ~ Introducción a kanban
¡A todo Kanban! ~ Introducción a kanban
Juan Rodríguez
 
01 el lenguaje Python
01 el lenguaje Python01 el lenguaje Python
01 el lenguaje Python
Juan Rodríguez
 
00 introducción a Python
00 introducción a Python00 introducción a Python
00 introducción a Python
Juan Rodríguez
 
Taller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con DjangoTaller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con Django
Juan Rodríguez
 
Presentación appy/pod
Presentación appy/podPresentación appy/pod
Presentación appy/pod
Juan Rodríguez
 
Presentacion Google Mini Adeje 16 Oct 2008
Presentacion Google Mini Adeje 16 Oct 2008Presentacion Google Mini Adeje 16 Oct 2008
Presentacion Google Mini Adeje 16 Oct 2008
Juan Rodríguez
 
Algunos recursos para desarrollo Web
Algunos recursos para desarrollo WebAlgunos recursos para desarrollo Web
Algunos recursos para desarrollo Web
Juan Rodríguez
 
Hojas de estilo CSS (Cascade Style Sheets)
Hojas de estilo CSS (Cascade Style Sheets)Hojas de estilo CSS (Cascade Style Sheets)
Hojas de estilo CSS (Cascade Style Sheets)
Juan Rodríguez
 

Más de Juan Rodríguez (20)

Estados imposibles y como evitarlos
Estados imposibles y como evitarlosEstados imposibles y como evitarlos
Estados imposibles y como evitarlos
 
Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)
 
Vue.js: El framework javascript para muggles
Vue.js: El framework javascript para mugglesVue.js: El framework javascript para muggles
Vue.js: El framework javascript para muggles
 
Introducción a jupyter (antes i python notebook)
Introducción a jupyter (antes i python notebook)Introducción a jupyter (antes i python notebook)
Introducción a jupyter (antes i python notebook)
 
Acceder a C desde Python (O viceversa)
Acceder a C desde Python (O viceversa)Acceder a C desde Python (O viceversa)
Acceder a C desde Python (O viceversa)
 
Viaje al centro de la locura con Javascript
Viaje al centro de la locura con JavascriptViaje al centro de la locura con Javascript
Viaje al centro de la locura con Javascript
 
Una imagen vale más que mil mentiras
Una imagen vale más que mil mentirasUna imagen vale más que mil mentiras
Una imagen vale más que mil mentiras
 
Introducción a DSL (Lenguajes Específicos de Dominios) con Python
Introducción a DSL (Lenguajes Específicos de Dominios) con PythonIntroducción a DSL (Lenguajes Específicos de Dominios) con Python
Introducción a DSL (Lenguajes Específicos de Dominios) con Python
 
Presentación estetoscopio
Presentación estetoscopioPresentación estetoscopio
Presentación estetoscopio
 
Charla introducción a RaspberryPI
Charla introducción a RaspberryPICharla introducción a RaspberryPI
Charla introducción a RaspberryPI
 
Guia (breve) de supervivencia a python 3
Guia (breve) de supervivencia a python 3Guia (breve) de supervivencia a python 3
Guia (breve) de supervivencia a python 3
 
¡A todo Kanban! ~ Introducción a kanban
¡A todo Kanban! ~ Introducción a kanban¡A todo Kanban! ~ Introducción a kanban
¡A todo Kanban! ~ Introducción a kanban
 
01 el lenguaje Python
01 el lenguaje Python01 el lenguaje Python
01 el lenguaje Python
 
00 introducción a Python
00 introducción a Python00 introducción a Python
00 introducción a Python
 
Taller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con DjangoTaller de introducción al desarrollo web con Django
Taller de introducción al desarrollo web con Django
 
Presentación appy/pod
Presentación appy/podPresentación appy/pod
Presentación appy/pod
 
Presentacion Google Mini Adeje 16 Oct 2008
Presentacion Google Mini Adeje 16 Oct 2008Presentacion Google Mini Adeje 16 Oct 2008
Presentacion Google Mini Adeje 16 Oct 2008
 
Algunos recursos para desarrollo Web
Algunos recursos para desarrollo WebAlgunos recursos para desarrollo Web
Algunos recursos para desarrollo Web
 
Hojas de estilo CSS (Cascade Style Sheets)
Hojas de estilo CSS (Cascade Style Sheets)Hojas de estilo CSS (Cascade Style Sheets)
Hojas de estilo CSS (Cascade Style Sheets)
 
Extranet Parlamento
Extranet ParlamentoExtranet Parlamento
Extranet Parlamento
 

Último

DESARROLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLO DE HABILIDADES DE PENSAMIENTO.pdfDESARROLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLO DE HABILIDADES DE PENSAMIENTO.pdf
marianabz2403
 
Diagrama de flujo basada en la reparacion de automoviles.pdf
Diagrama de flujo basada en la reparacion de automoviles.pdfDiagrama de flujo basada en la reparacion de automoviles.pdf
Diagrama de flujo basada en la reparacion de automoviles.pdf
ManuelCampos464987
 
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTALINFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
CrystalRomero18
 
Diagrama de flujo - ingenieria de sistemas 5to semestre
Diagrama de flujo - ingenieria de sistemas 5to semestreDiagrama de flujo - ingenieria de sistemas 5to semestre
Diagrama de flujo - ingenieria de sistemas 5to semestre
DiegoCampos433849
 
EduFlex, una educación accesible para quienes no entienden en clases
EduFlex, una educación accesible para quienes no entienden en clasesEduFlex, una educación accesible para quienes no entienden en clases
EduFlex, una educación accesible para quienes no entienden en clases
PABLOCESARGARZONBENI
 
Alan Turing Vida o biografía resumida como presentación
Alan Turing Vida o biografía resumida como presentaciónAlan Turing Vida o biografía resumida como presentación
Alan Turing Vida o biografía resumida como presentación
JuanPrez962115
 
Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5
JulyMuoz18
 
Estructuras básicas_ conceptos de programación (1).docx
Estructuras básicas_ conceptos de programación  (1).docxEstructuras básicas_ conceptos de programación  (1).docx
Estructuras básicas_ conceptos de programación (1).docx
SamuelRamirez83524
 
Inteligencia Artificial y Ciberseguridad.pdf
Inteligencia Artificial y Ciberseguridad.pdfInteligencia Artificial y Ciberseguridad.pdf
Inteligencia Artificial y Ciberseguridad.pdf
Emilio Casbas
 
Posnarrativas en la era de la IA generativa
Posnarrativas en la era de la IA generativaPosnarrativas en la era de la IA generativa
Posnarrativas en la era de la IA generativa
Fernando Villares
 
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Telefónica
 
Estructuras Básicas_Tecnología_Grado10-7.pdf
Estructuras Básicas_Tecnología_Grado10-7.pdfEstructuras Básicas_Tecnología_Grado10-7.pdf
Estructuras Básicas_Tecnología_Grado10-7.pdf
cristianrb0324
 
Estructuras básicas_ conceptos básicos de programación.pdf
Estructuras básicas_  conceptos básicos de programación.pdfEstructuras básicas_  conceptos básicos de programación.pdf
Estructuras básicas_ conceptos básicos de programación.pdf
ItsSofi
 
Estructuras Básicas_ Conceptos Basicos De Programacion.pdf
Estructuras Básicas_ Conceptos Basicos De Programacion.pdfEstructuras Básicas_ Conceptos Basicos De Programacion.pdf
Estructuras Básicas_ Conceptos Basicos De Programacion.pdf
IsabellaRubio6
 
Desarrollo de Habilidades de Pensamiento.
Desarrollo de Habilidades de Pensamiento.Desarrollo de Habilidades de Pensamiento.
Desarrollo de Habilidades de Pensamiento.
AlejandraCasallas7
 
3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto
cdraco
 
Conceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación ProyectoConceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación Proyecto
cofferub
 
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdfDesarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
AlejandraCasallas7
 
Robótica educativa para la eduacion primaria .pptx
Robótica educativa para la eduacion primaria .pptxRobótica educativa para la eduacion primaria .pptx
Robótica educativa para la eduacion primaria .pptx
44652726
 
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdfTRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
thomasdcroz38
 

Último (20)

DESARROLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLO DE HABILIDADES DE PENSAMIENTO.pdfDESARROLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLO DE HABILIDADES DE PENSAMIENTO.pdf
 
Diagrama de flujo basada en la reparacion de automoviles.pdf
Diagrama de flujo basada en la reparacion de automoviles.pdfDiagrama de flujo basada en la reparacion de automoviles.pdf
Diagrama de flujo basada en la reparacion de automoviles.pdf
 
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTALINFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
 
Diagrama de flujo - ingenieria de sistemas 5to semestre
Diagrama de flujo - ingenieria de sistemas 5to semestreDiagrama de flujo - ingenieria de sistemas 5to semestre
Diagrama de flujo - ingenieria de sistemas 5to semestre
 
EduFlex, una educación accesible para quienes no entienden en clases
EduFlex, una educación accesible para quienes no entienden en clasesEduFlex, una educación accesible para quienes no entienden en clases
EduFlex, una educación accesible para quienes no entienden en clases
 
Alan Turing Vida o biografía resumida como presentación
Alan Turing Vida o biografía resumida como presentaciónAlan Turing Vida o biografía resumida como presentación
Alan Turing Vida o biografía resumida como presentación
 
Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5
 
Estructuras básicas_ conceptos de programación (1).docx
Estructuras básicas_ conceptos de programación  (1).docxEstructuras básicas_ conceptos de programación  (1).docx
Estructuras básicas_ conceptos de programación (1).docx
 
Inteligencia Artificial y Ciberseguridad.pdf
Inteligencia Artificial y Ciberseguridad.pdfInteligencia Artificial y Ciberseguridad.pdf
Inteligencia Artificial y Ciberseguridad.pdf
 
Posnarrativas en la era de la IA generativa
Posnarrativas en la era de la IA generativaPosnarrativas en la era de la IA generativa
Posnarrativas en la era de la IA generativa
 
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
 
Estructuras Básicas_Tecnología_Grado10-7.pdf
Estructuras Básicas_Tecnología_Grado10-7.pdfEstructuras Básicas_Tecnología_Grado10-7.pdf
Estructuras Básicas_Tecnología_Grado10-7.pdf
 
Estructuras básicas_ conceptos básicos de programación.pdf
Estructuras básicas_  conceptos básicos de programación.pdfEstructuras básicas_  conceptos básicos de programación.pdf
Estructuras básicas_ conceptos básicos de programación.pdf
 
Estructuras Básicas_ Conceptos Basicos De Programacion.pdf
Estructuras Básicas_ Conceptos Basicos De Programacion.pdfEstructuras Básicas_ Conceptos Basicos De Programacion.pdf
Estructuras Básicas_ Conceptos Basicos De Programacion.pdf
 
Desarrollo de Habilidades de Pensamiento.
Desarrollo de Habilidades de Pensamiento.Desarrollo de Habilidades de Pensamiento.
Desarrollo de Habilidades de Pensamiento.
 
3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto
 
Conceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación ProyectoConceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación Proyecto
 
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdfDesarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
 
Robótica educativa para la eduacion primaria .pptx
Robótica educativa para la eduacion primaria .pptxRobótica educativa para la eduacion primaria .pptx
Robótica educativa para la eduacion primaria .pptx
 
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdfTRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
 

02 python Programación orientada a objetos y funcional

  • 1. H EL LENGUAJE DE PROGRAMACIÓN PYTHON Juan Ignacio Rodríguez de León jileon en twitter euribates @ gmail.com Programación orientada a objetos Programación funcional
  • 2. Objetos y Clases  Las clases permiten que podamos definir nuestros propios tipos de datos  Las Clases definen las propiedases (atributos) y las capacidades y comportamiento (métodos) general de los nuevos tipos  Un objeto se crea o instancia a partir de una clase
  • 3. Objetos  Un objeto es una variable que representa un caso particular dentro del conjunto de posibles instancias de una clase  De la misma forma que podemos considerar al número 7 como una instancia particular de la clase Numeros Enteros
  • 4. Creación de clases  Palabra reservada class  La clase más sencilla que podemos pensar es: >>> class X: ... pass >>> >>> class X: ... pass >>>  Instanciamos un objeto usando el nombre de la clase como si fuera una función: >>> x = X() >>> print(x) >>> x = X() >>> print(x)
  • 5. La clase Point  Inicializador: Método con el nombre especial __init__  No es el constructor, pero casi class Point: def __init__(self, lat, lng): self.latitud = lat self.longitud = lng x = Point(28.4779, -16.3118) print(x.latitud, x.longitud) class Point: def __init__(self, lat, lng): self.latitud = lat self.longitud = lng x = Point(28.4779, -16.3118) print(x.latitud, x.longitud)
  • 6. ¿self?  Se crea el objeto.  Inmediatamente a continuación, como hemos visto, se llama al inicializador – los dos parámetros que usamos al crear al objeto son los mismos valores que se pasan al método inicializador con los nombres lat y lng  Pero ¿De donde sale el primer parámetro, self? ¿Y qué representa?
  • 7. Para programadores de C++ o Java  Para programadores de C++ o Java es la variable "magica" this.  En Python se prefirió esta forma por considerarla más explicita.  De igual manera, los atributos dentro de la función tienen que venir precedidos por el self., no hay alias mágicos para los atributos de la instancia, para evitar la ambigüedad.
  • 8. Seguimos con self  Empezemos por la segunda pregunta: self representa al propio objeto recien creado  Este primer parámetro es lo que diferencia a las funciones que ya conociamos de los métodos: – un método siempre tienen como primer parámetro la instancia sobre la que está siendo ejecutado.
  • 9. Quien pone self ahí  Al definir métodos para una clase, hay que reservar el primer parámetro para el propio objeto  Al llamar al método desde la instancia, Python ya se ocupa de poner el valor correcto como primer parámetro  La tradición y la costumbre marcan que este primer parámetro se llame self, pero en realidad no existe obligación de hacerlo (pero es conveniente hacerlo, por legibilidad)
  • 10. Herencia  Para poder hablar de clases y objetos con propidad es necesario que haya algún tipo de herencia  La herencia nos permite definir una clase a base de refinar o modificar otra (herencia simple) u otras (herencia múltiple)
  • 11. Herencia simple  Si una clase A deriva o hereda de una clase B (o también se dice que la clase B es 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étodos e incluso modificar o borrar los que ha heredado.
  • 12. Como declarar herencia en Python  La forma de expresar esta herencia en python es >>> class A(B): ... pass >>> class A(B): ... pass  Si la clase modifique un método que ha heredado, se dice que ha reescrito o sobreescrito (override) el método.
  • 13. Características de la herencia  Como los objetos instanciados de A tienen los mismos atributos y métodos que B, deben poder ser ser usados en cualquier sitio donde se 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. Polimorfismo  A puede sobreescribir un método f() de B  Si tenemos una lista con objetos de tipo A y de tipo B mezclados, podemos invocar sin miedo el método f() en todos ellos, con la seguridad de que en cada caso se invocará al método adecuado.  Esta capacidad se llama polimorfismo (del griego Múltiples Formas)
  • 15. Métodos o atributos privados  No existen en Python  Existe una convención de uso, por la cual si un atributo o método empieza con el carácter subrayado, ha de entenderse que: – Es de uso interno – No deberías jugar con él a no ser que sepas muy bien lo que estás haciendo – Si en un futuro tu código deja de funcionar porque has usado ese atributo o método, no puedes culpar a nadie más que a ti mismo
  • 16. Beneficios de usar clases/objetos  Reducir el tamaño del código evitando repeticiones – Si organizamos las herencias correctamente en jerarquias, de mas genéricas a más específicas, podemos compatibilizar el código común de las primeras con el más específico de las últimas  Encapsulamiento  Polimorfismo  Delegación de responsabilidades
  • 17. super  ¿Que pasa si A sobreescribe un método de B, pero aun así ha de invocarlo?  En realidad es un caso muy común, A quiere hacer lo mismo que B, y un poquito más.  Desde Python 2.2 hay una función super() que nos 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. Funciones auxiliares  isinstance(objeto, clase) – nos devolverá verdadero si el objeto es una instancia de una clase en particular, o de alguna de sus subclases  issubclass(objeto, clase) – nos devolverá verdadero si el objeto es una instancia de una subclase de la clase indicada.
  • 19. Sobrecarga de operadores  Se puede, como en C++, sobreescribir los operadores (operadores aritméticos, acceso por índices, etc...) mediante una sintaxis especial  Los métodos y atributos que empiezan y acaban con un doble signo de subrayado tiene por lo general un significado especial.
  • 20. Sobrecarga de operadores: len  Si en nuestra clase definimos un método __len__(), podemos hacer que las instancias de esa clase puedan ser usadas con la función len()  Véase ejemplos/clases_02.py
  • 21. Sobrecarga de operadores: índices  Si a una clase le añadimos los métodos __setitem__ y __getitem__ podemos hacer que se comporte como si fuera una contenedor accesible mediante las operaciones de índices
  • 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 cara def __getitem__(self, index): if 0 <= index < 7: return self._Tabla[index] else: return 'Muchos' def __setitem__(self, index, value): pass 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 cara def __getitem__(self, index): if 0 <= index < 7: return self._Tabla[index] else: return 'Muchos' def __setitem__(self, index, value): pass Ejemplos/clases_03.py
  • 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 para sumar 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, poder hacer v3 = v1 + v2v3 = v1 + v2
  • 24. class Vector: def __init__(self, x, y): self.x = x self.y = y def __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 = x self.y = y def __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. Sobrecarga de operadores: +/-  Para eso definimos los métodos especiales __add__ y __sub__ para definir el comportamiento cuando se sumen o resten dos instancias de nuesta clase.  Véase ejemplos/clases_04.py  Existen muchos métodos especiales  A Guide to Python's Magic Methods: – http://www.rafekettler.com/magicmethods.html
  • 26. Excepciones  Errores sintáctis y excepciones  Información del error  Las excepciones se producen durante la ejecución – Pueden ser tratadas: “capturadas” – Si no se capturan, el programa acaba
  • 27. Tipos de excepciones  Según el error  ZeroDivisionError, ValueError, etc...  Como capturar excepciones: try/except try: a, b = 7, 0 c = a / b except ZeroDivisionError: print("No puedo dividir por cero") try: a, b = 7, 0 c = a / b except ZeroDivisionError: print("No puedo dividir por cero")
  • 28. Tratamiento de excepciones  Puede haber varias cláusulas except, para cada tipo de error  Una cláusula puede gestionar varios errores  Puede haber una clausula except general (No recomendado)  Podemos volver a “elevar” la excepcion que hemos capturado
  • 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. Argumento de la excepción  La excepción se representa con un valor que tiene los detalles del error  Usando la palabra reservada as podemos almacenar este 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. Legibilidad del código con excepciones  Los programas en C suelen consistir en una serie de llamadas a funciones intercaladas con comprobaciones de resultados  Con excepciones: – La gestión de los errores no se entromete con la función del algoritmo – Está centralizada y aparte
  • 32. Elevar excepciones  Podemos elevar nosotros mismos excepciones, usando la palabra reservada raise  Podemos definir nuestras propias excepciones – Derivadas de Exception – Jerarquía de excepciones
  • 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. Gestores de contexto: with  with nos permite "envolver" un bloque de código con operaciones a ejecutar antes y después del mismo  Simetría en las operaciones  Garantía de ejecución  Se pueden anidar  Ejemplos – ficheros: open/close – memoria: malloc/free
  • 35. Más claro try: f = open('fichero.datos', 'r') # proceso el fichero n = len(f.readlines()) finally: f.close() try: f = open('fichero.datos', 'r') # proceso el fichero n = 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. Como funciona with (1)  Usando Gestores de contexto  Son objetos que saben lo que hay que hacer antes y después de usar otro objeto  El generador de contexto de file sabe que hay que cerrar el archivo  Imposible olvidarse de cerrarlo
  • 37. Como funciona with (2) 1) Evaluación y obtención del gestor de contexto 2) Se carga __exit__() 3) Se ejecuta __enter__() (si devuelve un valor y se ha usado as, se asigna a la variable) 4) Se ejecuta el bloque 5) Se llama a __exit__() (con información de errores, si hubiera)
  • 38. Iteradores  Nuestras clases y objetos pueden ser iterables  Como funciona for internamente: – Se llama a iter() pasándole lo que quiera que sea que vamos a iterar – Obtenemos un iterador, es decir, un objeto con un metodo next() – Llamamos a next() repetidas veces... – Hasta que termina: se eleva StopIteration
  • 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. Es fácil añadir “iterabilidad”  Definir un método con el nombre __iter__() que devuelva un objeto  Este objeto debe implementar un método next() – Cada vez que se llame a next(), este debe devolver el siguiente elemento – A no ser que no queden, entonces, eleva StopIteration  Nuestra clase puede ser su propio iterador: basta con definir next() y en __iter__ devolver self
  • 41. Ejercicio  Crear una clase CuentaAtras, que sea iterable y que, ejem, cuente hacia atrás hasta llegar al cero.
  • 42. Solución class CuentaAtras: def __init__(self, tope): self.tope = tope def __iter__(self): self.counter = self.tope return self def next(self): return self.__next__() # python 2.7 def __next__(self): result = self.counter self.counter -= 1 if result < 0: raise StopIteration return result class CuentaAtras: def __init__(self, tope): self.tope = tope def __iter__(self): self.counter = self.tope return self def next(self): return self.__next__() # python 2.7 def __next__(self): result = self.counter self.counter -= 1 if result < 0: raise StopIteration return result
  • 43. Generadores  Forma sencilla y potente de crear iteradores  Como una función, pero devuelven resultados con yield, en vez de return  Cada vez que se llama a next(), el generador continua a partir de donde se quedó  Recuerda su estado: valores de las variables, última línea que se ejecutó, etc...
  • 44. Cuenta Atras (como generador) >>> def cuenta_atras(n): ... while n >= 0: ... yield n ... n -= 1 ... >>> for i in cuenta_atras(5): print(i) ... 5 4 3 2 1 0 >>> >>> def cuenta_atras(n): ... while n >= 0: ... yield n ... n -= 1 ... >>> for i in cuenta_atras(5): print(i) ... 5 4 3 2 1 0 >>>
  • 45. Ventajas  Igual potencia que un iterador  Solo por usar yield ya se sabe que es un generador  Normalmente más fáciles de escribir  Generación automática de next() y de __iter__()  Eleva automáticamente StopIteration
  • 46. Ejemplos de generadores/iteradores  El módulo os.path, como veremos más adelante, tiene una función walk, que es un generador que nos permite recorrer un árbol de directorios  El módulo itertools define una funcion combinations que nos da las combinaciones de m elementos tomandos de n en n
  • 47. Ejemplo de combinaciones  Combinaciones tomando los cuatro elementos 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.
  • 50. Ajustar cuentas  Estan investigando un caso de un ex-tesorero y una doble facturación  Hay una serie de ingresos por un lado  Y una serie de pagos por otro  Demostrar que la serie de pagos se corresponden, sumadas, con los ingresos.
  • 52. Los pagos 1404.93 € 207.68 € 297.39 € 1816.42 € 153.56 € 1286.85 € 322.90 € 175.04 € 335.43 € 259.74 € 301.28 € 1384.43 €
  • 53. ¿Como podemos hacerlo?  Empezar por uno de los ingresos – Tomar las combinaciones de pagos y tomarlas de una en una. Ver si sumadas coinciden con el ingreso – Tomar las combinaciones de pagos y tomarlas de dos en dos. Ver si sumadas coinciden con el ingreso – Seguir asi buscando combinaciones hasta que una coincida. Cuando se encuentra, retirar esos pagos de la lista de pagos y seguir con el siguiente ingreso
  • 54. Herramientas  Conseguir las combinaciones usando itertoos.combinations.  La función sum() nos suma los elementos de una secuencia  Empezar con una versión minima del problema: 2 ingresos, 4 pagos, por ejemplo.  Solución en: – ejemplos/facturacion_b.py
  • 55. facturacion_b.py (1) from decimal import Decimal import itertools ingresos = [ 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 Decimal import itertools ingresos = [ 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'), ]
  • 56. facturacion_b.py (2) for ingreso in ingresos: solucion = None for size in range(1, len(pagos)+1): # Probando combinaciones de size elementos for 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) break if solucion: for pago in solucion: pagos.remove(pago) for ingreso in ingresos: solucion = None for size in range(1, len(pagos)+1): # Probando combinaciones de size elementos for 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) break if solucion: for pago in solucion: pagos.remove(pago)
  • 57. Solución 1816.42 + 153.56 + 1286.85 + 322.9 + 175.04 + 335.43 = 4090.20 1404.93 + 207.68 + 297.39 = 1910.00 259.74 + 301.28 + 1384.43 = 1945.45
  • 58. Programación funcional  Las funciones solo son otro tipo de variable  Todo lo que se puede hacer con una variable, 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 primera clase”
  • 59. Funciones Lambda λ  Crear pequeñas funciones anónimas  lambda <argumentos>: <expresion>  Función que suma los dos parámetros que se le pasan: – lambda(x,y): x+y  No hace falta especificar return  Azucar sintáctico para una definición de función normal
  • 60. filter  Primer parámetro: una función  Segundo parámetro: una secuencia  Devuelve: otra secuencia en la que se estan sólo aquellos valores de la secuencia original para los que el resultado de aplicarles la función es True
  • 61. Ejemplo Calcular los primeros 200 números que son divisibles por 5 y por 7
  • 62. los primeros 200 números que 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) ... 35 70 105 140 175 >>> >>> def div57(x): ... return x % 5 == 0 and x % 7 == 0 ... >>> for i in filter(div57, range(1, 201)): ... print(i) ... 35 70 105 140 175 >>>
  • 63. map  Primer parámetro: una función  Segundo parámetro: una secuencia  Devuelve: otra secuencia, compuesta por los resultados de llamar a la función en cada uno de los elementos de la secuencia original
  • 64. 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] >>>
  • 65. map (2)  Podemos pasar más de una secuencia  La función pasada como parámetro debe aceptar tantos parámetros como secuencias haya  Ejercicio: media de los datos de otras dos listas
  • 66. 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] >>>
  • 67. 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 tiene que aceptar dos valores, y retornar uno – Se calcula el resultado de aplicar la función a los dos primeros valores de la secuencia – A continuación, se aplica de nuevo la función, usando como parámetros el dato anterior y al tercer elemento de la secuencia – Así hasta acabar la secuencia original
  • 68. Ejercicio: sumar los valores de una lista
  • 69. Ejercicio: sumar los valores de 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 >>>
  • 70. Ejercicio: sumar los valores de 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) = 3 Suma(3,3) = 6 Suma(6,4) = 10 Suma(10,5) = 15 Suma(15,6) = 21 Suma(21,7) = 28 Suma(28,8) = 36 Suma(36,9) = 45 Suma(45,10) = 55
  • 71. Ejercicio: sumar los valores de 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 ya existe una función incorporada para ello: sum(seq), que funciona exactamente igual, pero más rápido al estár implementada en C.
  • 72. Compresión de listas  Forma muy expresiva de crear listas  Usos comunes – Crear una lista cuyos elementos son resultado de aplicar una serie de operaciones a otra secuencia – Crear una sebsecuencia de aquellos elementos que cumplan una determinada condición  En resumen, nos permiten hacer lo mismo que map o filter, pero de forma más legible.
  • 73. 10 Números cuadrados  Podemos crear una lista con los cuadrados de los 10 primeros números así: >>> 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] >>>
  • 74. 10 Números cuadrados  O así, con map squares = map(lambda x: x**2, range(10))squares = map(lambda x: x**2, range(10))
  • 75. 10 Números cuadrados  Con comprensión de listas es aun más fácil squares = [x**2 for x in range(11)]squares = [x**2 for x in range(11)]
  • 76. Anatomía de una C.L.  Corchete [  Expresión  Cláusula for  Cero, una o más cláusulas if  Corchete ]
  • 77. Ejercicio  ¿Cuáles de los primeros 1500 números enteros cumplen la condición de que su cubo acaba en 272? – str() convierte un número en texto – endswith() es un metodo de los textos que devuelve True si la cadena de texto sobre la que se aplica acaba en el texto indicado como parámetro: ● 'hola'.endswith('a') → True
  • 78. 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]
  • 79. Expresiones generadoras  Muy similar a una conprensión de lista  Pero devuelve un generador, no una lista  La sintaxis es idéntica, sustituyendo los corchetes por paréntesis – con la lista obtenemos todos los elementos ya generados (y, por tanto, consumiendo memoria) – El generador nos irá dando los valores de uno en uno (lazy evaluation)
  • 80. 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) ... 1 4 [...] 81 100 >>> >>> 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) ... 1 4 [...] 81 100 >>>
  • 81. Comprensión de diccionarios  Crear diccionarios a partir de otras fuentes de datos  Sintaxis similar, pero cambiando corchetes/paréntesis por llaves: {}  La expresión tienen que tener la forma <clave>:<valor>
  • 82. 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'} >>>
  • 83. Conprensión de conjuntos  Definir un conjunto a partir de otros valores  Igual que con los diccionarios, pero la expresión no va en la forma <clave>:<valor>, sino como una expresión simple  NO se puede crear así un diccionario vacio (Crearía un diccionario)
  • 84. Ejemplo >>> s = {'a', 'b', 'c'} >>> s set(['a', 'c', 'b']) >>> s = {str(x**2) for x in range(7)} >>> type(s) <type 'set'> >>> s set(['25', '16', '36', '1', '0', '4', '9']) >>> >>> s = {'a', 'b', 'c'} >>> s set(['a', 'c', 'b']) >>> s = {str(x**2) for x in range(7)} >>> type(s) <type 'set'> >>> s set(['25', '16', '36', '1', '0', '4', '9']) >>>
  • 85. Decoradores  Funciones como objetos de primer nivel  Las funciones se pueden almacenar, pasar como parámetros...  … o ser devueltas como resultado de una función  Una función puede devolver otra función
  • 86. Suena raro... Una función … … puede devolver … … otra función
  • 87. 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
  • 88. ¿Qué es un decorador?  Sabiendo que esto es posible, un decorador es: – Una función que acepta como parámetro una función, y devuelve otra función, que normalmente sustituirá a la original. – Es decir, un decorador nos permite modificar una función (Normalmente haciendo algo antes, o después, o ambas cosas)
  • 90. ¿Para qué sirve un decorador?  El uso de decoradores se enfoca a resolver el siguiente problema: – Tenemos un conjunto de funciones – Queremos que todas ellas hagan una nueva cosa, algo por lo general ajeno al propio comportamiento de la función, y que todas lo hagan por igual. – En otras palabras, queremos añadir una funcionalidad horizontal.
  • 91. Ejemplo de situación  Supongamos que tenemos un conjunto de funciones a(), b(),..., z(), cada una de ellas con sus parámetros, particularidades, etc...  Queremos ahora, con el mínimo trabajo posible, que cada función escriba en un fichero log cuando empieza a trabajar y cuanto termina.
  • 92. Opción A (de “A lo bruto”) Reescribir cada una de las funciones def a(): # código de a def a(): # código de a Pasar de esto: def a(): with open('/tmp/log.txt', 'a') as log: log.write('Empieza la función an') # codigo de a with 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 a with open('/tmp/log.txt', 'a') as log: log.write('Acaba la función an') A esto:
  • 93. 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 queda difuminada con todas esas llamadas a escribir el log  Si queremos cambiar la información del log, (incluir fecha y hora, p.e.) hay que volver a modificar todas las funciones
  • 94. Opción D (De “decoradores”)  Intenta solucionar estos problemas  Un decorador coge las función original, (a(), b(),..., z() en nuestro caso), la modifica y la reemplaza  Ahora, cuando se llama a a(), se invoca en realidad a nuestra versión modificada (que a su vez invocará a la a() original)
  • 95. Decorador “logged”  Para el ejemplo de log, primero creamos una función decoradora, que llamaramos logged()  Para simplificar, en vez de escribir a un fichero log nos limitaremos a hacer dos prints, uno antes de que empieze la función y otro después
  • 96. Código de logged def 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 def 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
  • 97. Aplicación del decorador def a(): print('Soy a()') def b(): print('Soy b()') b = logged(b) @logged def c(): print('Soy c()') @logged def 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) @logged def c(): print('Soy c()') @logged def d(msg): print('Soy d y digo: {}'.format(msg)) a() b() c() d('Hola, mundo')
  • 98. Aplicación de decoradores La forma: @logged def c(): print('Soy c()') @logged def 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 el decorador es poner el símbolo @ y el nombre del decorador antes de la definición de la función
  • 99. Ventaja de los decoradores  Hay que tocar el código de cada función, si, pero el cambio es mínimo: añadir el decorador con el simbolo @  El código no se repite. No hay aumento apreciable de tamaño del mismo  El código interno de las funciones decoradas no se ve perturbado por la nueva funcionalidad.  Podemos añadir nuevas características a las funciones "logeadas" modificando solo una cosa: el decorador