Você está na página 1de 190

Python

PARA TODOS

Ral Gonzlez Duque

Python
PARA TODOS

Ral Gonzlez Duque

Python para todos por Ral Gonzlez Duque Este libro se distribuye bajo una licencia Creative Commons Reconocimiento 2. Espa!a. "sted es libre de# copiar$ distribuir y comunicar pblicamente la obra %acer obras derivadas &ajo las condiciones si'uientes# Reconocimiento. Debe reconocer y dar cr(dito al autor ori'inal )Ral Gonzlez Duque*

+uede descar'ar la versi,n ms reciente de este libro 'ratuitamente en la -eb %ttp#..mundo'ee/.net.tutorial-pyt%on.

0a im'en de portada es una 1oto'ra12a de una pit,n verde de la especie 3orelia viridis cuyo autor es 4an C%ien. 0a 1oto'ra12a est licenciada bajo Creative Commons 5ttribution 6%are5li/e 2.7

Contenido
Introduccin
89u( es +yt%on: 8+or qu( +yt%on: 4nstalaci,n de +yt%on >erramientas bsicas

7
; < = ?7

Mi primer programa en Python Tipos b sicos


@meros Cadenas &ooleanos

12 1!
?A 2? 22

"o#ecciones
0istas Cuplas Diccionarios

2$
2B 2A 2;

"ontro# de %#u&o
6entencias condicionales &ucles

2'
2= D2

(unciones Orientacin a Ob&etos


Clases y objetos >erencia >erencia mltiple +olimor1ismo Encapsulaci,n Clases de Enuevo-estiloF 3(todos especiales

)* $2
B2 B BA B; B< 7 7

Re+isitando Ob&etos
Diccionarios Cadenas 0istas

!)

D B

Programacin %unciona#
Gunciones de orden superior 4teraciones de orden superior sobre listas Gunciones lambda Comprensi,n de listas Generadores Decoradores

!7
; = A7 A? A2 AD

,-cepciones Mdu#os y Pa.uetes


3,dulos +aquetes

*! 72
;2 ;

,ntrada/Sa#ida 0 (icheros
Entrada estndar +armetros de l2nea de comando 6alida estndar 5rc%ivos

77
;; ;< ;< <2

,-presiones Regu#ares
+atrones "sando el m,dulo re

1!
< <=

Soc2ets Interactuar con 3ebs Threads


89u( son los procesos y los t%reads: El G40 C%reads en +yt%on 6incronizaci,n Datos 'lobales independientes Compartir in1ormaci,n

'2 '* 142


?72 ?7D ?7B ?7A ??? ???

Seria#i5acin de ob&etos 6ases de Datos


D& 5+4 Htras opciones

11) 117
??; ?2B

Documentacin

Docstrin's +ydoc Epydoc y re6tructuredCeIt Doctest unittest . +y"nit

12!

?2 ?2A ?2; ?D ?D=

Pruebas

1)!

Distribuir ap#icaciones Python


distutils setuptools Crear ejecutables .eIe

1$)
?BD ?B; ? 2

7ndice

1!!

introduCCi n
Qu es Python?
+yt%on es un len'uaje de pro'ramaci,n creado por Guido van Rossum a principios de los a!os =7 cuyo nombre est inspirado en el 'rupo de c,micos in'leses E3onty +yt%onF. Es un len'uaje similar a +erl$ pero con una sintaIis muy limpia y que 1avorece un c,di'o le'ible. 6e trata de un len'uaje interpretado o de script$ con tipado dinmico$ 1uertemente tipado$ multiplata1orma y orientado a objetos.

Lengua e interpretado o de s!ript


"n len'uaje interpretado o de script es aquel que se ejecuta utilizando un pro'rama intermedio llamado int(rprete$ en lu'ar de compilar el c,di'o a len'uaje mquina que pueda comprender y ejecutar directa- mente una computadora )len'uajes compilados*. 0a ventaja de los len'uajes compilados es que su ejecuci,n es ms rpida. 6in embar'o los len'uajes interpretados son ms 1leIibles y ms portables. +yt%on tiene$ no obstante$ muc%as de las caracter2sticas de los len'uajes compilados$ por lo que se podr2a decir que es semi interpretado. En +yt%on$ como en Java y muc%os otros len'uajes$ el c,di'o 1uente se traduce a un pseudo c,di'o mquina intermedio llamado bytecode la primera vez que se ejecuta$ 'enerando arc%ivos .pyc o .pyo )bytecode optimizado*$ que son los que se ejecutarn en sucesivas ocasiones.

"ipado din#i!o
0a caracter2stica de tipado dinmico se re1iere a que no es necesario declarar el tipo de dato que va a contener una
7

determinada variable$

Python para todos

sino que su tipo se determinar en tiempo de ejecuci,n se'n el tipo del valor al que se asi'ne$ y el tipo de esta variable puede cambiar si se le asi'na un valor de otro tipo.

$uerte#ente tipado
@o se permite tratar a una variable como si 1uera de un tipo distinto al que tiene$ es necesario convertir de 1orma eIpl2cita dic%a variable al nuevo tipo previamente. +or ejemplo$ si tenemos una variable que contiene un teIto )variable de tipo cadena o strin'* no podremos tratarla como un nmero )sumar la cadena E=F y el nmero <*. En otros len'uajes el tipo de la variable cambiar2a para adaptarse al comportamiento esperado$ aunque esto es ms propenso a errores.

%ultiplata&or#a
El int(rprete de +yt%on est disponible en multitud de plata1ormas )"@4K$ 6olaris$ 0inuI$ DH6$ Lindo-s$ H6.2$ 3ac H6$ etc.* por lo que si no utilizamos librer2as espec21icas de cada plata1orma nuestro pro'rama podr correr en todos estos sistemas sin 'randes cambios.

'rientado a o( etos
0a orientaci,n a objetos es un paradi'ma de pro'ramaci,n en el que los conceptos del mundo real relevantes para nuestro problema se trasladan a clases y objetos en nuestro pro'rama. 0a ejecuci,n del pro'rama consiste en una serie de interacciones entre los objetos. +yt%on tambi(n permite la pro'ramaci,n imperativa$ pro'ramaci,n 1uncional y pro'ramaci,n orientada a aspectos.

Por qu Python?
+yt%on es un len'uaje que todo el mundo deber2a conocer. 6u sintaIis simple$ clara y sencillaM el tipado dinmico$ el 'estor de memoria$ la 'ran cantidad de librer2as disponibles y la potencia del len'uaje$ entre otros$ %acen que desarrollar una aplicaci,n en +yt%on sea sencillo$ muy rpido y$ lo que es ms importante$ divertido. 0a sintaIis de +yt%on es tan sencilla y cercana al len'uaje natural que
9

Introduccin

los pro'ramas elaborados en +yt%on parecen pseudoc,di'o. +or este motivo se trata adems de uno de los mejores len'uajes para comenzar a pro'ramar. +yt%on no es adecuado sin embar'o para la pro'ramaci,n de bajo nivel o para aplicaciones en las que el rendimiento sea cr2tico. 5l'unos casos de (Iito en el uso de +yt%on son Goo'le$ Na%oo$ la @565$ 4ndustrias 0i'%t O 3a'ic$ y todas las distribuciones 0inuI$ en las que +yt%on cada vez representa un tanto por ciento mayor de los pro'ramas disponibles.

)nstala!in de Python
EIisten varias implementaciones distintas de +yt%on# C+yt%on$ Jyt%on$ 4ron+yt%on$ +y+y$ etc. C+yt%on es la ms utilizada$ la ms rpida y la ms madura. Cuando la 'ente %abla de +yt%on normalmente se re1iere a esta implementaci,n. En este caso tanto el int(rprete como los m,dulos estn escritos en C. Jyt%on es la implementaci,n en Java de +yt%on$ mientras que 4ron+yt%on es su contrapartida en CP ).@EC*. 6u inter(s estriba en que utilizando estas implementaciones se pueden utilizar todas las librer2as disponibles para los pro'ramadores de Java y .@EC. +y+y$ por ltimo$ como %abr(is adivinado por el nombre$ se trata de una implementaci,n en +yt%on de +yt%on. C+yt%on est instalado por de1ecto en la mayor parte de las distribuciones 0inuI y en las ltimas versiones de 3ac H6. +ara comprobar si est instalado abre una terminal y escribe pyt%on. 6i est instalado se iniciar la consola interactiva de +yt%on y obtendremos parecido a lo si'uiente#
+yt%on 2. .? )r2 ?# B<AD$ 3ay 2 277;$ ?A# A#D * QGCC B.?.2 )"buntu B.?.2-7ubuntuB*R on linuI2 Cype E%elpF$ Ecopyri'%tF$ EcreditsF or ElicenseF 1or more in1ormation. SSS

10

Python para todos

