Python para Todos
Python para Todos
Python para Todos
PARA TODOS
Introducción 6
¿Qué es Python? 6
¿Por qué Python? 7
Instalación de Python 8
Herramientas básicas 9
Mi primer programa en Python 11
Tipos básicos 14
Números 15
Cadenas 20
Booleanos 20
Colecciones 22
Listas 22
Tuplas 24
Diccionarios 25
Control de flujo 27
Sentencias condicionales 27
Bucles 30
Funciones 34
Orientación a Objetos 40
Clases y objetos 40
Herencia 43
Herencia múltiple 44
Polimorfismo 45
Encapsulación 46
Clases de “nuevo-estilo” 48
Métodos especiales 48
Revisitando Objetos 51
Diccionarios 51
Cadenas 52
Listas 52
Programación funcional 54
Funciones de orden superior 54
Iteraciones de orden superior sobre listas 56
Funciones lambda 57
Comprensión de listas 58
Generadores 59
Decoradores 60
Excepciones 62
Módulos y Paquetes 69
Módulos 69
Paquetes 72
Entrada/Salida Y Ficheros 73
Entrada estándar 73
Parámetros de línea de comando 74
Salida estándar 74
Archivos 78
Expresiones Regulares 81
Patrones 81
Usando el módulo re 85
Sockets 88
Interactuar con webs 92
Threads 98
¿Qué son los procesos y los threads? 98
El GIL 99
Threads en Python 100
Sincronización 102
Datos globales independientes 107
Compartir información 107
Introducción
¿Qué es Python?
Python es un lenguaje de programación creado por Guido van Rossum
a principios de los años 90 cuyo nombre está inspirado en el grupo de
cómicos ingleses “Monty Python”. Es un lenguaje similar a Perl, pero
con una sintaxis muy limpia y que favorece un código legible.
Tipado dinámico
La característica de tipado dinámico se refiere a que no es necesario
declarar el tipo de dato que va a contener una determinada variable,
6
Introducción
Fuertemente tipado
No se permite tratar a una variable como si fuera de un tipo distinto
al que tiene, es necesario convertir de forma explícita dicha variable
al nuevo tipo previamente. Por ejemplo, si tenemos una variable que
contiene un texto (variable de tipo cadena o string) no podremos tra-
tarla como un número (sumar la cadena “9” y el número 8). En otros
lenguajes el tipo de la variable cambiaría para adaptarse al comporta-
miento esperado, aunque esto es más propenso a errores.
Multiplataforma
El intérprete de Python está disponible en multitud de plataformas
(UNIX, Solaris, Linux, DOS, Windows, OS/2, Mac OS, etc.) por lo
que si no utilizamos librerías específicas de cada plataforma nuestro
programa podrá correr en todos estos sistemas sin grandes cambios.
Orientado a objetos
La orientación a objetos es un paradigma de programación en el que
los conceptos del mundo real relevantes para nuestro problema se tras-
ladan a clases y objetos en nuestro programa. La ejecución del progra-
ma consiste en una serie de interacciones entre los objetos.
Instalación de Python
Existen varias implementaciones distintas de Python: CPython,
Jython, IronPython, PyPy, etc.
8
Introducción
Herramientas básicas
Existen dos formas de ejecutar código Python. Podemos escribir líneas
de código en el intérprete y obtener una respuesta del intérprete para
cada línea (sesión interactiva) o bien podemos escribir el código de un
programa en un archivo de texto y ejecutarlo.
In [3]: str?
Type: type
Base Class:
String Form:
9
Python para todos
10
Mi primer
programa en
Python
python hola.py
11
Python para todos
De esta forma se mostrará una consola con el texto Hola Mundo hasta
que pulsemos Enter.
#!/usr/bin/python
print “Hola Mundo”
raw_input()
#!/usr/bin/env python
print “Hola Mundo”
raw_input()
chmod +x hola.py
./hola.py
13
Tipos básicos
# y esto es un entero
e = 23
14
Tipos básicos
Números
Como decíamos, en Python se pueden representar números enteros,
reales y complejos.
Enteros
Los números enteros son aquellos números positivos o negativos que
no tienen decimales (además del cero). En Python se pueden repre-
sentar mediante el tipo int (de integer, entero) o el tipo long (largo).
La única diferencia es que el tipo long permite almacenar números
más grandes. Es aconsejable no utilizar el tipo long a menos que sea
necesario, para no malgastar memoria.
15
Python para todos
Reales
Los números reales son los que tienen decimales. En Python se expre-
san mediante el tipo float. En otros lenguajes de programación, como
C, tenemos también el tipo double, similar a float pero de mayor
precisión (double = doble precisión). Python, sin embargo, implementa
su tipo float a bajo nivel mediante una variable de tipo double de C,
es decir, utilizando 64 bits, luego en Python siempre se utiliza doble
precisión, y en concreto se sigue el estándar IEEE 754: 1 bit para el
signo, 11 para el exponente, y 52 para la mantisa. Esto significa que los
valores que podemos representar van desde ±2,2250738585072020 x
10-308 hasta ±1,7976931348623157×10308.
real = 0.2703
16
Tipos básicos
real = 0.1e-3
Complejos
Los números complejos son aquellos que tienen parte imaginaria. Si
no conocías de su existencia, es más que probable que nunca lo vayas a
necesitar, por lo que puedes saltarte este apartado tranquilamente. De
hecho la mayor parte de lenguajes de programación carecen de este
tipo, aunque sea muy utilizado por ingenieros y científicos en general.
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.
Operadores aritméticos
Operador Descripción Ejemplo
+ Suma r = 3 + 2 # r es 5
- Resta r = 4 - 7 # r es -3
17
Python para todos
* Multiplicación r = 2 * 6 # r es 12
** Exponente r = 2 ** 6 # r es 64
% Módulo r = 7 % 2 # r es 1
r = 3.0 / 2
r = float(3) / 2
18
Tipos básicos
vierte todos los operandos al tipo más complejo de entre los tipos de
los operandos.
Por ejemplo, si veis una operación como 3 & 2, lo que estais viendo es
un and bit a bit entre los números binarios 11 y 10 (las representacio-
nes en binario de 3 y 2).
El operador and (&), del inglés “y”, devuelve 1 si el primer bit operando
es 1 y el segundo bit operando es 1. Se devuelve 0 en caso contrario.
El operador not (~), del inglés “no”, sirve para negar uno a uno cada
bit; es decir, si el operando es 0, cambia a 1 y si es 1, cambia a 0.
| or r = 3 | 2 # r es 3
^ xor r = 3 ^ 2 # r es 1
~ not r = ~3 # r es -4
19
Python para todos
Cadenas
Las cadenas no son más que texto encerrado entre comillas simples
(‘cadena’) o dobles (“cadena”). Dentro de las comillas se pueden
añadir caracteres especiales escapándolos con \, como \n, el carácter de
nueva línea, o \t, el de tabulación.
unicode = u”äóè”
raw = r”\n”
a = “uno”
b = “dos”
c = a + b # c es “unodos”
c = a * 3 # c es “unounouno”
Booleanos
20
Tipos básicos
En realidad el tipo bool (el tipo de los booleanos) es una subclase del
tipo int. Puede que esto no tenga mucho sentido para tí si no conoces
los términos de la orientación a objetos, que veremos más adelantes,
aunque tampoco es nada importante.
Estos son los distintos tipos de operadores con los que podemos traba-
jar con valores booleanos, los llamados operadores lógicos o condicio-
nales:
21
Colecciones
Listas
La lista es un tipo de colección ordenada. Sería equivalente a lo que en
otros lenguajes se conoce por arrays, o vectores.
Crear una lista es tan sencillo como indicar entre corchetes, y separa-
dos por comas, los valores que queremos incluir en la lista:
l = [11, False]
mi_var = l[0] # mi_var vale 11
22
Colecciones
l = [22, True]
# Ahora l valdrá [99, True]
l[0] = 99
En todo caso las listas ofrecen mecanismos más cómodos para ser mo-
dificadas a través de las funciones de la clase correspondiente, aunque
no veremos estos mecanismos hasta más adelante, después de explicar
lo que son las clases, los objetos y las funciones.
Tuplas
Todo lo que hemos explicado sobre las listas se aplica también a las
tuplas, a excepción de la forma de definirla, para lo que se utilizan
paréntesis en lugar de corchetes.
>>> t = 1, 2, 3
>>> type(t)
type “tuple”
Además hay que tener en cuenta que es necesario añadir una coma
para tuplas de un solo elemento, para diferenciarlo de un elemento
entre paréntesis.
>>> t = (1)
24
Colecciones
>>> type(t)
type “int”
>>> t = (1,)
>>> type(t)
type “tuple”
c = “hola mundo”
c[0] # h
c[5:] # mundo
c[::3] # hauo
A cambio de estas limitaciones las tuplas son más “ligeras” que las
listas, por lo que si el uso que le vamos a dar a una colección es muy
básico, puedes utilizar tuplas en lugar de listas y ahorrar memoria.
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:
Sin embargo en este caso no se puede utilizar slicing, entre otras cosas
porque los diccionarios no son secuencias, si no mappings (mapeados,
asociaciones).
26
Control de flujo
Sentencias condicionales
Si un programa no fuera más que una lista de órdenes a ejecutar de
forma secuencial, una por una, no tendría mucha utilidad. Los con-
dicionales nos permiten comprobar condiciones y hacer que nuestro
programa se comporte de una forma u otra, que ejecute un fragmento
de código u otro, dependiendo de esta condición.
if
La forma más simple de un estamento condicional es un if (del inglés
si) seguido de la condición a evaluar, dos puntos (:) y en la siguiente
línea e indentado, el código a ejecutar en caso de que se cumpla dicha
condición.
fav = “mundogeek.net”
# si (if) fav es igual a “mundogeek.net”
if fav == “mundogeek.net”:
print “Tienes buen gusto!”
print “Gracias”
if fav == “mundogeek.net”:
print “Tienes buen gusto!”
print “Gracias”
if … else
Vamos a ver ahora un condicional algo más complicado. ¿Qué haría-
mos si quisiéramos que se ejecutaran unas ciertas órdenes en el caso de
que la condición no se cumpliera? Sin duda podríamos añadir otro if
que tuviera como condición la negación del primero:
if fav == “mundogeek.net”:
print “Tienes buen gusto!”
print “Gracias”
if fav != “mundogeek.net”:
print “Vaya, que lástima”
if fav == “mundogeek.net”:
print “Tienes buen gusto!”
print “Gracias”
else:
print “Vaya, que lástima”
28
Control de flujo
if numero < 0:
print “Negativo”
elif numero > 0:
print “Positivo”
else:
print “Cero”
elif es una contracción de else if, por lo tanto elif numero > 0 puede
leerse como “si no, si numero es mayor que 0”. Es decir, primero se
evalúa la condición del if. Si es cierta, se ejecuta su código y se con-
tinúa ejecutando el código posterior al condicional; si no se cumple,
se evalúa la condición del elif. Si se cumple la condición del elif
se ejecuta su código y se continua ejecutando el código posterior al
condicional; si no se cumple y hay más de un elif se continúa con el
siguiente en orden de aparición. Si no se cumple la condición del if ni
de ninguno de los elif, se ejecuta el código del else.
A if C else B
Bucles
Mientras que los condicionales nos permiten ejecutar distintos frag-
mentos de código dependiendo de ciertas condiciones, los bucles nos
permiten ejecutar un mismo fragmento de código un cierto número de
veces, mientras se cumpla una determinada condición.
while
El bucle while (mientras) ejecuta un fragmento de código mientras se
cumpla una condición.
edad = 0
while edad < 18:
edad = edad + 1
print “Felicidades, tienes “ + str(edad)
30
Control de flujo
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 usua-
rio diga hasta que escriba adios.
while True:
entrada = raw_input(“> “)
if entrada == “adios”:
break
else:
print entrada
salir = False
while not salir:
entrada = raw_input()
if entrada == “adios”:
salir = True
else:
print entrada
Otra palabra clave que nos podemos encontrar dentro de los bucles es
continue (continuar). Como habréis adivinado no hace otra cosa que
pasar directamente a la siguiente iteración del bucle.
edad = 0
while edad < 18:
31
Python para todos
edad = edad + 1
if edad % 2 == 0:
continue
print “Felicidades, tienes “ + str(edad)
for … in
A los que hayáis tenido experiencia previa con según que lenguajes este
bucle os va a sorprender gratamente. En Python for se utiliza como
una forma genérica de iterar sobre una secuencia. Y como tal intenta
facilitar su uso para este fin.
Como hemos dicho los for se utilizan en Python para recorrer secuen-
cias, por lo que vamos a utilizar un tipo secuencia, como es la lista, para
nuestro ejemplo.
Fácil y sencillo.
En C o C++, por ejemplo, lo que habríamos hecho sería iterar sobre las
32
Control de flujo
33
Funciones
mi_funcion(“hola”, 2)
>>> mi_funcion(“hola”)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: mi_funcion() takes exactly 2 arguments (1 given)
35
Python para todos
>>> imprimir(“hola”)
hola
>>> imprimir(“hola”, 2)
holahola
varios(1, 2)
varios(1, 2, 3)
varios(1, 2, 3, 4)
36
Funciones
varios(1, 2, tercero = 3)
x = 22
y = [22]
f(x, y)
print x, y
25 [22, 23]
22 [22, 23]
38
Funciones
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.
a, b = f(1, 2)
Sin embargo esto no quiere decir que las funciones Python puedan de-
volver 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.
39
Orientación a
Objetos
Clases y objetos
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.
Una clase, por otro lado, no es más que una plantilla genérica a partir
40
Orientación a objetos
de la cuál instanciar los objetos; plantilla que es la que define qué atri-
butos y métodos tendrán los objetos de esa clase.
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”
41
Python para todos
mi_coche = Coche(3)
42
Orientación a objetos
No se mueve
>>> mi_coche.arrancar()
No arranca
>>> print mi_coche.gasolina
0
Herencia
Hay tres conceptos que son básicos para cualquier lenguaje de pro-
gramación orientado a objetos: el encapsulamiento, la herencia y el
polimorfismo.
Para indicar que una clase hereda de otra se coloca el nombre de la cla-
se de la que se hereda entre paréntesis después del nombre de la clase:
class Instrumento:
def __init__(self, precio):
43
Python para todos
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
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
44
Orientación a objetos
class Terrestre:
def desplazar(self):
print “El animal anda”
class Acuatico:
def desplazar(self):
print “El animal nada”
c = Cocodrilo()
c.desplazar()
Polimorfismo
La palabra polimorfismo, del latín polys morphos (varias formas), se re-
fiere 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 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.
Encapsulación
La encapsulación se refiere a impedir el acceso a determinados mé-
todos y atributos de los objetos estableciendo así qué puede utilizarse
desde fuera de la clase.
46
Orientación a objetos
class Ejemplo:
def publico(self):
print “Publico”
def __privado(self):
print “Privado”
ej = Ejemplo()
ej.publico()
ej.__privado()
ej._Ejemplo__privado()
class Fecha():
def __init__(self):
self.__dia = 1
def getDia(self):
return self.__dia
mi_fecha = Fecha()
mi_fecha.setDia(33)
47
Python para todos
class Fecha(object):
def __init__(self):
self.__dia = 1
def getDia(self):
return self.__dia
mi_fecha = Fecha()
mi_fecha.dia = 33
Clases de “nuevo-estilo”
En el ejemplo anterior os habrá llamado la atención el hecho de que la
clase Fecha derive de object. La razón de esto es que para poder usar
propiedades la clase tiene que ser de “nuevo-estilo”, clases enriquecidas
introducidas en Python 2.2 que serán el estándar en Python 3.0 pero
que aún conviven con las clases “clásicas” por razones de retrocompa-
tibilidad. Además de las propiedades las clases de nuevo estilo añaden
otras funcionalidades como descriptores o métodos estáticos.
Para que una clase sea de nuevo estilo es necesario, por ahora, que
extienda una clase de nuevo-estilo. En el caso de que no sea necesa-
rio heredar el comportamiento o el estado de ninguna clase, como en
nuestro ejemplo anterior, se puede heredar de object, que es un objeto
vacio que sirve como base para todas las clases de nuevo estilo.
Métodos especiales
Ya vimos al principio del artículo el uso del método __init__. Exis-
48
Orientación a objetos
__init__(self, args)
Método llamado después de crear el objeto para realizar tareas de
inicialización.
__new__(cls, args)
Método exclusivo de las clases de nuevo estilo que se ejecuta antes que
__init__ y que se encarga de construir y devolver el objeto en sí. Es
equivalente a los constructores de C++ o Java. Se trata de un método
estático, es decir, que existe con independencia de las instancias de
la clase: es un método de clase, no de objeto, y por lo tanto el primer
parámetro no es self, sino la propia clase: cls.
__del__(self)
Método llamado cuando el objeto va a ser borrado. También llamado
destructor, se utiliza para realizar tareas de limpieza.
__str__(self)
Método llamado para crear una cadena de texto que represente a nues-
tro objeto. Se utiliza cuando usamos print para mostrar nuestro objeto
o cuando usamos la función str(obj) para crear una cadena a partir de
nuestro objeto.
__cmp__(self, otro)
Método llamado cuando se utilizan los operadores de comparación
para comprobar si nuestro objeto es menor, mayor o igual al objeto
pasado como parámetro. Debe devolver un número negativo si nuestro
objeto es menor, cero si son iguales, y un número positivo si nuestro
objeto es mayor. Si este método no está definido y se intenta com-
parar el objeto mediante los operadores <, <=, > o >= se lanzará una
excepción. Si se utilizan los operadores == o != para comprobar si dos
objetos son iguales, se comprueba si son el mismo objeto (si tienen el
mismo id).
__len__(self)
Método llamado para comprobar la longitud del objeto. Se utiliza, por
ejemplo, cuando se llama a la función len(obj) sobre nuestro objeto.
49
Python para todos
50
Revisitando
Objetos
Ahora que sabemos qué son las clases, los objetos, las funciones, y los
métodos es el momento de revisitar estos objetos para descubrir su
verdadero potencial.
Diccionarios
D.has_key(k)
Comprueba si el diccionario tiene la clave k. Es equivalente a la sin-
taxis k in D.
D.items()
Devuelve una lista de tuplas con pares clave-valor.
D.keys()
Devuelve una lista de las claves del diccionario.
D.pop(k[, d])
Borra la clave k del diccionario y devuelve su valor. Si no se encuentra
dicha clave se devuelve d si se especificó el parámetro o bien se lanza
51
Python para todos
una excepción.
D.values()
Devuelve una lista de los valores del diccionario.
Cadenas
S.count(sub[, start[, end]])
Devuelve el número de veces que se encuentra sub en la cadena. Los
parámetros opcionales start y end definen una subcadena en la que
buscar.
S.join(sequence)
Devuelve una cadena resultante de concatenar las cadenas de la se-
cuencia seq separadas por la cadena sobre la que se llama el método.
S.partition(sep)
Busca el separador sep en la cadena y devuelve una tupla con la sub-
cadena hasta dicho separador, el separador en si, y la subcadena del
separador hasta el final de la cadena. Si no se encuentra el separador, la
tupla contendrá la cadena en si y dos cadenas vacías.
S.split([sep [,maxsplit]])
Devuelve una lista conteniendo las subcadenas en las que se divide
nuestra cadena al dividirlas por el delimitador sep. En el caso de que
no se especifique sep, se usan espacios. Si se especifica maxsplit, este
indica el número máximo de particiones a realizar.
Listas
L.append(object)
52
Revisitando objetos
L.count(value)
Devuelve el número de veces que se encontró value en la lista.
L.extend(iterable)
Añade los elementos del iterable a la lista.
L.insert(index, object)
Inserta el objeto object en la posición index.
L.pop([index])
Devuelve el valor en la posición index y lo elimina de la lista. Si no se
especifica la posición, se utiliza el último elemento de la lista.
L.remove(value)
Eliminar la primera ocurrencia de value en la lista.
L.reverse()
Invierte la lista. Esta función trabaja sobre la propia lista desde la que
se invoca el método, no sobre una copia.
Por último, si se especifica, el parámetro key debe ser una función que
tome un elemento de la lista y devuelva una clave a utilizar a la hora de
comparar, en lugar del elemento en si.
53
Programación
funcional
def saludar(lang):
def saludar_es():
54
Programación funcional
print “Hola”
def saludar_en():
print “Hi”
def saludar_fr():
print “Salut”
f = saludar(“es”)
f()
>>> saludar(“en”)()
Hi
>>> saludar(“fr”)()
Salut
55
Python para todos
def cuadrado(n):
return n ** 2
l = [1, 2, 3]
l2 = map(cuadrado, l)
filter(function, sequence)
La funcion filter verifica que los elementos de una secuencia cum-
plan una determinada condición, devolviendo una secuencia con los
elementos que cumplen esa condición. Es decir, para cada elemento de
sequence se aplica la función function; si el resultado es True se añade
a la lista y en caso contrario se descarta.
def es_par(n):
return (n % 2.0 == 0)
l = [1, 2, 3]
56
Programación funcional
l2 = filter(es_par, l)
l = [1, 2, 3]
l2 = reduce(sumar, l)
Funciones lambda
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 referen-
ciadas más tarde.
l = [1, 2, 3]
l2 = filter(lambda n: n % 2.0 == 0, l)
def es_par(n):
return (n % 2.0 == 0)
l = [1, 2, 3]
l2 = filter(es_par, l)
57
Python para todos
expresión.
Comprensión de listas
En Python 3 map y filter se verán sustituidas por las list comprehen-
sions o comprensión de listas, característica tomada del lenguaje de
programación funcional Haskell y que está presente en Python desde
la versión 2.0.
l2 = [n ** 2 for n in l]
l2 = [n for n in l if n % 2.0 == 0]
l = [0, 1, 2, 3]
m = [“a”, “b”]
n = [s * v for s in m
for v in l
58
Programación funcional
if v > 0]
l = [0, 1, 2, 3]
m = [“a”, “b”]
n = []
for s in m:
for v in l:
if v > 0:
n.append(s* v)
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)
>>> 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>
>>> x = mi_generador(0, 5, 1)
>>> x
<generator object at 0×00E25710>
59
Python para todos
lista = list(mi_generador)
Decoradores
Un decorador no es es mas que una función que recibe una función
como parámetro y devuelve otra función como resultado. Por ejem-
plo 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
Supongamos como ejemplo una función imp que no hace otra cosa que
mostrar en pantalla la cadena pasada como parámetro.
>>> imp(“hola”)
60
Programación funcional
hola
>>> mi_decorador(imp)(“hola”)
Llamada a la función imp
hola
@mi_decorador
def imp(s):
print s
De esta forma cada vez que se llame a imp se estará llamando realmen-
te a la versión decorada. Python incorpora esta sintaxis desde la versión
2.4 en adelante.
@otro_decorador
@mi_decorador
def imp(s):
print s
61
Excepciones
def calcular():
division(1, 0)
calcular()
$ python ejemplo.py
Traceback (most recent call last):
File “ejemplo.py”, line 7, in
calcular()
File “ejemplo.py”, line 5, in calcular
division(1, 0)
File “ejemplo.py”, line 2, in division
a / b
ZeroDivisionError: integer division or modulo by zero
62
Excepciones
try:
f = file(“archivo.txt”)
except:
print “El archivo no existe”
try:
num = int(“3a”)
print no_existe
except NameError:
print “La variable no existe”
except ValueError:
print “El valor no es un numero”
63
Python para todos
Además podemos hacer que un mismo except sirva para tratar más
de una excepción usando una tupla para listar los tipos de error que
queremos que trate el bloque:
try:
num = int(“3a”)
print no_existe
except (NameError, ValueError):
print “Ocurrio un error”
try:
num = 33
except:
print “Hubo un error!”
else:
print “Todo esta bien”
try:
z = x / y
except ZeroDivisionError:
print “Division por cero”
finally:
print “Limpiando”
class MiError(Exception):
def __init__(self, valor):
self.valor = valor
64
Excepciones
def __str__(self):
return “Error “ + str(self.valor)
try:
if resultado > 20:
raise MiError(33)
except MiError, e:
print e
65
Python para todos
67
Python para todos
68
Módulos y
Paquetes
Módulos
Para facilitar el mantenimiento y la lectura los programas demasiado
largos pueden dividirse en módulos, agrupando elementos relaciona-
dos. Los módulos son entidades que permiten una organización y divi-
sión lógica de nuestro código. Los ficheros son su contrapartida física:
cada archivo Python almacenado en disco equivale a un módulo.
def mi_funcion():
print “una funcion”
class MiClase:
def __init__(self):
print “una clase”
import modulo
69
Python para todos
modulo.mi_funcion()
print time.asctime()
print asctime()
70
Módulos y paquetes
if __name__ == “__main__”:
print “Se muestra si no es importacion”
71
Python para todos
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 relacio-
nados. Mientras los módulos se corresponden a nivel físico con los
archivos, los paquetes se representan mediante directorios.
import paq.subpaq.modulo
paq.subpaq.modulo.func()
72
Entrada/Salida Y
Ficheros
Entrada estándar
La forma más sencilla de obtener información por parte del usuario
es mediante la función raw_input. Esta función toma como paráme-
tro una cadena a usar como prompt (es decir, como texto a mostrar al
usuario pidiendo la entrada) y devuelve una cadena con los caracteres
introducidos por el usuario hasta que pulsó la tecla Enter. Veamos un
pequeño ejemplo:
try:
edad = raw_input(“Cuantos anyos tienes? “)
73
Python para todos
import sys
Existen módulos, como optparse, que facilitan el trabajo con los argu-
mentos de la línea de comandos, pero explicar su uso queda fuera del
objetivo de este capítulo.
Salida estándar
La forma más sencilla de mostrar algo en la salida estándar es median-
te el uso de la sentencia print, como hemos visto multitud de veces en
74
Entrada/Salida. Ficheros
print “Hola\n\n\tmundo”
75
Python para todos
Esto se diferencia del uso del operador + para concatenar las cadenas
en que al utilizar las comas print introduce automáticamente un espa-
cio para separar cada una de las cadenas. Este no es el caso al utilizar
el operador +, ya que lo que le llega a print es un solo argumento: una
cadena ya concatenada.
76
Entrada/Salida. Ficheros
Especificador Formato
%s Cadena
%d Entero
%o Octal
%x Hexadecimal
%f Real
77
Python para todos
Archivos
Los ficheros en Python son objetos de tipo file creados mediante la
función open (abrir). Esta función toma como parámetros una cadena
con la ruta al fichero a abrir, que puede ser relativa o absoluta; una
cadena opcional indicando el modo de acceso (si no se especifica se
accede en modo lectura) y, por último, un entero opcional para especi-
ficar un tamaño de buffer distinto del utilizado por defecto.
f = open(“archivo.txt”, “w”)
Lectura de archivos
78
Entrada/Salida. Ficheros
completo = f.read()
parte = f2.read(512)
El método readline sirve para leer las líneas del fichero una por una.
Es decir, cada vez que se llama a este método, se devuelve el conteni-
do del archivo desde el puntero hasta que se encuentra un carácter de
nueva línea, incluyendo este carácter.
while True:
linea = f.readline()
if not linea: break
print line
Por último, readlines, funciona leyendo todas las líneas del archivo y
devolviendo una lista con las líneas leídas.
Escritura de archivos
Para la escritura de archivos se utilizan los método write y writelines.
Mientras el primero funciona escribiendo en el archivo una cadena de
texto que toma como parámetro, el segundo toma como parámetro una
lista de cadenas de texto indicando las líneas que queremos escribir en
el fichero.
Para esto se utiliza el método seek que toma como parámetro un nú-
79
Python para todos
80
Expresiones
Regulares
dir *.exe
‘*.exe’ sería una “expresión regular” que describiría todas las cadenas
de caracteres que empiezan con cualquier cosa seguida de ‘.exe’, es
decir, todos los archivos exe.
Patrones
La expresión regular más sencilla consiste en una cadena simple, que
81
Python para todos
describe un conjunto compuesto tan solo por esa misma cadena. Por
ejemplo, veamos cómo la cadena “python” coincide con la expresión
regular “python” usando la función match:
import re
if re.match(“python”, “python”):
print “cierto”
re.match(“.ython”, “python”)
re.match(“.ython”, “jython”)
re.match(“...\.”, “abc.”)
Si necesitáramos una expresión que sólo resultara cierta para las cade-
nas “python”, “jython” y “cython” y ninguna otra, podríamos utilizar
el carácter ‘|’ para expresar alternativa escribiendo los tres subpatro-
nes completos:
re.match(“python|jython|cython”, “python”)
o bien tan solo la parte que pueda cambiar, encerrada entre paréntesis,
formando lo que se conoce como un grupo. Los grupos tienen una
gran importancia a la hora de trabajar con expresiones regulares y este
no es su único uso, como veremos en la siguiente sección.
82
Expresiones regulares
re.match(“(p|j|c)ython”, “python”)
Otra opción consistiría en encerrar los caracteres ‘p’, ‘j’ y ‘c’ entre
corchetes para formar una clase de caracteres, indicando que en esa po-
sición puede colocarse cualquiera de los caracteres de la clase.
re.match(“[pjc]ython”, “python”)
re.match(“python[0-9]”, “python0”)
re.match(“python[0-9a-zA-Z]”, “pythonp”)
re.match(“python[.,]”, “python.”)
y no
re.match(“python[\.,]”, “python.”)
re.match(“python[^0-9a-z]”, “python+”)
Finalmente las llaves sirven para indicar el número de veces exacto que
puede aparecer el carácter de la izquierda, o bien un rango de veces que
puede aparecer. Por ejemplo {3} indicaría que tiene que aparecer exac-
tamente 3 veces, {3,8} indicaría que tiene que aparecer de 3 a 8 veces,
84
Expresiones regulares
Usando el módulo re
Ya hemos visto por encima cómo se utiliza la función match del módu-
lo re para comprobar si una cadena se ajusta a un determinado patrón.
El primer parámetro de la función es la expresión regular, el segundo,
la cadena a comprobar y existe un tercer parámetro opcional que con-
tiene distintos flags que se pueden utilizar para modificar el comporta-
miento de las expresiones regulares.
85
Python para todos
El método groups, por su parte, devuelve una lista con todos los gru-
pos, exceptuando el grupo 0, que se omite.
87
Sockets
socket_s = socket.socket()
socket_s.bind((“localhost”, 9999))
Por último utilizamos listen para hacer que el socket acepte conexio-
nes entrantes y accept para comenzar a escuchar. El método listen
requiere de un parámetro que indica el número de conexiones máximas
que queremos aceptar; evidentemente, este valor debe ser al menos 1.
socket_s.listen(10)
Una vez que tenemos este objeto socket podemos comunicarnos con
el cliente a través suyo, mediante los métodos recv y send (o recvfrom
y sendfrom en UDP) que permiten recibir o enviar mensajes respec-
tivamente. El método send toma como parámetros los datos a enviar,
mientras que el método recv toma como parámetro el número máxi-
mo de bytes a aceptar.
recibido = socket_c.recv(1024)
print “Recibido: “, recibio
socket_c.send(recibido)
89
Python para todos
Crear un cliente es aún más sencillo. Solo tenemos que crear el objeto
socket, utilizar el método connect para conectarnos al servidor y uti-
lizar los métodos send y recv que vimos anteriormente. El argumento
de connect es una tupla con host y puerto, exactamente igual que bind.
socket_c = socket.socket()
socket_c.connect((“localhost”, 9999))
socket_c.send(“hola”)
import socket
s = socket.socket()
s.bind((“localhost”, 9999))
s.listen(1)
while True:
recibido = sc.recv(1024)
if recibido == “quit”:
break
print “Recibido:”, recibido
sc.send(recibido)
print “adios”
sc.close()
s.close()
import socket
s = socket.socket()
s.connect((“localhost”, 9999))
90
Sockets
while True:
mensaje = raw_input(“> “)
s.send(mensaje)
mensaje == “quit”:
break
print “adios”
s.close()
91
Interactuar con
webs
import urllib2
92
Interactuar con webs
try:
f = urllib2.urlopen(“http://www.python.org”)
print f.read()
f.close()
except HTTPError, e:
print “Ocurrió un error”
print e.code
except URLError, e:
print “Ocurrió un error”
print e.reason
‘password=contrase%A4a&usuario=manuel’
leídos.
f = urllib2.urlopen(“http://ejemplo.com/login” +
“?” + params)
HTTPBasicAuthHandler:
aut_h = urllib2.HTTPBasicAuthHandler()
aut_h.add_password(“realm”, “host”, “usuario”, “password”)
opener = urllib2.build_opener(aut_h)
urllib2.install_opener(opener)
f = urllib2.urlopen(“http://www.python.org”)
opener = urllib2.build_opener(proxy_h)
urllib2.install_opener(opener)
f = urllib2.urlopen(“http://www.python.org”)
Para que se guarden las cookies que manda HTTP utilizamos el ma-
nejador HTTPCookieProcessor.
cookie_h = urllib2.HTTPCookieProcessor()
opener = urllib2.build_opener(cookie_h)
urllib2.install_opener(opener)
f = urllib2.urlopen(“http://www.python.org”)
Para leer las cookies mandadas basta crear un objeto iterable a partir
del CookieJar (también podríamos buscar las cabeceras correspondien-
tes, pero este sistema es más claro y sencillo):
96
Interactuar con webs
cookie_j = cookielib.CookieJar()
cookie_h = urllib2.HTTPCookieProcessor(cookie_j)
opener = urllib2.build_opener(cookie_h)
opener.open(“http://www.python.org”)
97
Threads
98
Threads
El GIL
La ejecución de los threads en Python está controlada por el GIL
(Global Interpreter Lock) de forma que sólo un thread puede ejecutar-
se a la vez, independientemente del número de procesadores con el que
cuente la máquina. Esto posibilita que el escribir extensiones en C para
Python sea mucho más sencillo, pero tiene la desventaja de limitar mu-
cho el rendimiento, por lo que a pesar de todo, en Python, en ocasiones
nos puede interesar más utilizar procesos que threads, que no sufren de
esta limitación.
Threads en Python
El trabajo con threads se lleva a cabo en Python mediante el módulo
thread. Este módulo es opcional y dependiente de la plataforma, y
puede ser necesario, aunque no es común, recompilar el intérprete para
añadir el soporte de threads.
import threading
class MiThread(threading.Thread):
def __init__(self, num):
threading.Thread.__init__(self)
self.num = num
def run(self):
print “Soy el hilo”, self.num
Para que el thread comience a ejecutar su código basta con crear una
instancia de la clase que acabamos de definir y llamar a su método
start. El código del hilo principal y el del que acabamos de crear se
ejecutarán de forma concurrente.
100
Threads
t = MiThread(i)
t.start()
t.join()
import threading
def imprime(num):
print “Soy el hilo”, num
101
Python para todos
Por último tenemos en el módulo threading una clase Timer que he-
reda de Thread y cuya utilidad es la de ejecutar el código de su método
run después de un periodo de tiempo indicado como parámetro en
su constructor. También incluye un método cancel mediante el que
cancelar la ejecución antes de que termine el periodo de espera.
Sincronización
Uno de los mayores problemas a los que tenemos que enfrentarnos al
utilizar threads es la necesidad de sincronizar el acceso a ciertos recur-
sos por parte de los threads. Entre los mecanismos de sincronización
que tenemos disponibles en el módulo threading se encuentran los
locks, locks reentrantes, semáforos, condiciones y eventos.
102
Threads
lista = []
lock = threading.Lock()
def anyadir(obj):
lock.acquire()
lista.append(obj)
lock.release()
def obtener():
lock.acquire()
obj = lista.pop()
lock.release()
return obj
103
Python para todos
semaforo = threading.Semaphore(4)
def descargar(url):
semaforo.acquire()
urllib.urlretrieve(url)
semaforo.release()
Las condiciones (clase Condition) son de utilidad para hacer que los
threads sólo puedan entrar en la sección crítica de darse una cierta
condición o evento. Para esto utilizan un Lock pasado como parámetro,
o crean un objeto RLock automaticamente si no se pasa ningún pará-
metro al constructor.
104
Threads
Tanto el thread que notifica como los que son notificados tienen que
terminar liberando el lock con release.
lista = []
cond = threading.Condition()
def consumir():
cond.acquire()
cond.wait()
obj = lista.pop()
cond.release()
return obj
def producir(obj):
cond.acquire()
lista.append(obj)
cond.notify()
cond.release()
Como vemos los eventos son muy similares a las condiciones, a excep-
ción de que se desbloquean todos los threads que esperaban el evento y
que no tenemos que llamar a acquire y release.
class MiThread(threading.Thread):
def __init__(self, evento):
threading.Thread.__init__(self)
self.evento = evento
def run(self):
print self.getName(), “esperando al evento”
self.evento.wait()
print self.getName(), “termina la espera”
evento = threading.Event()
t1 = MiThread(evento)
t1.start()
t2 = MiThread(evento)
t2.start()
# Esperamos un poco
time.sleep(5)
evento.set()
Por último, un pequeño extra. Si sois usuarios de Java sin duda estaréis
echando en falta una palabra clave syncronized para hacer que sólo
un thread pueda acceder al método sobre el que se utiliza a la vez. Una
construcción común es el uso de un decorador para implementar esta
funcionalidad usando un Lock. Sería algo así:
def synchronized(lock):
def dec(f):
def func_dec(*args, **kwargs):
lock.acquire()
try:
return f(*args, **kwargs)
finally:
lock.release()
return func_dec
return dec
class MyThread(threading.Thread):
@synchronized(mi_lock)
def run(self):
print “metodo sincronizado”
106
Threads
datos_locales = threading.local()
datos_locales.mi_var = “hola”
print datos_locales.mi_var
local = threading.local()
def f():
print local.var
local.var = “hola”
t = threading.Thread(target=f)
print local.var
t.start()
t.join()
Compartir información
Para compartir información entre los threads de forma sencilla po-
demos utilizar la clase Queue.Queue, que implementa una cola (una
estructura de datos de tipo FIFO) con soporte multihilo. Esta clase
utiliza las primitivas de threading para ahorrarnos tener que sincroni-
zar el acceso a los datos nosotros mismos.
107
Python para todos
q = Queue.Queue()
class MiThread(threading.Thread):
def __init__(self, q):
self.q = q
threading.Thread.__init__(self)
def run(self):
while True:
try:
obj = q.get(False)
except Queue.Empty:
print “Fin”
break
print obj
for i in range(10):
q.put(i)
t = MiThread(q)
t.start()
t.join()
108