Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 61

Lenguaje de programación Python

Lenguaje de programación
Python

1
Compilación: Alejandro Vergara Vargas

Lenguaje de programación
Python

Compilación: Alejandro Vergara Vargas

2
Lenguaje de programación Python

UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO

Director General de Cómputo y de Tecnologías de Información y Comunicación


Felipe Bracho Carpizo

Directora de Docencia en Tecnologías de Información y Comunicación


Adela Castillejos Salazar

LENGUAJE DE PROGRAMACIÓN PYTHON


Compilación
Alejandro Vergara Vargas

DIRECCIÓN GENERAL DE CÓMPUTO Y DE TECNOLOGÍAS DE INFORMACIÓN Y COMUNICACIÓN


Circuito exterior s/n, Ciudad Universitaria, Coyoacán, CP. 04510, México DF.

3
Compilación: Alejandro Vergara Vargas

Contenido

1. ELEMENTOS BÁSICOS DE UN PROGRAMA ________________ 7


1.1. Bibliotecas ............................................................................................... 7

1.2. Funciones................................................................................................... 7

1.3. Variables .................................................................................................... 8

2. ESTILO DE PROGRAMACIÓN ____________________________ 9


2.1. Indentación ................................................................................................. 9

2.2. Comentarios ............................................................................................... 9

3. TIPOS DE DATOS _____________________________________ 10


3.1. Numéricos ................................................................................................ 10

3.2. Booleanos ................................................................................................ 12

3.3. Cadenas ................................................................................................... 12

3.4. Listas ........................................................................................................ 14

3.5. Tuplas ...................................................................................................... 18

3.6. Conjuntos ................................................................................................. 19

3.7. Diccionarios .............................................................................................. 20

3.7.1 ¿Qué es una tabla Hash? ______________________________ 21

4. OPERADORES _______________________________________ 22
4.1. Aritméticos ............................................................................................... 22

4.2. Relacionales ............................................................................................. 23

5. ESTRUCTURAS DE CONTROL __________________________ 24


5.1. If ............................................................................................................... 24

5.2. If – Else .................................................................................................... 24

5.3. While ........................................................................................................ 25

4
Lenguaje de programación Python

5.3.1. Continue ___________________________________________ 25

5.3.2. Break _____________________________________________ 26

5.4. Do – while ................................................................................................ 26

5.5. Switch/Case ............................................................................................. 26

5.6. For ............................................................................................................ 27

5.6.1. For-each ___________________________________________ 27

5.6.2. Con rangos _________________________________________ 28

6. PROGRAMACIÓN FUNCIONAL__________________________ 29
6.1. Estructura de una función ........................................................................ 29

6.2. Generadores ............................................................................................ 33

6.3 Built-ins ..................................................................................................... 34

6.4. Decoradores ............................................................................................. 35

6.5. Listas por comprensión ............................................................................ 36

6.6. Lambdas .................................................................................................. 37

7. PROGRAMACIÓN ORIENTADA A OBJETOS_______________ 39


7.1. Clases ...................................................................................................... 39

7.2. Objetos ..................................................................................................... 41

7.3. Herencia ................................................................................................... 42

7.3.1. Herencia múltiple ____________________________________ 44

7.4. Polimorfismo ............................................................................................ 44

8. PROGRAMACIÓN MODULAR ___________________________ 46


8.1. Módulos.................................................................................................... 46

8.2. Paquetes .................................................................................................. 48

8.3. Namespaces ............................................................................................ 49

8.4. Generar ejecutables ................................................................................. 50

5
Compilación: Alejandro Vergara Vargas

8.5. Documentación ........................................................................................ 53

9. DEPURACIÓN ________________________________________ 54
9.1. Uso de PDB ............................................................................................. 54

BIBLIOGRAFÍA _________________________________________ 60
FUENTES ELECTRÓNICAS _______________________________ 61

6
Lenguaje de programación Python

1. ELEMENTOS BÁSICOS DE UN
PROGRAMA

1.1. Bibliotecas
Python proporciona una gran cantidad de bibliotecas de funciones que podemos
agregar a nuestros programas. Algunas bibliotecas se proporcionan como parte de la
instalación de Python en una computadora; Otras pueden ser cargadas desde internet.
Un programa de Python puede hacer uso de múltiples bibliotecas simultáneamente.

1.2. Funciones

Una función es un fragmento de código con un nombre asociado que


realiza una serie de tareas y devuelve un valor. A los fragmentos de código que
tienen un nombre asociado y no devuelven valores se les suele llamar
procedimientos. En Python no existen los procedimientos, ya que cuando el
programador no especifica un valor de retorno la función devuelve el valor None
(nada), equivalente al null de Java. Además de ayudarnos a programar y depurar
dividiendo el programa en partes las funciones también permiten reutilizar
código. En Python las funciones se declaran de la siguiente forma: def
mi_funcion(param1, param2): print param1 print param2 Es decir, la palabra
clave def seguida del nombre de la función y entre paréntesis los argumentos
separados por comas. A continuación, en otra línea, indentado y después de los
dos puntos tendríamos las líneas de código que conforman el código a ejecutar
por la función. También podemos encontrarnos con una cadena de texto como
primera línea del cuerpo de la función. Estas cadenas se conocen con el nombre
de docstring (cadena de documentación) y sirven, como su nombre indica, a
modo de documentación de la función. def mi_funcion(param1, param2): “““Esta
funcion imprime los dos valores pasados como parametros””” print param1 print
param2

7
Compilación: Alejandro Vergara Vargas

1.3. Variables
Una variable es un sitio donde guardamos una determinada información. En función del
tipo de información que guardemos (texto, números, booleanas, etc.), la variable será
de uno u otro tipo. Por simplicidad sólo vamos a ver las variables de texto y numéricas,
ya que son las que se usan en más del 80% de las ocasiones.

Cada variable tiene que tener un nombre con el que referirnos a ella. Python tiene en
cuenta si escribimos en mayúsculas o minúsculas la variable (lo que se conoce como
case sensitive). No es lo mismo una variable que se llame f1 que una que se llame F1.

Como es lógico y, para evitar confusiones, el nombre de la variable no puede coincidir


con los nombres de los “comandos” de python (if, for, etc.). Tampoco podremos usar
nombres de variables con tildes o con ñ.

8
Lenguaje de programación Python

2. ESTILO DE PROGRAMACIÓN

2.1. Indentación
Es una característica deliberada de Python, ya que obliga a los programadores a
producir código uniforme, regular y legible. Básicamente significa que debe alinear su
código verticalmente, en columnas, de acuerdo con su estructura lógica. El efecto que
se produce es hacer que su código sea más consistente y legible y por lo tanto
reutilizable y fácil de mantener; ya sea por usted o por otros programadores. Un
ejemplo:
while True:
respuesta = input('Dame el password: ')
if respuesta == 'nose\r' : break
print('No es el password!')
print('Bye')

Si usted modifica la indentación, por ejemplo, del último print, y lo alinea al nivel de
columna del print anterior, el programa será diferente, ya que el intérprete de Python lo
considerará como parte del while:
while True:
respuesta = input('Dame el password: ')
if respuesta == 'nose\r' : break
print('No es el password!')
print('Bye')

Se considera como línea indentada a partir de un carácter, sin embargo es común


emplear 4 caracteres por legibilidad.