0a primera l2nea nos indica la versi,n de +yt%on que tenemos instalada. 5l 1inal podemos ver el prompt )SSS* que nos indica que el int(rprete est esperando c,di'o del usuario. +odemos salir escribiendo eIit)*$ o pulsando Control T D. 6i no te muestra al'o parecido no te preocupes$ instalar +yt%on es muy sencillo. +uedes descar'ar la versi,n correspondiente a tu sistema operativo desde la -eb de +yt%on$ en http://www.python.org/download/. EIisten instaladores para Lindo-s y 3ac H6. 6i utilizas 0inuI es muy probable que puedas instalarlo usando la %erramienta de 'esti,n de paquetes de tu distribuci,n$ aunque tambi(n podemos descar'ar la aplicaci,n compilada desde la -eb de +yt%on.

*erra#ientas (si!as
EIisten dos 1ormas de ejecutar c,di'o +yt%on. +odemos escribir l2neas de c,di'o en el int(rprete y obtener una respuesta del int(rprete para cada l2nea )sesi,n interactiva* o bien podemos escribir el c,di'o de un pro'rama en un arc%ivo de teIto y ejecutarlo. 5 la %ora de realizar una sesi,n interactiva os aconsejo instalar y utilizar i+yt%on$ en lu'ar de la consola interactiva de +yt%on. 6e puede encontrar en http://ipython.scipy.org/. i+yt%on cuenta con caracter2sticas a!adidas muy interesantes$ como el autocompletado o el operador :. )para activar la caracter2stica de autocompletado en Lindo-s es necesario instalar +yReadline$ que puede descar'arse desde http://ipython. scipy.org/ moin/PyReadline/Intro* 0a 1unci,n de autocompletado se lanza pulsando el tabulador. 6i escribimos 1i y pulsamos Cab nos mostrar una lista de los objetos que comienzan con 1i )1ile$ 1ilter y 1inally*. 6i escribimos 1ile. y pulsamos Cab nos mostrar una lista de los m(todos y propiedades del objeto 1ile. El operador : nos muestra in1ormaci,n sobre los objetos. 6e utiliza a!adiendo el s2mbolo de interro'aci,n al 1inal del nombre del objeto del cual queremos ms in1ormaci,n. +or ejemplo#
4n QDR# str:

11

Introduccin
Cype# type &ase Class# 6trin' Gorm# @amespace# +yt%on builtin Docstrin'# str)object* -S strin' Return a nice strin' representation o1 t%e object. 41 t%e ar'ument is a strin'$ t%e return value is t%e same object.

En el campo de 4DEs y editores de c,di'o 'ratuitos +yDEU )http:// pydev.sourceforge.net/* se alza como cabeza de serie. +yDEU es un plu- 'in para Eclipse que permite utilizar este 4DE multiplata1orma para pro'ramar en +yt%on. Cuenta con autocompletado de c,di'o )con in1ormaci,n sobre cada elemento*$ resaltado de sintaIis$ un depurador 'r1ico$ resaltado de errores$ eIplorador de clases$ 1ormateo del c,di'o$ re1actorizaci,n$ etc. 6in duda es la opci,n ms completa$ sobre todo si instalamos las eItensiones comerciales$ aunque necesita de una canti- dad importante de memoria y no es del todo estable. Htras opciones 'ratuitas a considerar son 6+E o 6taniVs +yt%on Editor )http://sourceforge.net/projects/spe/*$ Eric )http://die-offenbachs.de/eric/*$ &H5 Constructor )http://boa-constructor.sourceforge.net/* o incluso emacs o vim. 6i no te importa desembolsar al'o de dinero$ Womodo )http://www. activestate.com/komodo ide/* y Lin' 4DE )http://www.wingware.com/* son tambi(n muy buenas opciones$ con montones de caracter2sticas interesantes$ como +yDEU$ pero muc%o ms estables y robustos. 5dems$ si desarrollas so1t-are libre no comercial puedes contactar con Lin' Lare y obtener$ con un poco de suerte$ una licencia 'ratuita para Lin' 4DE +ro1essional #*

12

%i pri%er progra%a en python


Como comentbamos en el cap2tulo anterior eIisten dos 1ormas de ejecutar c,di'o +yt%on$ bien en una sesi,n interactiva )l2nea a l2nea* con el int(rprete$ o bien de la 1orma %abitual$ escribiendo el c,di'o en un arc%ivo de c,di'o 1uente y ejecutndolo. El primer pro'rama que vamos a escribir en +yt%on es el clsico >ola 3undo$ y en este len'uaje es tan simple como#
print E>ola 3undoF

Uamos a probarlo primero en el int(rprete. Ejecuta pyt%on o ipyt%on se'n tus pre1erencias$ escribe la l2nea anterior y pulsa Enter. El int(r- prete responder mostrando en la consola el teIto >ola 3undo. Uamos a%ora a crear un arc%ivo de teIto con el c,di'o anterior$ de 1orma que pudi(ramos distribuir nuestro peque!o 'ran pro'rama entre nuestros ami'os. 5bre tu editor de teIto pre1erido o bien el 4DE que %ayas ele'ido y copia la l2nea anterior. Gurdalo como %ola.py$ por ejemplo. Ejecutar este pro'rama es tan sencillo como indicarle el nombre del arc%ivo a ejecutar al int(rprete de +yt%on
pyt%on %ola.py

13

Mi primer programa en Python

pero vamos a ver c,mo simpli1icarlo an ms. 6i utilizas Lindo-s los arc%ivos .py ya estarn asociados al int(rprete de +yt%on$ por lo que basta %acer doble clic sobre el arc%ivo para ejecutar el pro'rama. 6in embar'o como este pro'rama no %ace ms que imprimir un teIto en la consola$ la ejecuci,n es demasiado rpida para poder verlo si quiera. +ara remediarlo$ vamos a a!adir una nueva l2nea que espere la entrada de datos por parte del usuario.
print E>ola 3undoF ra-Xinput)*

De esta 1orma se mostrar una consola con el teIto >ola %asta que pulsemos Enter.

3undo

6i utilizas 0inuI )u otro "niI* para conse'uir este comportamiento$ es decir$ para que el sistema operativo abra el arc%ivo .py con el int(rprete adecuado$ es necesario a!adir una nueva l2nea al principio del arc%ivo#
PY.usr.bin.pyt%on print E>ola 3undoF ra-Xinput)*

5 esta l2nea se le conoce en el mundo "niI como shebang$ hashbang o sharpbang. El par de caracteres PY indica al sistema operativo que dic%o script se debe ejecutar utilizando el int(rprete especi1icado a continuaci,n. De esto se desprende$ evidentemente$ que si esta no es la ruta en la que est instalado nuestro int(rprete de +yt%on$ es necesario cambiarla. Htra opci,n es utilizar el pro'rama env )de environment$ entorno* para pre'untar al sistema por la ruta al int(rprete de +yt%on$ de 1orma que nuestros usuarios no ten'an nin'n problema si se diera el caso de que el pro'rama no estuviera instalado en dic%a ruta#
PY.usr.bin.env pyt%on print E>ola 3undoF ra-Xinput)*

+or supuesto adems de a!adir el s%eban'$ tendremos que dar permisos de ejecuci,n al pro'rama.

14

Python para todos

c%mod TI %ola.py

N listo$ si %acemos doble clic el pro'rama se ejecutar$ mostrando una consola con el teIto >ola 3undo$ como en el caso de Lindo-s. Cambi(n podr2amos correr el pro'rama desde la consola como si trata- ra de un ejecutable cualquiera#
..%ola.py

15

tipos ( siCos
En +yt%on los tipos bsicos se dividen en# Z Z Z @meros$ como pueden ser D )entero*$ ? . ; )de coma 1lotante* o ; T j )complejos* Cadenas de teIto$ como E>ola 3undoF Ualores booleanos# Crue )cierto* y Galse )1also*.

Uamos a crear un par de variables a modo de ejemplo. "na de tipo cadena y una de tipo entero#
P esto es una cadena c [ E>ola 3undoF P y esto es un entero e [ 2D P podemos comprobarlo con la 1unci,n type type)c* type)e*

Como veis en +yt%on$ a di1erencia de muc%os otros len'uajes$ no se declara el tipo de la variable al crearla. En Java$ por ejemplo$ escribir2a- mos#
6trin' c [ E>ola 3undoFM int e [ 2DM

Este peque!o ejemplo tambi(n nos %a servido para presentar los comentarios inline en +yt%on# cadenas de teIto que comienzan con el carcter P y que +yt%on i'nora totalmente. >ay ms tipos de comenta-

16

rios$ de los que %ablaremos ms adelante.

17

Python para todos

+#ero s
Como dec2amos$ en +yt%on se pueden representar nmeros enteros$ reales y complejos.

,nteros
0os nmeros enteros son aquellos nmeros positivos o ne'ativos que no tienen decimales )adems del cero*. En +yt%on se pueden repre- sentar mediante el tipo int )de inte'er$ entero* o el tipo lon' )lar'o*. 0a nica di1erencia es que el tipo lon' permite almacenar nmeros ms 'randes. Es aconsejable no utilizar el tipo lon' a menos que sea necesario$ para no mal'astar memoria. El tipo int de +yt%on se implementa a bajo nivel mediante un tipo lon' de C. N dado que +yt%on utiliza C por debajo$ como C$ y a di1erencia de Java$ el ran'o de los valores que puede representar depende de la plata1orma. En la mayor parte de las mquinas el lon' de C se almacena utilizando D2 bits$ es decir$ mediante el uso de una variable de tipo int de +yt%on podemos almacenar nmeros de -2D? a 2D? - ?$ o lo que es lo mismo$ de -2.?B;.B<D.AB< a 2.?B;.B<D.AB;. En plata1ormas de AB bits$ el ran'o es de -=.22D.D;2.7DA.< B.;; .<7< %asta =.22D.D;2.7DA.< B.;; .<7;. El tipo lon' de +yt%on permite almacenar nmeros de cualquier precisi,n$ estando limitados solo por la memoria disponible en la mquina. 5l asi'nar un nmero a una variable esta pasar a tener tipo int$ a menos que el nmero sea tan 'rande como para requerir el uso del tipo lon'.
P type)entero* devolver2a int entero [ 2D

Cambi(n podemos indicar a +yt%on que un nmero se almacene usando lon' a!adiendo una 0 al 1inal#
P type)entero* devolver2a lon' entero [ 2D0

16

ipos !"sicos

El literal que se asi'na a la variable tambi(n se puede eIpresar como un octal$ anteponiendo un cero#
P 72; octal [ 2D en base ?7 entero [ 72;

o bien en %eIadecimal$ anteponiendo un 7I#


P 7\?; %eIadecimal [ 2D en base ?7 entero [ 7\?;

Reales
0os nmeros reales son los que tienen decimales. En +yt%on se eIpresan mediante el tipo 1loat. En otros len'uajes de pro'ramaci,n$ como C$ tenemos tambi(n el tipo double$ similar a 1loat pero de mayor precisi,n )double [ doble precisi,n*. +yt%on$ sin embar'o$ implementa su tipo 1loat a bajo nivel mediante una variable de tipo double de C$ es decir$ utilizando AB bits$ lue'o en +yt%on siempre se utiliza doble precisi,n$ y en concreto se si'ue el estndar 4EEE ; B# ? bit para el si'no$ ?? para el eIponente$ y 2 para la mantisa. Esto si'ni1ica que los valores que podemos representar van desde ]2$22 7;D< < 7;2727 I ?7-D7< %asta ]?$;=;A=D?DB<A2D? ;\?7D7<. 0a mayor parte de los len'uajes de pro'ramaci,n si'uen el mismo esquema para la representaci,n interna. +ero como muc%os sabr(is esta tiene sus limitaciones$ impuestas por el %ard-are. +or eso desde +yt%on 2.B contamos tambi(n con un nuevo tipo Decimal$ para el caso de que se necesite representar 1racciones de 1orma ms precisa. 6in embar'o este tipo est 1uera del alcance de este tutorial$ y s,lo es necesario para el mbito de la pro'ramaci,n cient21ica y otros rela- cionados. +ara aplicaciones normales podeis utilizar el tipo 1loat sin miedo$ como %a venido %aci(ndose desde %ace a!os$ aunque teniendo en cuenta que los nmeros en coma 1lotante no son precisos )ni en este ni en otros len'uajes de pro'ramaci,n*. +ara representar un nmero real en +yt%on se escribe primero la parte

entera$ se'uido de un punto y por ltimo la parte decimal.


real [ 7.2;7D

ipos !"sicos

Python para todos

Cambi(n se puede utilizar notaci,n cient21ica$ y a!adir una e )de eIponente* para indicar un eIponente en base ?7. +or ejemplo#
real [ 7.?e-D

ser2a equivalente a 7.? I ?7-D [ 7.? I 7.77? [ 7.777?

Co#ple os
0os nmeros complejos son aquellos que tienen parte ima'inaria. 6i no conoc2as de su eIistencia$ es ms que probable que nunca lo vayas a necesitar$ por lo que puedes saltarte este apartado tranquilamente. De %ec%o la mayor parte de len'uajes de pro'ramaci,n carecen de este tipo$ aunque sea muy utilizado por in'enieros y cient21icos en 'eneral. En el caso de que necesit(is utilizar nmeros complejos$ o simplemente ten'is curiosidad$ os dir( que este tipo$ llamado compleI en +yt%on$ tambi(n se almacena usando coma 1lotante$ debido a que estos nmeros son una eItensi,n de los nmeros reales. En concreto se almacena en una estructura de C$ compuesta por dos variables de tipo double$ sirviendo una de ellas para almacenar la parte real y la otra para la parte ima'inaria. 0os nmeros complejos en +yt%on se representan de la si'uiente 1orma#
complejo [ 2.? T ;.<j

'peradores
Ueamos a%ora qu( podemos %acer con nuestros nmeros usando los operadores por de1ecto. +ara operaciones ms complejas podemos recurrir al m,dulo mat%.

'peradores arit#ti!os
Operador Descripcin T 6uma ,&emp#o
r [ D T 2 P r es

Resta

r [ B - ;

P r es -D

Python para todos

ipos !"sicos

Operador Descripcin ,&emp#o r [ -; @e'aci,n ^ 3ultiplicaci,n r [ 2 ^ A ^^ r [ 2 ^^ A EIponente . r [ D. . 2 Divisi,n .. Divisi,n entera r [ D. .. 2 _ r [ ; _ 2 3,dulo

P r es -; P r es ?2 P r es AB P r es ?.; P r es ?.7 P r es ?

+uede que ten'is dudas sobre c,mo 1unciona el operador de m,dulo$ y cul es la di1erencia entre divisi,n y divisi,n entera. El operador de m,dulo no %ace otra cosa que devolvernos el resto de la divisi,n entre los dos operandos. En el ejemplo$ ;.2 ser2a D$ con ? de resto$ lue'o el m,dulo es ?. 0a di1erencia 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 nmero real$ mientras que en la divisi,n entera el resultado que se devuelve es solo la parte entera. @o obstante %ay que tener en cuenta que si utilizamos dos operandos enteros$ +yt%on determinar que queremos que la variable resultado tambi(n sea un entero$ por lo que el resultado de$ por ejemplo$ D . 2 y D .. 2 ser2a el mismo# ?. 6i quisi(ramos obtener los decimales necesitar2amos que al menos uno de los operandos 1uera un nmero real$ bien indicando los decimales
r [ D.7 . 2

o bien utilizando la 1unci,n 1loat )no es necesario que sepais lo que si'ni1ica el t(rmino 1unci,n$ ni que recordeis esta 1orma$ lo veremos un poco ms adelante*#
r [ 1loat)D* . 2

Esto es as2 porque cuando se mezclan tipos de nmeros$ +yt%on con-

Python para todos

vierte todos los operandos al tipo ms complejo de entre los tipos de los operandos.

'peradores a ni-el de (it


6i no conoc(is estos operadores es poco probable que vayis a necesitarlos$ por lo que pod(is obviar esta parte. 6i an as2 ten(is curiosidad os dir( que estos son operadores que actan sobre las representaciones en binario de los operandos. +or ejemplo$ si veis una operaci,n como D O 2$ lo que estais viendo es un and bit a bit entre los nmeros binarios ?? y ?7 )las representacio- nes en binario de D y 2*. El operador and )O*$ del in'l(s EyF$ devuelve ? si el primer bit operando es ? y el se'undo bit operando es ?. 6e devuelve 7 en caso contrario. El resultado de aplicar and bit a bit a ?? y ?7 ser2a entonces el nmero binario ?7$ o lo que es lo mismo$ 2 en decimal )el primer d2'ito es ? para ambas ci1ras$ mientras que el se'undo es ? s,lo para una de ellas*. El operador or )`*$ del in'l(s EoF$ devuelve ? si el primer operando es ? o el se'undo operando es ?. +ara el resto de casos se devuelve 7. El operador !or u or eIclusivo )a* devuelve ? si uno de los operandos es ? y el otro no lo es. El operador not )b*$ del in'l(s EnoF$ sirve para ne'ar uno a uno cada bitM es decir$ si el operando es 7$ cambia a ? y si es ?$ cambia a 7. +or ltimo los operadores de desplazamiento )cc y SS* sirven para desplazar los bits n posiciones %acia la izquierda o la derec%a.

Operador Descripcin O and ` or a Ior b not

,&emp#o
r [ D O 2 r [ D ` 2 r [ D a 2 r [ bD

Python para todos


P r es 2 P r es D P r es ? P r es -B

ipos !"sicos

cc SS

Desplazamiento izq. Desplazamiento der.

r [ D cc ? P r es A r [ D SS ? P r es ?

Cadenas
0as cadenas no son ms que teIto encerrado entre comillas simples )dcadenaV* o dobles )EcadenaF*. Dentro de las comillas se pueden a!adir caracteres especiales escapndolos con e$ como en$ el carcter de nueva l2nea$ o et$ el de tabulaci,n. "na cadena puede estar precedida por el carcter u o el carcter r$ los cuales indican$ respectivamente$ que se trata de una cadena que utiliza codi1icaci,n "nicode y una cadena raw )del in'l(s$ cruda*. 0as cadenas ra- se distin'uen de las normales en que los caracteres escapados mediante la barra invertida )e* no se sustituyen por sus contrapartidas. Esto es especialmente til$ por ejemplo$ para las eIpresiones re'ulares$ como veremos en el cap2tulo correspondiente.
unicode [ uFf,gF ra- [ rFenF

Cambi(n es posible encerrar una cadena entre triples comillas )simples o dobles*. De esta 1orma podremos escribir el teIto en varias l2neas$ y al imprimir la cadena$ se respetarn los saltos de l2nea que introdujimos sin tener que recurrir al carcter en$ as2 como las comillas sin tener que escaparlas.
triple [ EEEprimera linea esto se vera en otra lineaFFF

0as cadenas tambi(n admiten operadores como T$ que 1unciona realizando una concatenaci,n de las cadenas utilizadas como operandos y ^$ en la que se repite la cadena tantas veces como lo indique el nmero utilizado como se'undo operando.
a [ EunoF b [ EdosF c [ a T b P c es EunodosF c [ a ^ D P c es EunounounoF

Python para todos

.ooleanos
Como dec2amos al comienzo del cap2tulo una variable de tipo booleano s,lo puede tener dos valores# Crue )cierto* y Galse )1also*. Estos valores son especialmente importantes para las eIpresiones condicionales y los bucles$ como veremos ms adelante. En realidad el tipo bool )el tipo de los booleanos* es una subclase del tipo int. +uede que esto no ten'a muc%o sentido para t2 si no conoces los t(rminos de la orientaci,n a objetos$ que veremos ms adelante$ aunque tampoco es nada importante. Estos son los distintos tipos de operadores con los que podemos trabajar con valores booleanos$ los llamados operadores l,'icos o condicionales# Operador Descripcin ,&emp#o and 8se cumple a y b: r [ Crue
Galse or not

and Galse P r es P r es P r es

8se cumple a o b: @o a

r [ Crue or Galse Crue r [ not Crue Galse

0os valores booleanos son adems el resultado de eIpresiones que utilizan operadores relacionales )comparaciones entre valores*# Operador
[[ Y[ c S

Descripcin 8son i'uales a y b: 8son distintos a y b: 8es a menor que b: 8es a mayor que b:

,&emp#o
r [ [[ D P r es Galse r [ Crue Y[ D P r es P r es P r es

r [ c D Galse r [ Crue S D

ipos !"sicos

c[ S[

8es a menor o i'ual que b: 8es a mayor o i'ual que b:

r [ Crue r [ Crue

c[

P r es

S[ D P r es

ColeCCiones
En el cap2tulo anterior vimos al'unos tipos bsicos$ como los nmeros$ las cadenas de teIto y los booleanos. En esta lecci,n veremos al'unos tipos de colecciones de datos# listas$ tuplas y diccionarios.

Listas
0a lista es un tipo de colecci,n ordenada. 6er2a equivalente a lo que en otros len'uajes se conoce por arrays$ o vectores. 0as listas pueden contener cualquier tipo de dato# nmeros$ cadenas$ booleanos$ h y tambi(n listas. Crear una lista es tan sencillo como indicar entre corc%etes$ y separados por comas$ los valores que queremos incluir en la lista#
l [ Q22$ Crue$ Euna listaF$ Q?$ 2RR

+odemos acceder a cada uno de los elementos de la lista escribiendo el nombre de la lista e indicando el 2ndice del elemento entre corc%etes. Cen en cuenta sin embar'o que el 2ndice del primer elemento de la lista es 7$ y no ?#
l [ Q??$ GalseR miXvar [ lQ7R P miXvar vale ??

6i queremos acceder a un elemento de una lista incluida dentro de otra lista tendremos que utilizar dos veces este operador$ primero para indicar a qu( posici,n de la lista eIterior queremos acceder$ y el se'undo para seleccionar el elemento de la lista interior#

l [ QEuna listaF$ Q?$ 2RR

#o$ecciones
miXvar [ lQ?RQ7R P miXvar vale ?

Cambi(n podemos utilizar este operador para modi1icar un elemento de la lista si lo colocamos en la parte izquierda de una asi'naci,n#
l [ Q22$ CrueR lQ7R [ == P Con esto l valdr Q==$ CrueR

El uso de los corc%etes para acceder y modi1icar los elementos de una lista es comn en muc%os len'uajes$ pero +yt%on nos depara varias sorpresas muy a'radables. "na curiosidad sobre el operador QR de +yt%on es que podemos utilizar tambi(n nmeros ne'ativos. 6i se utiliza un nmero ne'ativo como 2ndice$ esto se traduce en que el 2ndice empieza a contar desde el 1inal$ %acia la izquierdaM es decir$ con Q-?R acceder2amos al ltimo elemento de la lista$ con Q-2R al penltimo$ con Q-DR$ al antepenltimo$ y as2 sucesivamente. Htra cosa inusual es lo que en +yt%on se conoce como slicing o particionado$ y que consiste en ampliar este mecanismo para permitir selec- cionar porciones de la lista. 6i en lu'ar de un nmero escribimos dos nmeros inicio y 1in separados por dos puntos )inicio#1in* +yt%on interpretar que queremos una lista que vaya desde la posici,n inicio a la posici,n 1in$ sin incluir este ltimo. 6i escribimos tres nmeros )inicio#1in#salto* en lu'ar de dos$ el tercero se utiliza para determinar cada cuantas posiciones a!adir un elemento a la lista.
l [ Q==$ Crue$ Euna listaF$ Q?$ 2RR miXvar [ lQ7#2R P miXvar vale Q==$ CrueR miXvar [ lQ7#B#2R P miXvar vale Q==$ Euna listaFR

0os nmeros ne'ativos tambi(n se pueden utilizar en un slicin'$ con el mismo comportamiento que se coment, anteriormente. >ay que mencionar as2 mismo que no es necesario indicar el principio y el 1inal del slicin'$ sino que$ si estos se omiten$ se usarn por de1ecto las posiciones de inicio y 1in de la lista$ respectivamente#
l [ Q==$ Crue$ Euna listaFR

miXvar [ lQ?#R

P miXvar vale QCrue$ Euna listaFR

#o$ecciones

Python para todos


miXvar [ lQ#2R P miXvar vale Q==$ CrueR miXvar [ lQ#R P miXvar vale Q==$ Crue$ Euna listaFR miXvar [ lQ##2R P miXvar vale Q==$ Euna listaFR

Cambi(n podemos utilizar este mecanismo para modi1icar la lista#


l [ Q==$ Crue$ Euna listaF$ Q?$ 2RR lQ7#2R [ Q7$ ?R P l vale Q7$ ?$ Euna listaF$ Q?$ 2RR

pudiendo incluso modi1icar el tama!o de la lista si la lista de la parte derec%a de la asi'naci,n tiene un tama!o menor o mayor que el de la selecci,n de la parte izquierda de la asi'naci,n#
lQ7#2R [ QGalseR P l vale QGalse$ Euna listaF$ Q?$ 2RR

En todo caso las listas o1recen mecanismos ms c,modos para ser mo- di1icadas a trav(s de las 1unciones de la clase correspondiente$ aunque no veremos estos mecanismos %asta ms adelante$ despu(s de eIplicar lo que son las clases$ los objetos y las 1unciones.

"uplas
Codo lo que %emos eIplicado sobre las listas se aplica tambi(n a las tuplas$ a eIcepci,n de la 1orma de de1inirla$ para lo que se utilizan par(ntesis en lu'ar de corc%etes.
t [ )?$ 2$ Crue$ Epyt%onF*

En realidad el constructor de la tupla es la coma$ no el par(ntesis$ pero el int(rprete muestra los par(ntesis$ y nosotros deber2amos utilizarlos$ por claridad.
SSS t [ ?$ 2$ D SSS type)t* type EtupleF

5dems %ay que tener en cuenta que es necesario a!adir una coma para tuplas de un solo elemento$ para di1erenciarlo de un elemento entre par(ntesis.
SSS t [ )?* SSS type)t*

#o$ecciones
type EintF SSS t [ )?$* SSS type)t* type EtupleF

+ara re1erirnos a elementos de una tupla$ como en una lista$ se usa el operador QR#
miXvar [ tQ7R P miXvar es ? miXvar [ tQ7#2R P miXvar es )?$ 2*

+odemos utilizar el operador QR debido a que las tuplas$ al i'ual que las listas$ 1orman parte de un tipo de objetos llamados secuencias. +ermitirme un peque!o inciso para indicaros que las cadenas de teIto tambi(n son secuencias$ por lo que no os eItra!ar que podamos %acer cosas como estas#
c [ E%ola mundoF cQ7R P % cQ #R P mundo cQ##DR P %auo

Uolviendo al tema de las tuplas$ su di1erencia con las listas estriba en que las tuplas no poseen estos mecanismos de modi1icaci,n a trav(s de 1unciones tan tiles de los que %ablbamos al 1inal de la anterior secci,n. 5dems son inmutables$ es decir$ sus valores no se pueden modi1icar una vez creadaM y tienen un tama!o 1ijo. 5 cambio de estas limitaciones las tuplas son ms Eli'erasF que las listas$ por lo que si el uso que le vamos a dar a una colecci,n es muy bsico$ puedes utilizar tuplas en lu'ar de listas y a%orrar memoria.

Di!!ionarios
0os diccionarios$ tambi(n llamados matrices asociativas$ deben su nombre a que son colecciones que relacionan una clave y un valor. +or ejemplo$ veamos un diccionario de pel2culas y directores#
d [ iE0ove 5ctually E# ERic%ard

CurtisF$ EWill &illF# ECarantinoF$

#o$ecciones

Python para todos


E5m(lieF# EJean-+ierre JeunetFj

El primer valor se trata de la clave y el se'undo del valor asociado a la clave. Como clave podemos utilizar cualquier valor inmutable# podr2amos usar nmeros$ cadenas$ booleanos$ tuplas$ h pero no listas o diccionarios$ dado que son mutables. Esto es as2 porque los diccio- narios se implementan como tablas %as%$ y a la %ora de introducir un nuevo par clave-valor en el diccionario se calcula el %as% de la clave para despu(s poder encontrar la entrada correspondiente rpidamente. 6i se modi1icara el objeto clave despu(s de %aber sido introducido en el diccionario$ evidentemente$ su %as% tambi(n cambiar2a y no podr2a ser encontrado. 0a di1erencia 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 2ndice$ porque de %ec%o no tienen orden$ sino por su clave$ utilizando de nuevo el operador QR.
dQE0ove 5ctually ER P devuelve ERic%ard CurtisF

5l i'ual que en listas y tuplas tambi(n se puede utilizar este operador para reasi'nar valores.
dQEWill &illFR [ E9uentin CarantinoF

6in embar'o en este caso no se puede utilizar slicin'$ entre otras cosas porque los diccionarios no son secuencias$ si no mappings )mapeados$ asociaciones*.

Control de &lu o
En esta lecci,n vamos a ver los condicionales y los bucles.

/enten!ias !ondi!ionales
6i un pro'rama no 1uera ms que una lista de ,rdenes a ejecutar de 1orma secuencial$ una por una$ no tendr2a muc%a utilidad. 0os condicionales nos permiten comprobar condiciones y %acer que nuestro pro'rama se comporte de una 1orma u otra$ que ejecute un 1ra'mento de c,di'o u otro$ dependiendo de esta condici,n. 5qu2 es donde cobran su importancia el tipo booleano y los operadores l,'icos y relacionales que aprendimos en el cap2tulo sobre los tipos bsicos de +yt%on.

i&
0a 1orma ms simple de un estamento condicional es un i1 )del in'l(s si* se'uido de la condici,n a evaluar$ dos puntos )#* y en la si'uiente l2nea e indentado$ el c,di'o a ejecutar en caso de que se cumpla dic%a condici,n.
1av [ Emundo'ee/.netF P si )i1* 1av es i'ual a Emundo'ee/.netF i1 1av [[ Emundo'ee/.netF# print ECienes buen 'ustoYF print EGraciasF

Como veis es bastante sencillo. Eso si$ ase'uraros de que indentis el c,di'o tal cual se %a %ec%o en el ejemplo$ es decir$ ase'uraros de pulsar Cabulaci,n antes de las dos ,r- denes print$ dado que esta es la 1orma de +yt%on de saber que vuestra intenci,n es la de que los dos print se ejecuten s,lo en el

caso de que

Python para todos

se cumpla la condici,n$ y no la de que se imprima la primera cadena si se cumple la condici,n y la otra siempre$ cosa que se eIpresar2a as2#
i1 1av [[ Emundo'ee/.netF# print ECienes buen 'ustoYF print EGraciasF

En otros len'uajes de pro'ramaci,n los bloques de c,di'o se determinan encerrndolos entre llaves$ y el indentarlos no se trata ms que de una buena prctica para que sea ms sencillo se'uir el 1lujo del pro'ra- ma con un solo 'olpe de vista. +or ejemplo$ el c,di'o anterior eIpresa- do en Java ser2a al'o as2#
6trin' 1av [ Emundo'ee/.netFM i1 )1av.equals)Emundo'ee/.netF**i 6ystem.out.println)ECienes buen 'ustoYF*M 6ystem.out.println)EGraciasF*M j

6in embar'o$ como ya %emos comentado$ en +yt%on se trata de una obli'aci,n$ y no de una elecci,n. De esta 1orma se obli'a a los pro'ra- madores a indentar su c,di'o para que sea ms sencillo de leer #*

i& 0 else
Uamos a ver a%ora un condicional al'o ms complicado. 89u( %ar2amos si quisi(ramos que se ejecutaran unas ciertas ,rdenes en el caso de que la condici,n no se cumpliera: 6in duda podr2amos a!adir otro i1 que tuviera como condici,n la ne'aci,n del primero#
i1 1av [[ Emundo'ee/.netF# print ECienes buen 'ustoYF print EGraciasF i1 1av Y[ Emundo'ee/.netF# print EUaya$ que lstimaF

pero el condicional tiene una se'unda construcci,n muc%o ms til#


i1 1av [[ Emundo'ee/.netF# print ECienes buen 'ustoYF print EGraciasF

else# print EUaya$ que lstimaF

Python para todos

#ontro$ de %$u&o

Uemos que la se'unda condici,n se puede sustituir con un else )del in'l(s# si no$ en caso contrario*. 6i leemos el c,di'o vemos que tiene bastante sentido# Esi 1av es i'ual a mundo'ee/.net$ imprime esto y esto$ si no$ imprime esto otroF.

i& 0 eli& 0 eli& 0 else


Codav2a queda una construcci,n ms que ver$ que es la que %ace uso del eli1.
i1 numero c 7# print E@e'ativoF eli1 numero S 7# print E+ositivoF else# print ECeroF

es una contracci,n de else if$ por lo tanto eli1 numero S 7 puede leerse como Esi no$ si numero es mayor que 7F. Es decir$ primero se evala la condici,n del i1. 6i es cierta$ se ejecuta su c,di'o y se con- tina ejecutando el c,di'o posterior al condicionalM si no se cumple$ se evala la condici,n del eli1. 6i se cumple la condici,n del eli1 se ejecuta su c,di'o y se continua ejecutando el c,di'o posterior al condicionalM si no se cumple y %ay ms de un eli1 se contina con el si'uiente en orden de aparici,n. 6i no se cumple la condici,n del i1 ni de nin'uno de los eli1$ se ejecuta el c,di'o del else.
eli1

1 i& C else .
Cambi(n eIiste una construcci,n similar al operador : de otros len'uajes$ que no es ms que una 1orma compacta de eIpresar un i1 else. En esta construcci,n se evala el predicado C y se devuelve 5 si se cumple o & si no se cumple# " i1 # else $. Ueamos un ejemplo#
var [ EparF i1 )num _ 2 [[ 7* else EimparF

N eso es todo. 6i conoc(is otros len'uajes de pro'ramaci,n puede que esperarais que os %ablara a%ora del s-itc%$ pero en +yt%on no eIiste esta construcci,n$ que podr2a emularse con un simple

diccionario$ as2 que pasemos directamente a los bucles.

#ontro$ de %$u&o

Python para todos

.u!les
3ientras que los condicionales nos permiten ejecutar distintos 1ra'mentos de c,di'o dependiendo de ciertas condiciones$ los bucles nos permiten ejecutar un mismo 1ra'mento de c,di'o un cierto nmero de veces$ mientras se cumpla una determinada condici,n.

2hile
El bucle -%ile )mientras* ejecuta un 1ra'mento de c,di'o mientras se cumpla una condici,n.
edad [ 7 -%ile edad c ?<# edad [ edad T ? print EGelicidades$ tienes E T str)edad*

0a variable edad comienza valiendo 7. Como la condici,n de que edad es menor que ?< es cierta )7 es menor que ?<*$ se entra en el bucle. 6e aumenta edad en ? y se imprime el mensaje in1ormando de que el usuario %a cumplido un a!o. Recordad que el operador T para las cadenas 1unciona concatenando ambas cadenas. Es necesario utilizar la 1unci,n str )de string$ cadena* para crear una cadena a partir del nmero$ dado que no podemos concatenar nmeros y cadenas$ pero ya comentaremos esto y muc%o ms en pr,Iimos cap2tulos. 5%ora se vuelve a evaluar la condici,n$ y ? si'ue siendo menor que ?<$ por lo que se vuelve a ejecutar el c,di'o que aumenta la edad en un a!o e imprime la edad en la pantalla. El bucle continuar ejecutndose %asta que edad sea i'ual a ?<$ momento en el cual la condici,n dejar de cumplirse y el pro'rama continuar2a ejecutando las instrucciones si'uientes al bucle. 5%ora ima'inemos que se nos olvidara escribir la instrucci,n que aumenta la edad. En ese caso nunca se lle'ar2a a la condici,n de que edad 1uese i'ual o mayor que ?<$ siempre ser2a 7$ y el bucle continuar2a inde1inidamente escribiendo en pantalla >as cumplido 7.

Esto es lo que se conoce como un bucle in1inito.

Python para todos

#ontro$ de %$u&o

6in embar'o %ay situaciones en las que un bucle in1inito es til. +or ejemplo$ veamos un peque!o pro'rama que repite todo lo que el usuario di'a %asta que escriba adios.
-%ile Crue# entrada [ ra-Xinput)ES E* i1 entrada [[ EadiosF# brea/ else# print entrada

+ara obtener lo que el usuario escriba en pantalla utilizamos la 1unci,n ra-Xinput. @o es necesario que sepais qu( es una 1unci,n ni c,mo 1unciona eIactamente$ simplemente aceptad por a%ora que en cada iteraci,n del bucle la variable entrada contendr lo que el usuario escribi, %asta pulsar Enter. Comprobamos entonces si lo que escribi, el usuario 1ue adios$ en cuyo caso se ejecuta la orden brea/ o si era cualquier otra cosa$ en cuyo caso se imprime en pantalla lo que el usuario escribi,. 0a palabra clave brea/ )romper* sale del bucle en el que estamos. Este bucle se podr2a %aber escrito tambi(n$ no obstante$ de la si'uiente 1orma#
salir [ Galse -%ile not salir# entrada [ ra-Xinput)* i1 entrada [[ EadiosF# salir [ Crue else# print entrada

pero nos %a servido para ver c,mo 1unciona brea/. Htra palabra clave que nos podemos encontrar dentro de los bucles es continue )continuar*. Como %abr(is adivinado no %ace otra cosa que pasar directamente a la si'uiente iteraci,n del bucle.
edad [ 7 -%ile edad c ?<#

Python para todos


edad [ edad T ? i1 edad _ 2 [[ 7# continue print EGelicidades$ tienes E T str)edad*

Como veis esta es una peque!a modi1icaci,n de nuestro pro'rama de 1elicitaciones. En esta ocasi,n %emos a!adido un i1 que comprueba si la edad es par$ en cuyo caso saltamos a la pr,Iima iteraci,n en lu'ar de imprimir el mensaje. Es decir$ con esta modi1icaci,n el pro'rama s,lo imprimir2a 1elicitaciones cuando la edad 1uera impar.

&or 0 in
5 los que %ayis tenido eIperiencia previa con se'n que len'uajes este bucle os va a sorprender 'ratamente. En +yt%on 1or se utiliza como una 1orma 'en(rica de iterar sobre una secuencia. N como tal intenta 1acilitar su uso para este 1in. Este es el aspecto de un bucle 1or en +yt%on#
secuencia [ QEunoF$ EdosF$ EtresFR 1or elemento in secuencia# print elemento

Como %emos dic%o los 1or se utilizan en +yt%on para recorrer secuencias$ por lo que vamos a utilizar un tipo secuencia$ como es la lista$ para nuestro ejemplo. 0eamos la cabecera del bucle como si de len'uaje natural se tratara# Epara cada elemento en secuenciaF. N esto es eIactamente lo que %ace el bucle# para cada elemento que ten'amos en la secuencia$ ejecuta estas l2neas de c,di'o. 0o que %ace la cabecera del bucle es obtener el si'uiente elemento de la secuencia secuencia y almacenarlo en una variable de nombre elemento. +or esta raz,n en la primera iteraci,n del bucle elemento valdr EunoF$ en la se'unda EdosF$ y en la tercera EtresF. Gcil y sencillo. En C o CTT$ por ejemplo$ lo que %abr2amos %ec%o ser2a iterar sobre las

#ontro$ de %$u&o

posiciones$ y no sobre los elementos#


int miXarrayQR [ i?$ 2$ D$ B$ jM int iM 1or)i [ 7M i c M iTT* i print1)E_denF$ miXarrayQiR*M j

Es decir$ tendr2amos un bucle 1or que 1uera aumentando una variable i en cada iteraci,n$ desde 7 al tama!o de la secuencia$ y utilizar2amos esta variable a modo de 2ndice para obtener cada elemento e imprimirlo. Como veis el en1oque de +yt%on es ms natural e intuitivo. +ero$ 8qu( ocurre si quisi(ramos utilizar el 1or como si estuvi(ramos en C o en Java$ por ejemplo$ para imprimir los nmeros de D7 a 7: @o os preocup(is$ porque no necesitar2ais crear una lista y a!adir uno a uno los nmeros del D7 al 7. +yt%on proporciona una 1unci,n llamada ran'e )ran'o* que permite 'enerar una lista que vaya desde el primer nmero que le indiquemos al se'undo. 0o veremos despu(s de ver al 1in a qu( se re1iere ese t(rmino tan recurrente# las 1unciones.

&unCiones
"na 1unci,n es un 1ra'mento de c,di'o con un nombre asociado que realiza una serie de tareas y devuelve un valor. 5 los 1ra'mentos de c,di'o que tienen un nombre asociado y no devuelven valores se les suele llamar procedimientos. En +yt%on no eIisten los procedimientos$ ya que cuando el pro'ramador no especi1ica un valor de retorno la 1unci,n devuelve el valor @one )nada*$ equivalente al null de Java. 5dems de ayudarnos a pro'ramar y depurar dividiendo el pro'rama en partes las 1unciones tambi(n permiten reutilizar c,di'o. En +yt%on las 1unciones se declaran de la si'uiente 1orma#
de1 miX1uncion)param?$ param2*# print param? print param2

Es decir$ la palabra clave de1 se'uida del nombre de la 1unci,n y entre par(ntesis los ar'umentos separados por comas. 5 continuaci,n$ en otra l2nea$ indentado y despu(s de los dos puntos tendr2amos las l2neas de c,di'o que con1orman el c,di'o a ejecutar por la 1unci,n. Cambi(n podemos encontrarnos con una cadena de teIto como primera l2nea del cuerpo de la 1unci,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 1unci,n.
de1 miX1uncion)param?$ param2*# EEEEsta 1uncion imprime los dos valores pasados como parametrosFFF print param? print param2

Esto es lo que imprime el opeardor : de i+yt%on o la 1unci,n %elp

'unciones

del len'uaje para proporcionar una ayuda sobre el uso y utilidad de las 1unciones. Codos los objetos pueden tener docstrin's$ no solo las 1unciones$ como veremos ms adelante. Uolviendo a la declaraci,n de 1unciones$ es importante aclarar que al declarar la 1unci,n lo nico que %acemos es asociar un nombre al 1ra'mento de c,di'o que con1orma la 1unci,n$ de 1orma que podamos ejecutar dic%o c,di'o ms tarde re1erencindolo por su nombre. Es decir$ a la %ora de escribir estas l2neas no se ejecuta la 1unci,n. +ara llamar a la 1unci,n )ejecutar su c,di'o* se escribir2a#
miX1uncion)E%olaF$ 2*

Es decir$ el nombre de la 1unci,n a la que queremos llamar se'uido de los valores que queramos pasar como parmetros entre par(ntesis. 0a asociaci,n de los parmetros y los valores pasados a la 1unci,n se %ace normalmente de izquierda a derec%a# como a param? le %emos dado un valor E%olaF y param2 vale 2$ miX1uncion imprimir2a %ola en una l2nea$ y a continuaci,n 2. 6in embar'o tambi(n es posible modi1icar el orden de los parmetros si indicamos el nombre del parmetro al que asociar el valor a la %ora de llamar a la 1unci,n#
miX1uncion)param2 [ 2$ param? [ E%olaF*

El nmero de valores que se pasan como parmetro al llamar a la 1unci,n tiene que coincidir con el nmero de parmetros que la 1unci,n acepta se'n la declaraci,n de la 1unci,n. En caso contrario +yt%on se quejar#
SSS miX1uncion)E%olaF* Cracebac/ )most recent call last*# Gile EcstdinSF$ line ?$ in cmoduleS CypeError# miX1uncion)* ta/es eIactly 2 ar'uments )? 'iven*

Cambi(n es posible$ no obstante$ de1inir 1unciones con un nmero variable de ar'umentos$ o bien asi'nar valores por de1ecto a los parmetros para el caso de que no se indique nin'n valor para ese parmetro al llamar a la 1unci,n.

Python para todos

0os valores por de1ecto para los parmetros se de1inen situando un si'no i'ual despu(s del nombre del parmetro y a continuaci,n el valor por de1ecto#
de1 imprimir)teIto$ veces [ ?*# print veces ^ teIto

En el ejemplo anterior si no indicamos un valor para el se'undo parmetro se imprimir una sola vez la cadena que le pasamos como primer parmetro#
SSS imprimir)E%olaF* %ola

si se le indica otro valor$ ser este el que se utilice#


SSS imprimir)E%olaF$ 2* %ola%ola

+ara de1inir 1unciones con un nmero variable de ar'umentos colocamos un ltimo parmetro para la 1unci,n cuyo nombre debe precederse de un si'no ^#
de1 varios)param?$ param2$ ^otros*# 1or val in otros# print val varios)?$ 2* varios)?$ 2$ D* varios)?$ 2$ D$ B*

Esta sintaIis 1unciona creando una tupla )de nombre otros en el ejemplo* en la que se almacenan los valores de todos los parmetros eItra pasados como ar'umento. +ara la primera llamada$ varios)?$ 2*$ la tupla otros estar2a vac2a dado que no se %an pasado ms parmetros que los dos de1inidos por de1ecto$ por lo tanto no se imprimir2a nada. En la se'unda llamada otros valdr2a )D$ *$ y en la tercera )D$ B*. Cambi(n se puede preceder el nombre del ltimo parmetro con ^^$ en cuyo caso en lu'ar de una tupla se utilizar2a un diccionario. 0as claves de este diccionario ser2an los nombres de los parmetros indicados al

'unciones

llamar a la 1unci,n y los valores del diccionario$ los valores asociados a estos parmetros. En el si'uiente ejemplo se utiliza la 1unci,n items de los diccionarios$ que devuelve una lista con sus elementos$ para imprimir los parmetros que contiene el diccionario.
de1 varios)param?$ param2$ ^^otros*# 1or i in otros.items)*# print i varios)?$ 2$ tercero [ D*

0os que conozcis al'n otro len'uaje de pro'ramaci,n os estar(is pre'untando si en +yt%on al pasar una variable como ar'umento de una 1unci,n estas se pasan por re1erencia o por valor. En el paso por re1erencia lo que se pasa como ar'umento es una re1erencia 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 ar'umento es el valor que conte- n2a la variable. 0a di1erencia entre ambos estriba en que en el paso por valor los cambios que se %a'an sobre el parmetro no se ven 1uera de la 1unci,n$ dado que los ar'umentos de la 1unci,n son variables locales a la 1unci,n que contienen los valores indicados por las variables que se pasaron como ar'umento. Es decir$ en realidad lo que se le pasa a la 1unci,n son copias de los valores y no las variables en si. 6i quisi(ramos modi1icar el valor de uno de los ar'umentos y que estos cambios se re1lejaran 1uera de la 1unci,n tendr2amos que pasar el par- metro por re1erencia. En C los ar'umentos de las 1unciones se pasan por valor$ aunque se puede simular el paso por re1erencia usando punteros. En Java tambi(n se usa paso por valor$ aunque para las variables que son objetos lo que se %ace es pasar por valor la re1erencia al objeto$ por lo que en realidad parece paso por re1erencia. En +yt%on tambi(n se utiliza el paso por valor de re1erencias a objetos$

Python para todos

como en Java$ aunque en el caso de +yt%on$ a di1erencia de Java$ todo es un objeto )para ser eIactos lo que ocurre en realidad es que al objeto se le asi'na otra etiqueta o nombre en el espacio de nombres local de la 1unci,n*. 6in embar'o no todos los cambios que %a'amos a los parmetros dentro de una 1unci,n +yt%on se re1lejarn 1uera de esta$ ya que %ay que tener en cuenta que en +yt%on eIisten objetos inmutables$ como las tuplas$ por lo que si intentramos modi1icar una tupla pasada como parmetro lo que ocurrir2a en realidad es que se crear2a una nueva ins- tancia$ por lo que los cambios no se ver2an 1uera de la 1unci,n. Ueamos un peque!o pro'rama para demostrarlo. En este ejemplo se %ace uso del m(todo append de las listas. "n m(todo no es ms que una 1unci,n que pertenece a un objeto$ en este caso a una listaM y append$ en concreto$ sirve para a!adir un elemento a una lista.
de1 1)I$ y*# I [ I T D y.append)2D* print I$ y I [ 22 y [ Q22R 1)I$ y* print I$ y

El resultado de la ejecuci,n de este pro'rama ser2a


2 Q22$ 2DR 22 Q22$ 2DR

Como vemos la variable I no conserva los cambios una vez salimos de la 1unci,n porque los enteros son inmutables en +yt%on. 6in embar'o la variable y si los conserva$ porque las listas son mutables. En resumen# los valores mutables se comportan como paso por re1e- rencia$ y los inmutables como paso por valor. Con esto terminamos todo lo relacionado con los parmetros de las

1unciones. Ueamos por ltimo c,mo devolver valores$ para lo que se utiliza la palabra clave return#

Python para todos

'unciones

de1 sumar)I$ y*# return I T y print sumar)D$ 2*

Como vemos esta 1unci,n tan sencilla no %ace otra cosa que sumar los valores pasados como parmetro y devolver el resultado como valor de retorno. Cambi(n podr2amos pasar varios valores que retornar a return.
de1 1)I$ y*# return I ^ 2$ y ^ 2 a$ b [ 1)?$ 2*

6in embar'o esto no quiere decir que las 1unciones +yt%on puedan devolver varios valores$ lo que ocurre en realidad es que +yt%on crea una tupla al vuelo cuyos elementos son los valores a retornar$ y esta nica variable es la que se devuelve.

orientaCi n a o( etos
En el cap2tulo de introducci,n ya comentbamos que +yt%on es un len'uaje multiparadi'ma en el se pod2a trabajar con pro'ramaci,n estructurada$ como ven2amos %aciendo %asta a%ora$ o con pro'ramaci,n orientada a objetos o pro'ramaci,n 1uncional. 0a +ro'ramaci,n Hrientada a Hbjetos )+HH u HH+ se'n sus si'las en in'l(s* es un paradi'ma de pro'ramaci,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 pro'rama consiste en una serie de interacciones entre estos objetos.

Clases y o( etos
+ara entender este paradi'ma primero tenemos que comprender qu( es una clase y qu( es un objeto. "n objeto es una entidad que a'rupa un estado y una 1uncionalidad relacionadas. El estado del objeto se de1ine a trav(s de variables llamadas atributos$ mientras que la 1uncionalidad se modela a trav(s de 1unciones a las que se les conoce con el nombre de m(todos del objeto. "n ejemplo de objeto podr2a ser un coc%e$ en el que tendr2amos atributos como la marca$ el nmero de puertas o el tipo de carburante y m(todos como arrancar y parar. H bien cualquier otra combinaci,n de atributos y m(todos se'n lo que 1uera relevante para nuestro pro'ra- ma. "na clase$ por otro lado$ no es ms que una plantilla 'en(rica a partir

(rientacin a o!&etos

de la cul instanciar los objetosM plantilla que es la que de1ine qu( atributos y m(todos tendrn los objetos de esa clase. Uolviendo a nuestro ejemplo# en el mundo real eIiste un conjunto de objetos a los que llamamos coc%es y que tienen un conjunto de atributos comunes y un comportamiento comn$ esto es a lo que llamamos clase. 6in embar'o$ mi coc%e no es i'ual que el coc%e de mi vecino$ y aunque pertenecen a la misma clase de objetos$ son objetos distintos. En +yt%on las clases se de1inen mediante la palabra clave class se'uida del nombre de la clase$ dos puntos )#* y a continuaci,n$ indentado$ el cuerpo de la clase. Como en el caso de las 1unciones$ si la primera l2nea del cuerpo se trata de una cadena de teIto$ esta ser la cadena de documentaci,n de la clase o docstrin'.
class Coc%e# EFF5bstraccion de los objetos coc%e.FFF de1 init )sel1$ 'asolina*# sel1.'asolina [ 'asolina print ECenemosF$ 'asolina$ ElitrosF de1 arrancar)sel1*# i1 sel1.'asolina S 7# print E5rrancaF else# print E@o arrancaF de1 conducir)sel1*# i1 sel1.'asolina S 7# sel1.'asolina -[ ? print E9uedanF$ sel1.'asolina$ ElitrosF else# print E@o se mueveF

0o 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 capric%o. El m(todo init $ con una doble barra baja al principio y 1inal 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 su'iere su nombre$ para realizar cualquier proceso de inicializaci,n que sea necesario. Como vemos el primer parmetro de
init

y del resto de m(todos


43

Python para todos

de la clase es siempre sel1. Esta es una idea inspirada en 3odula-D y sirve para re1erirse al objeto actual. Este mecanismo es necesario para poder acceder a los atributos y m(todos del objeto di1erenciando$ por ejemplo$ una variable local miXvar de un atributo del objeto sel1. miXvar. 6i volvemos al m(todo init de nuestra clase Coc%e veremos c,mo se utiliza sel1 para asi'nar al atributo 'asolina del objeto )sel1.'asolina* el valor que el pro'ramador especi1ic, para el parmetro 'asolina. El parmetro 'asolina se destruye al 1inal de la 1unci,n$ mientras que el atributo 'asolina se conserva )y puede ser accedido* mientras el objeto viva. +ara crear un objeto se escribir2a el nombre de la clase se'uido de cual- quier parmetro que sea necesario entre par(ntesis. Estos parmetros son los que se pasarn al m(todo init $ que como dec2amos es el m(todo que se llama al instanciar la clase.
miXcoc%e [ Coc%e)D*

Hs pre'untareis entonces c,mo es posible que a la %ora de crear nuestro primer objeto pasemos un solo parmetro a init $ el nmero D$ cuando la de1inici,n de la 1unci,n indica claramente que precisa de dos parmetros )sel1 y 'asolina*. Esto es as2 porque +yt%on pasa el primer ar'umento )la re1erencia al objeto que se crea* autom'icamen- te. 5%ora que ya %emos creado nuestro objeto$ podemos acceder a sus atributos y m(todos mediante la sintaIis objeto.atributo y objeto. metodo)*#
SSS print miXcoc%e.'asolina D SSS miXcoc%e.arrancar)* 5rranca SSS miXcoc%e.conducir)* 9uedan 2 litros SSS miXcoc%e.conducir)* 9uedan ? litros SSS miXcoc%e.conducir)* 9uedan 7 litros SSS miXcoc%e.conducir)*

44

(rientacin a o!&etos
@o se mueve SSS miXcoc%e.arrancar)* @o arranca SSS print miXcoc%e.'asolina 7

Como ltimo apunte recordar que en +yt%on$ como ya se coment, en repetidas ocasiones anteriormente$ todo son objetos. 0as cadenas$ por ejemplo$ tienen m(todos como upper)*$ que devuelve el teIto en maysculas o count)sub*$ que devuelve el nmero de veces que se encontr, la cadena sub en el teIto.

*eren!ia
>ay tres conceptos que son bsicos para cualquier len'uaje de pro'ramaci,n orientado a objetos# el encapsulamiento$ la %erencia y el polimor1ismo. En un len'uaje orientado a objetos cuando %acemos que una clase )subclase* %erede de otra clase )superclase* estamos %aciendo que la subclase conten'a todos los atributos y m(todos que ten2a la superclase. @o obstante al acto de %eredar de una clase tambi(n se le llama a menudo EeItender una claseF. 6upon'amos que queremos modelar los instrumentos musicales de una banda$ tendremos entonces una clase Guitarra$ una clase &ater2a$ una clase &ajo$ etc. Cada una de estas clases tendr una serie de atributos y m(todos$ pero ocurre que$ por el mero %ec%o de ser instrumentos musicales$ estas clases compartirn muc%os de sus atributos y m(todosM un ejemplo ser2a el m(todo tocar)*. Es ms sencillo crear un tipo de objeto 4nstrumento con las atributos y m(todos comunes e indicar al pro'rama que Guitarra$ &ater2a y &ajo son tipos de instrumentos$ %aciendo que %ereden de 4nstrumento. +ara indicar que una clase %ereda de otra se coloca el nombre de la cla- se de la que se %ereda entre par(ntesis despu(s del nombre de la clase#
class 4nstrumento# de1 init )sel1$ precio*#

45

Python para todos


sel1.precio [ precio de1 tocar)sel1*# print EEstamos tocando musicaF de1 romper)sel1*# print EEso lo pa'as tuF print E6onF$ sel1.precio$ EkkkF class &ateria)4nstrumento*# pass class Guitarra)4nstrumento*# pass

Como &ateria y Guitarra %eredan de 4nstrumento$ ambos tienen un m(todo tocar)* y un m(todo romper)*$ y se inicializan pasando un parmetro precio. +ero$ 8qu( ocurrir2a si quisi(ramos especi1icar un nuevo parmetro tipoXcuerda a la %ora de crear un objeto Guitarra: &astar2a con escribir un nuevo m(todo init para la clase Guitarra que se ejecutar2a en lu'ar del init de 4nstrumento. Esto es lo que se conoce como sobreescribir m(todos. 5%ora bien$ puede ocurrir en al'unos 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 ms que ejecutar un par de nuevas instrucciones eItra. En ese caso usar2amos la sintaIis 6uperClase.metodo)sel1$ ar's* para llamar al m(todo de i'ual nombre de la clase padre. +or ejemplo$ para llamar al m(todo init de 4nstrumento desde Guitarra usar2amos 4nstrumento. init )sel1$ precio*

Hbservad que en este caso si es necesario especi1icar el parmetro sel1.

*eren!ia #ltiple
En +yt%on$ a di1erencia de otros len'uajes como Java o CP$ se permite la %erencia mltiple$ es decir$ una clase puede %eredar de varias clases a la vez. +or ejemplo$ podr2amos tener una clase Cocodrilo que %eredara de la clase Cerrestre$ con m(todos como caminar)* y atributos como velocidadXcaminar y de la clase 5cuatico$ con m(todos como nadar)* y atributos como velocidadXnadar. &asta con enumerar las clases de 46

(rientacin a o!&etos

las que se %ereda separndolas por comas#


class Cocodrilo)Cerrestre$ 5cuatico*# pass

En el caso de que al'una de las clases padre tuvieran m(todos con el mismo nombre y nmero de parmetros las clases sobreescribir2an la implementaci,n de los m(todos de las clases ms a su derec%a en la de1inici,n. En el si'uiente ejemplo$ como Cerrestre se encuentra ms a la izquierda$ ser2a la de1inici,n de desplazar de esta clase la que prevalecer2a$ y por lo tanto si llamamos al m(todo desplazar de un objeto de tipo Cocodrilo lo que se imprimir2a ser2a EEl animal andaF.
class Cerrestre# de1 desplazar)sel1*# print EEl animal andaF class 5cuatico# de1 desplazar)sel1*# print EEl animal nadaF class Cocodrilo)Cerrestre$ 5cuatico*# pass c [ Cocodrilo)* c.desplazar)*

Poli#or&is#o
0a palabra polimor1ismo$ del 'rie'o poly morphos )varias 1ormas*$ se re- 1iere a la %abilidad de objetos de distintas clases de responder al mismo mensaje. Esto se puede conse'uir a trav(s de la %erencia# un objeto de una clase derivada es al mismo tiempo un objeto de la clase padre$ de 1orma que all2 donde se requiere un objeto de la clase padre tambi(n se puede utilizar uno de la clase %ija. +yt%on$ al ser de tipado dinmico$ no impone restricciones a los tipos que se le pueden pasar a una 1unci,n$ por ejemplo$ ms all de que el objeto se comporte como se espera# si se va a llamar a un m(todo 1)* del objeto pasado como parmetro$ por ejemplo$ evidentemente el objeto tendr que contar con ese m(todo. +or ese motivo$ a di1erencia 47

Python para todos

de len'uajes de tipado esttico como Java o CTT$ el polimor1ismo en +yt%on no es de 'ran importancia. En ocasiones tambi(n se utiliza el t(rmino polimor1ismo para re1erirse a la sobrecar'a de m(todos$ t(rmino que se de1ine como la capacidad del len'uaje de determinar qu( m(todo ejecutar de entre varios m(todos con i'ual nombre se'n el tipo o nmero de los parmetros que se le pasa. En +yt%on no eIiste sobrecar'a de m(todos )el ltimo m(todo sobreescribir2a la implementaci,n de los anteriores*$ aunque se puede conse'uir un comportamiento similar recurriendo a 1unciones con valores por de1ecto para los parmetros o a la sintaIis ^params o ^^params eIplicada en el cap2tulo sobre las 1unciones en +yt%on$ o bien usando decoradores )mecanismo que veremos ms adelante*.

,n!apsula!in
0a encapsulaci,n se re1iere a impedir el acceso a determinados m(todos y atributos de los objetos estableciendo as2 qu( puede utilizarse desde 1uera de la clase. Esto se consi'ue en otros len'uajes de pro'ramaci,n como Java utilizando modi1icadores de acceso que de1inen si cualquiera puede acceder a esa 1unci,n o variable )public* o si est restrin'ido el acceso a la propia clase )private*. En +yt%on no eIisten los modi1icadores de acceso$ y lo que se suele %acer es que el acceso a una variable o 1unci,n viene determinado por su nombre# si el nombre comienza con dos 'uiones bajos )y no termina tambi(n con dos 'uiones bajos* se trata de una variable o 1unci,n pri- vada$ en caso contrario es pblica. 0os m(todos cuyo nombre comien- za y termina con dos 'uiones bajos son m(todos especiales que +yt%on llama automticamente bajo ciertas circunstancias$ como veremos al 1inal del cap2tulo. En el si'uiente ejemplo s,lo se imprimir la cadena correspondiente al m(todo publico)*$ mientras que al intentar llamar al m(todo pri- vado)* +yt%on lanzar una eIcepci,n quejndose de que no eIiste )evidentemente eIiste$ pero no lo podemos ver porque es privado*.
48

(rientacin a o!&etos

class Ejemplo# de1 publico)sel1*# print E+ublicoF de1 privado)sel1*# print E+rivadoF

ej [ Ejemplo)* ej.publico)* ej. privado)*

Este mecanismo se basa en que los nombres que comienzan con un doble 'ui,n bajo se renombran para incluir el nombre de la clase )caracter2stica que se conoce con el nombre de name mangling*. Esto implica que el m(todo o atributo no es realmente privado$ y podemos acceder a (l mediante una peque!a trampa#
ej.XEjemplo privado)*

En ocasiones tambi(n puede suceder que queramos permitir el acceso a al'n atributo de nuestro objeto$ pero que este se produzca de 1orma controlada. +ara esto podemos escribir m(todos cuyo nico cometido sea este$ m(todos que normalmente$ por convenci,n$ tienen nombres como 'etUariable y setUariableM de a%2 que se conozcan tambi(n con el nombre de getters y setters.
class Gec%a)*# de1 init )sel1*# sel1. dia [ ? de1 'etDia)sel1*# return sel1. dia de1 setDia)sel1$ dia*# i1 dia S 7 and dia c D?# sel1. dia [ dia else# print EErrorF miX1ec%a [ Gec%a)* miX1ec%a.setDia)DD*

Esto se podr2a simpli1icar mediante propiedades$ que abstraen al usuario del %ec%o de que se est utilizando m(todos entre bambalinas para obtener y modi1icar los valores del atributo#
49

Python para todos

class Gec%a)object*# de1 init )sel1*# sel1. dia [ ? de1 'etDia)sel1*# return sel1. dia de1 setDia)sel1$ dia*# i1 dia S 7 and dia c D?# sel1. dia [ dia else# print EErrorF dia [ property)'etDia$ setDia* miX1ec%a [ Gec%a)* miX1ec%a.dia [ DD

Clases de 3nue-o4estilo5
En el ejemplo anterior os %abr llamado la atenci,n el %ec%o de que la clase Gec%a derive de object. 0a raz,n de esto es que para poder usar propiedades la clase tiene que ser de Enuevo-estiloF$ clases enriquecidas introducidas en +yt%on 2.2 que sern el estndar en +yt%on D.7 pero que an conviven con las clases EclsicasF por razones de retrocompatibilidad. 5dems de las propiedades las clases de nuevo estilo a!aden otras 1uncionalidades como descriptores o m(todos estticos. +ara que una clase sea de nuevo estilo es necesario$ por a%ora$ que eItienda una clase de nuevo-estilo. En el caso de que no sea necesario %eredar el comportamiento o el estado de nin'una clase$ como en nuestro ejemplo anterior$ se puede %eredar de object$ que es un objeto vacio que sirve como base para todas las clases de nuevo estilo. 0a di1erencia principal entre las clases anti'uas y las de nuevo estilo consiste en que a la %ora de crear una nueva clase anteriormente no se de1in2a realmente un nuevo tipo$ sino que todos los objetos creados a partir de clases$ 1ueran estas las clases que 1ueran$ eran de tipo instan- ce.

%todos espe!iales
50

(rientacin a o!&etos

Na vimos al principio del art2culo el uso del m(todo init . EIisten otros m(todos con si'ni1icados especiales$ cuyos nombres siempre comienzan y terminan con dos 'uiones bajos. 5 continuaci,n se listan al'unos especialmente tiles.
init )sel1$ ar's*

3(todo llamado despu(s de crear el objeto para realizar tareas de inicializaci,n.


ne)cls$ ar's*

3(todo eIclusivo de las clases de nuevo estilo que se ejecuta antes que init y que se encar'a de construir y devolver el objeto en s2. Es equivalente a los constructores de CTT o Java. 6e trata de un m(todo esttico$ es decir$ que eIiste con independencia de las instancias de la clase# es un m(todo de clase$ no de objeto$ y por lo tanto el primer parmetro no es sel1$ sino la propia clase# cls.
del )sel1*

3(todo llamado cuando el objeto va a ser borrado. Cambi(n llamado destructor$ se utiliza para realizar tareas de limpieza.
str )sel1*

3(todo llamado para crear una cadena de teIto que represente a nuestro objeto. 6e utiliza cuando usamos print para mostrar nuestro objeto o cuando usamos la 1unci,n str)obj* para crear una cadena a partir de nuestro objeto.
cmp )sel1$ otro*

3(todo llamado cuando se utilizan los operadores de comparaci,n para comprobar si nuestro objeto es menor$ mayor o i'ual al objeto pasado como parmetro. Debe devolver un nmero ne'ativo si nuestro objeto es menor$ cero si son i'uales$ y un nmero positivo si nuestro objeto es mayor. 6i este m(todo no est de1inido y se intenta comparar el objeto mediante los operadores c$ c[$ S o S[ se lanzar una eIcepci,n. 6i se utilizan los operadores [[ o Y[ para comprobar si dos objetos son i'uales$ se comprueba si son el mismo objeto )si tienen el mismo id*.
len )sel1*

3(todo llamado para comprobar la lon'itud del objeto. 6e utiliza$ por 51

Python para todos

ejemplo$ cuando se llama a la 1unci,n len)obj* sobre nuestro objeto. Como es de suponer$ el m(todo debe devolver la lon'itud del objeto. EIisten bastantes ms m(todos especiales$ que permite entre otras cosas utilizar el mecanismo de slicin' sobre nuestro objeto$ utilizar los operadores aritm(ticos o usar la sintaIis de diccionarios$ pero un estudio eI%austivo de todos los m(todos queda 1uera del prop,sito del cap2tulo.

52

re-isitando o( etos
En los cap2tulos dedicados a los tipos simples y las colecciones ve2amos por primera vez al'unos de los objetos del len'uaje +yt%on# nmeros$ booleanos$ cadenas de teIto$ diccionarios$ listas y tuplas. 5%ora que sabemos qu( son las clases$ los objetos$ las 1unciones$ y los m(todos es el momento de revisitar estos objetos para descubrir su verdadero potencial. Ueremos a continuaci,n al'unos m(todos tiles de estos objetos. Evi- dentemente$ no es necesario memorizarlos$ pero si$ al menos$ recordar que eIisten para cuando sean necesarios.

Di!!ionarios
D.'et)/Q$ dR*

&usca el valor de la clave / en el diccionario. Es equivalente a utilizar DQ/R pero al utilizar este m(todo podemos indicar un valor a devolver por de1ecto si no se encuentra la clave$ mientras que con la sintaIis DQ/R$ de no eIistir la clave se lanzar2a una eIcepci,n.
D.%asX/ey)/*

Comprueba si el diccionario tiene la clave /. Es equivalente a la sin- taIis / in D.


D.items)*

Devuelve una lista de tuplas con pares clave-valor.

53

Python para todos


D./eys)*

Devuelve una lista de las claves del diccionario.


D.pop)/Q$ dR*

&orra la clave / del diccionario y devuelve su valor. 6i no se encuentra dic%a clave se devuelve d si se especi1ic, el parmetro o bien se lanza una eIcepci,n.
D.values)*

Devuelve una lista de los valores del diccionario.

Cadenas
6.count)subQ$ startQ$ endRR*

Devuelve el nmero de veces que se encuentra sub en la cadena. 0os parmetros opcionales start y end de1inen una subcadena en la que buscar.
6.1ind)subQ$ startQ$ endRR*

Devuelve la posici,n en la que se encontr, por primera vez sub en la cadena o -? si no se encontr,.
6.join)sequence*

Devuelve una cadena resultante de concatenar las cadenas de la secuencia seq separadas por la cadena sobre la que se llama el m(todo.
6.partition)sep*

&usca el separador sep en la cadena y devuelve una tupla con la subcadena %asta dic%o separador$ el separador en si$ y la subcadena del separador %asta el 1inal de la cadena. 6i no se encuentra el separador$ la tupla contendr la cadena en si y dos cadenas vac2as.
6.replace)old$ ne-Q$ countR*

Devuelve una cadena en la que se %an reemplazado todas las ocurrencias de la cadena old por la cadena ne-. 6i se especi1ica el parmetro count$ este indica el nmero mIimo de ocurrencias a reemplazar.
6.split)Qsep Q$maIsplitRR*

Devuelve una lista conteniendo las subcadenas en las que se divide nuestra cadena al dividirlas por el delimitador sep. En el caso de

54

que

Python para todos

55

)e*isitando o!&etos

no se especi1ique sep$ se usan espacios. 6i se especi1ica este indica el nmero mIimo de particiones a realizar.

maIsplit$

Listas
0.append)object*

5!ade un objeto al 1inal de la lista.


0.count)value*

Devuelve el nmero de veces que se encontr, value en la lista.


0.eItend)iterable*

5!ade los elementos del iterable a la lista.


0.indeI)valueQ$ startQ$ stopRR*

Devuelve la posici,n en la que se encontr, la primera ocurrencia de value. 6i se especi1ican$ start y stop de1inen las posiciones de inicio y 1in de una sublista en la que buscar.
0.insert)indeI$ object*

4nserta el objeto object en la posici,n indeI.


0.pop)QindeIR*

Devuelve el valor en la posici,n indeI y lo elimina de la lista. 6i no se especi1ica la posici,n$ se utiliza el ltimo elemento de la lista.
0.remove)value*

Eliminar la primera ocurrencia de value en la lista.


0.reverse)*

4nvierte la lista. Esta 1unci,n trabaja sobre la propia lista desde la que se invoca el m(todo$ no sobre una copia.
0.sort)cmp[@one$ reverse[Galse* /ey[@one$

Hrdena la lista. 6i se especi1ica cmp$ este debe ser una 1unci,n que tome como parmetro dos valores I e y de la lista y devuelva -? si I es menor que y$ 7 si son i'uales y ? si I es mayor que y.
56

El parmetro reverse es un booleano que indica si se debe ordenar la lista de 1orma inversa$ lo que ser2a equivalente a llamar primero a 0.sort)* y despu(s a 0.reverse)*.

)e*isitando o!&etos

57

Python para todos

+or ltimo$ si se especi1ica$ el parmetro /ey debe ser una 1unci,n que tome un elemento de la lista y devuelva una clave a utilizar a la %ora de comparar$ en lu'ar del elemento en si.

58

progra%aCi n &unCional
0a pro'ramaci,n 1uncional es un paradi'ma en el que la pro'ramaci,n se basa casi en su totalidad en 1unciones$ entendiendo el concepto de 1unci,n se'n su de1inici,n matemtica$ y no como los simples subpro'ramas de los len'uajes imperativos que %emos visto %asta a%ora. En los len'uajes 1uncionales puros un pro'rama consiste eIclusivamente en la aplicaci,n de distintas 1unciones a un valor de entrada para obtener un valor de salida. +yt%on$ sin ser un len'uaje puramente 1uncional incluye varias caracte- r2sticas tomadas de los len'uajes 1uncionales como son las 1unciones de orden superior o las 1unciones lambda )1unciones an,nimas*.

$un!iones de orden superior


El concepto de 1unciones de orden superior se re1iere al uso de 1unciones como si de un valor cualquiera se tratara$ posibilitando el pasar 1unciones como parmetros de otras 1unciones o devolver 1unciones como valor de retorno. Esto es posible porque$ como %emos insistido ya en varias ocasiones$ en +yt%on todo son objetos. N las 1unciones no son una eIcepci,n. Ueamos un peque!o ejemplo
de1 saludar)lan'*# de1 saludarXes)*#

59

Python para todos


print E>olaF de1 saludarXen)*# print E>iF de1 saludarX1r)*# print E6alutF lan'X1unc [ iEesF# saludarXes$ EenF# saludarXen$ E1rF# saludarX1rj return lan'X1uncQlan'R 1 [ saludar)EesF* 1)*

Como podemos observar lo primero que %acemos en nuestro peque!o pro'rama es llamar a la 1unci,n saludar con un parmetro EesF. En la 1unci,n saludar se de1inen varias 1unciones# saludarXes$ saludarXen y saludarX1r y a continuaci,n se crea un diccionario que tiene como cla- ves cadenas de teIto que identi1ican a cada len'uaje$ y como valores las 1unciones. El valor de retorno de la 1unci,n es una de estas 1unciones. 0a 1unci,n a devolver viene determinada por el valor del parmetro lan' que se pas, como ar'umento de saludar. Como el valor de retorno de saludar es una 1unci,n$ como %emos visto$ esto quiere decir que 1 es una variable que contiene una 1unci,n. +odemos entonces llamar a la 1unci,n a la que se re1iere 1 de la 1orma en que llamar2amos a cualquier otra 1unci,n$ a!adiendo unos par(nte- sis y$ de 1orma opcional$ una serie de parmetros entre los par(ntesis. Esto se podr2a acortar$ ya que no es necesario almacenar la 1unci,n que nos pasan como valor de retorno en una variable para poder llamarla#
SSS saludar)EenF*)* >i SSS saludar)E1rF*)* 6alut

En este caso el primer par de par(ntesis indica los parmetros de la 1unci,n saludar$ y el se'undo par$ los de la 1unci,n devuelta por salu- dar.
58

Programacin %unciona$

)tera!iones de orden superior so4 (re listas


"na de las cosas ms interesantes que podemos %acer con nuestras 1unciones de orden superior es pasarlas como ar'umentos de las 1unciones map$ 1ilter y reduce. Estas 1unciones nos permiten sustituir los bucles t2picos de los len'uajes imperativos mediante construcciones equivalentes.

#ap6&un!tion7 sequen!e87 sequen!e7 999:;


0a 1unci,n map aplica una 1unci,n a cada elemento de una secuencia y devuelve una lista con el resultado de aplicar la 1unci,n a cada elemen- to. 6i se pasan como parmetros n secuencias$ la 1unci,n tendr que aceptar n ar'umentos. 6i al'una de las secuencias es ms peque!a que las dems$ el valor que le lle'a a la 1unci,n 1unction para posiciones mayores que el tama!o de dic%a secuencia ser @one. 5 continuaci,n podemos ver un ejemplo en el que se utiliza map para elevar al cuadrado todos los elementos de una lista#
de1 cuadrado)n*# return n ^^ 2 l [ Q?$ 2$ DR l2 [ map)cuadrado$ l*

%i#ter8%unction9 se.uence:
0a 1uncion 1ilter veri1ica que los elementos de una secuencia cumplan 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 1unci,n 1unctionM si el resultado es Crue se a!ade a la lista y en caso contrario se descarta. 5 continuaci,n podemos ver un ejemplo en el que se utiliza 1ilter para conservar solo los nmeros que son pares.
de1 esXpar)n*# return )n _ 2.7 [[ 7* l [ Q?$ 2$ DR

59

Python para todos


l2 [ 1ilter)esXpar$ l*

redu!e6&un!tion7 sequen!e87 initial:;


0a 1unci,n reduce aplica una 1unci,n a pares de elementos de una secuencia %asta dejarla en un solo valor. 5 continuaci,n podemos ver un ejemplo en el que se utiliza reduce para sumar todos los elementos de una lista.
de1 sumar)I$ y*# return I T y l [ Q?$ 2$ DR l2 [ reduce)sumar$ l*

$un!iones la#(da
El operador lambda sirve para crear 1unciones an,nimas en l2nea. 5l ser 1unciones an,nimas$ es decir$ sin nombre$ estas no podrn ser re1eren- ciadas ms tarde. 0as 1unciones lambda se construyen mediante el operador lambda$ los parmetros de la 1unci,n separados por comas )atenci,n$ 64@ par(ntesis*$ dos puntos )#* y el c,di'o de la 1unci,n. Esta construcci,n podr2an %aber sido de utilidad en los ejemplos anteriores para reducir c,di'o. El pro'rama que utilizamos para eIplicar 1ilter$ por ejemplo$ podr2a eIpresarse as2#
l [ Q?$ 2$ DR l2 [ 1ilter)lambda n# n _ 2.7 [[ 7$ l*

Comparemoslo con la versi,n anterior#


de1 esXpar)n*# return )n _ 2.7 [[ 7* l [ Q?$ 2$ DR l2 [ 1ilter)esXpar$ l*

0as 1unciones lambda estn restrin'idas por la sintaIis a una sola


60

Programacin %unciona$

eIpresi,n.

Co#prensin de listas
En +yt%on D777 map$ 1ilter y reduce perdern importancia. N aunque estas 1unciones se mantendrn$ reduce pasar a 1ormar parte del m,dulo 1unctools$ con lo que quedar 1uera de las 1unciones disponibles por de1ecto$ y map y 1ilter se desaconsejarn en 1avor de las list comprehensions o comprensi,n de listas. 0a comprensi,n de listas es una caracter2stica tomada del len'uaje de pro'ramaci,n 1uncional >as/ell que est presente en +yt%on desde la versi,n 2.7 y consiste en una construcci,n que permite crear listas a partir de otras listas. Cada una de estas construcciones consta de una eIpresi,n que determina c,mo modi1icar el elemento de la lista ori'inal$ se'uida de una o varias clausulas 1or y opcionalmente una o varias clausulas i1. Ueamos un ejemplo de c,mo se podr2a utilizar la comprensi,n de listas para elevar al cuadrado todos los elementos de una lista$ como %icimos en nuestro ejemplo de map.
l2 [ Qn ^^ 2 1or n in lR

Esta eIpresi,n se leer2a como Epara cada n en l %az n ^^ 2F. Como vemos tenemos primero la eIpresi,n que modi1ica los valores de la lista ori'inal )n ^^ 2*$ despu(s el 1or$ el nombre que vamos a utilizar para re1erirnos al elemento actual de la lista ori'inal$ el in$ y la lista sobre la que se itera. El ejemplo que utilizamos para la 1unci,n 1ilter )conservar solo los nmeros que son pares* se podr2a eIpresar con comprensi,n de listas as2#
l2 [ Qn 1or n in l i1 n _ 2.7 [[ 7R

Ueamos por ltimo un ejemplo de compresi,n de listas con varias clausulas 1or#
61

Python para todos

l [ Q7$ ?$ 2$ DR m [ QEaF$ EbFR n [ Qs ^ v 1or s in m 1or v in l i1 v S 7R

Esta construcci,n ser2a equivalente a una serie de 1or-in anidados#


l [ Q7$ ?$ 2$ DR m [ QEaF$ EbFR n [ QR 1or s in m# 1or v in l# i1 v S 7# n.append)s^ v*

Generadores
0as eIpresiones 'eneradoras 1uncionan de 1orma muy similar a la comprensi,n de listas. De %ec%o su sintaIis es eIactamente i'ual$ a eIcepci,n de que se utilizan par(ntesis en lu'ar de corc%etes#
l2 [ )n ^^ 2 1or n in l*

6in embar'o las eIpresiones 'eneradoras se di1erencian de la compren- si,n de listas en que no se devuelve una lista$ sino un 'enerador.
SSS l2 [ Qn ^^ 2 1or n in lR SSS l2 Q7$ ?$ B$ =R SSS l2 [ )n ^^ 2 1or n in l* SSS l2 c'enerator object at 7\77EDD2?7S

"n 'enerador es una clase especial de 1unci,n que 'enera valores sobre los que iterar. +ara devolver el si'uiente valor sobre el que iterar se utiliza la palabra clave yield en lu'ar de return. Ueamos por ejemplo un 'enerador que devuelva nmeros de n a m con un salto s.
de1 miX'enerador)n$ m$ s*# -%ile)n c[ m*# yield n n T[ s

62

Programacin %unciona$

SSS I [ miX'enerador)7$ $ ?* SSS I c'enerator object at 7\77E2 ;?7S

El 'enerador se puede utilizar en cualquier lu'ar donde se necesite un objeto iterable. +or ejemplo en un 1or-in#
1or n in miX'enerador)7$ print n $ ?*#

Como no estamos creando una lista completa en memoria$ sino 'enerando un solo valor cada vez que se necesita$ en situaciones en las que no sea necesario tener la lista completa el uso de 'eneradores puede suponer una 'ran di1erencia de memoria. En todo caso siempre es posible crear una lista a partir de un 'enerador mediante la 1unci,n list#
lista [ list)miX'enerador*

De!oradores
"n decorador no es es mas que una 1unci,n que recibe una 1unci,n como parmetro y devuelve otra 1unci,n como resultado. +or ejemplo podr2amos querer a!adir la 1uncionalidad de que se imprimiera el nombre de la 1unci,n llamada por motivos de depuraci,n#
de1 miXdecorador)1uncion*# de1 nueva)^ar's*# print E0lamada a la 1uncionF$ 1uncion. retorno [ 1uncion)^ar's* return retorno return nueva

name

Como vemos el c,di'o de la 1unci,n miXdecorador no %ace ms que crear una nueva 1unci,n y devolverla. Esta nueva 1unci,n imprime el nombre de la 1unci,n a la que EdecoramosF$ ejecuta el c,di'o de dic%a 1unci,n$ y devuelve su valor de retorno. Es decir$ que si llamramos a la nueva 1unci,n que nos devuelve miXdecorador$ el resultado ser2a el mismo que el de llamar directamente a la 1unci,n que le pasamos como parmetro$ eIceptuando el que se imprimir2a adems el nombre de la 1unci,n.
63

Python para todos

6upon'amos como ejemplo una 1unci,n imp que no %ace otra cosa que mostrar en pantalla la cadena pasada como parmetro.
SSS imp)E%olaF* %ola SSS miXdecorador)imp*)E%olaF* 0lamada a la 1unci,n imp %ola

0a sintaIis para llamar a la 1unci,n que nos devuelve miXdecorador no es muy clara$ aunque si lo estudiamos detenidamente veremos que no tiene mayor complicaci,n. +rimero se llama a la 1unci,n que decora con la 1unci,n a decorar# miXdecorador)imp*M y una vez obtenida la 1unci,n ya decorada se la puede llamar pasando el mismo parmetro que se pas, anteriormente# miXdecorador)imp*)E%olaF* Esto se podr2a eIpresar ms claramente precediendo la de1inici,n de la 1unci,n que queremos decorar con el si'no l se'uido del nombre de la 1unci,n decoradora#
lmiXdecorador de1 imp)s*# print s

De esta 1orma cada vez que se llame a imp se estar llamando realmente a la versi,n decorada. +yt%on incorpora esta sintaIis desde la versi,n 2.B en adelante. 6i quisi(ramos aplicar ms de un decorador bastar2a a!adir una nueva l2nea con el nuevo decorador.
lotroXdecorador lmiXdecorador de1 imp)s*# print s

Es importante advertir que los decoradores se ejecutarn de abajo a arriba. Es decir$ en este ejemplo primero se ejecutar2a miXdecorador y despu(s otroXdecorador.

64

e<CepCiones
0as eIcepciones son errores detectados por +yt%on durante la ejecuci,n del pro'rama. Cuando el int(rprete se encuentra con una situaci,n eIcepcional$ como el intentar dividir un nmero entre 7 o el intentar acceder a un arc%ivo que no eIiste$ este 'enera o lanza una eIcepci,n$ in1ormando al usuario de que eIiste al'n problema. 6i la eIcepci,n no se captura el 1lujo de ejecuci,n se interrumpe y se muestra la in1ormaci,n asociada a la eIcepci,n en la consola de 1orma que el pro'ramador pueda solucionar el problema. Ueamos un peque!o pro'rama que lanzar2a una eIcepci,n al intentar dividir ? entre 7.
de1 division)a$ b*# return a . b de1 calcular)*# division)?$ 7* calcular)*

6i lo ejecutamos obtendremos el si'uiente mensaje de error#


k pyt%on ejemplo.py Cracebac/ )most recent call last*# Gile Eejemplo.pyF$ line ;$ in calcular)* Gile Eejemplo.pyF$ line $ in calcular division)?$ 7* Gile Eejemplo.pyF$ line 2$ in division a . b meroDivisionError# inte'er division or modulo by zero

0o primero que se muestra es el trazado de pila o traceback$ que consiste en una lista con las llamadas que provocaron la eIcepci,n.
65

Como

66

Python para todos

vemos en el trazado de pila$ el error estuvo causado por la llamada a calcular)* de la l2nea ;$ que a su vez llama a division)?$ 7* en la l2nea y en ltima instancia por la ejecuci,n de la sentencia a . b de la l2nea 2 de division. 5 continuaci,n vemos el tipo de la eIcepci,n$ meroDivisionError$ junto a una descripci,n del error# Einte'er division or modulo by zeroF )m,dulo o divisi,n entera entre cero*. En +yt%on se utiliza una construcci,n try-eIcept para capturar y tratar las eIcepciones. El bloque try )intentar* de1ine el 1ra'mento de c,di'o en el que creemos que podr2a producirse una eIcepci,n. El bloque eIcept )eIcepci,n* permite indicar el tratamiento que se llevar a cabo de producirse dic%a eIcepci,n. 3uc%as veces nuestro tratamiento de la eIcepci,n consistir simplemente en imprimir un mensaje ms ami'able para el usuario$ otras veces nos interesar re'istrar los errores y de vez en cuando podremos establecer una estrate'ia de resoluci,n del problema. En el si'uiente ejemplo intentamos crear un objeto 1 de tipo 1ic%ero. De no eIistir el arc%ivo pasado como parmetro$ se lanza una eIcep- ci,n de tipo 4HError$ que capturamos 'racias a nuestro try-eIcept.
try# 1 [ 1ile)Earc%ivo.tItF* eIcept# print EEl arc%ivo no eIisteF

+yt%on permite utilizar varios eIcept para un solo bloque try$ de 1orma que podamos dar un tratamiento distinto a la eIcepci,n dependiendo del tipo de eIcepci,n de la que se trate. Esto es una buena prctica$ y es tan sencillo como indicar el nombre del tipo a continuaci,n del eIcept.
try# num [ int)EDaF* print noXeIiste eIcept @ameError# print E0a variable no eIisteF eIcept UalueError# print EEl valor no es un numeroF

67

+,cepciones

Cuando se lanza una eIcepci,n en el bloque try$ se busca en cada una de las clausulas eIcept un manejador adecuado para el tipo de error que se produjo. En caso de que no se encuentre$ se propa'a la eIcep- ci,n. 5dems podemos %acer que un mismo eIcept sirva para tratar ms de una eIcepci,n usando una tupla para listar los tipos de error que queremos que trate el bloque#
try# num [ int)EDaF* print noXeIiste eIcept )@ameError$ UalueError*# print EHcurrio un errorF

0a construcci,n try-eIcept puede contar adems con una clausula else$ que de1ine un 1ra'mento de c,di'o a ejecutar s,lo si no se %a producido nin'una eIcepci,n en el try.
try# num [ DD eIcept# print E>ubo un errorYF else# print ECodo esta bienF

Cambi(n eIiste una clausula 1inally que se ejecuta siempre$ se pro- duzca o no una eIcepci,n. Esta clausula se suele utilizar$ entre otras cosas$ para tareas de limpieza.
try# z [ I . y eIcept meroDivisionError# print EDivision por ceroF 1inally# print E0impiandoF

Cambi(n es interesante comentar que como pro'ramadores podemos crear y lanzar nuestras propias eIcepciones. &asta crear una clase que %erede de EIception o cualquiera de sus %ijas y lanzarla con raise.
class 3iError)EIception*# de1 init )sel1$ valor*# sel1.valor [ valor

68

Python para todos

de1 try#

str )sel1*# return EError E T str)sel1.valor*

i1 resultado S 27# raise 3iError)DD* eIcept 3iError$ e# print e

+or ltimo$ a continuaci,n se listan a modo de re1erencia las eIcepcio- nes disponibles por de1ecto$ as2 como la clase de la que deriva cada una de ellas entre par(ntesis.
&aseEIception#

Clase

de

la

que

%eredan

todas

las

eIcepciones.
EIception)&aseEIception*#

6uper clase de todas las eIcepciones que 6e pide que se sal'a de un

no sean de salida.
GeneratorEIit)EIception*#

'enerador.
6tandardError)EIception*#

Clase base para todas las eIcepciones que no ten'an que ver con salir del int(rprete.
5rit%meticError)6tandardError*#

Clase base para los errores aritm(Error en una operaci,n de

ticos.
Gloatin'+ointError)5rit%meticError* #

coma 1lotante.
Hver1lo-Error)5rit%meticError*#

Resultado demasiado 'rande para

poder representarse.
meroDivisionError)5rit%meticError* #

0anzada cuando el se'undo ar'umento de una operaci,n de divisi,n o m,dulo era 7.


5ssertionError)6tandardError* # assert. 5ttributeError)6tandardError*#

Gall, la condici,n de un estamento @o se encontr, el atributo.

69

+,cepciones
EHGError)6tandardError*#

6e intent, leer ms all del 1inal de 1ic%ero. Clase padre de los errores relacio-

EnvironmentError)6tandardError*#

nados con la entrada.salida.


4HError)EnvironmentError*# H6Error)EnvironmentError*# Lindo-sError)H6Error*#

Error en una operaci,n de entrada.salida. Error en una llamada a sistema.

Error en una llamada a sistema en Lindo-s.

4mportError)6tandardError*#

@o se encuentra el m,dulo o el elemento del m,dulo que se quer2a importar.


0oo/upError)6tandardError*# 4ndeIError)0oo/upError*#

Clase padre de los errores de acceso.

El 2ndice de la secuencia est 1uera del

ran'o posible.
WeyError)0oo/upError*#

0a clave no eIiste. @o queda memoria su1iciente.

3emoryError)6tandardError*# @ameError)6tandardError*#

@o se encontr, nin'n elemento con ese El nombre no est asociado a nin'una El objeto no tiene nin'una re1eren-

nombre.
"nbound0ocalError)@ameError*#

variable.
Re1erenceError)6tandardError* #

cia 1uerte apuntando %acia (l.


RuntimeError)6tandardError*#

Error en tiempo de ejecuci,n no espeEse m(todo o 1unci,n no est

ci1icado.
@ot4mplementedError)RuntimeError* #

implementado.
6yntaIError)6tandardError*#

Clase padre para los errores sintcticos.


70

Python para todos


4ndentationError)6yntaIError*# CabError)4ndentationError*#

Error en la indentaci,n del arc%ivo.

Error debido a la mezcla de espacios y Error interno del int(rprete.

tabuladores.
6ystemError)6tandardError*# CypeError)6tandardError*#

Cipo de ar'umento no apropiado. Ualor del ar'umento no apropiado.

UalueError)6tandardError*# "nicodeError)UalueError*#

Clase padre para los errores

relacionados con unicode.


"nicodeDecodeError)"nicodeError*# "nicodeEncodeError)"nicodeError*#

Error de decodi1icaci,n unicode. Error de codi1icaci,n unicode. Error de traducci,n unicode.

"nicodeCranslateError)"nicodeError* # 6top4teration)EIception*#

6e utiliza para indicar el 1inal del

iterador. Larnin')EIception*# Clase padre para los avisos.


DeprecationLarnin')Larnin'*#

Clase padre para avisos sobre caracte-

r2sticas obsoletas.
GutureLarnin')Larnin'*#

5viso. 0a semntica de la construcci,n cam5viso sobre posibles errores a la %ora

biar en un 1uturo.
4mportLarnin')Larnin'*#

de importar.
+endin'DeprecationLarnin')Larnin'*#

5viso sobre caracter2sticas que se marcarn como obsoletas en un 1uturo pr,Iimo.


RuntimeLarnin')Larnin'*#

5viso sobre comportmaientos dudosos en


71

tiempo de ejecuci,n.

+,cepciones
6yntaILarnin')Larnin'*#

5viso sobre sintaIis dudosa.

"nicodeLarnin')Larnin'*#

5viso sobre problemas relacionados con "nicode$ sobre todo con problemas de conversi,n.
"serLarnin')Larnin'*#

Clase padre para avisos creados por el pro'raEl pro'rama 1u( interrumpido

mador.
Weyboard4nterrupt)&aseEIception*#

por el usuario.
6ystemEIit)&aseEIception*#

+etici,n del int(rprete para terminar la

ejecuci,n.

72

% dulos y paquete s
%dulos
+ara 1acilitar el mantenimiento y la lectura los pro'ramas demasiado lar'os pueden dividirse en m,dulos$ a'rupando elementos relacionados. 0os m,dulos son entidades que permiten una or'anizaci,n y divi- si,n l,'ica de nuestro c,di'o. 0os 1ic%eros son su contrapartida 12sica# cada arc%ivo +yt%on almacenado en disco equivale a un m,dulo. Uamos a crear nuestro primer m,dulo entonces creando un peque!o arc%ivo modulo.py con el si'uiente contenido#
de1 miX1uncion)*# print Euna 1uncionF class 3iClase# de1 init )sel1*# print Euna claseF print Eun moduloF

6i quisi(ramos utilizar la 1uncionalidad de1inida en este m,dulo en nuestro pro'rama tendr2amos que importarlo. +ara importar un m,dulo se utiliza la palabra clave import se'uida del nombre del m,dulo$ que consiste en el nombre del arc%ivo menos la eItensi,n. Como ejemplo$ creemos un arc%ivo pro'rama.py en el mismo directorio en el que 'uardamos el arc%ivo del m,dulo )esto es importante$ porque si no se encuentra en el mismo directorio +yt%on no podr encontrarlo*$ con 73 el

si'uiente contenido#
import modulo

74

Mdu$os y pa-uetes

modulo.miX1uncion)*

El import no solo %ace que ten'amos disponible todo lo de1inido dentro del m,dulo$ sino que tambi(n ejecuta el c,di'o del m,dulo. +or esta raz,n nuestro pro'rama$ adems de imprimir el teIto Euna 1un- cionF al llamar a miX1uncion$ tambi(n imprimir2a el teIto Eun moduloF$ debido al print del m,dulo importado. @o se imprimir2a$ no obstante$ el teIto Euna claseF$ ya que lo que se %izo en el m,dulo 1ue tan solo de1inir de la clase$ no instanciarla. 0a clausula import tambi(n permite importar varios m,dulos en la misma l2nea. En el si'uiente ejemplo podemos ver c,mo se importa con una sola clausula import los m,dulos de la distribuci,n por de1ecto de +yt%on os$ que en'loba 1uncionalidad relativa al sistema operativoM sys$ con 1uncionalidad relacionada con el propio int(rprete de +yt%on y time$ en el que se almacenan 1unciones para manipular 1ec%as y %oras.
import os$ sys$ time print time.asctime)*

6in duda os %abr(is 1ijado 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 al'n otro objeto que tuviera el mismo nombre al importar otro m,dulo. 6in embar'o es posible utilizar la construcci,n 1rom-import para a%orrarnos el tener que indicar el nombre del m,dulo antes del objeto que nos interesa. De esta 1orma se importa el objeto o los objetos que indiquemos al espacio de nombres actual.
1rom time import asctime print asctime)*

75

Python para todos

5unque se considera una mala prctica$ tambi(n es posible importar todos los nombres del m,dulo al espacio de nombres actual usando el caracter ^#
1rom time import ^

5%ora bien$ recordareis que a la %ora de crear nuestro primer m,dulo insist2 en que lo 'uardarais en el mismo directorio en el que se en- contraba el pro'rama que lo importaba. Entonces$ 8c,mo podemos importar los m,dulos os$ sys o time si no se encuentran los arc%ivos os.py$ sys.py y time.py en el mismo directorio: 5 la %ora de importar un m,dulo +yt%on recorre todos los directorios indicados en la variable de entorno +NC>H@+5C> en busca de un arc%ivo con el nombre adecuado. El valor de la variable +NC>H@+5C> se puede consultar desde +yt%on mediante sys.pat%
SSS import sys SSS sys.pat%

De esta 1orma para que nuestro m,dulo estuviera disponible para todos los pro'ramas del sistema bastar2a con que lo copiramos a uno de los directorios indicados en +NC>H@+5C>. En el caso de que +yt%on no encontrara nin'n m,dulo con el nombre especi1icado$ se lanzar2a una eIcepci,n de tipo 4mportError. +or ltimo es interesante comentar que en +yt%on los m,dulos tambi(n son objetosM de tipo module en concreto. +or supuesto esto si'ni1ica que pueden tener atributos y m(todos. "no de sus atributos$ name $ se utiliza a menudo para incluir c,di'o ejecutable en un m,dulo pero que este s,lo se ejecute si se llama al m,dulo como pro'rama$ y no al importarlo. +ara lo'rar esto basta saber que cuando se ejecuta el m,dulo directamente name tiene como valor E main F$ mientras que cuando se importa$ el valor de name es el nombre del m,dulo#
print i1 E6e muestra siempreF

name [[ E main F# print E6e muestra si no es importacionF

76

Mdu$os y pa-uetes

Htro atributo interesante es doc $ que$ como en el caso de 1unciones y clases$ sirve a modo de documentaci,n del objeto )docstrin' o cadena de documentaci,n*. 6u valor es el de la primera l2nea del cuerpo del m,dulo$ en el caso de que esta sea una cadena de teItoM en caso contrario valdr @one.

Paquetes
6i los m,dulos sirven para or'anizar el c,di'o$ los paquetes sirven para or'anizar los m,dulos. 0os paquetes son tipos especiales de m,dulos )ambos son de tipo module* que permiten a'rupar m,dulos relacio- nados. 3ientras los m,dulos se corresponden a nivel 12sico con los arc%ivos$ los paquetes se representan mediante directorios. En una aplicaci,n cualquiera podr2amos tener$ por ejemplo$ un paque- te iu para la inter1az o un paquete bbdd para la persistencia a base de datos. +ara %acer que +yt%on trate a un directorio como un paquete es necesario crear un arc%ivo init .py en dic%a carpeta. En este arc%ivo se pueden de1inir elementos que pertenezcan a dic%o paquete$ como una constante DR4UER para el paquete bbdd$ aunque %abitualmente se tratar de un arc%ivo vac2o. +ara %acer que un cierto m,dulo se encuentre dentro de un paquete$ basta con copiar el arc%ivo que de1ine el m,dulo al directorio del paquete. Como los modulos$ para importar paquetes tambi(n se utiliza import y 1rom-import y el caracter . para separar paquetes$ subpaquetes y m,dulos.
import paq.subpaq.modulo paq.subpaq.modulo.1unc)*

5 lo lar'o de los pr,Iimos cap2tulos veremos al'unos m,dulos y paquetes de utilidad. +ara encontrar al'n m,dulo o paquete que cubra una cierta necesidad$ puedes consultar la lista de +y+4 )+yt%on +ac/a'e 4ndeI* en http://pypi.python.org/$ que cuenta a la %ora de escribir
77

Python para todos

estas l2neas$ con ms de B777 paquetes distintos.

78

entrada=salida y &iCheros
@uestros pro'ramas ser2an de muy poca utilidad si no 1ueran capaces de interaccionar con el usuario. En cap2tulos anteriores vimos$ de pasa- da$ el uso de la palabra clave print para mostrar mensajes en pantalla. En esta lecci,n$ adems de describir ms detalladamente del uso de print para mostrar mensajes al usuario$ aprenderemos a utilizar las 1unciones input y ra-Xinput para pedir in1ormaci,n$ as2 como los ar'umentos de l2nea de comandos y$ por ltimo$ la entrada.salida de 1ic%eros.

,ntrada estndar
0a 1orma ms sencilla de obtener in1ormaci,n por parte del usuario es mediante la 1unci,n ra-Xinput. Esta 1unci,n toma como parmetro una cadena a usar como prompt )es decir$ como teIto a mostrar al usuario pidiendo la entrada* y devuelve una cadena con los caracteres introducidos por el usuario %asta que puls, la tecla Enter. Ueamos un peque!o ejemplo#
nombre [ ra-Xinput)EComo te llamas: E* print EEncantado$ E T nombre

6i necesitramos un entero como entrada en lu'ar de una cadena$ por ejemplo$ podr2amos utilizar la 1unci,n int para convertir la cadena a entero$ aunque ser2a conveniente tener en cuenta que puede lanzarse una eIcepci,n si lo que introduce el usuario no es un nmero.
try# edad [ ra-Xinput)ECuantos anyos tienes: E*

79

Python para todos


dias [ int)edad* ^ DA print E>as vivido E T str)dias* T E diasF eIcept UalueError# print EEso no es un numeroF

0a 1unci,n input es un poco ms complicada. 0o que %ace esta 1unci,n es utilizar ra-Xinput para leer una cadena de la entrada estndar$ y despu(s pasa a evaluarla como si de c,di'o +yt%on se trataraM por lo tanto input deber2a tratarse con sumo cuidado.

Par#etros de l>nea de !o#ando


5dems del uso de input y ra-Xinput el pro'ramador +yt%on cuenta con otros m(todos para obtener datos del usuario. "no de ellos es el uso de parmetros a la %ora de llamar al pro'rama en la l2nea de comandos. +or ejemplo#
pyt%on editor.py %ola.tIt

En este caso %ola.tIt ser2a el parmetro$ al que se puede acceder a trav(s de la lista sys.ar'v$ aunque$ como es de suponer$ antes de poder utilizar dic%a variable debemos importar el m,dulo sys. sys.ar'vQ7R contiene siempre el nombre del pro'rama tal como lo %a ejecutado el usuario$ sys.ar'vQ?R$ si eIiste$ ser2a el primer parmetroM sys.ar'vQ2R el se'undo$ y as2 sucesivamente.
import sys i1)len)sys.ar'v* S ?*# print E5briendo E T sys.ar'vQ?R else# print EDebes indicar el nombre del arc%ivoF

EIisten m,dulos$ como optparse$ que 1acilitan el trabajo con los ar'u- mentos de la l2nea de comandos$ pero eIplicar su uso queda 1uera del objetivo de este cap2tulo.

/alida estndar
0a 1orma ms sencilla de mostrar al'o en la salida estndar es mediante el uso de la sentencia print$ como %emos visto multitud de veces en
80

+ntrada./a$ida0 'icheros

ejemplos anteriores. En su 1orma ms bsica a la palabra clave print le si'ue una cadena$ que se mostrar en la salida estndar al ejecutarse el estamento.
SSS print E>ola mundoF >ola mundo

Despu(s de imprimir la cadena pasada como parmetro el puntero se sita en la si'uiente l2nea de la pantalla$ por lo que el print de +yt%on 1unciona i'ual que el println de Java. En al'unas 1unciones equivalentes de otros len'uajes de pro'ramaci,n es necesario a!adir un carcter de nueva l2nea para indicar eIpl2citamente que queremos pasar a la si'uiente l2nea. Este es el caso de la 1unci,n print1 de C o la propia 1unci,n print de Java. Na eIplicamos el uso de estos caracteres especiales durante la eIplica- ci,n del tipo cadena en el cap2tulo sobre los tipos bsicos de +yt%on. 0a si'uiente sentencia$ por ejemplo$ imprimir2a la palabra E>olaF$ se'uida de un ren'l,n vac2o )dos caracteres de nueva l2nea$ denV*$ y a continuaci,n la palabra EmundoF indentada )un carcter tabulador$ detV*.
print E>olaenenetmundoF

+ara que la si'uiente impresi,n se realizara en la misma l2nea tendr2a- mos que colocar una coma al 1inal de la sentencia. Comparemos el resultado de este c,di'o#
SSS 1or i in ran'e)D*# SSS ...print i$ 7 ? 2

Con el de este otro$ en el que no utiliza una coma al 1inal de la sentencia#


SSS 1or i in ran'e)D*# SSS ...print i 7 ? 2

81

Python para todos

Este mecanismo de colocar una coma al 1inal de la sentencia 1unciona debido a que es el s2mbolo que se utiliza para separar cadenas que queramos imprimir en la misma l2nea.
SSS print E>olaF$ EmundoF >ola mundo

Esto se di1erencia del uso del operador T para concatenar las cadenas en que al utilizar las comas print introduce automticamente un espacio para separar cada una de las cadenas. Este no es el caso al utilizar el operador T$ ya que lo que le lle'a a print es un solo ar'umento# una cadena ya concatenada.
SSS print E>olaF T EmundoF >olamundo

5dems$ al utilizar el operador T tendr2amos que convertir antes cada ar'umento en una cadena de no serlo ya$ ya que no es posible concate- nar cadenas y otros tipos$ mientras que al usar el primer m(todo no es necesaria la conversi,n.
SSS print ECuestaF$ D$ EeurosF Cuesta D euros SSS print ECuestaF T D T EeurosF ctype deIceptions.CypeErrorVS# cannot concatenate dstrV and dintV objects

0a sentencia print$ o ms bien las cadenas que imprime$ permiten tambi(n utilizar t(cnicas avanzadas de 1ormateo$ de 1orma similar al sprint1 de C. Ueamos un ejemplo bastante simple#
print E>ola _sF _ EmundoF print E_s _sF _ )E>olaF$ EmundoF*

0o que %ace la primera l2nea es introducir los valores a la derec%a del s2mbolo _ )la cadena EmundoF* en las posiciones indicadas por los espe- ci1icadores de conversi,n de la cadena a la izquierda del s2mbolo _$ tras convertirlos al tipo adecuado. En la se'unda l2nea$ vemos c,mo se puede pasar ms de un valor a sustituir$ por medio de una tupla.
82

+ntrada./a$ida0 'icheros

En este ejemplo s,lo tenemos un especi1icador de conversi,n# _s. 0os especi1icadores ms sencillos estn 1ormados por el s2mbolo _ se'uido de una letra que indica el tipo con el que 1ormatear el valor +or ejemplo# ,speci%icador
_s _d _o _I _1

(ormato Cadena Entero Hctal >eIadecimal Real

6e puede introducir un nmero entre el _ y el carcter que indica el tipo al que 1ormatear$ indicando el nmero m2nimo de caracteres que queremos que ocupe la cadena. 6i el tama!o de la cadena resultante es menor que este nmero$ se a!adirn espacios a la izquierda de la cadena. En el caso de que el nmero sea ne'ativo$ ocurrir eIactamente lo mismo$ s,lo que los espacios se a!adirn a la derec%a de la cadena.
SSS print >ola SSS print >ola E_?7s mundoF _ E>olaF mundo E_-?7s mundoF _ E>olaF mundo

En el caso de los reales es posible indicar la precisi,n a utilizar prece- diendo la 1 de un punto se'uido del nmero de decimales que quere- mos mostrar#
SSS 1rom mat% import pi SSS print E_.B1F _ pi D.?B?A

0a misma sintaIis se puede utilizar para indicar el nmero de caracte- res de la cadena que queremos mostrar
SSS print E_.BsF _ E%ola mundoF %ola

83

Python para todos

1r!hi-os
0os 1ic%eros en +yt%on son objetos de tipo 1ile creados mediante la 1unci,n open )abrir*. Esta 1unci,n toma como parmetros una cadena con la ruta al 1ic%ero a abrir$ que puede ser relativa o absolutaM una cadena opcional indicando el modo de acceso )si no se especi1ica se accede en modo lectura* y$ por ltimo$ un entero opcional para especi- 1icar un tama!o de bu11er distinto del utilizado por de1ecto. El modo de acceso puede ser cualquier combinaci,n l,'ica de los si'uientes modos# Z Z Z
drV#

Z Z Z

read$ lectura. 5bre el arc%ivo en modo lectura. El arc%ivo tiene que eIistir previamente$ en caso contrario se lanzar una eIcepci,n de tipo 4HError. d-V# -rite$ escritura. 5bre el arc%ivo en modo escritura. 6i el arc%i- vo no eIiste se crea. 6i eIiste$ sobreescribe el contenido. daV# append$ a!adir. 5bre el arc%ivo en modo escritura. 6e di1eren- cia del modo d-V en que en este caso no se sobreescribe el conteni- do del arc%ivo$ sino que se comienza a escribir al 1inal del arc%ivo. dbV# binary$ binario. dTV# permite lectura y escritura simultneas. d"V# universal ne-line$ saltos de l2nea universales. +ermite trabajar con arc%ivos que ten'an un 1ormato para los saltos de l2nea que no coincide con el de la plata1orma actual )en Lindo-s se utiliza el caracter CR 0G$ en "niI 0G y en 3ac H6 CR*.
1 [ open)Earc%ivo.tItF$ E-F*

Cras crear el objeto que representa nuestro arc%ivo mediante la 1unci,n open podremos realizar las operaciones de lectura.escritura pertinentes utilizando los m(todos del objeto que veremos en las si'uientes secciones. "na vez terminemos de trabajar con el arc%ivo debemos cerrarlo utili- zando el m(todo close.

Le!tura de ar!hi-os

84

+ntrada./a$ida0 'icheros

+ara la lectura de arc%ivos se utilizan los m(todos read$ readline y realines. El m(todo read devuelve una cadena con el contenido del arc%ivo o bien el contenido de los primeros n bytes$ si se especi1ica el tama!o mIimo a leer.
completo [ 1.read)* parte [ 12.read) ?2*

El m(todo readline sirve para leer las l2neas del 1ic%ero una por una. Es decir$ cada vez que se llama a este m(todo$ se devuelve el conteni- do del arc%ivo desde el puntero %asta que se encuentra un carcter de nueva l2nea$ incluyendo este carcter.
-%ile Crue# linea [ 1.readline)* i1 not linea# brea/ print linea

+or ltimo$ readlines$ 1unciona leyendo todas las l2neas del arc%ivo y devolviendo una lista con las l2neas le2das.

,s!ritura de ar!hi-os
+ara la escritura de arc%ivos se utilizan los m(todo -rite y -ritelines. 3ientras el primero 1unciona escribiendo en el arc%ivo una cadena de teIto que toma como parmetro$ el se'undo toma como parmetro una lista de cadenas de teIto indicando las l2neas que queremos escribir en el 1ic%ero.

%o-er el puntero de le!tura=es!ritura


>ay situaciones en las que nos puede interesar mover el puntero de lectura.escritura a una posici,n determinada del arc%ivo. +or ejemplo si queremos empezar a escribir en una posici,n determinada y no al 1inal o al principio del arc%ivo. +ara esto se utiliza el m(todo
see/

que toma como parmetro un n-

Python para todos

mero positivo o ne'ativo a utilizar como desplazamiento. Cambi(n es posible utilizar un se'undo parmetro para indicar desde d,nde queremos que se %a'a el desplazamiento# 7 indicar que el desplazamiento se re1iere al principio del 1ic%ero )comportamiento por de1ecto*$ ? se re1iere a la posici,n actual$ y 2$ al 1inal del 1ic%ero. +ara determinar la posici,n en la que se encuentra actualmente el puntero se utiliza el m(todo tell)*$ que devuelve un entero indicando la distancia en bytes desde el principio del 1ic%ero.

e<presiones regulares
0as eIpresiones re'ulares$ tambi(n llamadas rege! o rege!p$ consisten en patrones que describen conjuntos de cadenas de caracteres. 5l'o parecido ser2a escribir en la l2nea de comandos de Lindo-s
dir ^.eIe

ser2a una EeIpresi,n re'ularF que describir2a todas las cadenas de caracteres que empiezan con cualquier cosa se'uida de d.eIeV$ es decir$ todos los arc%ivos eIe.
d^.eIeV

El trabajo con eIpresiones re'ulares en +yt%on se realiza mediante el m,dulo re$ que data de +yt%on ?. y que proporciona una sintaIis para la creaci,n de patrones similar a la de +erl. En +yt%on ?.A el m,dulo se reescribi, para dotarlo de soporte de cadenas unicode y mejorar su rendimiento. El m,dulo re contiene 1unciones para buscar patrones dentro de una cadena )searc%*$ comprobar si una cadena se ajusta a un determinado criterio descrito mediante un patr,n )matc%*$ dividir la cadena usando las ocurrencias del patr,n como puntos de ruptura )split* o para sustituir todas las ocurrencias del patr,n por otra cadena )sub*. Ueremos estas 1unciones y al'una ms en la pr,Iima secci,n$ pero por a%ora$ aprendamos al'o ms sobre la sintaIis de las eIpresiones re'ulares.

Patrones
0a eIpresi,n re'ular ms sencilla consiste en una cadena simple$ que

Python para todos

describe un conjunto compuesto tan solo por esa misma cadena. +or ejemplo$ veamos c,mo la cadena Epyt%onF coincide con la eIpresi,n re'ular Epyt%onF usando la 1unci,n matc%#
import re i1 re.matc%)Epyt%onF$ Epyt%onF*# print EciertoF

6i quisi(ramos comprobar si la cadena es Epyt%onF$ Ejyt%onF$ Ecyt%onF o cualquier otra cosa que termine en Eyt%onF$ podr2amos utilizar el carcter comod2n$ el punto d.V#
re.matc%)E.yt%onF$ Epyt%onF* re.matc%)E.yt%onF$ Ejyt%onF*

0a eIpresi,n re'ular E.yt%onF describir2a a todas las cadenas que con- sistan en un carcter cualquiera$ menos el de nueva l2nea$ se'uido de Eyt%onF. "n carcter cualquiera y solo uno. @o cero$ ni dos$ ni tres. En el caso de que necesitramos el carcter d.V en la eIpresi,n re'ular$ o cualquier otro de los caracteres especiales que veremos a continua- ci,n$ tendr2amos que escaparlo utilizando la barra invertida. +ara comprobar si la cadena consiste en D caracteres se'uidos de un punto$ por ejemplo$ podr2amos utilizar lo si'uiente#
re.matc%)E...e.F$ Eabc.F*

6i necesitramos una eIpresi,n que s,lo resultara cierta para las cade- nas Epyt%onF$ Ejyt%onF y Ecyt%onF y nin'una otra$ podr2amos utilizar el carcter d`V para eIpresar alternativa escribiendo los tres subpatro- nes completos#
re.matc%)Epyt%on`jyt%on`cyt%onF$ Epyt%onF*

o bien tan solo la parte que pueda cambiar$ encerrada entre par(ntesis$ 1ormando lo que se conoce como un 'rupo. 0os 'rupos tienen una 'ran importancia a la %ora de trabajar con eIpresiones re'ulares y este no es su nico uso$ como veremos en la si'uiente

secci,n.

Python para todos

+,presiones regu$ares
re.matc%)E)p`j`c*yt%onF$ Epyt%onF*

Htra opci,n consistir2a en encerrar los caracteres dpV$ djV y dcV entre corc%etes para 1ormar una clase de caracteres$ indicando que en esa posici,n puede colocarse cualquiera de los caracteres de la clase.
re.matc%)EQpjcRyt%onF$ Epyt%onF*

8N si quisi(ramos comprobar si la cadena es Epyt%on7F$ Epyt%on?F$ Epyt%on2F$ ... $ Epyt%on=F: En lu'ar de tener que encerrar los ?7 d2'itos dentro de los corc%etes podemos utilizar el 'ui,n$ que sirve para indi- car ran'os. +or ejemplo a-d indicar2a todas las letras minsculas de la daV a la ddVM 7-= ser2an todos los nmeros de 7 a = inclusive.
re.matc%)Epyt%onQ7-=RF$ Epyt%on7F*

6i quisi(ramos$ por ejemplo$ que el ltimo carcter 1uera o un d2'ito o una letra simplemente se escribir2an dentro de los corc%etes todos los criterios$ uno detras de otro.
re.matc%)Epyt%onQ7-=a-z5-mRF$ Epyt%onpF*

Es necesario advertir que dentro de las clases de caracteres los caracte- res especiales no necesitan ser escapados. +ara comprobar si la cadena es Epyt%on.F o Epyt%on$F$ entonces$ escribir2amos#
re.matc%)Epyt%onQ.$RF$ Epyt%on.F*

y no
re.matc%)Epyt%onQe.$RF$ Epyt%on.F*

ya que en este ltimo caso estar2amos comprobando si la cadena es Epyt%on.F$ Epyt%on$F o Epyt%oneF. 0os conjuntos de caracteres tambi(n se pueden ne'ar utilizando el s2mbolo daV. 0a eIpresi,n Epyt%onQa7-=a-zRF$ por ejemplo$ indicar2a que nos interesan las cadenas que comiencen por Epyt%onF y ten'an como ltimo carcter al'o que no sea ni una letra minscula ni un nmero.

Python para todos

re.matc%)Epyt%onQa7-=a-zRF$ Epyt%onTF*

El uso de Q7-=R para re1erirse a un d2'ito no es muy comn$ ya que$ al ser la comprobaci,n de que un carcter es un d2'ito al'o muy utilizado$ eIiste una secuencia especial equivalente# dedV. EIisten otras secuen- cias disponibles que listamos a continuaci,n# Z Z Z Z Z Z
EedF# EeDF#

un d2'ito. Equivale a Q7-=R cualquier carcter que no sea un d2'ito. Equivale a Qa7-=R Ee-F# cualquier caracter al1anum(rico. Equivale a Qa-z5-m7-=XR EeLF# cualquier carcter no al1anum(rico. Equivale a Qaaz5- m7-=XR EesF# Ee6F#

cualquier carcter en blanco. Equivale a Q etenere1evR cualquier carcter que no sea un espacio en blanco. Equivale a Qa etenere1evR

Ueamos a%ora c,mo representar repeticiones de caracteres$ dado que no ser2a de muc%a utilidad tener que$ por ejemplo$ escribir una eIpresi,n re'ular con D7 caracteres dedV para buscar nmeros de D7 d2'itos. +ara este menester tenemos los caracteres especiales T$ ^ y :$ adems de las llaves ij. El carcter T indica que lo que tenemos a la izquierda$ sea un carcter como daV$ una clase como dQabcRV o un subpatr,n como )abc*$ puede encontrarse una o mas veces. +or ejemplo la eIpresi,n re'ular Epyt%onTF describir2a las cadenas Epyt%onF$ Epyt%onnF y Epyt%onnnF$ pero no Epyt%oF$ ya que debe %aber al menos una n. El carcter ^ es similar a T$ pero en este caso lo que se sita a su iz- quierda puede encontrarse cero o mas veces. El carcter : indica opcionalidad$ es decir$ lo que tenemos a la izquier- da puede o no aparecer )puede aparecer 7 o ? veces*. Ginalmente las llaves sirven para indicar el nmero de veces eIacto que puede aparecer el carcter de la izquierda$ o bien un ran'o de veces que puede aparecer. +or ejemplo iDj indicar2a que tiene que aparecer eIac- tamente D veces$ iD$<j indicar2a que tiene que aparecer de D a < veces$

+,presiones regu$ares
i$<j

de 7 a < veces y iD$j tres veces o mas )las que sean*.

Htro elemento interesante en las eIpresiones re'ulares$ para terminar$ es la especi1icaci,n de las posiciones en que se tiene que encontrar la cadena$ esa es la utilidad de a y k$ que indican$ respectivamente$ que el elemento sobre el que actan debe ir al principio de la cadena o al 1inal de esta. 0a cadena E%ttp#..mundo'ee/.netF$ por ejemplo$ se ajustar2a a la eIpresi,n re'ular Ea%ttpF$ mientras que la cadena EEl protocolo es %ttpF no lo %ar2a$ ya que el %ttp no se encuentra al principio de la cadena.

?sando el #dulo re
Na %emos visto por encima c,mo se utiliza la 1unci,n matc% del m,du- lo re para comprobar si una cadena se ajusta a un determinado patr,n. El primer parmetro de la 1unci,n es la eIpresi,n re'ular$ el se'undo$ la cadena a comprobar y eIiste un tercer parmetro opcional que contiene distintos 1la's que se pueden utilizar para modi1icar el comportamiento de las eIpresiones re'ulares. 5l'unos ejemplos de 1la's del m,dulo re son re.4G@HREC56E$ que %ace que no se ten'a en cuenta si las letras son maysculas o minsculas o re.UER&H6E$ que %ace que se i'noren los espacios y los comentarios en la cadena que representa la eIpresi,n re'ular. El valor de retorno de la 1unci,n ser @one en caso de que la cadena no se ajuste al patr,n o un objeto de tipo 3atc%Hbject en caso contrario. Este objeto 3atc%Hbject cuenta con m(todos start y end que devuel- ven la posici,n en la que comienza y 1inaliza la subcadena reconocida y m(todos 'roup y 'roups que permiten acceder a los 'rupos que propi- ciaron el reconocimiento de la cadena. 5l llamar al m(todo 'roup sin parmetros se nos devuelve el 'rupo 7 de la cadena reconocida. El 'rupo 7 es la subcadena reconocida por la eIpresi,n re'ular al completo$ aunque no eIistan par(ntesis

que delimiten el 'rupo.

+,presiones regu$ares

Python para todos

SSS mo [ re.matc%)E%ttp#...TenetF$ E%ttp#..mundo'ee/.netF* SSS print mo.'roup)* %ttp#..mundo'ee/.net

+odr2amos crear 'rupos utilizando los par(ntesis$ como aprendimos en la secci,n anterior$ obteniendo as2 la parte de la cadena que nos interese.
SSS mo [ re.matc%)E%ttp#..).T*enetF$ E%ttp#..mundo'ee/.netF* SSS print mo.'roup)7* %ttp#..mundo'ee/.net SSS print mo.'roup)?* mundo'ee/

El m(todo 'roups$ por su parte$ devuelve una lista con todos los 'rupos$ eIceptuando el 'rupo 7$ que se omite.
SSS mo [ re.matc%)E%ttp#..).T*e).iDj*F$ E%ttp#..mundo'ee/. netF* SSS print mo.'roups)* )dmundo'ee/V$ dnetV*

0a 1unci,n searc% del m,dulo re 1unciona de 1orma similar a matc%M contamos con los mismos parmetros y el mismo valor de retorno. 0a nica di1erencia es que al utilizar matc% la cadena debe ajustarse al patr,n desde el primer carcter de la cadena$ mientras que con searc% buscamos cualquier parte de la cadena que se ajuste al patr,n. +or esta raz,n el m(todo start de un objeto 3atc%Hbject obtenido mediante la 1unci,n matc% siempre devolver 7$ mientras que en el caso de searc% esto no tiene por qu( ser as2. Htra 1unci,n de bsqueda del m,dulo re es 1indall. Este toma los mismos parmetros que las dos 1unciones anteriores$ pero devuelve una lista con las subcadenas que cumplieron el patr,n. Htra posibilidad$ si no queremos todas las coincidencias$ es utilizar 1inditer$ que devuelve un iterador con el que consultar uno a uno los distintos 3atc%Hbject. 0as eIpresiones re'ulares no solo permiten realizar bsquedas o comprobaciones$ sino que$ como comentamos anteriormente$ tambi(n

+,presiones regu$ares

tenemos 1unciones disponibles para dividir la cadena o realizar reemplazos. 0a 1unci,n split sin ir ms lejos toma como parmetros un patr,n$ una cadena y un entero opcional indicando el nmero mIimo de elementos en los que queremos dividir la cadena$ y utiliza el patr,n a modo de puntos de separaci,n para la cadena$ devolviendo una lista con las subcadenas. 0a 1unci,n sub toma como parmetros un patr,n a sustituir$ una cadena que usar como reemplazo cada vez que encontremos el patr,n$ la cadena sobre la que realizar las sustituciones$ y un entero opcional indicando el nmero mIimo de sustituciones que queremos realizar. 5l llamar a estos m(todos lo que ocurre en realidad es que se crea un nuevo objeto de tipo Re'eIHbject que representa la eIpresi,n re'ular$ y se llama a m(todos de este objeto que tienen los mismos nombres que las 1unciones del m,dulo. 6i vamos a utilizar un mismo patr,n varias veces nos puede interesar crear un objeto de este tipo y llamar a sus m(todos nosotros mismosM de esta 1orma evitamos que el int(rprete ten'a que crear un nuevo objeto cada vez que usemos el patr,n y mejoraremos el rendimiento de la aplicaci,n. +ara crear un objeto Re'eIHbject se utiliza la 1unci,n compile del m,dulo$ al que se le pasa como parmetro la cadena que representa el patr,n que queremos utilizar para nuestra eIpresi,n re'ular y$ opcio- nalmente$ una serie de 1la's de entre los que comentamos anterior- mente.

soC@ets
0a comunicaci,n entre distintas entidades en una red se basa en +yt%on en el clsico concepto de sockets. 0os soc/ets son un concepto abstracto con el que se desi'na al punto 1inal de una coneIi,n. 0os pro'ramas utilizan soc/ets para comunicarse con otros pro'ramas$ que pueden estar situados en computadoras distintas. "n soc/et queda de1inido por la direcci,n 4+ de la mquina$ el puerto en el que escuc%a$ y el protocolo que utiliza. 0os tipos y 1unciones necesarios para trabajar con soc/ets se encuen- tran en +yt%on en el m,dulo soc/et$ como no podr2a ser de otra 1orma. 0os soc/ets se clasi1ican en soc/ets de 1lujo )soc/et.6HCWX6CRE53* o soc/ets de data'ramas )soc/et.6HCWXDGR53* dependiendo de si el servicio utiliza CC+$ que es orientado a coneIi,n y 1iable$ o "D+$ respec- tivamente. En este cap2tulo s,lo cubriremos los soc/ets de 1lujo$ que cubren un =7_ de las necesidades comunes. 0os soc/ets tambi(n se pueden clasi1icar se'n la 1amilia. Cenemos soc/ets "@4K )soc/et.5GX"@4K* que se crearon antes de la concepci,n de las redes y se basan en 1ic%eros$ soc/ets soc/et.5GX4@EC que son los que nos interesan$ soc/ets soc/et.5GX4@ECA para 4+vA$ etc. +ara crear un soc/et se utiliza el constructor soc/et.soc/et)* que pue- de tomar como parmetros opcionales la 1amilia$ el tipo y el protocolo. +or de1ecto se utiliza la 1amilia 5GX4@EC y el tipo 6HCWX6CRE53.

Ueremos durante el resto del cap2tulo c,mo crear un par de pro'ramas cliente y servidor a modo de ejemplo.

/oc1ets

0o primero que tenemos que %acer es crear un objeto soc/et para el servidor
soc/etXs [ soc/et.soc/et)*

Cenemos a%ora que indicar en qu( puerto se va a mantener a la escuc%a nuestro servidor utilizando el m(todo bind. +ara soc/ets 4+$ como es nuestro caso$ el ar'umento de bind es una tupla que contiene el %ost y el puerto. El %ost se puede dejar vac2o$ indicando al m(todo que puede utilizar cualquier nombre que est( disponible.
soc/etXs.bind))Elocal%ostF$ ====**

+or ltimo utilizamos listen para %acer que el soc/et acepte coneIiones entrantes y accept para comenzar a escuc%ar. El m(todo listen requiere de un parmetro que indica el nmero de coneIiones mIimas que queremos aceptarM evidentemente$ este valor debe ser al menos ?. El m(todo accept se mantiene a la espera de coneIiones entrantes$ bloqueando la ejecuci,n %asta que lle'a un mensaje. Cuando lle'a un mensaje$ accept desbloquea la ejecuci,n$ devolviendo un objeto soc/et que representa la coneIi,n del cliente y una tupla que contiene el %ost y puerto de dic%a coneIi,n.
soc/etXs.listen)?7* soc/etXc$ )%ostXc$ puertoXc* [ soc/etXs.accept)*

"na vez que tenemos este objeto soc/et podemos comunicarnos con el cliente a trav(s suyo$ mediante los m(todos recv y send )o recv1rom y send1rom en "D+* que permiten recibir o enviar mensajes respec- tivamente. El m(todo send toma como parmetros los datos a enviar$ mientras que el m(todo recv toma como parmetro el nmero mIi- mo de bytes a aceptar.
recibido [ soc/etXc.recv)?72B* print ERecibido# E$ recibio soc/etXc.send)recibido*

Python para todos

"na vez que %emos terminado de trabajar con el soc/et$ lo cerramos con el m(todo close. Crear un cliente es an ms sencillo. 6olo tenemos que crear el objeto soc/et $ utilizar el m(todo connect para conectarnos al servidor y utilizar los m(todos send y recv que vimos anteriormente. El ar'umento de connect es una tupla con %ost y puerto$ eIactamente i'ual que bind.
soc/etXc [ soc/et.soc/et)* soc/etXc.connect))Elocal%ostF$ ====** soc/etXc.send)E%olaF*

Ueamos por ltimo un ejemplo completo. En este ejemplo el cliente manda al servidor cualquier mensaje que escriba el usuario y el servidor no %ace ms que repetir el mensaje recibido. 0a ejecuci,n termina cuando el usuario escribe quit. Este ser2a el c,di'o del script servidor#
import soc/et s [ soc/et.soc/et)* s.bind))Elocal%ostF$ ====** s.listen)?* sc$ addr [ s.accept)* -%ile Crue# recibido [ sc.recv)?72B* i1 recibido [[ EquitF# brea/ print ERecibido#F$ recibido sc.send)recibido* print EadiosF sc.close)* s.close)*

N a continuaci,n tenemos el del script cliente#


import soc/et s [ soc/et.soc/et)* s.connect))Elocal%ostF$ ====**

/oc1ets
-%ile Crue# mensaje [ ra-Xinput)ES E* s.send)mensaje* mensaje [[ EquitF# brea/ print EadiosF s.close)*

interaCtuar Con 2e(s


EIisten dos m,dulos principales para leer datos de "R0s en +yt%on# urllib y urllib2. En esta lecci,n aprenderemos a utilizar urllib2 ya que es muc%o ms completo$ aunque urllib tiene 1uncionalidades propias que no se pueden encontrar en urllib2$ por lo que tambi(n lo tocaremos de pasada. puede leer datos de una "R0 usando varios protocolos como >CC+$ >CC+6$ G C+$ o Gop%er.
urllib2

6e utiliza una 1unci,n urlopen para crear un objeto parecido a un 1ic%ero con el que leer de la "R0. Este objeto cuenta con m(todos como read$ readline$ readlines y close$ los cuales 1uncionan eIactamente i'ual que en los objetos 1ile$ aunque en realidad estamos trabajando con un -rapper que nos abstrae de un soc/et que se utiliza por debajo. El m(todo read$ como recordareis$ sirve para leer el Earc%ivoF completo o el nmero de bytes especi1icado como parmetro$ readline para leer una l2nea$ y readlines para leer todas las l2neas y devolver una lista con ellas. Cambi(n contamos con un par de m(todos 'eturl$ para obtener la "R0 de la que estamos leyendo )que puede ser til para comprobar si %a %abido una redirecci,n* e in1o que nos devuelve un objeto con las cabeceras de respuesta del servidor )a las que tambi(n se puede acceder mediante el atributo %eaders*.
import urllib2

Interactuar con 2e!s

try# 1 [ urllib2.urlopen)E%ttp#..---.pyt%on.or'F* print 1.read)* 1.close)* eIcept >CC+Error$ e# print EHcurri, un errorF print e.code eIcept "R0Error$ e# print EHcurri, un errorF print e.reason

5l trabajar con urllib2 nos podemos encontrar$ como vemos$ con errores de tipo "R0Error. 6i trabajamos con >CC+ podemos encontrarnos tambi(n con errores de la subclase de "R0Error >CC+Error$ que se lanzan cuando el servidor devuelve un c,di'o de error >CC+$ como el error B7B cuando no se encuentra el recurso. Cambi(n podr2amos encontrarnos con errores lanzados por la librer2a que urllib2 utiliza por debajo para las trans1erencias >CC+# %ttplibM o con eIcepciones lanzadas por el propio m,dulo soc/et. 0a 1unci,n urlopen cuenta con un parmetro opcional data con el que poder enviar in1ormaci,n a direcciones >CC+ )y solo >CC+* usando +H6C )los parmetros se env2an en la propia petici,n*$ por ejemplo para responder a un 1ormulario. Este parmetro es una cadena codi1icada adecuadamente$ si'uiendo el 1ormato utilizado en las "R0s#
dpass-ord[contrase_5BaOusuario[manuelV

0o ms sencillo para codi1icar la cadena es utilizar el m(todo urlencode de urllib$ que acepta un diccionario o una lista de tuplas )clave$ valor* y 'enera la cadena codi1icada correspondiente#
import urllib$ urllib2 params [ urllib.urlencode)iEusuarioF# EmanuelF$ Epass-ordF# Econtrase!aFj* 1 [ urllib2.urlopen)E%ttp#..ejemplo.com.lo'inF$ params*

6i lo nico que queremos %acer es descar'ar el contenido de una "R0 a un arc%ivo local$ podemos utilizar la 1unci,n urlretrieve de urllib en lu'ar de leer de un objeto creado con urlopen y escribir los datos

Python para todos

le2dos. 0a 1unci,n urlretrieve toma como parmetros la "R0 a descar'ar y$ opcionalmente$ un parmetro 1ilename con la ruta local en la que 'uardar el arc%ivo$ un parmetro data similar al de urlopen y un parmetro report%oo/ con una 1unci,n que utilizar para in1ormar del pro'reso. 5 eIcepci,n de las ocasiones en las que se utiliza el parmetro data las coneIiones siempre se realizan utilizando GEC )los parmetros se env2an en la "R0*. +ara enviar datos usando GEC basta con concatenar la cadena resultante de urlencode con la "R0 a la que nos vamos a conectar mediante el s2mbolo :.
params [ urllib.urlencode)iEusuarioF# EmanuelF$ Epass-ordF# Econtrase!aFj* 1 [ urllib2.urlopen)E%ttp#..ejemplo.com.lo'inF T E:F T params*

En urllib tambi(n se utiliza una 1unci,n urlopen para crear nuestros pseudo-arc%ivos$ pero a di1erencia de la versi,n de urllib$ la 1unci,n urlopen de urllib2 tambi(n puede tomar como parmetro un objeto Request$ en lu'ar de la "R0 y los datos a enviar. 0a clase Request de1ine objetos que encapsulan toda la in1ormaci,n relativa a una petici,n. 5 trav(s de este objeto podemos realizar peti- ciones ms complejas$ a!adiendo nuestras propias cabeceras$ como el "ser-5'ent. El constructor ms sencillo para el objeto Request no toma ms que una cadena indicando la "R0 a la que conectarse$ por lo que utilizar este objeto como parmetro de urlopen ser2a equivalente a utilizar una cadena con la "R0 directamente. 6in embar'o el constructor de Request tambi(n tiene como parmetros opcionales una cadena data para mandar datos por +H6C y un diccionario %eaders con las cabeceras )adems de un par de campos ori'inXreqX%ost y unveri1iable$ que quedan 1uera del prop,sito del cap2tulo por ser de raro uso*.

Interactuar con 2e!s

Ueamos c,mo a!adir nuestras propias cabeceras utilizando como ejemplo la cabecera "ser-5'ent. El "ser-5'ent es una cabecera que sirve para identi1icar el nave'ador y sistema operativo que estamos utilizando para conectarnos a esa "R0. +or de1ecto urllib2 se identi1ica como E+yt%on-urllib.2. FM si quisi(ramos identi1icarnos como un 0inuI corriendo Wonqueror por ejemplo$ usar2amos un c,di'o similar al si'uiente#
ua [ E3ozilla. .7 )compatibleM Wonqueror.D. .<M 0inuI*F % [ iE"ser-5'entF# uaj r [ urllib2.Request)E%ttp#..---.pyt%on.or'F$ %eaders[%* 1 [ urllib2.urlopen)r* print 1.read)*

+ara personalizar la 1orma en que trabaja urllib2 podemos instalar un 'rupo de manejadores )handlers* a'rupados en un objeto de la clase HpenerDirector )opener o abridor*$ que ser el que se utilice a partir de ese momento al llamar a urlopen. +ara construir un opener se utiliza la 1unci,n buildXopener a la que se le pasa los manejadores que 1ormarn parte del opener. El opener se encar'ar de encadenar la ejecuci,n de los distintos manejadores en el orden dado. Cambi(n se puede usar el constructor de HpenerDirector$ y a!adir los manejadores usando su m(todo addX%andler. +ara instalar el opener una vez creado se utiliza la 1unci,n installXopener$ que toma como parmetro el opener a instalar. Cambi(n se podr2a$ si s,lo queremos abrir la "R0 con ese opener una sola vez$ utilizar el m(todo open del opener. cuenta con %andlers que se encar'an de manejar los esquemas disponibles )>CC+$ >CC+6$ G C+*$ manejar la autenticaci,n$ manejar las redirecciones$ etc.
urllib2

+ara a!adir autenticaci,n tendr2amos que instalar un opener que incluyera como manejador >CC+&asic5ut%>andler$ +roIy&asic5ut%>andler$ >CC+Di'est5ut%>andler y.o +roIyDi'est5ut%>andler. +ara utilizar autenticaci,n >CC+ bsica$ por ejemplo$ usar2amos

Python para todos


>CC+&asic5ut%>andler# autX% [ urllib2.>CC+&asic5ut%>andler)* autX%.addXpass-ord)ErealmF$ E%ostF$ EusuarioF$ Epass-ordF* opener [ urllib2.buildXopener)autX%* urllib2.installXopener)opener* 1 [ urllib2.urlopen)E%ttp#..---.pyt%on.or'F*

6i quisi(ramos especi1icar un proIy en el c,di'o tendr2amos que utilizar un opener que contuviera el manejador +roIy>andler. El manejador por de1ecto incluye una instacia de +roIy>andler construido llamando al inicializador sin parmetros$ con lo que se lee la lista de proIies a utilizar de la variable de entorno adecuada. 6in embar'o tambi(n podemos construir un +roIy>andler pasando como parmetro al inicializador un diccionario cuyas claves son los protocolos y los valores$ la "R0 del proIy a utilizar para dic%o protocolo.
proIyX% [ urllib2.+roIy>andler)iE%ttpF # E%ttp#..miproIy. net#?2DFj* opener [ urllib2.buildXopener)proIyX%* urllib2.installXopener)opener* 1 [ urllib2.urlopen)E%ttp#..---.pyt%on.or'F*

+ara que se 'uarden las coo/ies que manda >CC+ utilizamos el ma- nejador >CC+Coo/ie+rocessor.
coo/ieX% [ urllib2.>CC+Coo/ie+rocessor)* opener [ urllib2.buildXopener)coo/ieX%* urllib2.installXopener)opener* 1 [ urllib2.urlopen)E%ttp#..---.pyt%on.or'F*

6i queremos acceder a estas coo/ies o poder mandar nuestras propias coo/ies$ podemos pasarle como parmetro al inicializador de >CC+Coo- /ie+rocessor un objeto de tipo Coo/ieJar del m,dulo coo/ielib. +ara leer las coo/ies mandadas basta crear un objeto iterable a partir del Coo/ieJar )tambi(n podr2amos buscar las cabeceras correspondientes$ pero este sistema es ms claro y sencillo*#

Interactuar con 2e!s

import urllib2$ coo/ielib coo/ieXj [ coo/ielib.Coo/ieJar)* coo/ieX% [ urllib2.>CC+Coo/ie+rocessor)coo/ieXj* opener [ urllib2.buildXopener)coo/ieX%* opener.open)E%ttp#..---.pyt%on.or'F* 1or num$ coo/ie in enumerate)coo/ieXj*# print num$ coo/ie.name print coo/ie.value print

En el improbable caso de que necesitramos a!adir una coo/ie antes de realizar la coneIi,n$ en lu'ar de conectarnos para que el sitio la mande$ podr2amos utilizar el m(todo setXcoo/ie de Coo/ieJar$ al que le pasamos un objeto de tipo Coo/ie. El constructor de Coo/ie$ no obstante$ es bastante complicado.

threads
Qu son los pro!esos y los threads?
0as computadoras ser2an muc%o menos tiles si no pudi(ramos %acer ms de una cosa a la vez. 6i no pudi(ramos$ por ejemplo$ escuc%ar msica en nuestro reproductor de audio 1avorito mientras leemos un tutorial de +yt%on en 3undo Gee/. +ero$ 8c,mo se conse'u2a esto en computadoras anti'uas con un solo ncleo . una sola C+": 0o que ocurr2a$ y lo que ocurre a%ora$ es que en realidad no estamos ejecutando varios procesos a la vez )se llama proceso a un pro'rama en ejecuci,n*$ sino que los procesos se van turnando y$ dada la velocidad a la que ejecutan las instrucciones$ nosotros tenemos la impresi,n de que las tareas se ejecutan de 1orma paralela como si tuvi(ramos multitarea real. Cada vez que un proceso distinto pasa a ejecutarse es necesario realizar lo que se llama un cambio de conteIto$ durante el cual se salva el estado del pro'rama que se estaba ejecutando a memoria y se car'a el estado del pro'rama que va a entrar a ejecutarse. En +yt%on podemos crear nuevos procesos mediante la 1unci,n os. 1or/$ que ejecuta la llamada al sistema 1or/$ o mediante otras 1unciones ms avanzadas como popen2.popen2$ de 1orma que nuestro pro'rama pueda realizar varias tareas de 1orma paralela. 6in embar'o el cambio de conteIto puede ser relativamente lento$ y los recursos necesarios para mantener el estado demasiados$ por lo que a menudo es muc%o ms e1icaz utilizar lo que se conoce como threads$ %ilos de ejecuci,n$ o procesos li'eros.

hreads

0os t%reads son un concepto similar a los procesos# tambi(n se trata de c,di'o en ejecuci,n. 6in embar'o los t%reads se ejecutan dentro de un proceso$ y los t%reads del proceso comparten recursos entre si$ como la memoria$ por ejemplo. El sistema operativo necesita menos recursos para crear y 'estionar los t%reads$ y al compartir recursos$ el cambio de conteIto es ms rpido. 5dems$ dado que los t%reads comparten el mismo espacio de me- moria 'lobal$ es sencillo compartir in1ormaci,n entre ellos# cualquier variable 'lobal que ten'amos en nuestro pro'rama es vista por todos los t%reads.

,l G)L
0a ejecuci,n de los t%reads en +yt%on est controlada por el %I& )Global 4nterpreter 0oc/* de 1orma que s,lo un t%read puede ejecutarse a la vez$ independientemente del nmero de procesadores con el que cuente la mquina. Esto posibilita que el escribir eItensiones en C para +yt%on sea muc%o ms sencillo$ pero tiene la desventaja de limitar mu- c%o el rendimiento$ por lo que a pesar de todo$ en +yt%on$ en ocasiones nos puede interesar ms utilizar procesos que t%reads$ que no su1ren de esta limitaci,n. Cada cierto nmero de instrucciones de bytecode la mquina virtual para la ejecuci,n del t%read y eli'e otro de entre los que estaban espe- rando. +or de1ecto el cambio de t%read se realiza cada ?7 instrucciones de bytecode$ aunque se puede modi1icar mediante la 1unci,n sys.setc%ec/interval. Cambi(n se cambia de t%read cuando el %ilo se pone a dormir con time.sleep o cuando comienza una operaci,n de entrada. salida$ las cuales pueden tardar muc%o en 1inalizar$ y por lo tanto$ de no realizar el cambio$ tendr2amos a la C+" demasiado tiempo sin trabajar esperando a que la operaci,n de E.6 terminara. +ara minimizar un poco el e1ecto del G40 en el rendimiento de nuestra aplicaci,n es conveniente llamar al int(rprete con el 1la' -H$ lo que %ar que se 'enere un bytecode optimizado con menos instrucciones$

y$

hreads

Python para todos

por lo tanto$ menos cambios de conteIto. Cambi(n podemos plantearnos el utilizar procesos en lu'ar de t%reads$ como ya comentamos$ utilizando por ejemplo el m,dulo processin'M escribir el c,di'o en el que el rendimiento sea cr2tico en una eItensi,n en C o utilizar 4ron+yt%on o Jyt%on$ que carecen de G40.

"hreads en Python
El trabajo con t%reads se lleva a cabo en +yt%on mediante el m,dulo t%read. Este m,dulo es opcional y dependiente de la plata1orma$ y puede ser necesario$ aunque no es comn$ recompilar el int(rprete para a!adir el soporte de t%reads. 5dems de t%read$ tambi(n contamos con el m,dulo t%readin' que se apoya en el primero para proporcionarnos una 5+4 de ms alto nivel$ ms completa$ y orientada a objetos. El m,dulo t%readin' se basa li'eramente en el modelo de t%reads de Java. El m,dulo t%readin' contiene una clase C%read que debemos eItender para crear nuestros propios %ilos de ejecuci,n. El m(todo run contendr el c,di'o que queremos que ejecute el t%read. 6i queremos especi1icar nuestro propio constructor$ este deber llamar a t%readin'. C%read. init )sel1* para inicializar el objeto correctamente.
import t%readin' class 3iC%read)t%readin'.C%read*# de1 init )sel1$ num*# t%readin'.C%read. init )sel1* sel1.num [ num de1 run)sel1*# print E6oy el %iloF$ sel1.num

+ara que el t%read comience a ejecutar su c,di'o basta con crear una instancia de la clase que acabamos de de1inir y llamar a su m(todo start. El c,di'o del %ilo principal y el del que acabamos de crear se ejecutarn de 1orma concurrente.
print E6oy el %ilo principalF 1or i in ran'e)7$ ?7*#

hreads
t [ 3iC%read)i* t.start)* t.join)*

El m(todo join se utiliza para que el %ilo que ejecuta la llamada se bloquee %asta que 1inalice el t%read sobre el que se llama. En este caso se utiliza para que el %ilo principal no termine su ejecuci,n antes que los %ijos$ lo cul podr2a resultar en al'unas plata1ormas en la termina- ci,n de los %ijos antes de 1inalizar su ejecuci,n. El m(todo join puede tomar como parmetro un nmero en coma 1lotante indicando el nmero mIimo de se'undos a esperar. 6i se intenta llamar al m(todo start para una instancia que ya se est ejecutando$ obtendremos una eIcepci,n. 0a 1orma recomendada de crear nuevos %ilos de ejecuci,n consiste en eItender la clase C%read$ como %emos visto$ aunque tambi(n es posible crear una instancia de C%read directamente$ e indicar como parmetros del constructor una clase ejecutable )una clase con el m(todo especial call * o una 1unci,n a ejecutar$ y los ar'umentos en una tupla )parmetro ar's* o un diccionario )parmetro /-ar's*.
import t%readin' de1 imprime)num*# print E6oy el %iloF$ num print E6oy el %ilo principalF 1or i in ran'e)7$ ?7*# t [ t%readin'.C%read)tar'et[imprime$ ar's[)i$ ** t.start)*

5dems de los parmetros tar'et$ ar's y /-ar's tambi(n podemos pasar al constructor un parmetro de tipo cadena name con el nombre que queremos que tome el t%read )el t%read tendr un nombre predeterminado aunque no lo especi1iquemos*M un parmetro de tipo booleano verbose para indicar al m,dulo que imprima mensajes sobre el estado de los t%reads para la depuraci,n y un parmetro 'roup$ que por a%ora no admite nin'n valor pero que en el 1uturo se utilizar para crear 'rupos de t%reads y poder trabajar a nivel de 'rupos.

Python para todos

+ara comprobar si un t%read si'ue ejecutndose$ se puede utilizar el m(todo is5live. Cambi(n podemos asi'nar un nombre al %ilo y consultar su nombre con los m(todos set@ame y 'et@ame$ respectivamente. 3ediante la 1unci,n t%readin'.enumerate obtendremos una lista de los objetos C%read que se estn ejecutando$ incluyendo el %ilo principal )podemos comparar el objeto C%read con la variable mainXt%read para comprobar si se trata del %ilo principal* y con t%readin'.activeCount podemos consultar el nmero de t%reads ejecutndose. 0os objetos C%read tambi(n cuentan con un m(todo setDaemon que toma un valor booleano indicando si se trata de un demonio. 0a utilidad de esto es que si solo quedan t%reads de tipo demonio ejecutndose$ la aplicaci,n terminar automticamente$ terminando estos t%reads de 1orma se'ura. +or ltimo tenemos en el m,dulo t%readin' una clase Cimer que %ereda de C%read y cuya utilidad es la de ejecutar el c,di'o de su m(todo run despu(s de un periodo de tiempo indicado como parmetro en su constructor. Cambi(n incluye un m(todo cancel mediante el que cancelar la ejecuci,n antes de que termine el periodo de espera.

/in!roniza!in
"no de los mayores problemas a los que tenemos que en1rentarnos al utilizar t%reads es la necesidad de sincronizar el acceso a ciertos recur- sos por parte de los t%reads. Entre los mecanismos de sincronizaci,n que tenemos disponibles en el m,dulo t%readin' se encuentran los loc/s$ loc/s reentrantes$ sem1oros$ condiciones y eventos. 0os loc/s$ tambi(n llamados muteI )de mutual eIclusion*$ cierres de eIclusi,n mutua$ cierres o candados$ son objetos con dos estados posibles# adquirido o libre. Cuando un t%read adquiere el candado$ los dems t%reads que lle'uen a ese punto posteriormente y pidan adqui- rirlo se bloquearn %asta que el t%read que lo %a adquirido

libere el candado$ momento en el cul podr entrar otro t%read.

Python para todos

El candado se representa mediante la clase 0oc/. +ara adquirir el

hreads

candado se utiliza el m(todo acquire del objeto$ al que se le puede pasar un booleano para indicar si queremos esperar a que se libere )Crue* o no )Galse*. 6i indicamos que no queremos esperar$ el m(todo devolver Crue o Galse dependiendo de si se adquiri, o no el candado$ respectivamente. +or de1ecto$ si no se indica nada$ el %ilo se bloquea inde1inidamente. +ara liberar el candado una vez %emos terminado de ejecutar el bloque de c,di'o en el que pudiera producirse un problema de concurrencia$ se utiliza el m(todo release.
lista [ QR loc/ [ t%readin'.0oc/)* de1 anyadir)obj*# loc/.acquire)* lista.append)obj* loc/.release)* de1 obtener)*# loc/.acquire)* obj [ lista.pop)* loc/.release)* return obj

0a clase R0oc/ 1unciona de 1orma similar a 0oc/$ pero en este caso el candado puede ser adquirido por el mismo t%read varias veces$ y no quedar liberado %asta que el t%read llame a release tantas veces como llam, a acquire. Como en 0oc/$ y como en todas las primitivas de sincronizaci,n que veremos a continuaci,n$ es posible indicar a acquire si queremos que se bloquee o no. 0os sem1oros son otra clase de candados. 0a clase correspondiente$ 6emap%ore$ tambi(n cuenta con m(todos acquire y release$ pero se di- 1erencia de un 0oc/ normal en que el constructor de 6emap%ore puede tomar como parmetro opcional un entero value indicando el nmero mIimo de t%reads que pueden acceder a la vez a la secci,n de c,di'o cr2tico. 6i no se indica nada permite el acceso a un solo t%read. Cuando un t%read llama a acquire$ la variable que indica el nmero

de t%reads que pueden adquirir el sem1oro disminuye en ?$ porque

hreads

Python para todos

%emos permitido entrar en la secci,n de c,di'o cr2tico a un %ilo ms. Cuando un %ilo llama a release$ la variable aumenta en ?. @o es %asta que esta variable del sem1oro es 7$ que llamar a acquire producir un bloqueo en el t%read que realiz, la petici,n$ a la espera de que al'n otro t%read llame a release para liberar su plaza. Es importante destacar que el valor inicial de la variable tal como lo pasamos en el constructor$ no es un l2mite mIimo$ sino que mltiples llamadas a release pueden %acer que el valor de la variable sea mayor que su valor ori'inal. 6i no es esto lo que queremos$ podemos utilizar la clase &ounded6emap%ore en cuyo caso$ a%ora si$ se considerar2a un error llamar a release demasiadas veces$ y se lanzar2a una eIcepci,n de tipo UalueError de superarse el valor inicial. +odr2amos utilizar los sem1oros$ por ejemplo$ en un peque!o pro'rama en el que mltiples t%reads descar'aran datos de una "R0$ de 1orma que pudieramos limitar el nmero de coneIiones a realizar al sitio -eb para no bombardear el sitio con cientos de peticiones concurrentes.
sema1oro [ t%readin'.6emap%ore)B* de1 descar'ar)url*# sema1oro.acquire)* urllib.urlretrieve)url* sema1oro.release)*

0as condiciones )clase Condition* son de utilidad para %acer que los t%reads s,lo puedan entrar en la secci,n cr2tica de darse una cierta condici,n o evento. +ara esto utilizan un 0oc/ pasado como parmetro$ o crean un objeto R0oc/ automaticamente si no se pasa nin'n par- metro al constructor. 6on especialmente adecuadas para el clsico problema de productorconsumidor. 0a clase cuenta con m(todos acquire y release$ que llamarn a los m(todos correspondientes del candado asociado. Cambi(n tenemos m(todos -ait$ noti1y y noti1y5ll. El m(todo
-ait

debe llamarse despu(s de %aber adquirido el candado

hreads

con acquire. Este m(todo libera el candado y bloquea al t%read %asta que una llamada a noti1y o noti1y5ll en otro t%read le indican que se %a cumplido la condici,n por la que esperaba. El t%read que in1orma a los dems de que se %a producido la condici,n$ tambi(n debe llamar a acquire antes de llamar a noti1y o noti1y5ll. 5l llamar a noti1y$ se in1orma del evento a un solo t%read$ y por tanto se despierta un solo t%read. 5l llamar a noti1y5ll se despiertan todos los t%reads que esperaban a la condici,n. Canto el t%read que noti1ica como los que son noti1icados tienen que terminar liberando el loc/ con release.
lista [ QR cond [ t%readin'.Condition)* de1 consumir)*# cond.acquire)* cond.-ait)* obj [ lista.pop)* cond.release)* return obj de1 producir)obj*# cond.acquire)* lista.append)obj* cond.noti1y)* cond.release)*

0os eventos$ implementados mediante al clase Event$ son un -rapper por encima de Condition y sirven principalmente para coordinar t%reads mediante se!ales que indican que se %a producido un evento. 0os eventos nos abstraen del %ec%o de que estemos utilizando un 0oc/ por debajo$ por lo que carecen de m(todos acquire y release. El t%read que debe esperar el evento llama al m(todo -ait y se bloquea$ opcionalmente pasando como parmetro un nmero en coma 1lotante indicando el nmero mIimo de se'undos a esperar. Htro %ilo$ cuando ocurre el evento$ manda la se!al a los t%reads bloqueados a la espera de dic%o evento utilizando el m(todo set. 0os t%reads que estaban esperando se desbloquean una vez recibida la se!al. El 1la' que determina si se %a producido el evento se puede volver a establecer

a 1also usando clear.

hreads

Python para todos

Como vemos los eventos son muy similares a las condiciones$ a eIcepci,n de que se desbloquean todos los t%reads que esperaban el evento y que no tenemos que llamar a acquire y release.
import t%readin'$ time class 3iC%read)t%readin'.C%read*# de1 init )sel1$ evento*# t%readin'.C%read. init )sel1* sel1.evento [ evento de1 run)sel1*# print sel1.'et@ame)*$ Eesperando al eventoF sel1.evento.-ait)* print sel1.'et@ame)*$ Etermina la esperaF evento [ t%readin'.Event)* t? [ 3iC%read)evento* t?.start)* t2 [ 3iC%read)evento* t2.start)* P Esperamos un poco time.sleep) * evento.set)*

+or ltimo$ un peque!o eItra. 6i sois usuarios de Java sin duda estar(is ec%ando en 1alta una palabra clave syncronized para %acer que s,lo un t%read pueda acceder al m(todo sobre el que se utiliza a la vez. "na construcci,n comn es el uso de un decorador para implementar esta 1uncionalidad usando un 0oc/. 6er2a al'o as2#
de1 sync%ronized)loc/*# de1 dec)1*# de1 1uncXdec)^ar's$ ^^/-ar's*# loc/.acquire)* try# return 1)^ar's$ ^^/-ar's* 1inally# loc/.release)* return 1uncXdec return dec class 3yC%read)t%readin'.C%read*# lsync%ronized)miXloc/* de1 run)sel1*# print Emetodo sincronizadoF

hreads

Datos glo(ales independientes


Como ya %emos comentado los t%reads comparten las variables 'lobales. 6in embar'o pueden eIistir situaciones en las que queramos utilizar variables 'lobales pero que estas variables se comporten como si 1ueran locales a un solo t%read. Es decir$ que cada uno de los t%reads ten'an valores distintos independientes$ y que los cambios de un determinado t%read sobre el valor no se vean re1lejados en las copias de los dems t%reads. +ara lo'rar este comportamiento se puede utilizar la clase t%readin'. local$ que crea un almac(n de datos locales. +rimero debemos crear una instancia de la clase$ o de una subclase$ para despu(s almacenar y obtener los valores a trav(s de parmetros de la clase.
datosXlocales [ t%readin'.local)* datosXlocales.miXvar [ E%olaF print datosXlocales.miXvar

Gij(monos en el si'uiente c,di'o$ por ejemplo. +ara el %ilo principal el objeto local tiene un atributo var$ y por lo tanto el print imprime su valor sin problemas. 6in embar'o para el %ilo t ese atributo no eIiste$ y por lo tanto lanza una eIcepci,n.
local [ t%readin'.local)* de1 1)*# print local.var local.var [ E%olaF t [ t%readin'.C%read)tar'et[1* print local.var t.start)* t.join)*

Co#partir in&or#a!in
+ara compartir in1ormaci,n entre los t%reads de 1orma sencilla podemos utilizar la clase 9ueue.9ueue$ que implementa una cola )una estructura de datos de tipo G4GH* con soporte multi%ilo. Esta clase

utiliza las primitivas de t%readin' para a%orrarnos tener que sincronizar el acceso a los datos nosotros mismos.

Python para todos

El constructor de 9ueue toma un parmetro opcional indicando el tama!o mIimo de la cola. 6i no se indica nin'n valor no %ay l2mite de tama!o. +ara a!adir un elemento a la cola se utiliza el m(todo put)item*M para obtener el si'uiente elemento$ 'et)*. 5mbos m(todos tienen un parmetro booleano opcional bloc/ que indica si queremos que se espere %asta que %aya al'n elemento en la cola para poder devolverlo o %asta que la cola deje de estar llena para poder introducirlo. Cambi(n eIiste un parmetro opcional timeout que indica$ en se'undos$ el tiempo mIimo a esperar. 6i el timeout acaba sin poder %aber realizado la operaci,n debido a que la cola estaba llena o vac2a$ o bien si bloc/ era Galse$ se lanzar una eIcepci,n de tipo 9ueue.Gull o 9ueue.Empty$ respectivamente. Con qsize obtenemos el tama!o de la cola y con empty)* y 1ull)* podemos comprobar si est vac2a o llena.
q [ 9ueue.9ueue)* class 3iC%read)t%readin'.C%read*# de1 init )sel1$ q*# sel1.q [ q t%readin'.C%read. init )sel1* de1 run)sel1*# -%ile Crue# try# obj [ q.'et)Galse* eIcept 9ueue.Empty# print EGinF brea/ print obj 1or i in ran'e)?7*# q.put)i* t [ 3iC%read)q* t.start)* t.join)*

112

serializaCi n de o( etos
5l'unas veces tenemos la necesidad de 'uardar un objeto a disco para poder recuperarlo ms tarde$ o puede que nos sea necesario mandar un objeto a trav(s de la red$ a otro pro'rama en +yt%on ejecutndose en otra mquina. 5l proceso de trans1ormar el estado de un objeto en un 1ormato que se pueda almacenar$ recuperar y transportar se le conoce con el nombre de serializaci,n o marshalling. En +yt%on tenemos varios m,dulos que nos 1acilitan esta tarea$ como mars%al$ pic/le$ c+ic/le y s%elve. El m,dulo mars%al es el ms bsico y el ms primitivo de los tres$ y es que$ de %ec%o$ su prop,sito principal y su raz,n de ser no es el de serializar objetos$ sino trabajar con bytecode +yt%on )arc%ivos .pyc*. s,lo permite serializar objetos simples )la mayor2a de los tipos incluidos por de1ecto en +yt%on*$ y no proporciona nin'n tipo de mecanismo de se'uridad ni comprobaciones 1rente a datos corruptos o mal 1ormateados. Es ms$ el 1ormato utilizado para 'uardar el bytecode )y por tanto el 1ormato utilizado para 'uardar los objetos con mars%al* puede cambiar entre versiones$ por lo que no es adecuado para almace- nar datos de lar'a duraci,n.
mars%al pic/le$

por su parte$ permite serializar casi cualquier objeto )objetos de tipos de1inidos por el usuario$ colecciones que contienen colecciones$ etc* y cuenta con al'unos mecanismos de se'uridad bsicos. 6in em- bar'o$ al ser ms complejo que mars%al$ y$ sobre todo$ 113

al estar escrito en

114

Python para todos

+yt%on en lu'ar de en C$ como mars%al$ tambi(n es muc%o ms lento. 0a soluci,n$ si la velocidad de la serializaci,n es importante para nues- tra aplicaci,n$ es utilizar c+ic/le$ que no es ms que es una implemen- taci,n en C de pic/le. c+ic/le es %asta ?777 veces ms rpido que pic/le$ y prcticamente i'ual de rpido que mars%al. 6i intentamos importar c+ic/le y se produce un error por al'n motivo$ se lanzar una eIcepci,n de tipo 4mportError. +ara utilizar c+ic/le si est disponible y pic/le en caso contrario$ podr2amos usar un c,di'o similar al si'uiente#
try# import c+ic/le as pic/le eIcept 4mportError# import pic/le

en un import sirve para importar el elemento seleccionado utilizando otro nombre indicado$ en lu'ar de su nombre.
as

0a 1orma ms sencilla de serializar un objeto usando pic/le es mediante una llamada a la 1unci,n dump pasando como ar'umento el objeto a serializar y un objeto arc%ivo en el que 'uardarlo )o cualquier otro tipo de objeto similar a un arc%ivo$ siempre que o1rezca m(todos read$ realine y -rite*.
try# import c+ic/le as pic/le eIcept 4mportError# import pic/le 1ic%ero [ 1ile)Edatos.datF$ E-F* animales [ QEpitonF$ EmonoF$ EcamelloFR pic/le.dump)animales$ 1ic%ero* 1ic%ero.close)*

0a 1unci,n dump tambi(n tiene un parmetro opcional protocol que indica el protocolo a utilizar al 'uardar. +or de1ecto su valor es 7$ que utiliza 1ormato teIto y es el menos e1iciente. El protocolo ? es ms e1iciente que el 7$ pero menos que el 2. Canto el protocolo ? como el 2 utilizan un 1ormato binario para 'uardar los datos.
115

/eria$i3acin de o!&etos

try# import c+ic/le as pic/le eIcept 4mportError# import pic/le 1ic%ero [ 1ile)Edatos.datF$ E-F* animales [ QEpitonF$ EmonoF$ EcamelloFR pic/le.dump)animales$ 1ic%ero$ 2* 1ic%ero.close)*

+ara volver a car'ar un objeto serializado se utiliza la 1unci,n load$ a la que se le pasa el arc%ivo en el que se 'uard,.
try# import c+ic/le as pic/le eIcept 4mportError# import pic/le 1ic%ero [ 1ile)Edatos.datF$ E-F* animales [ QEpitonF$ EmonoF$ EcamelloFR pic/le.dump)animales$ 1ic%ero* 1ic%ero.close)* 1ic%ero [ 1ile)Edatos.datF* animales2 [ pic/le.load)1ic%ero* print animales2

6upon'amos a%ora que queremos almacenar un par de listas en un 1ic%ero. Esto ser2a tan sencillo como llamar una vez a dump por cada lista$ y llamar despu(s una vez a load por cada lista.
1ic%ero [ 1ile)Edatos.datF$ E-F* animales [ QEpitonF$ EmonoF$ EcamelloFR len'uajes [ QEpyt%onF$ EmonoF$ EperlFR pic/le.dump)animales$ 1ic%ero* pic/le.dump)len'uajes$ 1ic%ero* 1ic%ero [ 1ile)Edatos.datF* animales2 [ pic/le.load)1ic%ero* len'uajes2 [ pic/le.load)1ic%ero* print animales2 print len'uajes2

116

Python para todos

+ero$ 8y si %ubi(ramos 'uardado D7 objetos y quisi(ramos acceder al ltimo de ellos: 8o si no recordramos en qu( posici,n lo %ab2amos 'uardado: El m,dulo s%elve eItiende pic/le . c+ic/le para proporcionar una 1orma de realizar la serializaci,n ms clara y sencilla$ en la que podemos acceder a la versi,n serializada de un objeto mediante una cadena asociada$ a trav(s de una estructura parecida a un dicciona- rio. 0a nica 1unci,n que necesitamos conocer del m,dulo s%elve es open$ que cuenta con un parmetro 1ilename mediante el que indicar la ruta a un arc%ivo en el que 'uardar los objetos )en realidad se puede crear ms de un arc%ivo$ con nombres basados en 1ilename$ pero esto es transparente al usuario*. 0a 1unci,n open tambi(n cuenta con un parmetro opcional protocol$ con el que especi1icar el protocolo que queremos que utilice pic/le por debajo. Como resultado de la llamada a open obtenemos un objeto 6%el1$ con el que podemos trabajar como si de un diccionario normal se tratase )a eIcepci,n de que las claves s,lo pueden ser cadenas* para almacenar y recuperar nuestros objetos. Como un diccionario cualquiera la clase 6%el1 cuenta con m(todos 'et$ %asX/ey$ items$ /eys$ values$ h "na vez %ayamos terminado de trabajar con el objeto 6%el1$ lo cerrare- mos utilizando el m(todo close.
import s%elve animales [ QEpitonF$ EmonoF$ EcamelloFR len'uajes [ QEpyt%onF$ EmonoF$ EperlFR s%el1 [ s%elve.open)Edatos.datF* s%el1QEprimeraFR [ animales s%el1QEse'undaFR [ len'uajes print s%el1QEse'undaFR s%el1.close)*

117

(ases de datos
EIisten problemas para los que 'uardar nuestros datos en 1ic%eros de teIto plano$ en arc%ivos K30$ o mediante serializaci,n con pic/le o s%elve pueden ser soluciones poco convenientes. En ocasiones no queda ms remedio que recurrir a las bases de datos$ ya sea por cuestiones de escalabilidad$ de interoperabilidad$ de co%erencia$ de se'uridad$ de con1idencialidad$ etc. 5 lo lar'o de este cap2tulo aprenderemos a trabajar con bases de datos en +yt%on. 6in embar'o se asumen una serie de conocimientos bsicos$ como puede ser el manejo elemental de 690. 6i este no es el caso$ eIisten miles de recursos a disposici,n del lector en 4nternet para introducirse en el manejo de bases de datos.

D. 1P)
EIisten cientos de bases de datos en el mercado$ tanto comerciales como 'ratuitas. Cambi(n eIisten decenas de m,dulos distintos para trabajar con dic%as bases de datos en +yt%on$ lo que si'ni1ica decenas de 5+4s distintas por aprender. En +yt%on$ como en otros len'uajes como Java con JD&C$ eIiste una propuesta de 5+4 estndar para el manejo de bases de datos$ de 1orma que el c,di'o sea prcticamente i'ual independientemente de la base de datos que estemos utilizando por debajo. Esta especi1icaci,n recibe el nombre de +yt%on Database 5+4 o D&-5+4 y se reco'e en el +E+ 2B= )%ttp#..---.pyt%on.or'.dev.peps.pep-72B=.*. D&-5+4 se encuentra en estos momentos en su versi,n 2.7$ y eIisten implementaciones para las bases de datos relacionales ms conocidas$ as2 como para al'unas bases de datos no relacionales.
118

Python para todos

5 lo lar'o de este cap2tulo utilizaremos la base de datos 690ite para los ejemplos$ ya que no se necesita instalar y ejecutar un proceso servidor independiente con el que se comunique el pro'rama$ sino que se trata de una peque!a librer2a en C que se inte'ra con la aplicaci,n y que viene incluida con +yt%on por de1ecto desde la versi,n 2. . Desde la misma versi,n +yt%on tambi(n incorpora un m,dulo compatible con esta base de datos que si'ue la especi1icaci,n de D& 5+4 2.7# sqliteD$ por lo que no necesitaremos nin'n tipo de con1i'uraci,n eItra. @ada impide al lector$ no obstante$ instalar y utilizar cualquier otra base de datos$ como 3y690$ con la cul podemos trabajar a trav(s del driver compatible con D& 5+4 2.7 3y690db )%ttp#..mysql-pyt%on. source1or'e.net.*.

Aaria(les glo(ales
5ntes de comenzar a trabajar con sqliteD$ vamos a consultar al'unos datos interesantes sobre el m,dulo. Codos los drivers compatibles con D&-5+4 2.7 deben tener D variables 'lobales que los describen. 5 saber# Z Z
apilevel#

una cadena con la versi,n de D& 5+4 que utiliza. 5ctualmente s,lo puede tomar como valor E?.7F o E2.7F. 6i la variable no eIiste se asume que es ?.7. t%readsa1ety# se trata de un entero de 7 a D que describe lo se'uro que es el m,dulo para el uso con t%reads. 6i es 7 no se puede com- partir el m,dulo entre t%reads sin utilizar al'n tipo de mecanis- mo de sincronizaci,nM si es ?$ pueden compartir el m,dulo pero no las coneIionesM si es 2$ m,dulos y coneIiones pero no cursores y$ por ltimo$ si es D$ es totalmente thread-safe. paramstyle# in1orma sobre la sintaIis a utilizar para insertar valores en la consulta 690 de 1orma dinmica. qmar/# interro'aciones.
sql [ Eselect all 1rom t -%ere valor[:F

numeric# named#

un nmero indicando la posici,n.


119

sql [ Eselect all 1rom t -%ere valor[#?F

el nombre del valor.

4ases de datos
sql [ Eselect all 1rom t -%ere valor[#valorF

1ormat# especi1icadores de 1ormato similares a los del print1 de C.


sql [ Eselect all 1rom t -%ere valor[_sF

py1ormat# similar al anterior$ pero con las eItensiones de +yt%on.


sql [ Eselect all 1rom t -%ere valor[_)valor*F

Ueamos los valores correspondientes a sqliteD#


SSS import sqliteD as dbapi SSS print dbapi.apilevel 2.7 SSS print dbapi.t%readsa1ety ? SSS print dbapi.paramstyle qmar/

,<!ep!iones
5 continuaci,n pod(is encontrar la jerarqu2a de eIcepciones que deben proporcionar los m,dulos$ junto con una peque!a descripci,n de cada eIcepci,n$ a modo de re1erencia.
6tandardError ` Larnin' ` Error ` 4nter1aceError ` DatabaseError ` DataError ` HperationalError ` 4nte'rityError ` 4nternalError ` +ro'rammin'Error ` @ot6upportedError

Z Z Z Z Z Z

6tandardError# Larnin'#

6uper clase para todas las eIcepciones de D& 5+4. EIcepci,n que se lanza para avisos importantes. Error# 6uper clase de los errores. 4nter1aceError# Errores relacionados con la inter1az de la base de datos$ y no con la base de datos en s2. DatabaseError# Errores relacionados con la base de datos. DataError# Errores relacionados con los datos$ como una divisi,n entre cero.
120

Python para todos

Z Z Z Z Z

HperationalError#

Errores relacionados con el 1uncionamiento de la base de datos$ como una desconeIi,n inesperada. 4nte'rityError# Errores relacionados con la inte'ridad re1erencial. 4nternalError# Error interno de la base de datos. +ro'rammin'Error# Errores de pro'ramaci,n$ como errores en el c,di'o 690. @ot6upportedError# EIcepci,n que se lanza cuando se solicita un m(todo que no est soportado por la base de datos.

?so (si!o de D.41P)


+asemos a%ora a ver c,mo trabajar con nuestra base de datos a trav(s de D&-5+4. 0o primero que tendremos que %acer es realizar una coneIi,n con el servidor de la base de datos. Esto se %ace mediante la 1unci,n connect$ cuyos parmetros no estn estandarizados y dependen de la base de datos a la que estemos conectndonos. En el caso de sqliteD s,lo necesitamos pasar como parmetro una cadena con la ruta al arc%ivo en el que 'uardar los datos de la base de datos$ o bien la cadena E#memory#F para utilizar la memoria R53 en lu'ar de un 1ic%ero en disco. +or otro lado$ en el caso de 3y690db$ connect toma como parmetros la mquina en la que corre el servidor )%ost*$ el puerto )port*$ nombre de usuario con el que autenticarse )user*$ contrase!a )pass-ord* y base de datos a la que conectarnos de entre las que se encuentran en nuestro 6G&D )db*. 0a 1unci,n connect devuelve un objeto de tipo Connection que representa la coneIi,n con el servidor.
SSS bbdd [ dbapi.connect)Ebbdd.datF* SSS print bbdd csqliteD.Connection object at 7I775;?D57S

0as distintas operaciones que podemos realizar con la base de datos se realizan a trav(s de un objeto Cursor. +ara crear este objeto se utiliza el m(todo cursor)* del objeto Connection#
121

4ases de datos
c [ bbdd.cursor)*

0as operaciones se ejecutan a trav(s del m(todo eIecute de Cursor$ pa- sando como parmetro una cadena con el c,di'o 690 a ejecutar. Como ejemplo creemos una nueva tabla empleados en la base de datos#
c.eIecute)EFFcreate table empleados )dni teIt$ nombre teIt$ departamento teIt*FFF*

y a continuaci,n$ insertemos una tupla en nuestra nueva tabla#


c.eIecute)EFFinsert into empleados values )d?2DB A;<-5V$ d3anuel GilV$ dContabilidadV*FFF*

6i nuestra base de datos soporta transacciones$ si estas estn activadas$ y si la caracter2stica de auto-commit est desactivada$ ser necesario llamar al m(todo commit de la coneIion para que se lleven a cabo las operaciones de1inidas en la transacci,n. 6i en estas circunstancias utilizramos una %erramienta eIterna para comprobar el contenido de nuestra base de datos sin %acer primero el commit nos encontrar2amos entonces con una base de datos vac2a. 6i comprobramos el contenido de la base de datos desde +yt%on$ sin cerrar el cursor ni la coneIi,n$ recibir2amos el resultado del conteIto de la transacci,n$ por lo que parecer2a que se %an llevado a cabo los cambios$ aunque no es as2$ y los cambios s,lo se aplican$ como comen- tamos$ al llamar a commit. +ara bases de datos que no soporten transacciones el estndar dic- ta que debe proporcionarse un m(todo commit con implementaci,n vac2a$ por lo que no es mala idea llamar siempre a commit aunque no sea necesario para poder cambiar de sistema de base de datos con solo modi1icar la l2nea del import. 6i nuestra base de datos soporta la caracter2stica de rollback tambi(n podemos cancelar la transacci,n actual con#
122

Python para todos


bbdd.rollbac/)*

6i la base de datos no soporta rollbac/ llamar a este m(todo producir una eIcepci,n. Ueamos a%ora un ejemplo completo de uso#
import sqliteD as dbapi bbdd [ dbapi.connect)Ebbdd.datF* cursor [ bbdd.cursor)* cursor.eIecute)EFFcreate table empleados )dni teIt$ nombre teIt$ departamento teIt*FFF* cursor.eIecute)EFFinsert into empleados values )d?2DB A;<-5V$ d3anuel GilV$ dContabilidadV*FFF* bbdd.commit)* cursor.eIecute)EFFselect ^ 1rom empleados -%ere departamento[VContabilidadVFFF* 1or tupla in cursor.1etc%all)*# print tupla

Como vemos$ para realizar consultas a la base de datos tambi(n se utiliza eIecute. +ara consultar las tuplas resultantes de la sentencia 690 se puede llamar a los m(todos de Cursor 1etc%one$ 1etc%many o 1etc%all o usar el objeto Cursor como un iterador.
cursor.eIecute)EFFselect ^ 1rom empleados -%ere departamento[VContabilidadVFFF* 1or resultado in cursor# print tupla

El m(todo 1etc%one devuelve la si'uiente tupla del conjunto resultado o @one cuando no eIisten ms tuplas$ 1etc%many devuelve el nmero de tuplas indicado por el entero pasado como parmetro o bien el nmero indicado por el atributo Cursor.arraysize si no se pasa nin'n parmetro )Cursor.arraysize vale ? por de1ecto* y 1etc%all devuelve un objeto iterable con todas las tuplas.
123

4ases de datos

5 la %ora de trabajar con selects u otros tipos de sentencias 690 es importante tener en cuenta que no deber2an usarse los m(todos de cadena %abituales para construir las sentencias$ dado que esto nos %ar2a vulnerables a ataques de inyecci,n 690$ sino que en su lu'ar debe usarse la caracter2stica de sustituci,n de parmetros de D& 5+4. 6upon'amos que estamos desarrollando una aplicaci,n -eb con +yt%on para un banco y que se pudiera consultar una lista de sucursales del banco en una ciudad determinada con una "R0 de la 1orma %ttp#..---.mibanco.com.sucursales:ciudad[3adrid +odr2amos tener una consulta como esta#
cursor.eIecute)EFFselect ^ 1rom sucursales -%ere ciudad[VF T ciudad T EVFFF*

5 primera vista podr2a parecer que no eIiste nin'n problema# no %acemos ms que obtener las sucursales que se encuentren en la ciudad indicada por la variable ciudad. +ero$ 8qu( ocurrir2a si un usuario malintencionado accediera a una "R0 como E%ttp#..---.mibanco.com.s ucursales:ciudad[3adridVM6E0ECC ^ GRH3 contrasenyasF: Como no se realiza nin'una validaci,n sobre los valores que puede contener la variable ciudad$ ser2a sencillo que al'uien pudiera %acerse con el control total de la aplicaci,n. 0o correcto ser2a$ como dec2amos$ utilizar la caracter2stica de sustituci,n de parmetros de D& 5+4. El valor de paramstyle para el m,dulo sqliteD era qmar/. Esto si'ni1ica que debemos escribir un si'no de interro'aci,n en el lu'ar en el que queramos insertar el valor$ y basta pasar un se'undo parmetro a eIecute en 1orma de secuencia o mappin' con los valores a utilizar para que el m,dulo cree la sentencia por nosotros.
cursor.eIecute)EFFselect ^ 1rom sucursales -%ere ciudad[:FFF$ )ciudad$**

+or ltimo$ al 1inal del pro'rama se debe cerrar el cursor y la coneIion#


124

Python para todos


cursor.close)* bbdd.close)*

"ipos /QL
En ocasiones podemos necesitar trabajar con tipos de 690$ y almacenar$ por ejemplo$ 1ec%as u %oras usando Date y Cime y no con cadenas. 0a 5+4 de bases de datos de +yt%on incluye una serie de constructores a utilizar para crear estos tipos. Estos son# Z Z Z Z Z Z Z
Date)year$ mont%$ day*# Cime)%our$ minute$ second*#

+ara almacenar 1ec%as. +ara almacenar %oras. +ara

Cimestamp)year$ mont%$ day$ %our$ minute$ second*# DateGromCic/s)tic/s*#

almacenar timestamps )una 1ec%a con su %ora*. +ara crear una 1ec%a a partir de un nmero con los se'undos transcurridos desde el epoch )el ? de Enero de ?=;7 a las 77#77#77 G3C*. CimeGromCic/s)tic/s*# 6imilar al anterior$ para %oras en lu'ar de 1ec%as. CimestampGromCic/s)tic/s*# 6imilar al anterior$ para timestamps. &inary)strin'*# Ualor binario.

'tras op!iones
+or supuesto no estamos obli'ados a utilizar D&-5+4$ ni bases de datos relacionales. En +yt%on eIisten m,dulos para trabajar con bases de datos orientadas a objetos$ como mHD& )mope Hbject Database* y motores para mapeo objeto-relacional )HR3* como 6905lc%emy$ 690Hbject o 6torm. 5dems$ si utilizamos 4ron+yt%on en lu'ar de C+yt%on tenemos la posibilidad de utilizar las coneIiones a bases de datos de .@EC$ y si utilizamos Jyt%on$ las de Java.

125

doCu%entaCi n
Do!strings
En cap2tulos anteriores ya comentamos en varias ocasiones que todos los objetos cuentan con una variable especial doc mediante la que indicar el prop,sito y uso del objeto. Estos son los llamados docstrings o cadenas de documentaci,n. 5 estos atributos se les puede asociar el teIto correspondiente eIpl2citamente$ asi'nndolo al literal cadena correspondiente$ como con cual- quier otra variable. 6in embar'o$ por conveniencia$ +yt%on o1rece un mecanismo muc%o ms sencillo y es que si el primer estamento de la de1inici,n del objeto es una cadena$ esta se asocia a la variable doc automticamente.
de1 %azXal'o)ar'*# EFFEste es el docstrin' de la 1uncion.FFF print ar' print %azXal'o. %azXal'o. doc doc [ EFFEste es un nuevo docstrin'.FFF doc

print %azXal'o.

Como vemos lo interesante de estas cadenas es que$ a di1erencia de los comentarios normales de +yt%on y de los comentarios de otros len'uajes$ 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 1unci,n %elp del len'uaje$ o utilizando la sentencia print como en el ejemplo anterior.
SSS %elp)%azXal'o* >elp on 1unction %azXal'o in module %azXal'o)ar'* main #

126

Python para todos


Este es un nuevo docstrin'.

Pydo!
0a 1unci,n %elp$ que comentamos brevemente con anterioridad$ utiliza el m,dulo pydoc para 'enerar la documentaci,n de un objeto a partir de su docstrin' y los docstrin's de sus miembros. Este m,dulo$ incluido por de1ecto con +yt%on desde la versi,n 2.?$ se puede importar en nuestro c,di'o +yt%on y utilizarse pro'ramaticamente$ o bien se puede utilizar como una %erramienta de l2nea de comandos que ser2a el equivalente a la aplicaci,n Javadoc del mundo Java. puede mostrar la in1ormaci,n como teIto en la consola$ tal como lo utiliza %elp$ pero tambi(n puede 'enerar arc%ivos >C30 como javadoc o 1acilitar la in1ormaci,n a trav(s de un peque!o servidor -eb incluido con el m,dulo.
pydoc

+ydoc es muy sencillo de utilizar. Con


pydoc.py nombre? Qnombre2 ...R

se muestra la documentaci,n del tema$ m,dulo$ clase$ paquete$ 1unci,n o palabra clave indicada de 1orma similar a la 1unci,n %elp. 6i el nombre es /ey-ords$ topics o modules se listarn las distintas palabras claves$ temas y m,dulos respectivamente. 6i se pasa el 1la' --$ el script 'uardar la documentaci,n en uno o varios arc%ivos %tml en lu'ar de mostrarla por pantalla.
pydoc.py -- nombre? Qnombre2 ...R

El 1la' -/ sirve para buscar una determinada palabra en las sinopsis de todos los m,dulos disponibles. 0a sinopsis es la primera l2nea de la cadena de documentaci,n.
pydoc.py -/ Iml

Con -p podemos iniciar el servidor >CC+ en el puerto indicado.


pydoc.py -p puerto

127

5ocumentacin

"na vez %ec%o esto podemos acceder a la documentaci,n de todos los m,dulos disponibles abriendo la p'ina http://localhost:puerto en nuestro nave'ador. +or ltimo$ mediante el 1la' -' podemos lanzar una inter1az 'r1ica para buscar documentaci,n que utiliza el servidor >CC+ para mostrar los resultados.

,pydo! y re/tru!tured"e<t
El problema de pydoc es que es muy simple$ y no permite a!adir semntica o modi1icar estilos de la documentaci,n. @o podemos$ por ejemplo$ indicar que en una l2nea en concreto de entre las l2neas de documentaci,n de la 1unci,n describe un parmetro de la 1unci,n o mostrar un cierto t(rmino en cursiva. EIisten proyectos para 'enerar documentaci,n con 1uncionalidades ms avanzadas como Docutils$ Epydoc o 6p%inI$ aunque es necesario aprender sintaIis especiales. Docutils es un proyecto desarrollado por David Good'er que incluye distintas %erramientas para 'enerar documentaci,n utilizando el 1ormato re6tructuredCeIt$ un 1ormato de teIto plano creado por el mismo autor$ y que es el 1ormato ms utilizado en la comunidad +yt%on. re6tructuredCeIt se utiliza$ entre otros$ para la creaci,n de los +E+s )Python 'nhancement Proposals*. 6in embar'o$ actualmente Docutils es ms indicado para 'enerar documentos a partir de arc%ivos de teIto$ y no a partir de docstrin's eItra2dos de c,di'o 1uente +yt%on$ ya que el parser encar'ado de este trabajo dista muc%o de estar terminado. EpyDoc es una de las %erramientas de 'eneraci,n de documentaci,n para +yt%on ms utilizadas. 5dems de teIto plano y de su propio 1ormato$ llamado epyteIt$ soporta re6tructuredCeIt y sintaIis Javadoc$ cosa que los pro'ramadores Java a'radecern. 5 lo lar'o del resto del cap2tulo utilizaremos re6tructuredCeIt como
128

Python para todos

len'uaje de marcado y EpyDoc para 'enerar los documentos 1inales. Epydoc se puede descar'ar desde su p'ina -eb en 1orma de instala- dor eIe para Lindo-s$ paquete R+3 para Gedora o similares$ o en arc%ivos zip y tar.'z que incluyen scripts de instalaci,n# http://epydoc. sourceforge.net/. Cambi(n se encuentra en los repositorios de varias distribuciones 0inuI. "na vez %ayamos instalado Epydoc si'uiendo el m(todo adecuado para nuestro sistema operativo tendremos acceso a su 1uncionalidad a trav(s de dos inter1aces de usuario distintas# el script epydoc$ que consiste en una aplicaci,n de l2nea de comandos$ y el script epydoc'ui )epydoc.py- en Lindo-s*$ que o1rece una inter1az 'r1ica. 5dems tambi(n podemos acceder a la 1uncionalidad de epydoc pro'ramatica- mente$ como en el caso de pydoc. Uamos a crear un peque!o m,dulo con un par de clases para ver primero el resultado de utilizar epydoc con docstrin's de teIto plano$ sin nin'n tipo de marcado especial.
EFF3odulo para ejempli1icar el uso de epydoc.FFF class +ersona# EFF3i clase de ejemplo.FFF de1 init )sel1$ nombre*# EFF4nicializador de la clase +ersona.FFF sel1.nombre [ nombre sel1.mostrarXnombre)* de1 mostrarXnombre)sel1*# EFF4mprime el nombre de la personaFFF print EEsta es la persona _sF _ sel1.nombre class Empleado)+ersona*# EFF6ubclase de +ersona.FFF pass i1 name [[ E main F# raul [ +ersona)ERaulF*

El 1ormato de salida por de1ecto de epydoc es >C30. +or lo tanto para 'enerar la documentaci,n en 1orma de documentos >C30 bastar2a escribir al'o as2#

129

5ocumentacin
epydoc ejemplo.py

o bien
epydoc --%tml ejemplo.py

+ara 'enerar un arc%ivo +DG$ utilizando 0aCeK$ se utilizar2a el 1la' --pd1#


epydoc --pd1 ejemplo.py

6i 0aCeK no est instalado o epydoc no encuentra el ejecutable no ser posible 'enerar el +DG. Cambi(n podemos indicar el nombre del proyecto y la "R0 mediante las opciones --name y --url#
epydoc --name Ejemplo --url %ttp#..mundo'ee/.net ejemplo.py

E incluso a!adir dia'ramas mostrando la clase base y subclases )--'rap% classtree*$ las llamadas entre 1unciones y m(todos )-'rap% call'rap% *$ clases y subclases usando notaci,n "30 )--'rap% uml- classtree* o todos ellos )--'rap% all*.
epydoc --'rap% all ejemplo.py

+ara 'enerar el 'ra1o de llamadas$ no obstante$ es necesario 'enerar un arc%ivo con la in1ormaci,n necesaria utilizando el m,dulo pro1ile o el m,dulo %ots%ot e indicar el arc%ivo resultante utilizando el 1la' --pstat#
epydoc --'rap% all --pstat pro1ile.out ejemplo.py

Ueamos a%ora al'unas 1uncionalidades bsicas de marcado en re6truc- turedCeIt. +ara poner un teIto en itlica se rodea el teIto con asteriscos#
^itlica^

-S it(lica
130

Python para todos

+ara ponerlo en ne'rita$ se utilizan dos asteriscos#


^^ne'rita^^

-S negrita

+ara mostrar el teIto como monoespacio$ por ejemplo para mostrar c,di'o inline$ se utiliza E.
EmonoespacioF

-S

monoespacio

6i necesitamos utilizar cualquiera de estos caracteres especiales$ se pueden escapar utilizando la barra invertida.
e^ es un carcter especial

-S ^ es un carcter especial

0os t2tulos se crean a!adiendo una l2nea de caracteres no al1anum(ricos por debajo del teIto$ o por encima y por debajo del teIto. +ara crear un subtitulo basta utilizar una nueva combinaci,n.
C2tulo [[[[[[ 6ubtitulo nnnnnnnnn

T;tu#o
6ubtitulo
+ara crear una lista no ordenada se empieza cada l2nea con el caracter d^V$ d-V o dTV#
^ +yt%on ^ C ^ Java

Z Z Z

+yt%on C Java

+ara crear una lista numerada se empieza la l2nea con el nmero se131

5ocumentacin

'uido de un punto$ o bien con el s2mbolo dPV para que se introduzca el nmero automticamente.
?. +yt%on 2. C D. Java

?. +yt%on 2. C D. Java +ara describir propiedades de los elementos que estamos documentando se utilizan los campos o 1ields. En re6tructuredCeIt los campos comienzan con d#V$ le si'ue el nombre del campo y opcionalmente sus ar'umentos$ y se cierra de nuevo con d#V$ para terminar con el cuerpo del campo. Estos son al'unos de los campos que soporta Epydoc# (unciones y m<todos
#param p# "n parmetro #type p# str

#return# Crue si son i'uales #rtype# str #/ey-ord p# "n parmetro #raise e# 6i el parmetro es cero

Describe el parmetro p. Especi1ica el tipo esperado para el parmetro p. Ualor de retorno. Cipo del valor de retorno. Descripci,n del parmetro con valor por de1ecto y nombre p. Describe las circunstancias para las que se lanza la eIcepci,n e.

=ariab#es
#ivar v# "na variable #cvar v# "na variable

#var v# "na variable

Descripci,n de la instancia v. Descripci,n de la variable esttica de clase v. Descripci,n de la variable v del m,dulo.
132

Python para todos

#type v# str

Cipo de la variable v.

>otas
#note# "na nota #attention# 4mportante

#bu'# @o 1unciona para el valor 7 #-arnin'# Cuidado con el valor 7 #see# Uer d+yt%on para todosV

"na nota sobre el objeto. "na nota importante sobre el objeto. Descripci,n de un error en el objeto. "na advertencia acerca de un objeto. +ara indicar in1ormaci,n relacionada.

Estado
#version# ?.7 #c%an'e# Uersi,n inicial #todo# 4nternacionalizaci,n #status# Uersi,n estable

Uersi,n actual del objeto. 0istado de cambios. "n cambio planeado para el objeto. Estado del objeto.

Autor;a
#aut%or# Raul Gonzalez #or'anization# 3undo 'ee/ #license# G+0 #contact# en 'mail zootropo

5utor o autores del objeto. Hr'anizaci,n que cre, o mantiene el objeto. 0icencia del objeto. 4n1ormaci,n de contacto del autor.

+ara que Epydoc sepa que utilizamos re6tructuredCeIt es necesario indicarlo mediante una variable doc1ormat en el c,di'o$ o bien mediante la opci,n --doc1ormat de l2nea de comandos. 0as opciones posibles son epyteIt$ plainteIt$ restructuredteIt o javadoc.
133

5ocumentacin

Ueamos un ejemplo con campos#


EFF3odulo para ejempli1icar el uso de ^epydoc^. #aut%or# Raul Gonzalez #version# 7.?FFF doc1ormat [ ErestructuredteItF

class +ersona# EFF3odela una persona.FFF de1 init )sel1$ nombre$ edad*# EFF4nicializador de la clase o+ersonao. #param nombre# @ombre de la persona. #param edad# Edad de la personaFFF sel1.nombre [ nombre sel1.edad [ edad sel1.mostrarXnombre)* de1 mostrarXnombre)sel1*# EFF4mprime el nombre de la personaFFF print EEsta es la persona _sF _ sel1.nombre class Empleado)+ersona*# EFF6ubclase de o+ersonao correspondiente a las personas que trabajan para la or'anizacion. #todo# Escribir implementacion.FFF pass i1 name [[ E main F# juan [ +ersona)EJuanF$ 2A*

re6tructuredCeIt tambi(n soporta un se'undo tipo de campos en el que el cuerpo del campo es una lista. De esta 1orma podemos$ por ejemplo$ describir todos los parmetros de una 1unci,n o m(todo con un solo campo #+arameters#$ en lu'ar de con un campo #param# para cada parmetro.
class +ersona# EFF3odela una persona.FFF de1 init )sel1$ nombre$ edad*# EFF4nicializador de la clase o+ersonao. #+arameters# - onombreo# @ombre de la persona. - oedado# Edad de la persona. EFF sel1.nombre [ nombre sel1.edad [ edad sel1.mostrarXnombre)*

134

Python para todos

Htros campos que admiten listas son #EIceptions# para indicar varias eIcepciones )#eIcept#*$ #Uariables# para comentar varias variables )#var#* o #4variables# para comentar varias instancias )#ivar#*.

prue(as
+ara ase'urar en la medida de lo posible el correcto 1uncionamiento y la calidad del so1t-are se suelen utilizar distintos tipos de pruebas$ como pueden ser las pruebas unitarias$ las pruebas de inte'raci,n$ o las pruebas de re'resi,n. 5 lo lar'o de este cap2tulo nos centraremos en las pruebas unitarias$ mediante las que se comprueba el correcto 1uncionamiento de las unidades l,'icas en las que se divide el pro'rama$ sin tener en cuenta la interrelaci,n con otras unidades. 0a soluci,n ms eItendida para las pruebas unitarias en el mundo +yt%on es unittest$ a menudo combinado con doctest para pruebas ms sencillas. 5mbos m,dulos estn inclu2dos en la librer2a estndar de +yt%on.

Do!test
Como es de suponer por el nombre del m,dulo$ doctest permite combinar las pruebas con la documentaci,n. Esta idea de utilizar las pruebas unitarias para probar el c,di'o y tambi(n a modo de documentaci,n permite realizar pruebas de 1orma muy sencilla$ propicia el que las pruebas se manten'an actualizadas$ y sirve a modo de ejemplo de uso del c,di'o y como ayuda para entender su prop,sito. Cuando doctest encuentra una l2nea en la documentaci,n que comienza con dSSSV se asume que lo que le si'ue es c,di'o +yt%on a ejecutar$ y que la respuesta esperada se encuentra en la l2nea o l2neas si'uientes$ sin SSS. El teIto de la prueba termina cuando se encuentra una l2nea en blanco$ o cuando se lle'a al 1inal de la cadena de documentaci,n.

Python para todos

Comemos como ejemplo la si'uiente 1unci,n$ que devuelve una lista con los cuadrados de todos los nmeros que componen la lista pasada como parmetro#
de1 cuadrados)lista*# EFFCalcula el cuadrado de los numeros de una listaFFF return Qn ^^ 2 1or n in listaR

+odr2amos crear una prueba como la si'uiente$ en la que comprobamos que el resultado al pasar la lista Q7$ ?$ 2$ esperbamos#

DR

es el que

de1 cuadrados)lista*# EFFCalcula el cuadrado de los numeros de una lista SSS l [ Q7$ ?$ 2$ DR SSS cuadrados)l* Q7$ ?$ B$ =R EFF return Qn ^^ 2 1or n in listaR

0o que %acemos en este ejemplo es indicar a doctest que cree un lista l con valor Q7$ ?$ 2$ DR$ que llame a continuaci,n a la 1unci,n cuadra- dos con l como ar'umento$ y que compruebe que el resultado devuelto sea i'ual a Q7$ ?$ B$ =R. +ara ejecutar las pruebas se utiliza la 1unci,n testmod del m,dulo$ a la que se le puede pasar opcionalmente el nombre de un m,dulo a eva- luar )parmetro name*. En el caso de que no se indique nin'n ar'u- mento$ como en este caso$ se evala el m,dulo actual#
de1 cuadrados)lista*# EFFCalcula el cuadrado de los numeros de una lista SSS l [ Q7$ ?$ 2$ DR SSS cuadrados)l* Q7$ ?$ B$ =R EFF return Qn ^^ 2 1or n in listaR de1 Xtest)*# import doctest doctest.testmod)*

Prue!as
i1 name [[ E main F# Xtest)*

En el caso de que el c,di'o no pase al'una de las pruebas que %emos de1inido$ doctest mostrar el resultado obtenido y el resultado esperado. En caso contrario$ si todo es correcto$ no se mostrar nin'n mensaje$ a menos que a!adamos la opci,n -v al llamar al script o el pa- rmetro verbose[Crue a la 1unci,n tesmod$ en cuyo caso se mostrarn todas las pruebas ejecutadas$ independientemente de si se ejecutaron con (Iito. Este ser2a el aspecto de la salida de doctest utilizando el parmetro -v#
Cryin'# l [ Q7$ ?$ 2$ DR EIpectin' not%in' o/ Cryin'# cuadrados)l* EIpectin'# Q7$ ?$ B$ =R o/ 2 items %ad no tests# main main .Xtest ? items passed all tests# 2 tests in main .cuadrados 2 tests in D items. 2 passed and 7 1ailed. Cest passed.

5%ora vamos a introducir un error en el c,di'o de la 1unci,n para ver el aspecto de un mensaje de error de doctest. 6upon'amos$ por ejemplo$ que %ubieramos escrito un operador de multiplicaci,n )d^V* en lu'ar de uno de eIponenciaci,n )d^^V*#
de1 cuadrados)lista*# EFFCalcula el cuadrado de los numeros de una lista SSS l [ Q7$ ?$ 2$ DR SSS cuadrados)l* Q7$ ?$ B$ =R EFF return Qn ^ 2 1or n in listaR de1 Xtest)*#

Python para todos


import doctest doctest.testmod)* i1 name [[ E main F# Xtest)*

Hbtendr2amos al'o parecido a esto#


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Gile Eejemplo.pyF$ line $ in main .cuadrados Gailed eIample# cuadrados)l* EIpected# Q7$ ?$ B$ =R Got# Q7$ 2$ B$ AR ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ? items %ad 1ailures# ? o1 2 in main .cuadrados ^^^Cest Gailed^^^ ? 1ailures.

Como vemos$ el mensaje nos indica que %a 1allado la prueba de la l2nea $ al llamar a cuadrados)l*$ cuyo resultado deber2a ser Q7$ ?$ B$ =R$ y sin embar'o obtuvimos Q7$ 2$ B$ AR. Ueamos por ltimo c,mo utilizar sentencias anidadas para %acer cosas un poco ms complicadas con doctest. En el ejemplo si'uiente nuestra 1unci,n calcula el cuadrado de un nico nmero pasado como par- metro$ y dise!amos una prueba que compruebe que el resultado es el adecuado para varias llamadas con distintos valores. 0as sentencias anidadas comienzan con E...F en lu'ar de ESSSF#
de1 cuadrado)num*# EFFCalcula el cuadrado de un numero. SSS l [ Q7$ ?$ 2$ DR SSS 1or n in l# ... cuadrado)n* Q7$ ?$ B$ =R EFF return num ^^ 2 de1 Xtest)*# import doctest doctest.testmod)*

Prue!as
i1 name [[ E main F# Xtest)*

unittest = Py?nit
unittest $

tambi(n llamado +y"nit$ 1orma parte de una 1amilia de %erramientas conocida colectivamente como I"nit$ un conjunto de 1rame-or/s basados en el so1t-are 6"nit para 6malltal/$ creado por Went &ec/$ uno de los padres de la eKtreme +ro'rammin'. Htros ejemplos de %erramientas que 1orman parte de esta 1amilia son J"nit para Java$ creada por el propio Went &ec/ junto a Eric% Gamma$ o @"nit$ para .@EC. El uso de unittest es muy sencillo. +ara cada 'rupo de pruebas tene- mos que crear una clase que %erede de unittest.CestCase$ y a!adir una serie de m(todos que comiencen con test$ que sern cada una de las pruebas que queremos ejecutar dentro de esa bater2a de pruebas. +ara ejecutar las pruebas$ basta llamar a la 1unci,n main)* del m,dulo$ con lo que se ejecutarn todos los m(todos cuyo nombre comience con test$ en orden al1anum(rico. 5l ejecutar cada una de las pruebas el resultado puede ser# Z Z Z
HW# 0a G540#

prueba %a pasado con (Iito. 0a prueba no %a pasado con (Iito. 6e lanza una eIcepci,n 5ssertionError para indicarlo. ERRHR# 5l ejecutar la prueba se lanz, una eIcepci,n distinta de 5ssertionError.

En el si'uiente ejemplo$ dado que el m(todo que modela nuestra prueba no lanza nin'una eIcepci,n$ la prueba pasar2a con (Iito.
import unittest class Ejemplo+ruebas)unittest.CestCase*# de1 test)sel1*# pass i1 name [[ E main F# unittest.main)*

Python para todos

En este otro$ sin embar'o$ 1allar2a#


import unittest class Ejemplo+ruebas)unittest.CestCase*# de1 test)sel1*# raise 5ssertionError)* i1 name [[ E main F# unittest.main)*

@ada nos impide utilizar clusulas i1 para evaluar las condiciones que nos interesen y lanzar una eIcepci,n de tipo 5ssertionError cuando no sea as2$ pero la clase CestCase cuenta con varios m(todos que nos pueden 1acilitar la tarea de realizar comprobaciones sencillas. 6on los si'uientes# Z
second$ places[;$ ms'[@one*# Comprueba que los objetos pasados como parmetros sean i'uales %asta el s(ptimo decimal )o el nmero de decimales indicado por places*. assertEqual)1irst$ second$ ms'[@one*# Comprueba que los objetos pasados como parmetros sean i'uales. assertGalse)eIpr$ ms'[@one*# Comprueba que la eIpresi,n sea 1alsa. assert@ot5lmostEqual)1irst$ second$ places[;$ ms'[@one*# Comprueba que los objetos pasados como parmetros no sean i'uales %asta el s(ptimo decimal )o %asta el nmero de decimales indicado por places*. assert@otEqual)1irst$ second$ ms'[@one*# Comprueba que los objetos pasados como parmetros no sean i'uales. assertRaises)eIcClass$ callableHbj$ ^ar's$ ^^/-ar's*# Comprueba que al llamar al objeto callableHbj con los parmetros de1inidos por ^ar's y ^^/-ar's se lanza una eIcepci,n de tipo eIcClass. assertCrue)eIpr$ ms'[@one*# Comprueba que la eIpresi,n sea cierta. assertX)eIpr$ ms'[@one*# Comprueba que la eIpresi,n sea cierta. 1ail)ms'[@one*# Galla inmediatamente. 1ail41)eIpr$ ms'[@one*# Galla si la eIpresi,n es cierta. 1ail415lmostEqual)1irst$ second$ places[;$ ms'[@one*# Galla assert5lmostEqual)1irst$

Z Z Z

Z Z

Z Z Z Z Z

Prue!as

Z Z Z

Z Z

si los objetos pasados como parmetros son i'uales %asta el s(ptimo decimal )o %asta el nmero de decimales indicado por places*. 1ail41Equal)1irst$ second$ ms'[@one*# Galla si los objetos pasa- dos como parmetros son i'uales. 1ail"nless)eIpr$ ms'[@one*# Galla a menos que la eIpresi,n sea cierta. 1ail"nless5lmostEqual)1irst$ second$ places[;$ ms'[@one*# Galla a menos que los objetos pasados como parmetros sean i'uales %asta el s(ptimo decimal )o %asta el nmero de decimales indicado por places*. 1ail"nlessEqual)1irst$ second$ ms'[@one*# Galla a menos que los objetos pasados como parmetros sean i'uales. 1ail"nlessRaises)eIcClass$ callableHbj$ ^ar's$ ^^/-ar's*# Galla a menos que al llamar al objeto callableHbj con los parme- tros de1inidos por ^ar's y ^^/-ar's se lance una eIcepci,n de tipo eIcClass.

Como vemos todos los m(todos cuentan con un parmetro opcional ms' con un mensaje a mostrar cuando dic%a comprobaci,n 1alle. Retomemos nuestra peque!a 1unci,n para calcular el cuadrado de un nmero. +ara probar el 1uncionamiento de la 1unci,n podr2amos %acer$ por ejemplo$ al'o as2#
import unittest de1 cuadrado)num*# EFFCalcula el cuadrado de un numero.FFF return num ^^ 2 class Ejemplo+ruebas)unittest.CestCase*# de1 test)sel1*# l [ Q7$ ?$ 2$ DR r [ Qcuadrado)n* 1or n in lR sel1.assertEqual)r$ Q7$ ?$ B$ =R* i1 name [[ E main F# unittest.main)*

Prepara!in del !onte<to


En ocasiones es necesario preparar el entorno en el que queremos que

Python para todos

se ejecuten las pruebas. +or ejemplo$ puede ser necesario introducir unos valores por de1ecto en una base de datos$ crear una coneIi,n con una mquina$ crear al'n arc%ivo$ etc. Esto es lo que se conoce en el mundo de I"nit como test fi!ture. 0a clase CestCase proporciona un par de m(todos que podemos sobreescribir para construir y desconstruir el entorno y que se ejecutan antes y despu(s de las pruebas de1inidas en esa clase. Estos m(todos son set"p)* y tearDo-n)*.
class EjemploGiIture)unittest.CestCase*# de1 set"p)sel1*# print E+reparando conteItoF sel1.lista [ Q7$ ?$ 2$ DR de1 test)sel1*# print EEjecutando pruebaF r [ Qcuadrado)n* 1or n in sel1.listaR sel1.assertEqual)r$ Q7$ ?$ B$ =R* de1 tearDo-n)sel1*# print EDesconstruyendo conteItoF del sel1.lista

distri(uir apliCaCiones python


"na vez terminemos con el desarrollo de nuestra nueva aplicaci,n es conveniente empaquetarla de 1orma que sea sencillo para los usuarios instalarla$ y para nosotros distribuirla. En +yt%on eIisten dos m,dulos principales para este cometido# distutils$ que es parte de la librer2a estndar y era el m(todo ms utilizado %asta %ace poco$ y setuptools$ que eItiende la 1uncionalidad de distu- tils y es cada vez ms popular. En este cap2tulo veremos el 1uncionamiento de ambas %erramientas$ y terminaremos eIplicando c,mo crear ejecutables .eIe para Lindo-s a partir de nuestro pro'rama en +yt%on.

distutils
Codo pro'rama distribuido con distutils contiene un script llamado por convenci,n setup.py$ que se encar'a de instalar la aplicaci,n llamando a la 1unci,n setup de distutils.core. Esta 1unci,n tiene montones de ar'umentos$ que controlan$ entre otras cosas$ c,mo instalar la aplicaci,n. Destinados a describir la aplicaci,n tenemos los si'uientes ar'umen- tos#

Python para todos

Z Z Z Z Z Z Z Z Z Z Z

name#

El nombre del paquete. El nmero de versi,n. description# "na l2nea describiendo el paquete. lon'Xdescription# Descripci,n completa del paquete. aut%or# @ombre del autor de la aplicaci,n. aut%orXemail# Correo electr,nico del autor. maintainer# @ombre de la persona encar'ada de mantener el paquete$ si di1iere del autor. maintainerXemail# Correo de la persona encar'ada de mantener el paquete$ si di1iere del autor. url# Leb de la aplicaci,n. do-nloadXurl# "rl de la que descar'ar la aplicaci,n. license# 0icencia de la aplicaci,n
version#

Cambi(n tenemos ar'umentos que controlan los arc%ivos y directorios que deben instalarse$ como son pac/a'es$ pyXmodules$ scripts y eItXmodules. El parmetro scripts$ que es una lista de cadenas$ indica el nombre del m,dulo o m,dulos principales$ es decir$ los que ejecuta el usuario. 6i nuestra aplicaci,n consistiera$ por ejemplo$ en un solo script ejemplo.py$ el c,di'o de setup.py podr2a tener un aspecto similar al si'uien- te#
1rom distutils.core import setup setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR *

6i %emos escrito otros m,dulos para ser utilizados por el script principal$ estos se indican mediante el parmetro pyXmodules. +or ejemplo$ supon'amos que la aplicaci,n consiste en un script principal ejemplo. py$ y un m,dulo de apoyo apoyo.py#

1rom distutils.core import setup

Python para todos

5istri!uir ap$icaciones Python

setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ pyXmodules[QEapoyoFR *

+ara instalar paquetes +yt%on )directorios que contienen varios m,dulos y un arc%ivo init .py* usar2amos el parmetro pac/a'es. 6i adems del m,dulo ejemplo.py quisi(ramos instalar los paquetes 'ui y bbdd$ por ejemplo$ %ar2amos al'o as2#
1rom distutils.core import setup setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ pac/a'es[QE'uiF$ EbbddFR * eItXmodules$

por ltimo$ sirve para incluir eItensiones que utilice el pro'rama$ en C$ CTT$ Gortran$ h Ueamos a%ora c,mo se utilizar2a el arc%ivo setup.py una vez creado. 5l ejecutar el comando
pyt%on setup.py install

los m,dulos y paquetes especi1icados por pyXmodules y pac/a'es se instalan en el directorio 0ib de +yt%on. 0os pro'ramas indicados en scripts$ se copian al directorio 6cripts de +yt%on. "na vez %emos comprobado que la aplicaci,n se instala correctamente$ procedemos a crear arc%ivos mediante los que

distribuir la aplicaci,n

5istri!uir ap$icaciones Python

Python para todos

a los usuarios. +ara crear arc%ivos con el c,di'o 1uente se utiliza la opci,n sdist de setup.py$ que crea por de1ecto un arc%ivo tar.'z en "niI y un zip en Lindo-s.
pyt%on setup.py sdist

6in embar'o se puede utilizar --1ormats para especi1icar el 1ormato o 1ormatos que queramos 'enerar bztar 'ztar tar zip ztar .tar.bz2 .tar.'z .tar .zip .tar.m

+ara crear un arc%ivo tar.bz2$ un tar.'z y un zip$ por ejemplo$ se utilizar2a la si'uiente orden#
pyt%on setup.py sdist --1ormats[bztar$'ztar$zip

+ara 'enerar un arc%ivo de distribuci,n binaria$ se usa la opci,n bdist#


pyt%on setup.py bdist

0os 1ormatos que soporta bdist son los si'uientes# rpm 'ztar bztar ztar tar -ininst zip R+3 .tar.'z .tar.bz2 .tar.m .tar 4nstalador Lindo-s .zip

+ara crear un arc%ivo rpm y un instalador de Lindo-s$ por ejemplo$ escribir2amos#

5istri!uir ap$icaciones Python


pyt%on setup.py bdist --1ormats[-ininst$rpm

Cambi(n es posible crear otros tipos de arc%ivos de distribuci,n utili- zando scripts que eItienden distutils$ como es el caso de los paquetes deb mediante el script stdeb )%ttp#..stdeb.pyt%on%ostin'.com.*

setuptools
setuptools eItediende distutils a!adiendo una serie de 1uncionalidades muy interesantes# introduce un nuevo 1ormato de arc%ivo para distribuci,n de aplicaciones +yt%on llamado egg$ se encar'a de buscar todos los paquetes que deben instalarse y a!adir las posibles dependencias$ permite instalar paquetes de +y+4 con un solo comando$ etc. 5dems$ como setuptools se basa en distutils$ un script de instalaci,n bsico utilizando setuptools es prcticamente i'ual a su equivalente con distutils. Can s,lo cambiar2a la sentencia de importaci,n.
1rom setuptools import setup setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ *

El nico inconveniente que podr2amos encontrar al uso de setuptools es que no est incluido por de1ecto en +yt%on 2. $ aunque es probable que esto cambie en pr,Iimas versiones debido a su 'ran uso. +ero los desarrolladores de setuptools %an pensado en todo$ e incluso esto no deber2a suponer nin'n problema$ ya que con un m2nimo es1uerzo por nuestra parte podemos %acer que setuptools se descar'ue e instale automticamente en la mquina del usuario si este no se encuentra ya en el sistema. &asta distribuir con nuestro paquete un peque!o m,dulo eItra ezXsetup.py que viene incluido por de1ecto con setup-

tools )%ttp#..pea/.telecommunity.com.dist.ezXsetup.py* y llamar a la 1unci,n useXsetuptools del m,dulo al inicio de setup.py#

5istri!uir ap$icaciones Python

Python para todos


1rom ezXsetup import useXsetuptools useXsetuptools)* 1rom setuptools import setup setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ *

Ueamos a%ora con ms detenimiento al'unos de los cambios y noveda- des que introduce setuptools.

)ntegra!in !on PyP)


5l estilo de C+5@ en +erl setuptools permite instalar de 1orma 1cil y sencilla los paquetes pertenecientes a +y+4$ el pndice de +aquetes +yt%on )%ttp#..pypi.pyt%on.or'.pypi*$ as2 como subir nuestros propios paquetes. +y+4 cuenta en el momento de escribir estas l2neas con B;<2 paquetes$ por lo que poder instalar los paquetes de este repositorio con un simple comando supone una ayuda muy a tener en cuenta. 4nstalar un paquete de +y+4 es tan sencillo como pasar al comando easyXinstall el nombre del paquete a instalar
easyXinstall docutils 6earc%in' 1or docutils Readin' %ttp#..pypi.pyt%on.or'.simple.docutils. Readin' %ttp#..docutils.source1or'e.net. &est matc%# docutils 7. Do-nloadin' %ttp#..prdo-nloads.source1or'e.net.docutils. docutils-7. .tar.'z:do-nload +rocessin' docutils-7. .tar.'z Runnin' docutils-7. .setup.py -q bdistXe'' --dist-dir .tmp. easyXinstall--"5y"m.docutils-7. .e''-dist-tmp-/L///v EoptparseF module already presentM i'norin' eItras.optparse. py. EteIt-rapF module already presentM i'norin' eItras.teIt-rap. py. zipXsa1e 1la' not setM analyzin' arc%ive contentsh

5istri!uir ap$icaciones Python


docutils.-riters.ne-lateI2e. init # module re1erences 1ile docutils.-riters.pepX%tml. init # module re1erences 1ile docutils.-riters.%tmlBcss?. init # module re1erences 1ile docutils.-riters.s X%tml. init # module re1erences 1ile docutils.parsers.rst.directives.misc# module re1erences 1ile 5ddin' docutils 7. to easy-install.pt% 1ile 4nstallin' rst2pseudoIml.py script to .usr.bin 4nstallin' rst2%tml.py script to .usr.bin 4nstallin' rst2lateI.py script to .usr.bin 4nstallin' rst2s .py script to .usr.bin 4nstallin' rst2ne-lateI.py script to .usr.bin 4nstallin' rstpep2%tml.py script to .usr.bin 4nstallin' rst2Iml.py script to .usr.bin 4nstalled .usr.lib.pyt%on2. .site-pac/a'es.docutils-7. py2. .e'' +rocessin' dependencies 1or docutils Ginis%ed processin' dependencies 1or docutils

+oder subir nuestros paquetes a +y+4 requiere de un proceso un poco ms laborioso. +rimero re'istramos los detalles de nuestra aplicaci,n en +y+4 mediante la opci,n re'ister del script setup.py$ el cul nos pre'untar por nuestro nombre de usuario$ contrase!a y correo electr,nico si no tenemos cuenta en +y+4$ o nombre de usuario y contrase!a si nos re'istramos anteriormente#
pyt%on setup.py re'ister runnin' re'ister runnin' e''Xin1o creatin' 5plicacionXdeXejemplo.e''-in1o -ritin' 5plicacionXdeXejemplo.e''-in1o.+WG-4@GH -ritin' top-level names to 5plicacionXdeXejemplo.e''-in1o. topXlevel.tIt -ritin' dependencyXlin/s to 5plicacionXdeXejemplo.e''-in1o. dependencyXlin/s.tIt -ritin' mani1est 1ile d5plicacionXdeXejemplo.e''-in1o.6H"RCE6.tItV readin' mani1est 1ile d5plicacionXdeXejemplo.e''-in1o.6H"RCE6.tItV -ritin' mani1est 1ile d5plicacionXdeXejemplo.e''-in1o.6H"RCE6.tItV Le need to /no- -%o you are$ so please c%oose eit%er# ?. use your eIistin' lo'in$ 2. re'ister as a ne- user$ D. %ave t%e server 'enerate a ne- pass-ord 1or you )and

email it to you*$ or

5istri!uir ap$icaciones Python

Python para todos


B. quit Nour selection Qde1ault ?R# ? "sername# zootropo +ass-ord# 6erver response )277*# HW 4 can store your +y+4 lo'in so 1uture submissions -ill be 1aster. )t%e lo'in -ill be stored in .%ome.zootropo..pypirc* 6ave your lo'in )y.@*:y

+ara crear y subir una distribuci,n con el c,di'o 1uente de nuestra aplicaci,n se utiliza la opci,n sdist upload#
pyt%on setup.py sdist upload

Cambi(n podr2amos crear y subir un e'' )un 1ormato de arc%ivo para distribuir aplicaciones +yt%on que veremos en la pr,Iima secci,n* utilizando la opci,n bdistXe'' upload#
pyt%on setup.py bdistXe'' upload

H combinar los tres pasos en un solo comando#


pyt%on setup.py re'ister sdist bdistXe'' upload

"na vez subido el paquete cualquier persona podr2a instalarlo en su sistema utilizando easyXinstall$ de la misma 1orma que cualquier otro paquete de +y+4#
easyXinstall mi-paquete

,ggs
0os eggs )%uevo en in'l(s* son arc%ivos de eItensi,n .e'' mediante los que distribuir aplicaciones en +yt%on. 6er2an al'o as2 como el equiva- lente a los arc%ivos .jar del mundo Java. 6on multiplata1orma$ permi- ten manejar dependencias$ y permiten instalar distintas versiones del mismo paquete. 0a 1orma ms sencilla de instalar aplicaciones distribuidas como arc%ivos e'' es mediante el comando easyXinstall$ el cul comentamos brevemente en el punto anterior al %ablar sobre su uso para instalar

5istri!uir ap$icaciones Python

paquetes de +y+4. +ara instalar un arc%ivo e'' no tenemos ms que pasarle el nombre del arc%ivo al comando easyXinstall#
easyXinstall mi-aplicacion.e''

o bien podemos pasarle la "R0 de la que descar'ar el e''#


easyXinstall %ttp#..mundo'ee/.net.mi-aplicacion.e''

+ara construir nuestros propios e''s podemos utilizar el comando bdistXe'' de setup.py$ de 1orma similar a la manera en que constru2amos paquetes R+3 o instaladores para Lindo-s con distutils#
pyt%on setup.py bdistXe''

'tros !a#(ios desta!a(les


"no de los cambios ms interesantes es la incorporaci,n de un nuevo ar'umento para la 1unci,n setup llamado installXrequires$ que consiste en una cadena o lista de cadenas que indica los paquetes de los que depende la aplicaci,n. 6i nuestra aplicaci,n necesitara tener insta- lado el paquete apoyo para poder ejecutarse$ por ejemplo$ escribir2amos lo si'uiente#
installXrequires [ QEapoyoFR

N de esta 1orma$ easyXinstall se encar'ar2a de buscar e instalar el paquete si 1uera necesario$ bien en +y+4$ o en cualquier otro repositorio indicado por el parmetro dependencyXlin/s. 5dems podemos especi1icar que se necesita una versi,n concreta del paquete requerido$ que sea mayor o menor que una cierta versi,n$ o que no se trate de una versi,n determinada utilizando operadores relacionales )[[$ Y[$ c$ c[$ S$ S[*#
installXrequires [ QEapoyo S[ ?.7 c 2.7FR

Cambi(n eIisten ar'umentos similares para declarar paquetes que deben instalarse para poder ejecutar el script de instalaci,n )setupXre- quires*$ para poder ejecutar las posibles pruebas inclu2das con el paquete )testsXrequire* y para conse'uir 1uncionalidades adicionales

Python para todos

)eItrasXrequire$ que consiste en este caso en un diccionario*. setuptools incluye tambi(n atajos tiles$ como la 1unci,n 1indXpac/a- 'es)* que nos evita tener que listar todos y cada uno de los paquetes que utiliza nuestro script en el parmetro pac/a'es$ como era el caso de distutils#
1rom ezXsetup import useXsetuptools useXsetuptools)* 1rom setuptools import setup$ 1indXpac/a'es setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ pac/a'es [ 1indXpac/a'es)* *

Crear e e!uta(les 9e<e


Canto en 3ac H6 como en la mayor parte de las distribuciones 0inuI el int(rprete de +yt%on est instalado por de1ecto$ por lo que los usuarios de estos sistemas no tienen mayor complicaci,n a la %ora de instalar y ejecutar aplicaciones escritas en +yt%on. En el caso de Lindo-s$ esto no es as2$ por lo que ser2a interesante que los usuarios de este sistema operativo no tuvieran que instalar el int(rprete de +yt%on. Cambi(n ser2a interesante que nuestro pro'rama consistiera en un arc%ivo .eIe en lu'ar de uno o varios arc%ivos .py$ para simpli1icar las cosas. Codo esto lo podemos lo'rar 'racias a py2eIe$ una eItensi,n para distutils que$ como su nombre indica$ permite crear ejecutables para Lindo-s a partir de c,di'o +yt%on$ y que permite ejecutar estas aplicaciones sin necesidad de tener instalado el int(rprete de +yt%on en el sistema. +y2eIe 1unciona eIaminando nuestro c,di'o 1uente en busca de los

5istri!uir ap$icaciones Python

m,dulos y paquetes que utilizamos$ compilndolos y construyendo un nuevo arc%ivo que incluye estos arc%ivos y un peque!o int(rprete de +yt%on inte'rado. +ara probar el 1uncionamiento de py2eIe creemos un peque!o pro'rama ejemplo.py
print E6oy un .eIeF

y el arc%ivo setup.py correspondiente. 0os cambios que tenemos que realizar a setup.py son sencillos# importar py2eIe$ y utilizar los ar'u- mentos console y -indo-s para indicar el nombre del script o scripts que queramos convertir en ejecutables de consola o ejecutables de inter1az 'r1ica$ respectivamente.
1rom distutils.core import setup import py2eIe setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ console[QEejemplo.pyFR *

+ara crear el ejecutable$ utilizamos una nueva opci,n de l2nea de comandos para setup.py disponible tras importar el m,dulo y llamada$ c,mo no$ py2eIe#
pyt%on setup.py py2eIe

Con esto py2eIe 'enerar un directorio build$ con las librer2as com- piladas$ y un directorio dist$ con los arc%ivos que con1orman nuestra aplicaci,n. Entre los arc%ivos que podemos encontrar en dist tendremos uno o varios ejecutables con el mismo nombre que los scripts indicados en console y -indo-s$ un arc%ivo pyt%on^.dll$ que es el int(rprete de +yt%on$ y un arc%ivo library.zip$ que contiene varios arc%ivos pyc que

Python para todos

son los m,dulos que utiliza la aplicaci,n compilados. 6i queremos reducir el nmero de arc%ivos a distribuir$ podemos utili- zar la opci,n --bundle de py2eIe para a!adir a library.zip las dll y los pyd )--bundle 2* o las dll$ los pyd y el int(rprete )--bundle ?*.
pyt%on setup.py py2eIe --bundle ?

o bien podemos a!adir un nuevo ar'umento options a la 1unci,n setup que indique el valor a utilizar )opci,n bundleX1iles*$ de 1orma que no ten'amos que a!adir el 1la' --bundle cada vez que usemos el comando py2eIe#
1rom distutils.core import setup import py2eIe setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ console[QEejemplo.pyFR$ options[iEpy2eIeF# iEbundleX1ilesF# ?jj *

+or ltimo podemos incluso prescindir de library.zip e incrustarlo en el ejecutable utilizando el ar'umento zip1ile[@one
1rom distutils.core import setup import py2eIe setup)name[F5plicacion de ejemploF$ version[F7.?F$ description[FEjemplo del 1uncionamiento de distutilsF$ aut%or[FRaul GonzalezF$ aut%orXemail[Fzootropo en 'mailF$ url[F%ttp#..mundo'ee/.net.tutorial-pyt%on.F$ license[FG+0F$ scripts[QEejemplo.pyFR$ console[QEejemplo.pyFR$ options[iEpy2eIeF# iEbundleX1ilesF# ?jj$ zip1ile[@one *

BndiCe
S;mbo#os
call cmp del doc init len main name nestr )*+ +) +) ,+$ )-+ ./ +) ,. ,. +) +)

A
arc%ivos 0atributos .-

6
bases de datos )), bool -brea/ //

"
cadenas$ m(todos +. candados )*1 clases .clases de nuevo estilo +* class ./ close 0cola multi%ilo ))) colecciones diccionarios -, listas -.

155

tuplas -1 comentarios 2 compile 2) comprensi,n de listas 1) condiciones$ sincronizaci,n )*0 continue // coo/ies )** count .+ c+ic/le )).

D
db api )), decoradores 1/ de1 /1 diccionario$ m(todos +/ distutils )./ docstrin' /1 docstrin's )-+ doctest )/+ docutils )-,

,
e''s )+* eli1 /) else /* encapsulaci,n .0 env )-, epydoc )*2 eventos 1+ eIcepciones 11 eIcept 0+

(
Galse -1ic%eros 01ile 01ilter +2 1inally 1, 1indall 2* 1loat ), 1or ... in /. 1or/ )*1rom ... import ,/

156

1uertemente tipado 0 1unciones /1 1unciones de orden superior +, 1unciones lambda 1*

?
'eneradores 1G40 )*/ Global 4nterpreter 0oc/ )*/

@
%as%ban' )/ %elp /1 %erencia .+ %erencia mltiple .1 %ilos )*-

I
i1 -2 import ,input ,0 int )*. 34ase a5u6 enteros i+yt%on /2

A
Jyt%on 2

B
Womodo ))

C
lambda 1* len'uaje compilado , len'uaje de script , len'uaje interpretado , len'uaje semi interpretado , listas$ m(todos ++ loc/s )*1

M
map +2
157

mars%al ))/ mars%allin' ))/ matc% 01 m(todos .module ,+ m,dulos ,muteI )*1

>
name man'lin' .2 @one /1

O
objetos .open 0operaciones relacionales -operadores a nivel de bit -* operadores aritm(ticos )0 operadores l,'icos -orientaci,n a objetos 0

P
paquetes ,+ parmetros$ 1unciones /, parmetros por l2nea de comando ,0 parmetros$ valores por de1ecto /0 particionado -+ paso por re1erencia /2 paso por valor /2 patrones )eIpresiones re'ulares* 0+ pic/le ))/ polimor1ismo ., print ,0 procesos )*pro'ramaci,n 1uncional +, pro'ramaci,n orientada a objetos .propiedades .2 pruebas )/+ py2eIe )++yDEU )) pydoc )-1 +y+4 ).0 +y+y 2

158

+yt%on de1inici,n 2 instalaci,n 0 ventajas ,. +NC>H@+5C> )/2

R
raise 1, ra-$ cadena -) ra-Xinput ,, read 0/ readline 0/ readlines 0/ reduce 1* re6tructuredCeIt )-, return .*

S
searc% 2* see/ 0/ sel1 .. sem1oros )*, serializaci,n ))/ setuptools )., s%arpban' )/ s%eban' )/ s%elve ))1 sincronizaci,n )*1 slicin' -+ soc/ets 2split 2) sub 2) subclase .+ superclase .+ sys.ar'v ,0

T
tell 0. test 1iIture ).) tests )/+ t%readin' )*. t%reads )*tipado dinmico ,

159

tipado 1uerte 0 tipos bsicos )+ booleanos -cadenas -) nmeros complejos )1 enteros ), reales -Crue 11 try )+

D
unittest )/2 upper .+ urllib 21 urllib2 21

=
valores inmutables .* valores mutables .*

E
-%ile /Lin' 4DE )) -rite 0/ -ritelines 0/

0
yield 1-

160

Você também pode gostar