2.2. Comentarios
Los comentarios en Python se pueden colocar de dos formas, escribiendo el
símbolo gato o almohadilla (#) primero, y después el comentario, o escribiendo triple
comilla doble (”””) al principio y al final del comentario (para comentarios que usen más
de una línea). Ejemplo:

# Declaramos las variables


celsius=0
farenheit=0
""" A continuacion declaramos los métodos
que se usarán para convertir
de grados Celsius a grados Farenheit y viceversa.
"""

9
Compilación: Alejandro Vergara Vargas

3. TIPOS DE DATOS

3.1. Numéricos
La mayoría de los tipos numéricos en Python son los comunes a los otros
lenguajes de programación.

En Python, los números no son realmente un solo tipo de objeto, sino una
categoría de tipos muy similares.

Python admite los tipos numéricos habituales (enteros y puntos flotantes), así
como literales para crear números y expresiones para procesarlos. Además, Python
proporciona un soporte de programación numérica más avanzada y objetos para un
trabajo más avanzado.

La lista completa de la caja de herramientas numérica de Python incluye:

• Objetos enteros y de punto flotante

• Objetos de números complejos

• Decimales: objetos de precisión fija.

• Fracciones: objetos de números racionales.

• Conjuntos: colecciones con operaciones numéricas.

Entre sus tipos básicos, Python proporciona los números enteros, que son números
enteros positivos y negativos, y números de punto flotante, que son números con una
parte fraccionaria (a veces llamados "flotantes"). Python también nos permite escribir
números enteros usando literales hexadecimales, octales y binarios; ofrece un tipo de
número complejo; y permite que los enteros tengan una precisión ilimitada; pueden
crecer hasta tener tantos dígitos como su espacio de memoria lo permita. En Python 3,
el tipo de datos long ha sido eliminado y todos los valores enteros son manejados por la
clase Int. El tamaño predeterminado de Int dependerá de la arquitectura de su CPU.

En los sistemas de 32 bits, el tipo de datos predeterminado para los enteros será 'Int32'.
En los sistemas de 64 bits, el tipo de datos predeterminado para los enteros será 'Int64'.
Los valores mínimos / máximos de cada tipo se pueden encontrar a continuación:

Int8: [-128,127]

Int16: [-32768,32767]

10
Lenguaje de programación Python

Int32: [-2147483648,2147483647]

Int64: [-9223372036854775808,9223372036854775807]

Int128:[-170141183460469231731687303715884105728,
170141183460469231731687303715884105727]

UInt8: [0,255]

UInt16: [0,65535]

UInt32: [0,4294967295]

UInt64: [0,18446744073709551615]

UInt128: [0,340282366920938463463374607431768211455]

Si el tamaño de tu Int supera los límites mencionados anteriormente, Python 3


cambiará automáticamente su tipo y asignará más memoria para manejar este aumento
en los valores mínimo / máximo.

Ejemplos de tipos númericos:

entero = 23
print(type(entero)) #imprime <class 'int'>

flotante =23.5
print(type(flotante)) #imprime <class 'float'>

complejo = 5+3j
print(type(complejo)) #imprime <class 'complex'>
print("------------------------")

numBinario=0b111
print("El numero binario {0} en base 10 es = {1}".format(bin(numBinario),numBinario))

numOctal=0o20
print("El numero octal {0} en base 10 es = {1}".format(oct(numOctal),numOctal))

numHex=0xff
print("El numero hexadecimal {0} en base 10 es = {1}".format(hex(numHex),numHex))
print("------------------------")

from fractions import Fraction


fraccion1 = Fraction(5,10)
fraccion2 = Fraction(1,4)
print("{0} + {1} = {2}".format(fraccion1,fraccion2,fraccion1 + fraccion2))
print("{0} - {1} = {2}".format(fraccion1,fraccion2,fraccion1 - fraccion2))
print("{0} / {1} = {2}".format(fraccion1,fraccion2,fraccion1 / fraccion2))

11
Compilación: Alejandro Vergara Vargas

print("{0} * {1} = {2}".format(fraccion1,fraccion2,fraccion1 * fraccion2))

numDecimal = 2.25
fraccion3 = Fraction(numDecimal)
print("{0} = {1}".format(numDecimal,fraccion3))
print("------------------------")

3.2. Booleanos
El tipo booleano, tiene como representación solamente 2 valores: 0 (cero) y 1
(uno). Este nombre proviene del matemático George Boole, inventor de la Álgebra
Booleana.

Estos dos valores posibles se prestan a diversas intepretaciones: Sí/No,


Encendido/Apagado, Verdadero/Falso, en fin, todo aquello que represente dos estados
contrarios. En Python su representación es mediante las constantes True (1,
verdadero) y False (0, falso).

print("El valor booleano verdadero se representa como: {0}".format(True))


print("El valor booleano falso se representa como: {0}".format(False))

3.3. Cadenas
En Python podemos crear una cadena de caracteres simplemente encerrando el
contenido entre comillas dobles:

saludo = "Hola mundo!"

Así mismo, podemos hacer operaciones con las cadenas de caracteres, por
ejemplo para unir o concatenar dos o más cadenas, empleamos el operador de suma
(+):

#Concatenar
saludo = 'Hola' + ' ' + 'mundo!'
print(saludo)

En caso de requerir copias de una cadena de caracteres se utiliza el operador de


multiplicación(*):

#Copias de cadenas
saludos = 'Hola ' * 4
destinatario = 'Mundo!'
print(saludos + destinatario)

12
Lenguaje de programación Python

Para añadir texto al final de una cadena, se utiliza el operador (+=):

#Añadir texto al final de una cadena de caracteres


mensaje = 'Hola'
mensaje += ' '
mensaje += 'Mundo'
print(mensaje)

Para determinar el número de caracteres que hay en una cadena se utiliza el


método len. Por cierto, el carácter espacio también cuenta:

#Longitud de una cadena


oracion = 'hola' + ' ' + 'mundo!'
print("La longitud de la oracion '{0}' es de {1} caracteres".format(oracion,len(oracion)))

Para buscar una sub-cadena en una cadena de caracteres se emplea el método


find y el método indicará el índice de inicio de la misma. Los índices están numerados
de izquierda a derecha y el número con el que se inicia a contar la posición es el 0:

#Buscar la posicion de una sub-cadena


salu2 = "Hola Mundo"
subCadena = salu2.find("Mundo")
print("La palabra 'Mundo' inicia en la posicion {0}, de la cadena '{1}'".format(subCadena,salu2))

Si la sub-cadena no está presente, el método devolverá el valor -1.

En caso de necesitar convertir una cadena de caracteres a minúsculas, se utiliza


el método lower:

#Convertir MAYUSCULAS a minusculas


mayusculas = "HOLA MUNDO!"
minusculas = mayusculas.lower()
print("mensaje original '{0}', mensaje convertido a minusculas
'{1}'".format(mayusculas,minusculas))

La operación contraria es el método upper.

Cuando se requiera cambiar una sub-cadena de una cadena se puede utilizar el


método replace:

#Reemplazar una cadena de caracteres


original = "HOLA MUNDO!"
nueva = original.replace("MUNDO", "CRAYOLA")
print("Mensaje original '{0}', mensaje nuevo '{1}'".format(original,nueva))

13
Compilación: Alejandro Vergara Vargas

También se puede cortar parte de la cadena a partir de una posición concreta


hasta otra posición específica:

#Recorte de una cadena de caracteres


saludo3 = "Hola Mundo!"
saludo4 = saludo3[1:7]
saludo5 = saludo3[8:11]
otroSaludo = saludo4 + saludo5
print(otroSaludo)

Las secuencias de escape nos permiten por ejemplo, escribir las comillas dobles
adentro de un print y que Python no lo interprete como el fin del mensaje a imprimir:

#Secuencias de escape
print("El texto siguiente puede estar \"entre comillado\" \ngracias a las
secuencias de escape.")
print("\tTambien puedo escribir con tabulador \ny en otra linea.")

3.4. Listas
Las listas son conjuntos ordenados de elementos (números, cadenas, listas, etc).
Las listas se delimitan por corchetes ([ ]) y los elementos se separan por comas.

#Las listas pueden contener elementos homogeneos:


primos = [2, 3, 5, 7, 11, 13]
diasLaborables = ["Lunes", "Martes", "Miercoles", "Jueves", "Viernes"]
print(primos)
print(diasLaborables)

#Las listas pueden contener elementos heterogéneos:


fecha = ["Georgina", 27, "Mayo", 2010]
print(fecha)

#Las listas pueden contener listas


peliculas = [ ["Senderos de Gloria", 1957], ["El Resplandor", 1980]]
print(peliculas)
#Imprimir el segundo elemento de la lista peliculas:
print(peliculas[1])

#Las listas pueden tener muchos niveles de anidamiento:


directores = [ ["Stanley Kubrick", ["Senderos de Gloria", 1957]], ["Akira
Kurosawa", ["Los Siete Samurais", 1957]] ]
print(directores[0])

14
Lenguaje de programación Python

#Al definir una lista se puede hacer referencia a otras variables.


nombreDirector = "Stanley"
edadDirector = 68
director = [nombreDirector, edadDirector]
print(director)

#Si se trata objetos inmutables, el resto de variables no resultan afectadas,


como muestra el siguiente ejemplo:
nombre = "Pepe"
edad = 25
lista = [nombre, edad]
print(lista)
nombre = "Juan"
print(lista)

""" Pero si se trata de objetos mutables y al modificar la variable se


modifica el objeto,
el resto de variables si resultan afectadas, como muestra el siguiente
ejemplo:
"""
nombresAlumnos = ["Ana", "Bernardo"]
edadesAlumnos = [22, 21]
alumnos = [nombresAlumnos, edadesAlumnos]
print(alumnos)
nombresAlumnos += ["Cristina"]
print(alumnos)

#Se pueden concatenar listas utilizando el operador de suma.


#Solamente aplica a listas con listas.
empleado1 = ["Ana", 25]
empleado2 = ["Benito", 23]
empleado3 = ["Diana", 22]
empleados = empleado1 + empleado2 + empleado3
print(empleados)

#También se puede utilizar el operador += para añadir elementos a una


lista:
empleado4 = ["Norma", 24]
empleados += empleado4
print(empleados)

"""De una lista se pueden extraer sublistas, utilizando la notacion


nombreDeLista[inicio:limite],
donde inicio y limite hacen el mismo papel que en el tipo range(inicio,
limite).
"""

15
Compilación: Alejandro Vergara Vargas

dias = ["Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes",


"Sabado"]
diasClase = dias[1:6] # Se extrae una lista con los valores 1, 2, 3, 4 y 5
print(diasClase)

# Se extrae una lista con el valor 4


print(dias[4:5])

# Se extrae una lista vacia


print(dias[4:4])

# Se extrae una lista hasta el valor 4 (no incluido)


print(dias[:4])

# Se extrae una lista desde el valor 4 (incluido)


print(dias[4:])

# Se extrae una lista con todos los valores


print(dias[:])

"""La palabra reservada del permite eliminar un elemento o


varios elementos a la vez de una lista, e incluso la misma lista.
"""
alfabeto = ["A", "B", "C", "D", "E", "F", "G", "H"]

# Elimina la sublista ['E']


del alfabeto[4]
print(alfabeto)

# Elimina la sublista ['B', 'C', 'D']


del alfabeto[1:4]
print(alfabeto)

# Elimina completamente la lista


del alfabeto
#No se puede imprimir ya que no existe la lista
#print(alfabeto)
print("----------------------------")

"""Con variables de tipo entero, decimal o de cadena,


es facil tener una copia de una variable para conservar
un valor que en la variable original se ha perdido:
"""
a=5
b = a # Hacemos una copia del valor de a
print(a, b)

16
Lenguaje de programación Python

a = 4 # de manera que aunque cambiemos el valor de a ...


print(a, b) # ... b conserva el valor anterior de a en caso de necesitarlo
print("----------------------------")
#Pero si hacemos esto mismo con listas, nos podemos llevar un sorpresa:

listaLetras1 = ["A", "B", "C"]


temporal1 = listaLetras1 # Intentamos hacer una copia de la lista
listaLetras1
print(listaLetras1, temporal1)

del listaLetras1[1] # Eliminamos el elemento ['B'] de la lista listaLetras1 ...


print(listaLetras1, temporal1) # ... pero descubrimos que tambien ha
desparecido de la lista temporal1
print("----------------------------")
"""Los enteros, decimales y cadenas son objetos inmutables
y las listas son objetos mutables.
Si queremos copiar una lista, de manera que conservemos su valor
aunque modifiquemos la lista original,
debemos utilizar la notacion de sublistas.
"""
listaLetras2 = ["A", "B", "C"]

# Hacemos una copia de la lista listaLetras


temporal = listaLetras2[:]# <----- ojo aquí
print(listaLetras2, temporal)

# Eliminamos el elemento ['B'] de la lista listaLetras2 ...


del listaLetras2[1]

# ... y en este caso temporal sigue conservando el valor original de


listaLetras2
print(listaLetras2, temporal)

"""En el primer caso las variables listaLetras2 y temporal


hacen referencia a la misma lista almacenada en la memoria del
ordenador.
Por eso al eliminar un elemento de listaLetras2, tambien desaparece de
temporal.
“””
# Una vez creada una lista, se pueden añadir cuantos valores se desee.
# el método append agregará el elemento especificado al final de la lista.
impares = [1, 3, 5, 7]
print(impares)
print(type(impares))
impares.append(9)
print(impares)

17
Compilación: Alejandro Vergara Vargas

3.5. Tuplas

Las tuplas son inmutables. Una vez que se crea una tupla, no se puede
cambiar ni su contenido ni su tamaño, a menos que se haga una copia de la
tupla. En las tuplas no se permite añadir, eliminar, mover elementos, etc. Es
decir, no se utiliza el append, extend, remove. Por otro lado, las tuplas si
permiten extraer porciones, pero el resultado de la extracción es una tupla
nueva. Se permiten búsquedas (index); también se permite comprobar si un
elemento se encuentra en la tupla.
Las tuplas se escriben entre paréntesis ( ) en vez de entre corchetes [ ].
Por lo tanto, las tuplas consisten en un conjunto de objetos ordenados que
pueden ser de cualquier tipo (es decir, strings, listas, diccionarios, tuplas, etc.), y
se puede acceder a cada elemento mediante un índice. Es importante señalar
que las tuplas almacenan referencias de los objetos que contienen.

Las ventajas de las tuplas respecto a las listas es que ocupan menos
espacio en memoria, son más rápidas para su acceso en tiempo de procesador,
formatean strings y pueden utilizarse como claves en un diccionario (las listas,
no).
Veamos algunos ejemplos:

# Creamos dos tuplas y las comparamos


a = ()
b = tuple()
print("La tupla a{0} == b{1}? {2}".format(a, b, a == b))

""" Como las tuplas son estaticas,


se deben especificar sus elementos durante la creacion:
"""

a = (793, "Doroteo", "Arango", "Garcia", True, -1.5)

""" Si se quiere crear una tupla con un unico elemento,


debe anadirse una coma (,) antes de cerrar el parentesis:
"""
c = (5,) # Tupla unitaria
print(type(c)) # Imprime <class 'tuple'>

# En cambio, esta es una lista unitaria


d = [5]
print(type(d)) # Imprime <class 'list'>

""" Puedes acceder a los distintos elementos de una tupla


indicando el indice (comenzando desde el 0) entre corchetes.

18
Lenguaje de programación Python

"""
a = (793, "Doroteo", "Arango", "Garcia", True, -1.5)
print(a[0])
print(a[2])
print(a[1])

3.6. Conjuntos

Python también tiene definido por default el tipo de datos Conjunto (Set), y
desde el lenguaje podemos hacer las operaciones típicas con ellos:

# Creando un conjunto en python


A = {1,2,0}

# Creando un conjunto a partir de una lista


frutas = ["toronjas", "kiwis", "naranjas", "limones"]
Acidas = set(frutas)

# Cardinalidad de un conjunto con len().


print("La cardinalidad del conjunto A = {0} es {1}".format(A,len(A)))

# comprobando membresía
pertenece = 2 in A
print("El elemento {0} esta en el conjunto {1} ? {2}".format(2,A,pertenece))

# Igualdad entre conjuntos. El orden de los elementos no importa.


B = {1,2,3,4}
C = {4,2,3,0}
print("El conjunto {0} == {1} ? {2}".format(B,C,B == C))

# Union de conjuntos
D = {1,2,3,4,5}
E = {4,5,6,7,8,9,10,0}
print("{0} union {1} = \n{2}".format(D,E,D.union(E)))

# Intersección de conjuntos
print("{0} interseccion {1} = \n{2}".format(D,E,D.intersection(E)))

# Diferencia entre conjuntos


print("{0} - {1} = \n{2}".format(D,E,D-E))
print("{0} - {1} = \n{2}".format(E,D,E-D))
print("------------------------")

19
Compilación: Alejandro Vergara Vargas

3.7. Diccionarios
Los diccionarios, también llamados matrices asociativas, deben su
nombre a que son colecciones que relacionan una clave y un valor. Por ejemplo,
veamos un diccionario de películas y directores:

d = {“Love Actually “: “Richard Curtis”,


“Kill Bill”: “Tarantino”,
“Amélie”: “Jean-Pierre Jeunet”}

El primer valor se trata de la clave y el segundo del valor asociado a la


clave. Como clave podemos utilizar cualquier valor inmutable: podríamos usar
números, cadenas, booleanos, tuplas, … pero no listas o diccionarios, dado que
son mutables. Esto es así porque los diccionarios se implementan como tablas
hash**, y a la hora de introducir un nuevo par clave-valor en el diccionario se
calcula el hash de la clave para después poder encontrar la entrada
correspondiente rápidamente. Si se modificara el objeto clave después de haber
sido introducido en el diccionario, evidentemente, su hash también cambiaría y
no podría ser encontrado.
La diferencia principal entre los diccionarios y las listas o las tuplas es que
a los valores almacenados en un diccionario se les accede no por su índice,
porque de hecho no tienen orden, sino por su clave, utilizando de nuevo el
operador [].

d[“Love Actually “] # devuelve “Richard Curtis”

Al igual que en listas y tuplas también se puede utilizar este operador para
reasignar valores.

d[“Kill Bill”] = “Quentin Tarantino”

Sin embargo, en este caso no se puede utilizar slicing, entre otras cosas
porque los diccionarios no son secuencias, si no mappings (mapeados,
asociaciones).

20
Lenguaje de programación Python

3.7.1 ¿Qué es una tabla Hash?

21
Compilación: Alejandro Vergara Vargas

4. OPERADORES
Veamos ahora qué podemos hacer con nuestros números usando los
operadores por defecto. Para operaciones más complejas podemos recurrir al módulo
math.

4.1. Aritméticos

Operadores aritméticos
Operador Descripción Ejemplo
+ Suma r = 3 + 2 # r es 5
- Resta r = 4 - 7 # r es -3
- Negación r = -7 # r es -7
* Multiplicación r = 2 * 6 # r es 12
** Exponente r = 2 ** 6 # r es 64
/ División r = 3.5 / 2 # r es 1.75
// División entera r = 3.5 // 2 # r es 1.0
% Módulo r = 7 % 2 # r es 1

Puede que tenga dudas sobre cómo funciona el operador de módulo, y cuál es la
diferencia entre división y división entera.

El operador de módulo no hace otra cosa que devolvernos el resto de la división


entre los dos operandos. En el ejemplo, 7/2 sería 3, con 1 de resto, luego el módulo es
1.

La diferencia entre división y división entera no es otra que la que indica su


nombre. En la división el resultado que se devuelve es un número real, mientras que en
la división entera el resultado que se devuelve es solo la parte entera.

No obstante, hay que tener en cuenta que, si utilizamos dos operandos enteros,
Python determinará que queremos que la variable resultado también sea un entero, por
lo que el resultado de, por ejemplo, 3 / 2 y 3 // 2 sería el mismo: 1.

Si quisiéramos obtener los decimales necesitaríamos que al menos uno de los


operandos fuera un número real, bien indicando los decimales
r = 3.0 / 2

o bien utilizando la función float (no es necesario que sepais lo que significa el
término función, ni que recordeis esta forma, lo veremos un poco más adelante):

22
Lenguaje de programación Python

r = float(3) / 2

Esto es así porque cuando se mezclan tipos de números, Python con Python para
todos 20

vierte todos los operandos al tipo más complejo de entre los tipos de los
operandos.

4.2. Relacionales

Para describir la evaluación a realizar sobre una condición, se utilizan


operadores relacionales (o de comparación):

Y para evaluar más de una condición simultáneamente, se utilizan operadores


lógicos

23
Compilación: Alejandro Vergara Vargas

5. ESTRUCTURAS DE CONTROL
Las estructuras de control condicionales, son aquellas que nos permiten
evaluar si una o más condiciones se cumplen, para decir qué acción vamos a
ejecutar. La evaluación de condiciones, solo puede arrojar 1 de 2 resultados:
verdadero o falso (True o False).

5.1. If
Se utiliza para evaluar solo una condición verdadera

5.2. If – Else

Se utiliza para evaluar condición verdadera y condición falsa

Para evaluar Múltiples condiciones utilizamos if – elif – else

24
Lenguaje de programación Python

5.3. While
El bucle while (mientras) ejecuta un fragmento de código mientras se cumpla una
condición.

En ocasiones, tenemos que repetir varias veces una determinada tarea hasta
conseguir nuestro objetivo. En Python esto se realiza con el comando while.

Esto es lo que se conoce como un blucle infinito.

5.3.1. Continue
Sentencia que nos permite saltar sentecias de ejecución de una estructura
repetitive y avanza al siguiente elemento de comparación de la estructura.

Sólo imprimirá los Felicidades para la edad con número par.

25
Compilación: Alejandro Vergara Vargas

5.3.2. Break
Sentencia que nos permite salir de una estructura repetitiva.
Sin embargo hay situaciones en las que un bucle infinito es útil. Por
ejemplo, veamos un pequeño programa que repite todo lo que el usuario diga
hasta que escriba adios.

5.4. Do – while
No existe directamente en Python, pero se puede emular de la siguiente
manera:
A veces nos encontramos con situaciones en las que queremos utilizar el
do-whilebucle antiguo en Python. La importancia de un do-whilebucle es que es
un post-test loop, lo que significa que comprueba la condición onlydespués de
ejecutar el bloque de bucle una vez. Aunque Python no lo tiene explícitamente,
seguramente podemos emularlo.

5.5. Switch/Case

No existe una estructura específica como en otros lenguajes de


programación.
La forma de Python de implementar la instrucción switch es utilizar las
asignaciones de diccionarios, también conocidas como matrices asociativas, que
proporcionan asignaciones simples de clave-valor de uno a uno.

26
Lenguaje de programación Python

5.6. For

El bucle for en Python se usa para iterar sobre una secuencia (lista, tupla,
cadena) u otros objetos iterables. Iterar sobre una secuencia se llama recorrido.

5.6.1. For-each

Generalmente este es el único ciclo que puede hacer la estructura For,


para cada elemento ejecuta las sentencias del cuerpo For

27
Compilación: Alejandro Vergara Vargas

5.6.2. Con rangos

También permite especificar dentro de los elementos de la secuencia

28
Lenguaje de programación Python

6. PROGRAMACIÓN FUNCIONAL
La programación funcional es un paradigma en el que la programación se
basa casi en su totalidad en funciones, entendiendo el concepto de función
según su definición matemática, y no como los simples subprogramas de los
lenguajes imperativos que hemos visto hasta ahora.

En los lenguajes funcionales puros un programa consiste exclusivamente


en la aplicación de distintas funciones a un valor de entrada para obtener un
valor de salida.

Python, sin ser un lenguaje puramente funcional incluye varias


características tomadas de los lenguajes funcionales como son las funciones de
orden superior o las funciones lambda (funciones anónimas).

6.1. Estructura de una función


En Python las funciones se declaran de la siguiente forma:
def mi_funcion(param1, param2):

print param1
print param2

Es decir, la palabra clave def seguida del nombre de la función y entre


paréntesis los argumentos separados por comas. A continuación, en otra línea,
indentado y después de los dos puntos tendríamos las líneas de código que
conforman el código a ejecutar por la función.

También podemos encontrarnos con una cadena de texto como primera


línea del cuerpo de la función. Estas cadenas se conocen con el nombre de
docstring (cadena de documentación) y sirven, como su nombre indica, a modo
de documentación de la función.

def mi_funcion(param1, param2):


“““Esta funcion imprime los dos valores pasados
como parametros”””
print param1
print param2

Volviendo a la declaración de funciones, es importante aclarar que al


declarar la función lo único que hacemos es asociar un nombre al fragmento de
código que conforma la función, de forma que podamos ejecutar dicho código

29
Compilación: Alejandro Vergara Vargas

más tarde referenciándolo por su nombre. Es decir, a la hora de escribir estas


líneas no se ejecuta la función. Para llamar a la función (ejecutar su código) se
escribiría:

mi_funcion(“hola”, 2)

Es decir, el nombre de la función a la que queremos llamar seguido de los


valores que queramos pasar como parámetros entre paréntesis. La asociación
de los parámetros y los valores pasados a la función se hace normalmente de
izquierda a derecha: como a param1 le hemos dado un valor “hola” y param2
vale 2, mi_funcion imprimiría hola en una línea, y a continuación 2.

Sin embargo también es posible modificar el orden de los parámetros si


indicamos el nombre del parámetro al que asociar el valor a la hora de llamar a
la función:

mi_funcion(param2 = 2, param1 = “hola”)

El número de valores que se pasan como parámetro al llamar a la función


tiene que coincidir con el número de parámetros que la función acepta según la
declaración de la función. En caso contrario Python se quejará:

>>> mi_funcion(“hola”)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: mi_funcion() takes exactly 2 arguments (1 given)

También es posible, no obstante, definir funciones con un número variable


de argumentos, o bien asignar valores por defecto a los parámetros para el caso
de que no se indique ningún valor para ese parámetro al llamar a la función.

Los valores por defecto para los parámetros se definen situando un signo
igual después del nombre del parámetro y a continuación el valor por defecto:

def imprimir(texto, veces = 1):


print veces * texto

En el ejemplo anterior si no indicamos un valor para el segundo parámetro


se imprimirá una sola vez la cadena que le pasamos como primer parámetro:

>>> imprimir(“hola”)
hola

si se le indica otro valor, será este el que se utilice:

>>> imprimir(“hola”, 2)
holahola

30
Lenguaje de programación Python

Para definir funciones con un número variable de argumentos colocamos


un último parámetro para la función cuyo nombre debe precederse de un signo *:

def varios(param1, param2, *otros):


for val in otros:
print val
varios(1, 2)
varios(1, 2, 3)
varios(1, 2, 3, 4)

Esta sintaxis funciona creando una tupla (de nombre otros en el ejemplo)
en la que se almacenan los valores de todos los parámetros extra pasados como
argumento. Para la primera llamada, varios(1, 2), la tupla otros estaría vacía
dado que no se han pasado más parámetros que los dos definidos por defecto,
por lo tanto no se imprimiría nada. En la segunda llamada otros valdría (3, ), y en
la tercera (3, 4).

También se puede preceder el nombre del último parámetro con **, en


cuyo caso en lugar de una tupla se utilizaría un diccionario. Las claves de este
diccionario serían los nombres de los parámetros indicados al llamar a la función
y los valores del diccionario, los valores asociados a estos parámetros.

En el siguiente ejemplo se utiliza la función items de los diccionarios, que


devuelve una lista con sus elementos, para imprimir los parámetros que contiene
el diccionario.

def varios(param1, param2, **otros):


for i in otros.items():
print i

varios(1, 2, tercero = 3)

Por cierto, quizás surga la duda ahora de si en Python al pasar una


variable como argumento de una función estas se pasan por referencia o por
valor. En el paso por referencia lo que se pasa como argumento es una
referencia o puntero a la variable, es decir, la dirección de memoria en la que se
encuentra el contenido de la variable, y no el contenido en si. En el paso por
valor, por el contrario, lo que se pasa como argumento es el valor que contenía
la variable.

La diferencia entre ambos estriba en que en el paso por valor los cambios
que se hagan sobre el parámetro no se ven fuera de la función, dado que los
argumentos de la función son variables locales a la función que contienen los
valores indicados por las variables que se pasaron como argumento. Es decir, en
realidad lo que se le pasa a la función son copias de los valores y no las
variables en si.

31
Compilación: Alejandro Vergara Vargas

Si quisiéramos modificar el valor de uno de los argumentos y que estos


cambios se reflejaran fuera de la función tendríamos que pasar el parámetro por
referencia.

En Python se utiliza el paso por valor de referencias a objetos, ya que


Python todo es un objeto (para ser exactos lo que ocurre en realidad es que al
objeto se le asigna otra etiqueta o nombre en el espacio de nombres local de la
función).

Sin embargo, no todos los cambios que hagamos a los parámetros dentro
de una función Python se reflejarán fuera de esta, ya que hay que tener en
cuenta que en Python existen objetos inmutables, como las tuplas, por lo que si
intentáramos modificar una tupla pasada como parámetro lo que ocurriría en
realidad es que se crearía una nueva instancia, por lo que los cambios no se
verían fuera de la función.

Veamos un pequeño programa para demostrarlo. En este ejemplo se hace


uso del método append de las listas. Un método no es más que una función que
pertenece a un objeto, en este caso a una lista; y append, en concreto, sirve
para añadir un elemento a una lista.

def f(x, y):


x=x+3
y.append(23)
print x, y

x = 22
y = [22]
f(x, y)
print x, y

El resultado de la ejecución de este programa sería:

25 [22, 23]
22 [22, 23]

Como vemos la variable x no conserva los cambios una vez salimos de la


función porque los enteros son inmutables en Python. Sin embargo, la variable y
si los conserva, porque las listas son mutables.

En resumen: los valores mutables se comportan como paso por


referencia, y los inmutables como paso por valor.

Con esto terminamos todo lo relacionado con los parámetros de las


funciones. Veamos por último cómo devolver valores, para lo que se utiliza la
palabra clave return:

32
Lenguaje de programación Python

def sumar(x, y):


return x + y

print sumar(3, 2)

Como vemos esta función tan sencilla no hace otra cosa que sumar los
valores pasados como parámetro y devolver el resultado como valor de retorno.

También podríamos pasar varios valores que retornar a return.

def f(x, y):


return x * 2, y * 2

a, b = f(1, 2)

Sin embargo, esto no quiere decir que las funciones Python puedan
devolver varios valores, lo que ocurre en realidad es que Python crea una tupla
al vuelo cuyos elementos son los valores a retornar, y esta única variable es la
que se devuelve.

6.2. Generadores
Las expresiones generadoras funcionan de forma muy similar a la
comprensión de listas. De hecho, su sintaxis es exactamente igual, a excepción
de que se utilizan paréntesis en lugar de corchetes:

l2 = (n ** 2 for n in l)

Sin embargo, las expresiones generadoras se diferencian de la


comprensión de listas en que no se devuelve una lista, sino un generador.

>>> l2 = [n ** 2 for n in l]
>>> l2
[0, 1, 4, 9]
>>> l2 = (n ** 2 for n in l)
>>> l2
<generator object at 0×00E33210>

Un generador es una clase especial de función que genera valores sobre


los que iterar. Para devolver el siguiente valor sobre el que iterar se utiliza la
palabra clave yield en lugar de return. Veamos por ejemplo un generador que
devuelva números de n a m con un salto s.

33
Compilación: Alejandro Vergara Vargas

def mi_generador(n, m, s):


while(n <= m):
yield n
n += s

>>> x = mi_generador(0, 5, 1)
>>> x
<generator object at 0×00E25710>

El generador se puede utilizar en cualquier lugar donde se necesite un


objeto iterable. Por ejemplo en un for-in:

for n in mi_generador(0, 5, 1):


print n

Como no estamos creando una lista completa en memoria, sino


generando un solo valor cada vez que se necesita, en situaciones en las que no
sea necesario tener la lista completa el uso de generadores puede suponer una
gran diferencia de memoria. En todo caso siempre es posible crear una lista a
partir de un generador mediante la función list:

lista = list(mi_generador)

6.3 Built-ins

El intérprete de Python tiene una serie de funciones y tipos incorporados


que siempre están disponibles. Se enumeran aquí en orden alfabético (Ver 3.7).

34
Lenguaje de programación Python

6.4. Decoradores
Un decorador no es es más que una función que recibe una función como
parámetro y devuelve otra función como resultado. Por ejemplo, podríamos
querer añadir la funcionalidad de que se imprimiera el nombre de la función
llamada por motivos de depuración:

def mi_decorador(funcion):
def nueva(*args):
print “Llamada a la funcion”, funcion.__name__
retorno = funcion(*args)
return retorno
return nueva

Como vemos el código de la función mi_decorador no hace más que crear


una nueva función y devolverla. Esta nueva función imprime el nombre de la
función a la que “decoramos”, ejecuta el código de dicha función, y devuelve su
valor de retorno. Es decir, que si llamáramos a la nueva función que nos
devuelve mi_decorador, el resultado sería el mismo que el de llamar
directamente a la función que le pasamos como parámetro, exceptuando el que
se imprimiría además el nombre de la función.

Supongamos como ejemplo una función imp que no hace otra cosa que
mostrar en pantalla la cadena pasada como parámetro.

35
Compilación: Alejandro Vergara Vargas

>>> imp(“hola”)
hola
>>> mi_decorador(imp)(“hola”)
Llamada a la función imp
Hola

La sintaxis para llamar a la función que nos devuelve mi_decorador no es


muy clara, aunque si lo estudiamos detenidamente veremos que no tiene mayor
complicación. Primero se llama a la función que decora con la función a decorar:
mi_decorador(imp); y una vez obtenida la función ya decorada se la puede
llamar pasando el mismo parámetro que se pasó anteriormente:
mi_decorador(imp)(“hola”)
Esto se podría expresar más claramente precediendo la definición de la
función que queremos decorar con el signo @ seguido del nombre de la función
decoradora:

@mi_decorador
def imp(s):
print s
De esta forma cada vez que se llame a imp se estará llamando realmente
a la versión decorada. Python incorpora esta sintaxis desde la versión 2.4 en
adelante.

Si quisiéramos aplicar más de un decorador bastaría añadir una nueva


línea con el nuevo decorador.

@otro_decorador
@mi_decorador
def imp(s):
print s

Es importante advertir que los decoradores se ejecutarán de abajo a


arriba. Es decir, en este ejemplo primero se ejecutaría mi_decorador y después
otro_decorador.

6.5. Listas por comprensión


La comprensión de listas es una característica tomada del lenguaje de
programación funcional Haskell que está presente en Python desde la versión
2.0 y consiste en una construcción que permite crear listas a partir de otras
listas.
Cada una de estas construcciones consta de una expresión que
determina cómo modificar el elemento de la lista original, seguida de una o
varias clausulas for y opcionalmente una o varias clausulas if.

36
Lenguaje de programación Python

Veamos un ejemplo de cómo se podría utilizar la comprensión de listas


para elevar al cuadrado todos los elementos de una lista:

l2 = [n ** 2 for n in l]

Esta expresión se leería como “para cada n en l haz n ** 2”.

Como vemos tenemos primero la expresión que modifica los valores de la


lista original (n ** 2), después el for, el nombre que vamos a utilizar para
referirnos al elemento actual de la lista original, el in, y la lista sobre la que se
itera.
El ejemplo que utilizamos para la función filter (conservar solo los
números que son pares) se podría expresar con comprensión de listas así:

l2 = [n for n in l if n % 2.0 == 0]

Veamos por último un ejemplo de compresión de listas con varias


clausulas for:

l = [0, 1, 2, 3]
m = [“a”, “b”]
n = [s * v for s in m
for v in l
if v > 0]

Esta construcción sería equivalente a una serie de for-in anidados:

l = [0, 1, 2, 3]
m = [“a”, “b”]
n = []

for s in m:
for v in l:
if v > 0:
n.append(s* v)

6.6. Lambdas
El operador lambda sirve para crear funciones anónimas en línea. Al ser
funciones anónimas, es decir, sin nombre, estas no podrán ser referenciadas
más tarde.

Las funciones lambda se construyen mediante el operador lambda, los


parámetros de la función separados por comas (atención, SIN paréntesis), dos
puntos (:) y el código de la función.

37
Compilación: Alejandro Vergara Vargas

En una funcion que conserva sólo los números pares, quedaría de la


forma tradicional así:

def es_par(n):
return (n % 2.0 == 0)

l = [1, 2, 3]
l2 = filter(es_par, l)

Con la función lambda sería:

l = [1, 2, 3]
l2 = filter(lambda n: n % 2.0 == 0, l)

Las funciones lambda están restringidas por la sintaxis a una sola


expresión.

38
Lenguaje de programación Python

7. PROGRAMACIÓN ORIENTADA A
OBJETOS
Python es un lenguaje multiparadigma en el se puede trabajar con
programación estructurada, o con programación orientada a objetos o con el
paradigma de programación funcional.

La Programación Orientada a Objetos (POO u OOP según sus siglas en


inglés) es un paradigma de programación en el que los conceptos del mundo
real relevantes para nuestro problema se modelan a través de clases y objetos, y
en el que nuestro programa consiste en una serie de interacciones entre estos
objetos.

7.1. Clases
Para entender este paradigma primero tenemos que comprender qué es
una clase y qué es un objeto. Un objeto es una entidad que agrupa un estado y
una funcionalidad relacionadas. El estado del objeto se define a través de
variables llamadas atributos, mientras que la funcionalidad se modela a través de
funciones a las que se les conoce con el nombre de métodos del objeto.

Un ejemplo de objeto podría ser un coche, en el que tendríamos atributos


como la marca, el número de puertas o el tipo de carburante y métodos como
arrancar y parar. O bien cualquier otra combinación de atributos y métodos
según lo que fuera relevante para nuestro programa.

Una clase, por otro lado, no es más que una plantilla genérica a partir de
la cuál instanciar los objetos; plantilla que es la que define qué atributos y
métodos tendrán los objetos de esa clase.

Volviendo a nuestro ejemplo: en el mundo real existe un conjunto de


objetos a los que llamamos coches y que tienen un conjunto de atributos
comunes y un comportamiento común, esto es a lo que llamamos clase. Sin
embargo, mi coche no es igual que el coche de mi vecino, y aunque pertenecen
a la misma clase de objetos, son objetos distintos.

En Python las clases se definen mediante la palabra clave class seguida


del nombre de la clase, dos puntos (:) y a continuación, indentado, el cuerpo de
la clase. Como en el caso de las funciones, si la primera línea del cuerpo se trata
de una cadena de texto, esta será la cadena de documentación de la clase o
docstring.

39
Compilación: Alejandro Vergara Vargas

class Coche:
“””Abstraccion de los objetos coche.”””
def __init__(self, gasolina):
self.gasolina = gasolina
print “Tenemos”, gasolina, “litros”

def arrancar(self):
if self.gasolina > 0:
print “Arranca”
else:
print “No arranca”

def conducir(self):
if self.gasolina > 0:
self.gasolina -= 1
print “Quedan”, self.gasolina, “litros”
else:
print “No se mueve”

Lo primero que llama la atención en el ejemplo anterior es el nombre tan


curioso que tiene el método __init__. Este nombre es una convención y no un
capricho. El método __init__, con una doble barra baja al principio y final del
nombre, se ejecuta justo después de crear un nuevo objeto a partir de la clase,
proceso que se conoce con el nombre de instanciación. El método __init__ sirve,
como sugiere su nombre, para realizar cualquier proceso de inicialización que
sea necesario.

Como vemos el primer parámetro de __init__ y del resto de métodos de la


clase es siempre self. Esta es una idea inspirada en Modula-3 y sirve para
referirse al objeto actual. Este mecanismo es necesario para poder acceder a los
atributos y métodos del objeto diferenciando, por ejemplo, una variable local
mi_var de un atributo del objeto self.mi_var.

Si volvemos al método __init__ de nuestra clase Coche veremos cómo se


utiliza self para asignar al atributo gasolina del objeto (self.gasolina) el valor que
el programador especificó para el parámetro gasolina. El parámetro gasolina se
destruye al final de la función, mientras que el atributo gasolina se conserva (y
puede ser accedido) mientras el objeto viva.

Para crear un objeto se escribiría el nombre de la clase seguido de


cualquier parámetro que sea necesario entre paréntesis. Estos parámetros son
los que se pasarán al método __init__, que como decíamos es el método que se
llama al instanciar la clase.

mi_coche = Coche(3)

40
Lenguaje de programación Python

¿Cómo es posible que a la hora de crear nuestro primer objeto pasemos


un solo parámetro a __init__, el número 3, cuando la definición de la función
indica claramente que precisa de dos parámetros (self y gasolina)? esto es así
porque Python pasa el primer argumento (la referencia al objeto que se crea)
automáticamente.

Ahora que ya hemos creado nuestro objeto, podemos acceder a sus


atributos y métodos mediante la sintaxis objeto.atributo y objeto.metodo():

>>> print mi_coche.gasolina


3
>>> mi_coche.arrancar()
Arranca
>>> mi_coche.conducir()
Quedan 2 litros
>>> mi_coche.conducir()
Quedan 1 litros
>>> mi_coche.conducir()
Quedan 0 litros
>>> mi_coche.conducir()
Orientación a objetos
45
No se mueve
>>> mi_coche.arrancar()
No arranca
>>> print mi_coche.gasolina
0

Por último, pero no menos importante hay que recordar que en Python,
todo son objetos. Las cadenas, por ejemplo, tienen métodos como upper(), que
devuelve el texto en mayúsculas o count(sub), que devuelve el número de veces
que se encontró la cadena sub en el texto.

7.2. Objetos
Para crear un objeto se escribiría el nombre de la clase seguido de
cualquier parámetro que sea necesario entre paréntesis. Estos parámetros son
los que se pasarán al método __init__, que como decíamos es el método que se
llama al instanciar la clase.

mi_coche = Coche(3)

¿Cómo es posible que a la hora de crear nuestro primer objeto pasemos


un solo parámetro a __init__, el número 3, cuando la definición de la función
indica claramente que precisa de dos parámetros (self y gasolina)? esto es así

41
Compilación: Alejandro Vergara Vargas

porque Python pasa el primer argumento (la referencia al objeto que se crea)
automáticamente.

Ahora que ya hemos creado nuestro objeto, podemos acceder a sus


atributos y métodos mediante la sintaxis objeto.atributo y objeto.metodo():

>>> print mi_coche.gasolina


3
>>> mi_coche.arrancar()
Arranca
>>> mi_coche.conducir()
Quedan 2 litros
>>> mi_coche.conducir()
Quedan 1 litros
>>> mi_coche.conducir()
Quedan 0 litros
>>> mi_coche.conducir()
Orientación a objetos
45
No se mueve
>>> mi_coche.arrancar()
No arranca
>>> print mi_coche.gasolina
0

Por último, pero no menos importante hay que recordar que en Python,
todo son objetos. Las cadenas, por ejemplo, tienen métodos como upper(), que
devuelve el texto en mayúsculas o count(sub), que devuelve el número de veces
que se encontró la cadena sub en el texto.

7.3. Herencia
Hay tres conceptos que son básicos para cualquier lenguaje de
programación orientado a objetos: el encapsulamiento, la herencia y el
polimorfismo.

En un lenguaje orientado a objetos cuando hacemos que una clase


(subclase) herede de otra clase (superclase) estamos haciendo que la subclase
contenga todos los atributos y métodos que tenía la superclase. No obstante, al
acto de heredar de una clase también se le llama a menudo “extender una
clase”.

Supongamos que queremos modelar los instrumentos musicales de una


banda, tendremos entonces una clase Guitarra, una clase Batería, una clase
Bajo, etc. Cada una de estas clases tendrá una serie de atributos y métodos,
pero ocurre que, por el mero hecho de ser instrumentos musicales, estas clases

42
Lenguaje de programación Python

compartirán muchos de sus atributos y métodos; un ejemplo sería el método


tocar().

Es más sencillo crear un tipo de objeto Instrumento con las atributos y


métodos comunes e indicar al programa que Guitarra, Batería y Bajo son tipos
de instrumentos, haciendo que hereden de Instrumento.

Para indicar que una clase hereda de otra se coloca el nombre de la clase
de la que se hereda entre paréntesis después del nombre de la clase:

class Instrumento:

def __init__(self, precio):


self.precio = precio

def tocar(self):
print “Estamos tocando musica”

def romper(self):
print “Eso lo pagas tu”
print “Son”, self.precio, “$$$”

class Bateria(Instrumento):
pass

class Guitarra(Instrumento):
pass

Como Bateria y Guitarra heredan de Instrumento, ambos tienen un


método tocar() y un método romper(), y se inicializan pasando un parámetro
precio.

Pero, ¿qué ocurriría si quisiéramos especificar un nuevo parámetro


tipo_cuerda a la hora de crear un objeto Guitarra? Bastaría con escribir un
nuevo método __init__ para la clase Guitarra que se ejecutaría en lugar del
__init__ de Instrumento.

Esto es lo que se conoce como sobreescribir de métodos. Ahora bien,


puede ocurrir en algunos casos que necesitemos sobreescribir un método de la
clase padre, pero que en ese método queramos ejecutar el método de la clase
padre porque nuestro nuevo método no necesite más que ejecutar un par de
nuevas instrucciones extra. En ese caso usaríamos la sintaxis
SuperClase.metodo(self, args) para llamar al método de igual nombre de la clase
padre. Por ejemplo, para llamar al método __init__ de Instrumento desde
Guitarra usaríamos Instrumento.__init__(self, precio)

43
Compilación: Alejandro Vergara Vargas

Hay que observar que en este caso, si es necesario especificar el


parámetro self.

7.3.1. Herencia múltiple

En Python, a diferencia de otros lenguajes como Java o C#, se permite la


herencia múltiple, es decir, una clase puede heredar de varias clases a la vez.
Por ejemplo, podríamos tener una clase Cocodrilo que heredara de la clase
Terrestre, con métodos como caminar() y atributos como velocidad_caminar y de
la clase Acuatico, con métodos como nadar() y atributos como velocidad_nadar.
Basta con enumerar las clases de las que se hereda separándolas por comas:

class Cocodrilo(Terrestre, Acuatico):


pass

En el caso de que alguna de las clases padre tuvieran métodos con el


mismo nombre y número de parámetros las clases sobreescribirían la
implementación de los métodos de las clases más a su derecha en la definición.

En el siguiente ejemplo, como Terrestre se encuentra más a la izquierda,


sería la definición de desplazar de esta clase la que prevalecería, y por lo tanto si
llamamos al método desplazar de un objeto de tipo Cocodrilo lo que se
imprimiría sería “El animal anda”.

class Terrestre:
def desplazar(self):
print “El animal anda”

class Acuatico:
def desplazar(self):
print “El animal nada”

class Cocodrilo(Terrestre, Acuatico):


pass

c = Cocodrilo()
c.desplazar()

7.4. Polimorfismo
La palabra polimorfismo, del griego poly morphos (varias formas), se
refiere a la habilidad de objetos de distintas clases de responder al mismo
mensaje. Esto se puede conseguir a través de la herencia: un objeto de una

44
Lenguaje de programación Python

clase derivada es al mismo tiempo un objeto de la clase padre, de forma que allí
donde se requiere un objeto de la clase padre también se puede utilizar uno de
la clase hija.

Python, al ser de tipado dinámico, no impone restricciones a los tipos que


se le pueden pasar a una función, por ejemplo, más allá de que el objeto se
comporte como se espera: si se va a llamar a un método f() del objeto pasado
como parámetro, por ejemplo, evidentemente el objeto tendrá que contar con
ese método. Por ese motivo, a diferencia de lenguajes de tipado estático como
Java o C++, el polimorfismo en Python no es de gran importancia.

En ocasiones también se utiliza el término polimorfismo para referirse a la


sobrecarga de métodos, término que se define como la capacidad del lenguaje
de determinar qué método ejecutar de entre varios métodos con igual nombre
según el tipo o número de los parámetros que se le pasa. En Python no existe
sobrecarga de métodos (el último método sobreescribiría la implementación de
los anteriores), aunque se puede conseguir un comportamiento similar
recurriendo a funciones con valores por defecto para los parámetros o a la
sintaxis *params o **params explicada en el capítulo sobre las funciones en
Python, o bien usando decoradores.

45
Compilación: Alejandro Vergara Vargas

8. PROGRAMACIÓN MODULAR

8.1. Módulos
Para facilitar el mantenimiento y la lectura los programas demasiado
largos pueden dividirse en módulos, agrupando elementos relacionados. Los
módulos son entidades que permiten una organización y división lógica de
nuestro código. Los archivos son su contrapartida física: cada archivo Python
almacenado en disco equivale a un módulo.

Vamos a crear nuestro primer módulo entonces creando un pequeño


archivo modulo.py con el siguiente contenido:

def mi_funcion():
print “una funcion”

class MiClase:
def __init__(self):
print “una clase”
print “un modulo”

Si quisiéramos utilizar la funcionalidad definida en este módulo en nuestro


programa tendríamos que importarlo. Para importar un módulo se utiliza la
palabra clave import seguida del nombre del módulo, que consiste en el nombre
del archivo menos la extensión. Como ejemplo, creemos un archivo programa.py
en el mismo directorio en el que guardamos el archivo del módulo (esto es
importante, porque si no se encuentra en el mismo directorio Python no podrá
encontrarlo), con el siguiente contenido:

import modulo
modulo.mi_funcion()

El import no solo hace que tengamos disponible todo lo definido dentro del
módulo, sino que también ejecuta el código del módulo. Por esta razón nuestro
programa, además de imprimir el texto “una funcion” al llamar a mi_funcion,
también imprimiría el texto “un modulo”, debido al print del módulo importado. No
se imprimiría, no obstante, el texto “una clase”, ya que lo que se hizo en el
módulo fue tan solo definir de la clase, no instanciarla.

La cláusula import también permite importar varios módulos en la misma


línea. En el siguiente ejemplo podemos ver cómo se importa con una sola

46
Lenguaje de programación Python

clausula import los módulos de la distribución por defecto de Python os, que
engloba funcionalidad relativa al sistema operativo; sys, con funcionalidad
relacionada con el propio intérprete de Python y time, en el que se almacenan
funciones para manipular fechas y horas.

import os, sys, time


print time.asctime()

Podremos observar en este y el anterior ejemplo en un detalle importante,


y es que, como vemos, es necesario preceder el nombre de los objetos que
importamos de un módulo con el nombre del módulo al que pertenecen, o lo que
es lo mismo, el espacio de nombres en el que se encuentran. Esto permite que
no sobreescribamos accidentalmente algún otro objeto que tuviera el mismo
nombre al importar otro módulo.

Sin embargo, es posible utilizar la construcción from-import para


ahorrarnos el tener que indicar el nombre del módulo antes del objeto que nos
interesa. De esta forma se importa el objeto o los objetos que indiquemos al
espacio de nombres actual.

from time import asctime


print asctime()

Aunque se considera una mala práctica, también es posible importar todos


los nombres del módulo al espacio de nombres actual usando el caracter *:

from time import *

Ahora bien, recordemos que a la hora de crear nuestro primer módulo se


insistió en que se guarde en el mismo directorio en el que se encontraba el
programa que lo importaba. Entonces, ¿cómo podemos importar los módulos os,
sys o time si no se encuentran los archivos os.py, sys.py y time.py en el mismo
directorio?
A la hora de importar un módulo Python recorre todos los directorios
indicados en la variable de entorno PYTHONPATH en busca de un archivo con
el nombre adecuado. El valor de la variable PYTHONPATH se puede consultar
desde Python mediante sys.path

>>> import sys


>>> sys.path

De esta forma para que nuestro módulo estuviera disponible para todos
los programas del sistema bastaría con que lo copiáramos a uno de los
directorios indicados en PYTHONPATH.

En el caso de que Python no encontrara ningún módulo con el nombre


especificado, se lanzaría una excepción de tipo ImportError.

47
Compilación: Alejandro Vergara Vargas

Por último, es interesante comentar que en Python los módulos también


son objetos; de tipo module en concreto. Por supuesto esto significa que pueden
tener atributos y métodos. Uno de sus atributos, __name__, se utiliza a menudo
para incluir código ejecutable en un módulo pero que este sólo se ejecute si se
llama al módulo como programa, y no al importarlo. Para lograr esto basta saber
que cuando se ejecuta el módulo directamente __name__ tiene como valor
“__main__”, mientras que cuando se importa, el valor de __name__ es el
nombre del módulo:

print “Se muestra siempre”

if __name__ == “__main__”:
print “Se muestra si no es importacion”

Otro atributo interesante es __doc__, que, como en el caso de funciones y


clases, sirve a modo de documentación del objeto (docstring o cadena de
documentación). Su valor es el de la primera línea del cuerpo del módulo, en el
caso de que esta sea una cadena de texto; en caso contrario, valdrá None.

8.2. Paquetes
Si los módulos sirven para organizar el código, los paquetes sirven para
organizar los módulos. Los paquetes son tipos especiales de módulos (ambos
son de tipo module) que permiten agrupar módulos relacionados. Mientras los
módulos se corresponden a nivel físico con los archivos, los paquetes se
representan mediante directorios.

En una aplicación cualquiera podríamos tener, por ejemplo, un paquete iu


para la interfaz o un paquete bbdd para la persistencia a base de datos.

Para hacer que Python trate a un directorio como un paquete es necesario


crear un archivo __init__.py en dicha carpeta. En este archivo se pueden definir
elementos que pertenezcan a dicho paquete, como una constante DRIVER para
el paquete bbdd, aunque habitualmente se tratará de un archivo vacío. Para
hacer que un cierto módulo se encuentre dentro de un paquete, basta con copiar
el archivo que define el módulo al directorio del paquete.

Como los modulos, para importar paquetes también se utiliza import y


from-import y el caracter . para separar paquetes, subpaquetes y módulos.

import paq.subpaq.modulo

paq.subpaq.modulo.func()

48
Lenguaje de programación Python

Para encontrar algún módulo o paquete que cubra una cierta necesidad,
se puede consultar la lista de PyPI (Python Package Index) en
http://pypi.python.org/, que cuenta con más de 4000 paquetes distintos.

8.3. Namespaces

El caso básico de cargar un solo módulo de tareas funciona bien


inicialmente, pero los usuarios avanzados normalmente necesitan más
organización, como separar las tareas en un árbol anidado de namespaces.

La clase Collection proporciona una API para organizar tareas (y su


configuración) en una estructura similar a un árbol. Cuando se hace referencia a
las cadenas (por ejemplo, en la CLI o en ganchos anteriores / posteriores), las
tareas en namespaces anidados utilizan una sintaxis separada por puntos, por
ejemplo docs.build..

En esta sección, mostramos cómo la creación de namespaces con esta


API es flexible, pero también permite seguir los diseños de paquetes de Python
con un mínimo de repetición.
Una colección sin nombre es siempre la raíz del namespace; en el caso
base implícito, invoke crea uno para usted a partir de las tareas en su módulo de
tareas. Cree su propio nombre, namespace o ns, para configurar un namespace
explícito:

from invoke import Collection

ns = Collection()
# o: namespace = Collection()

Añadir tarear con Collection.add_task. add_task puede tomar un objeto


Task, como los generados por el decorador de tareas:

from invoke import Collection, task

@task
def release(c):
c.run("python setup.py sdist register upload")

ns = Collection()
ns.add_task(release)

Nuestra lista de tareas disponibles ahora se ve así:

$ invoke --list

49
Compilación: Alejandro Vergara Vargas

Available tasks:

Release

De forma predeterminada, el nombre de la función de una tarea se usa


como su identificador de namespaces, pero puede anularlo dando un argumento
de nombre a @task (es decir, en el momento de la definición) o
Collection.add_task.

Por ejemplo, supongamos que tiene una colisión de nombre de variable


en el módulo de tareas; tal vez desee exponer una tarea dir, que oculte un
Python incorporado. Poner nombre a tu función en sí mismo es una mala idea,
pero puede nombrarla como dir_ y luego decirle a @task el nombre "real":

@task(name='dir')
def dir_(c):
# ...

Por otro lado, es posible que haya obtenido un objeto de tarea que no
encaja con los nombres que desea en su namespace, y puede cambiar su
nombre en el momento de la conexión. Tal vez queremos cambiar el nombre de
nuestra tarea de lanzamiento para que se llame deploy en su lugar:

ns = Collection()
ns.add_task(release, name='deploy')

El resultado:

$ invoke --list
Available tasks:

deploy

El argumento de la palabra clave, nombre, es el segundo argumento de


add_task, por lo que aquellos con prisa pueden expresarlo como:

ns.add_task(release, 'deploy')

8.4. Generar ejecutables


Tanto en Mac OS como en la mayor parte de las distribuciones Linux el
intérprete de Python está instalado por defecto, por lo que los usuarios de estos
sistemas no tienen mayor complicación a la hora de instalar y ejecutar
aplicaciones escritas en Python.

50
Lenguaje de programación Python

En el caso de Windows, esto no es así, por lo que sería interesante que


los usuarios de este sistema operativo no tuvieran que instalar el intérprete de
Python. También sería interesante que nuestro programa consistiera en un
archivo .exe en lugar de uno o varios archivos .py, para simplificar las cosas.

Todo esto lo podemos lograr gracias a py2exe, una extensión para


distutils que, como su nombre indica, permite crear ejecutables para Windows a
partir de código Python, y que permite ejecutar estas aplicaciones sin necesidad
de tener instalado el intérprete de Python en el sistema.

Py2exe funciona examinando nuestro código fuente en busca de los


módulos y paquetes que utilizamos, compilándolos y construyendo un nuevo
archivo que incluye estos archivos y un pequeño intérprete de Python integrado.

Para probar el funcionamiento de py2exe creemos un pequeño programa


ejemplo.py

print “Soy un .exe”

y el archivo setup.py correspondiente. Los cambios que tenemos que


realizar a setup.py son sencillos: importar py2exe, y utilizar los argumentos
console y windows para indicar el nombre del script o scripts que queramos
convertir en ejecutables de consola o ejecutables de interfaz gráfica,
respectivamente.

from distutils.core import setup


import py2exe

setup(name=”Aplicacion de ejemplo”,
version=”0.1”,
description=”Ejemplo del funcionamiento de distutils”,
author=”Raul Gonzalez”,
author_email=”zootropo en gmail”,
url=”http://mundogeek.net/tutorial-python/”,
license=”GPL”,
scripts=[“ejemplo.py”],
console=[“ejemplo.py”]
)

Para crear el ejecutable, utilizamos una nueva opción de línea de


comandos para setup.py disponible tras importar el módulo y llamada, cómo no,
py2exe:

python setup.py py2exe

Con esto py2exe generará un directorio build, con las librerías compiladas,
y un directorio dist, con los archivos que conforman nuestra aplicación.

51
Compilación: Alejandro Vergara Vargas

Entre los archivos que podemos encontrar en dist tendremos uno o varios
ejecutables con el mismo nombre que los scripts indicados en console y
windows, un archivo python*.dll, que es el intérprete de Python, y un archivo
library.zip, que contiene varios archivos pyc que son los módulos que utiliza la
aplicación compilados.

Si queremos reducir el número de archivos a distribuir, podemos utilizar la


opción --bundle de py2exe para añadir a library.zip las dll y los pyd (--bundle 2) o
las dll, los pyd y el intérprete (--bundle 1).

python setup.py py2exe --bundle 1

o bien podemos añadir un nuevo argumento options a la función setup que


indique el valor a utilizar (opción bundle_files), de forma que no tengamos que
añadir el flag --bundle cada vez que usemos el comando py2exe:

from distutils.core import setup


import py2exe

setup(name=”Aplicacion de ejemplo”,
version=”0.1”,
description=”Ejemplo del funcionamiento de distutils”,
author=”Raul Gonzalez”,
author_email=”zootropo en gmail”,
url=”http://mundogeek.net/tutorial-python/”,
license=”GPL”,
scripts=[“ejemplo.py”],
console=[“ejemplo.py”],
options={“py2exe”: {“bundle_files”: 1}}
)

Por último podemos incluso prescindir de library.zip e incrustarlo en el


ejecutable utilizando el argumento zipfile=None

from distutils.core import setup


import py2exe

setup(name=”Aplicacion de ejemplo”,
version=”0.1”,
description=”Ejemplo del funcionamiento de distutils”,
author=”Raul Gonzalez”,
author_email=”zootropo en gmail”,
url=”http://mundogeek.net/tutorial-python/”,
license=”GPL”,
scripts=[“ejemplo.py”],
console=[“ejemplo.py”],

52
Lenguaje de programación Python

options={“py2exe”: {“bundle_files”: 1}},


zipfile=None
)

8.5. Documentación
Recordemos que todos los objetos cuentan con una variable especial
__doc__ mediante la cual podemos indicar el propósito y uso del objeto. Estos
son los llamados docstrings o cadenas de documentación.
A estos atributos se les puede asociar el texto correspondiente
explícitamente, asignándolo a la cadena correspondiente, como con cualquier
otra variable. Sin embargo, por conveniencia, Python ofrece un mecanismo
mucho más sencillo y es que si el primer estamento de la definición del objeto es
una cadena, esta se asocia a la variable __doc__ automáticamente.

def haz_algo(arg):
“””Este es el docstring de la funcion.”””
print arg

print haz_algo.__doc__

haz_algo.__doc__ = “””Este es un nuevo docstring.”””

print haz_algo.__doc__

Como vemos lo interesante de estas cadenas es que, a diferencia de los


comentarios normales de Python y de los comentarios de otros lenguajes, las
cadenas de documentación no se eliminan del bytecode, por lo que se pueden
consultar en tiempo de ejecución, usando, por ejemplo, la función help del
lenguaje, o utilizando la sentencia print como en el ejemplo anterior.

>>> help(haz_algo)
Help on function haz_algo in module __main__:
haz_algo(arg)
Este es un nuevo docstring.

53
Compilación: Alejandro Vergara Vargas

9. DEPURACIÓN

9.1. Uso de PDB

El depurador python, pdb: http://docs.python.org/library/pdb.html, te


permite inspeccionar tu código de forma interactiva.

Te permite:

Ver el código fuente.


Ir hacia arriba y hacia abajo del punto donde se ha producido un error.
Inspeccionar valores de variables.
Modificar valores de variables.
Establecer breakpoints (punto de parada del proceso).

print

Sí, las declaraciones print sirven como herramienta de depuración. Sin


embargo, para inspeccionar en tiempo de ejecución es más eficiente usar el
depurador.

Formas de lanzar el depurador:

 Postmortem, lanza el depurador después de que se hayan


producido errores.
 Lanza el módulo con el depurador.
 Llama al depurador desde dentro del módulo.

Postmortem
Situación: Estás trabajando en ipython y obtienes un error (traceback).

En este caso estamos depurando el fichero `index_error.py


http://pybonacci.github.io/scipy-lecture-notes-ES/_downloads/index_error.py
Cuando lo ejecutes verás como se lanza un IndexError. Escribe %debug y
entrarás en el depurador (este es el archivo con el error):

54
Lenguaje de programación Python

"""Small snippet to raise an IndexError."""

def index_error():
lst = list('foobar')
print lst[len(lst)]

if __name__ == '__main__':
index_error()

In [1]: %run index_error.py


---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
/home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/index_error.py
in <module>()
6
7 if __name__ == '__main__':
----> 8 index_error()
9

/home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/index_error.py
in index_error()
3 def index_error():
4 lst = list('foobar')
----> 5 print lst[len(lst)]
6
7 if __name__ == '__main__':

IndexError: list index out of range

In [2]: %debug
> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/index_error.py(5)index_error()
4 lst = list('foobar')
----> 5 print lst[len(lst)]
6

ipdb> list
1 """Small snippet to raise an IndexError."""
2
3 def index_error():
4 lst = list('foobar')
----> 5 print lst[len(lst)]
6
7 if __name__ == '__main__':
8 index_error()
9

ipdb> len(lst)
6
ipdb> print lst[len(lst)-1]
r
ipdb> quit

55
Compilación: Alejandro Vergara Vargas

In [3]:

Depuración post-mortem sin ipython

En algunas situaciones no podrás usar IPython, por ejemplo para depurar


un script que ha sido llamado desde la línea de comandos. En este caso, puedes
ejecutar el script de la siguiente forma python -m pdb script.py:

$ python -m pdb index_error.py


> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/index_error.py(1)<module>()
-> """Small snippet to raise an IndexError."""
(Pdb) continue
Traceback (most recent call last):
File "/usr/lib/python2.6/pdb.py", line 1296, in main
pdb._runscript(mainpyfile)
File "/usr/lib/python2.6/pdb.py", line 1215, in _runscript
self.run(statement)
File "/usr/lib/python2.6/bdb.py", line 372, in run
exec cmd in globals, locals
File "<string>", line 1, in <module>
File "index_error.py", line 8, in <module>
index_error()
File "index_error.py", line 5, in index_error
print lst[len(lst)]
IndexError: list index out of range
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/index_error.py(5)index_error()
-> print lst[len(lst)]
(Pdb)

Ejecución paso a paso


Situación: Crees que existe un error en un módulo, pero no estás seguro
donde.

Por ejemplo, estamos intentado depurar wiener_filtering.py. A


continuación, se muestra el código:

""" Wiener filtering a noisy Lena: this module is buggy


"""

import numpy as np
import scipy as sp
import pylab as pl
from scipy import signal

56
Lenguaje de programación Python

def local_mean(img, size=3):


""" Compute a image of the local average
"""
structure_element = np.ones((size, size), dtype=img.dtype)
l_mean = signal.correlate(img, structure_element, mode='same')
l_mean /= size**2
return l_mean

def local_var(img, size=3):


""" Compute a image of the local variance
"""
structure_element = np.ones((size, size), dtype=img.dtype)
l_var = signal.correlate(img**2, structure_element, mode='same')
l_var /= size**2
l_var -= local_mean(img, size=size)**2
return l_var

def iterated_wiener(noisy_img, size=3):


""" Wiener filter with iterative computation of the noise variance.

Do not use this: this is crappy code to demo bugs!


"""
noisy_img = noisy_img
denoised_img = local_mean(noisy_img, size=size)
l_var = local_var(noisy_img, size=size)
for i in range(3):
res = noisy_img - denoised_img
noise = (res**2).sum()/res.size
noise_level = (1 - noise/l_var )
noise_level[noise_level<0] = 0
denoised_img += noise_level*res
return denoised_img

###########################################################
##
cut = (slice(128, -128), slice(128, -128))

np.random.seed(7)

lena = sp.misc.lena()
noisy_lena = lena + 20*np.random.randint(3, size=lena.shape) - 30

57
Compilación: Alejandro Vergara Vargas

pl.matshow(lena[cut], cmap=pl.cm.gray)
pl.matshow(noisy_lena[cut], cmap=pl.cm.gray)

denoised_lena = iterated_wiener(noisy_lena)
pl.matshow(denoised_lena[cut], cmap=pl.cm.gray)

pl.show()

A pesar de que el código se ejecuta, observamos que el filtrado no se


está haciendo correctamente.

Ejecuta el script en IPython con el depurador usando %run -d


wiener_filtering.py:

In [1]: %run -d wiener_filtering.py


*** Blank or comment
*** Blank or comment
*** Blank or comment
Breakpoint 1 at /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/wiener_filtering.py:4
NOTE: Enter 'c' at the ipdb> prompt to start your script.
> <string>(1)<module>()

Coloca un breakpoint en la línea 34 usando b 34:

ipdb> n
> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/wiener_filtering.py(4)<module>()
3
1---> 4 import numpy as np
5 import scipy as sp

ipdb> b 34
Breakpoint 2 at /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/wiener_filtering.py:34

Continua la ejecución hasta el siguiente breakpoint con c(ont(inue)):

ipdb> c
> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/wiener_filtering.py(34)iterated_wiener()
33 """
2--> 34 noisy_img = noisy_img
35 denoised_img = local_mean(noisy_img, size=size)

Da pasos hacia adelante y detrás del código con n(ext) y s(tep). next salta
hasta la siguiente declaración en el actual contexto de ejecución mientras que

58
Lenguaje de programación Python

step se moverá entre los contextos en ejecución, i.e. permitiendo explorar dentro
de llamadas a funciones:

ipdb> s
> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/wiener_filtering.py(35)iterated_wiener()
2 34 noisy_img = noisy_img
---> 35 denoised_img = local_mean(noisy_img, size=size)
36 l_var = local_var(noisy_img, size=size)

ipdb> n
> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/wiener_filtering.py(36)iterated_wiener()
35 denoised_img = local_mean(noisy_img, size=size)
---> 36 l_var = local_var(noisy_img, size=size)
37 for i in range(3):

Muévete unas pocas líneas y explora las variables locales:

ipdb> n
> /home/varoquau/dev/scipy-lecture-
notes/advanced/debugging_optimizing/wiener_filtering.py(37)iterated_wiener()
36 l_var = local_var(noisy_img, size=size)
---> 37 for i in range(3):
38 res = noisy_img - denoised_img
ipdb> print l_var
[[5868 5379 5316 ..., 5071 4799 5149]
[5013 363 437 ..., 346 262 4355]
[5379 410 344 ..., 392 604 3377]
...,
[ 435 362 308 ..., 275 198 1632]
[ 548 392 290 ..., 248 263 1653]
[ 466 789 736 ..., 1835 1725 1940]]
ipdb> print l_var.min()
0

Aquí está nuestro error, estamos haciendo aritmética con enteros.

59
Compilación: Alejandro Vergara Vargas

BIBLIOGRAFÍA
González Duque, Raúl, Python para todos

Sweigart, Al, Invent Your Own Computer Games, 2nd edition

60
Lenguaje de programación Python

FUENTES ELECTRÓNICAS
https://recursospython.com/guias-y-manuales/listas-y-tuplas/

http://www.it.uc3m.es/abel/as/MMC/M2/HashTable_es.html

http://www.pythondiario.com/2018/06/tabla-hash-en-python.html

https://docs.python.org/3/library/functions.html

http://docs.pyinvoke.org/en/1.1/concepts/namespaces.html

https://entrenamiento-python-basico.readthedocs.io/es/latest/leccion6/depuracion.html

61

También podría gustarte