Sie sind auf Seite 1von 155

Inmersin en Python 3 o por Mark Pilgrim Copyright c 2009.

Traduccin al espaol: Jos Miguel Gonzlez Aguilera o n e a Copyright de la traduccin c 2009. o Website de la traduccin: http://code.google.com/p/inmersionenpython3 o Agradecimientos del Traductor: A Mark Pilgrim. A Nieves, Alba y a Miguel. Licencia:

Este trabajo est licenciado bajo la licencia de Reconocimiento-No comercial-Compartir a bajo la misma licencia Creative Commons 3.0 Espaa. Para ver una copia de esta n licencia, visita http://creativecommons.org/licenses/by-nc-sa/3.0/es/ o env una a carta a Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. A continuacin se muestra un resumen de la licencia. o Usted es libre de: Compartir copiar, distribuir y comunicar pblicamente la obra u Rehacer hacer obras derivadas Bajo las condiciones siguientes: Reconocimiento. Debe reconocer los crditos de la obra de la manera especicada e por el autor o el licenciador (pero no de una manera que sugiera que tiene su apoyo o apoyan el uso que hacer de su obra). No comercial. No puede utilizar esta obra para nes no comerciales.

Compartir bajo la misma licencia. Si altera o transforma esta obra, o genera una obra derivada, slo puede distribuir la obra generada bajo una licencia o idntica a sta. e e Al reutilizar o distribuir la obra, tiene que dejar bien claro los trminos de la licencia e de esta obra. Alguna de las condiciones puede no aplicarse si se obtiene el permiso del titular de los derechos de esta obra. Nada en esta licencia menoscaba o restringe los derechos morales del autor.

Cap tulo -1 Novedades de Inmersin en o Python 3


No es de aqu de donde venimos? Pink Floyd, The Wall

-1.1.

Alias Bajo el nivel del mar

Posiblemente hayas le el libro original Dive into Python y puede que hasta do lo hayas comprado. (Si es el caso: gracias!) Ya conoces bastante el lenguaje Python. Ests preparado para dar el salto a Python 3. . . . Si lo dicho es cierto, sigue leyendo. a (Si no es as tal vez sea mejor que comiences desde el principio en el cap , tulo ??). Python 3 viene con un script denominado 2to3. Aprende a usarlo y a quererlo. El apndice ?? es una referencia sobre las cosas que la herramienta 2to3 puede e arreglar automticamente en la conversin del cdigo de la versin 2 a la 3 de python. a o o o Puesto que muchas cosas son cambios de sintaxis, una buena forma de comenzar es aprender estas diferencias. Por ejemplo: print ahora es una funcin. . . o El caso de estudio del cap tulo ?? documenta mi esfuerzo (al n cumplido con xito!) de convertir una librer real de Python 2 a Python 3. Puede servirte o no. Es e a un ejemplo complejo de entender puesto que en primer lugar tienes que comprender algo el funcionamiento de la librer de forma que puedas entender lo que deja de a, funcionar y como lo arregl. Mucho de lo que se rompi al pasar a la versin 3 de e o o Python fue por causa de las cadenas. Por cierto, hablando de cadenas. . . Cadenas. U!. Por dnde podr empezar. Python 2 ten cadenas y cao a a denas unicode. Python 3 tiene bytes y cadenas. Lo que signica que todas las

cadenas ahora son unicode, y si quieres trabajar con un puado de bytes tienes que n usar el tipo bold bytes. Python 3 nunca convertir impl a citamente entre cadenas y bytes, por lo que si no estas seguro de lo que contiene una variable en un momento dado, el cdigo o seguro que fallar en algn momento. Lee el cap a u tulo 4 sobre cadenas para conocer los detalles. La divisin entre bytes y cadenas surgir en diversas partes del libro: o a 1. En el cap tulo ?? dedicado a los cheros, aprenders la diferencia entre leer a cheros en modo binario o en modo texto. La lectura (y escritura) de cheros en modo texto requiere que se utilice el parmetro encoding. Existen mtodos a e que cuentan los caracteres de un chero y mtodos que cuentan bytes. Si el e cdigo asume que un carcter es igual a un byte, no funcionar cuando el o a a 1 chero contenga caracteres multibyte . 2. En el cap tulo ?? dedicado a los servicios web n http, se muestra el mdulo o httplib2 que lee cabeceras y datos de HTTP. Las cabeceras se obtienen como cadenas, pero el contenido del cuerpo se obtiene como bytes. 3. En el cap tulo ?? aprenders el motivo por el que el mdulo pickle de Python a o 3 dene un formato de datos nuevo que es incompatible con Python 2 (Pista: Se debe a los bytes y cadenas). Tambin afecta al mdulo JSON, que no es e o capaz de manejar el tipo bytes. Te ensear como salvar este escollo. n e 4. En el cap tulo ?? sobre la conversin de la librer chardet a Python 3 se o a ver que la mayor parte de los problemas de conversin provienen de los bytes a o y cadenas. Incluso aunque no tengas inters en Unicode, que tendrs!, querrs leer sobre e a a el formateo de cadenas en Python 3 en el cap tulo ??, que es completamente diferente a Python 2. Los iteradores estn en todas partes en Python 3, y ahora los entiendo mucho a mejor que hace cinco aos cuando escrib Inmersin en Python. Debes comprenn o derlos t tambin, puesto que muchas funciones que anteriormente retornaban listas u e ahora, en Python 3, devuelven iteradores. Como m nimo, deber leer la segunda as parte del cap tulo ?? dedicado a los iteradores y la segunda parte del cap tulo ?? sobre el uso avanzado de los iteradores. Por peticin popular, he aadido el apndice ?? sobre nombres de mtodo o n e e especiales que guarda cierta similitud con el apartado similar de la documentacin o ocial de Python 3 pero con cierta iron a.
1

En unicode muchos caracteres se representan utilizando ms de un byte a

Cuando estaba escribiendo Inmersin en Python todas las librer de XML o as disponibles eran bastante malas. Entonces Fedrik Lundh escribi bold Elemento Tree, que es todo lo contrario a lo existente anteriormente. Los dioses de Python, actuando inteligentemente, incorporaron ElementTree a la librer estndar. Ahora a a esta librer es el fundamento del cap a tulo ?? sobre XML. Los viejos mtodos para e recorrer XML estn an disponibles, pero deber evitarlos, apestan! a u as Algo que es tambin nuevo no en el lenguaje, pero s en la comunidad es e la creacin de repositorios de cdigo como el o o ndice de paquetes de python (PyPI). Python dispone de utilidades para empaquetar el cdigo en formatos estndares y o a distribuirlos en PyPI. Lee el cap tulo ?? sobre cmo empaquetar librer en Python. o as

Cap tulo 0 Instalacin de Python o


Nivel de dicultad:     Tempora mutantur nos et mutamur in illis (Los tiempos cambian, y nosotros cambiamos con ellos) antiguo proverbio romano

0.1.

Inmersin o

Bienvenido a Python 3. Vamos a mojarnos! En este cap tulo, vas a instalar la versin de Python adecuada para ti. o

0.2.

Cul es la versin adecuada para ti? a o

Lo primero que necesitas hacer es instalar Python 3. Si ests utilizando una sesin en un servidor remoto (posiblemente a travs a o e de Internet), el administrador del servidor puede que ya lo haya instalado por ti. Si ests utilizando Linux1 en casa, puede que tambin lo tengas ya instalado, aunque a e 2 actualmente la mayor parte de las distribuciones de Linux vienen con Python 2 instalado (como vers en este cap a tulo, puedes tener simultneamente ms de una a a versin de Python en tu ordenador sin problemas). En los Mac OS X se incluye una o versin de l o nea de comando de Python 2, pero no Python 3. Microsoft Windows no
Nota del Traductor: El nombre correcto del sistema operativo Linux es GNU/Linux, no obstante, por comodidad, en este libro se utilizar unicamente Linux para mayor comodidad a 2 ao 2009 n
1

trae ninguna versin de Python. Pero no te preocupes! siempre puedes instalarlo o t mismo, tengas el sistema operativo que tengas. u La forma ms sencilla para comprobar si tienes instalado Python 3 en tu a sistema Linux o Mac OS X es abrir un terminal de l nea de comandos. Para ello debes hacer lo siguiente: Si ests en Linux, busca en el men de Aplicaciones un programa denominado a u terminal (puede estar en un submen, posiblemente Accesorios o Sistema). u Si ests en Mac OS X, existe una aplicacin que se llama Terminal.app en la a o carpeta /Aplicaciones/Utilidades/. Una vez te encuentres en la l nea de comando3 , teclea python3 (en minsculas u y sin espacios) y observa lo que sucede. En mi sistema Linux, Python 3 ya est insa talado, por lo que el resultado de ejecutar este comando hace que el terminal entre en la consola4 interactiva de Python.
jmgaguilera@acerNetbook-jmga:~$ python3 Python 3.0.1+ (r301:69556, Apr 15 2009, 15:59:22) [GCC 4.3.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>

(Para salir de la consola interactiva de Python escribe exit() y pulsa la tecla INTRO.) Al ejecutar esta misma sentencia python3 en un ordenador Linux que no tenga instalado Python 3 el mensaje que se obtendr ser parecido al siguiente: a a
jmgaguilera@acerNetbook-jmga:~$ python3 bash: python3: orden no encontrada jmgaguilera@acerNetbook-jmga:~$ python3

Bueno, volviendo ahora a la pregunta sobre cul es la versin de Python 3 a o apropiada para ti, queda claro que es aquella que se ejecute en el ordenador que tengas. Para conocer cmo instalar Python 3, contina leyendo en el apartado que o u corresponda a tu sistema operativo.
3 4

Tambin conocido como el prompt e En ingls shell e

0.3.

Instalacin en Microsoft Windows o

Windows se ejecuta actualmente en dos plataformas diferentes: 32 y 64 bits. Asimismo, existen diferentes versiones de Windows XP, Vista, Windows 7 y Python 3 funciona en todas ellas. Es ms importante, con vistas a la instalacin, la a o distincin que existe entre los dos tipos de arquitecturas. Si no sabes de qu tipo es o e la arquitectura de tu ordenador, lo ms probable es que sea de 32 bits. a Visita python.org/download/ para descargar la aplicacin de instalacin de o o Python 3 que sea correcta para para la arquitectura de tu ordenador. Las posibilidades sern parecidas a: a Python 3.*.* x86 Windows installer (Windows binary does not include sources) Python 3.*.* AMD64 Windows installer (Windows AMD64 binary does not include sources) La descarga exacta var en funcin de las actualizaciones. Por eso he puesto a o asteriscos en lugar del nmero de versin. Deber instalar siempre la ultima versin u o as o disponible de Python 3.x a menos que tengas alguna razn importante para no o hacerlo.

Figura 1: Advertencia al inicio

Cuando la descarga nalize, pulsa (doble click) sobre el chero .msi que has descargado. Windows mostrar una alerta de seguridad (gura 1) para avisarte de a que ests intentando ejecutar un chero que instalar cosas en tu ordenador. El a a chero instalador de Python est rmado electrnicamente por la Python Software a o 7

Foundation, que es la organizacin sin animo de lucro que supervisa el desarrollo de o Python. No aceptes imitaciones! Pulsa el botn Run o Ejecutar5 para que se inicie la ejecucin del programa o o instalador de Python.

Figura 2: Tipo de instalacin o

Lo primero que pide el programa instalador (gura 2) es que le indiques si quieres instalar Python 3 para todos los usuarios del ordenadores o unicamente para ti. Por defecto aparece seleccionada la opcin Instalar para todos los usuarios, que o es la mejor opcin, a no ser que tengas una buena razn para no hacerlo6 . o o Cuando hayas seleccionado la opcin deseada, pulsa el botn Next o Siguiente o o para continuar con la instalacin. o Lo siguiente que pedir el instalador (gura 3) es que le digas el directorio a de instalacin. El valor por defecto para todas las versiones de Python 3.1.x es o C:zPython31z, que es un valor adecuado para la mayor de los usuarios. Salvo que a tengas una razn espec o ca para cambiarlo, como por ejemplo, que mantengas una unidad separada para la instalacin de aplicaciones, puedes usar este directorio para o instalar Python. Para cambiar el directorio de instalacin, puedes utilizar las opciones de pano
depender del idioma en el que se encuentre tu sistema operativo a Una posible razn por la podr querer instalarlo unicamente para tu usuario es que estuvieras o as instalando Python en el ordenador de la empresa y no tengas permisos de administrador en tu cuenta de usuario. Pero en ese caso, qu haces instalando Python sin permiso del administrador e de tu empresa? A m no me metas en problemas, eso es cosa tuya.
6 5

talla o, simplemente, teclear el directorio deseado (con el path completo) en la caja de texto.

Figura 3: Directorio de instalacin o

Puedes instalar Python en el disco duro en el lugar que desees. Cuando hayas nalizado, pulsa el botn Next o Siguiente para continuar. o

Figura 4: Seleccin de elementos a instalar o

La siguiente pantalla (gura 4) parece ms compleja, pero en realidad no lo a es. Como pasa con otros muchos instaladores, te ofrece la opcin de que seleccioo 9

nes qu cosas concretas quieres instalar. Puedes instalar todos los componentes de e Python 3, y si el espacio en disco es justo, puedes excluir ciertos componentes. Registrar las extensiones. Si seleccionas esta opcin, el instalador modio car la conguracin de Windows para que te permita ejecutar los scripts7 de a o Python con solo hacer doble click sobre el chero. Esta opcin no necesita de o espacio en disco, por lo que no tiene mucho sentido no marcarla. TclzTk es la librer grca que utiliza la consola de Python. La usaremos a a a lo largo de todo el libro, por lo que es muy recomendable que la mantengas entre los componentes a instalar. Documentacin instala un chero de ayuda que contiene gran parte de la o informacin que se encuentra en docs.python.org. Es recomendable instalar o esta opcin cuando es previsible que no dispongas de conexin permanente a o o Internet. Scripts de utilidades. Estos scripts incluyen diversas utilidades, entre ellas el script 2to3.py sobre el que hablaremos ms adelante. Es necesaria si vas a a migrar cdigo de Python 2 a Python 3. Si no dispones de cdigo para migrar o o puedes saltarte esta opcin. o Suite de pruebas. Es una coleccin de scripts que se utilizan para probar o el buen funcionamiento del intrprete de Python. En este libro no lo vamos a e usar, yo no lo he usado jams en el largo tiempo que llevo programando en a Python. Es totalmente opcional su instalacin. o Si no ests seguro de cuando espacio en disco tienes libre, pulsa el botn Disk a o Usage. El instalador te mostrar las unidades de disco (gura 5) y el espacio libre a disponible en cada una de ellas, as como el espacio que quedar despus de la a e instalacin. o Cuando termines la comprobacin, pulsa el botn OK para volver a la pantalla o o anterior. Si decides excluir alguna opcin (gura 6), selecciona el botn desplegable o o que aparece a la izquierda del texto de la opcin y selecciona Entire feature will be o unavailable. Por ejemplo, si excluyes la suite de pruebas ahorrars 7908 KBytes de a espacio en disco. Pulsa el botn Next para conrmar tu seleccin de opciones. o o
7

cheros que contienen sentencias de Python, que normalmente tienen la extensin .py o

10

Figura 5: Espacio libre

Figura 6: Excluir una opcin o

El instalador copiar todos los cheros (gura 7 al directorio de destino que a hayas seleccionado (Suele ser tan rpido, que tuve que probarlo tres veces antes de a conseguir sacar una foto de la pantalla mostrndolo). a Por ultimo, pulsa el botn Finish para salir del instalador (gura 8). o Si ahora buscas en el men de Inicio, deber encontrar un nuevo elemento u as denominado Python 3.1. Dentro de esta nueva opcin de men encontrars dos proo u a

11

Figura 7: Instalacin o

Figura 8: Instalacin completada o

gramas denominados Python e IDLE. Selecciona uno de estos dos elementos para ejecutar la consola interactiva de Python (gura 9). Contina en el apartado 0.7 u

12

Figura 9: Instalacin completada o

0.4.

Instalacin en un Mac OS X o

Todos los ordenadores Apple Macintosh modernos utilizan procesadores de Intel8 Los Macintosh antiguos utilizaban procesadores Power PC. No es necesario que conozcas esta diferencia puesto que unicamente existe un instalador para todos los tipos de Macs. Visita python.org/download/ para descargar la aplicacin de instalacin de o o Python 3 para Mac. Debes buscar un enlace cuyo nombre sea algo as como Mac Installer Disk Image (3.*.*. El nmero de versin puede variar, pero asegrate u o u de descargar una versin de Python 3 y no de Python 2. o Tu navegador deber montar de forma automtica esta imagen de disco y a a abrir una ventana de Finder para mostrarte el contenido de la imagen. Si no fuese as debers buscar la imagen de disco en el directorio de descargas y hacer doble click , a sobre ella para que se cargue. El nombre de la imagen de disco ser algo as como a python-3-1.dmg. Una vez tengas visible en pantalla el contenido de la imagen de disco (gura 10), podrs observar que contiene varios cheros de texto (Build.txt, a License.txt, ReadMe.txt), y el el chero del paquete de instalacin Python.mpkg. o
8

Como la mayor de ordenadores con Windows a

13

Figura 10: Finder: contenido de la imagen de disco

Haz doble click con el cursor sobre el chero de instalacin Python.mpkg para o iniciar el instalador de Python para Mac.

Figura 11: Bienvenida a la instalacin o La primera pgina (gura 11) que muestra el programa de instalacin describe a o de forma concisa qu es Python, y remite al chero ReadMe.txt (que seguramente e no te le verdad?) por si deseas conocer ms detalles. ste a Pulsa el botn Continue para avanzar en la instalacin. o o La siguiente pantalla (gura 12) muestra informacin importante: Python neo cesita que tengas instalado Mac OS X 10.3 o superior. Si ests ejecutando una versin a o de Mac OS X 10.2 o anterior, deber actualizar tu ordenador a ultima versin. Una as o de las razones ms convincentes, es que Apple ya no proporciona actualizaciones de a seguridad para tu versin del sistema operativo, por lo que tu ordenadores est en o a riesgo cada vez que est conectado a Internet. Otra razn, no menos convincente, es a o que no puedes ejecutar Python 3. 14

Figura 12: Informacin importante o

Pulsa el botn Continue para avanzar en la instalacin. o o

Figura 13: Licencia

Como todos los buenos instaladores, lo siguiente que el instalador de Python muestra es la pantalla de aceptacin de la licencia (gura 13). Python es Open o Source (software de fuentes abiertas) cuya licencia cuenta con la aprobacin de la o iniciativa de Cdigo Abierto. Python cuenta con un cierto nmero de propietarios y o u patrocinadores a lo largo de su historia, cada uno de los cuales ha dejado su marca en la licencia. Pero el resultado nal es este: Python es Cdigo Abierto, y puedes o usarlo en cualquier plataforma, para lo que desees, sin necesidad de pagar ningn u canon, ni obligacin, ni nada a cambio. o Pulsa el botn Continue de nuevo para avanzar en la instalacin. o o Debido a las peculiaridades del proceso de instalacin estndar de Apple, es o a 15

Figura 14: Aceptacin de la Licencia o

necesario que aceptes la licencia (gura 14) para que el instalador te permita continuar. Puesto que Python es Cdigo Abierto, en realidad ests aceptando una licencia o a que te garantiza derechos adicionales, en lugar de quitrtelos. a Pulsa el botn Agree para continuar. o La siguiente pantalla (gura 15) te permite modicar la ubicacin en la que o se efectuar la instalacin. Debes instalar Python en el disco de arranque, pero a o debido a ciertas limitaciones en el instalador, ste no te obliga a ello, por lo que e ten cuidado!. En realidad, yo nunca he tenido la necesidad de cambiar la ubicacin o de instalacin, por ello, salvo causa justicada, acepta la ubicacin sugerida por el o o instalador.

Figura 15: Seleccin de la ubicacin o o

Desde esta pantalla tambin puedes modicar la instalacin con el n de que no e o 16

se instalen algunas funcionalidades. Si quieres hacer esto pulsa el botn Customize, o en caso contrario pulsa el botn Instalar. o

Figura 16: Personalizacin de la instalacin o o

Si eliges una instalacin personalizada (has pulsado el botn Customize), el o o instalador te muestra (gura 16) una pantalla con una lista de caracter sticas: Python Framework. Es el ncleo de Python, por lo que est seleccionado y u a deshabilitado con el n de que no puedas cambiarlo. Aplicaciones GUI incluye IDLE, la consola interactiva grca de Python a que usaremos a lo largo de todo el libro. Te recomiendo encarecidamente que mantengas esta opcin seleccionada. o Herramientas de l nea de comandos, que incluyen la aplicacin python3. o Tambin te recomiendo que mantegas esta opcin seleccionada. e o Documentacin de Python, que contiene mucha de la informacin dispoo o nible en docs.python.org. Muy recomendables si tienes previsto estar desconectado de Internet. Actualizador del perl de la consola, que controla si actualizas tu perl de consola (utilizado por la aplicacin Terminal.app) con el n de que la versin o o de Python que ests instalando se encuentre en el camino de bsqueda de la a u consola. Para los propsitos de este libro, esta opcin no es necesario que la o o instales. Actualizar la versin de Python del sistema. Esta opcin no deber o o a modicarse. Le dice a tu ordenador Mac que utilice Python 3 como versin o 17

por defecto para todos los scripts, incluido aquellos que vienen con el sistema operativo. Seleccionar esta opcin podr producir efectos muy negativos en tu o a sistema, puesto que la mayor parte de los scripts del sistema operativo estn a escritos para Python 2, y pueden fallar en Python 3. Pulsa el botn Install para continuar. o

Figura 17: Solicitando derechos administrativos

Debido a que el instalador copia archivos binarios en /usr/local/bin/, antes de iniciar dicha copia se solicitan permisos de administrador mediante una pantalla (gura 17) en la que hay que teclear la clave del administrador del sistema. No es posible instalar Python en Mac sin disponer de las credenciales de administrador. Pulsa el botn OK para comenzar la instalacin. o o El instalador mostrar una barra de progreso (gura 18) mientras se instalan a las funcionalidades que hayas seleccionado. Si todo va bien, el instalador mostrar en pantalla (gura 19) una marca verde a para indicar que la instalacin de ha completado satisfactoriamente. o Pulsa el botn Close para salir del instalador. o Si no has cambiado la ubicacin de la instalacin, Python 3.1.* se habr inso o a talado en una carpeta denominada Python 3.1 (gura 20) dentro de la carpeta /Aplications. El elemento ms importante en ella es IDLE, que es la consola grca a a interactiva de Python. Haz doble click con el cursor sobre IDLE para ejecutar la consola de Python. La mayor parte del tiempo la pasars explorando Python mediante el uso de a

18

Figura 18: Instalacin o

Figura 19: Fin de la instalacin o

esta consola (gura 21). Los ejemplos de este libro asumen que eres capaz de ejecutar esta consola en todo momento. Contina en el apartado 0.7 u

0.5.

Instalacin en Ubuntu Linux o

Las diferentes distribuciones existentes hoy d de Linux suelen disponer de a vastos repositorios de aplicaciones listas para instalar de forma sencilla. Los detalles exactos var en funcin de la distribucin de Linux. En Ubuntu Linux, la forma an o o ms sencilla de instalar Python 3 consiste en usar la opcin Aadir y quitar... del a o n men de Aplicaciones (gura 22). u 19

Figura 20: Carpeta Python

Figura 21: Consola grca a

Cuando ejecutas por primera vez el programa para Aadir/Quitar aplicacion nes, se muestra una lista de aplicaciones preseleccionadas en diferentes categor as. Algunas ya se encuentran instaladas en tu ordenador, pero la mayor no. Puesto a

20

Figura 22: Aadir/Quitar aplicaciones n

que este repositorio consta de ms de 10.000 aplicaciones, encontrar la que se desea a puede ser dif para facilitar la labor es posible aplicar diferentes ltros que limicil, tan las aplicaciones que se muestran en la lista de pantalla. El ltro por defecto es aplicaciones mantenidas por Canonical que es el pequeo subconjunto formado n por aquellas apliicaciones que se mantienen ocialmente por parte de Canonical, la compa que distribuye y mantiene Ubuntu Linux. na Como Python 3 no est en este subconjunto de aplicaciones, el primer paso es a desplegar los ltros (Mostrar:) y seleccionar Todas las aplicaciones libres (gura 23).

Figura 23: Todas las aplicaciones libres

Despus puedes ltrar an ms utilizando la caja de texto de bsqueda con el e u a u n de buscar el texto Python 3 (gura 24). Ahora la lista de aplicaciones que se muestran se limita a aquellas que, de algn u modo, incluyen la cadena Python 3. Ahora debes marcar dos paquetes. El primero es Python (v3.0). Que contiene el intrprete de Python 3. e 21

Figura 24: Bsqueda de aplicaciones relacionadas con Python 3 u

Figura 25: Seleccin del paquete Python 3 o

El segundo paquete que hay que marcar se encuentra inmediatamente delante, IDLE (usando Python 3.0), que es la consola grca que usaremos a lo largo de todo a el libro (gura 26). Una vez hayas seleccionado los dos paquetes, pulsa el botn Aplicar cambios o para continuar. El gestor de paquetes solicitar que conrmes que quieres instalar tanto IDLE a (usando Python 3.0) como Python (3.0) (gura 27). Pulsa el botn Aplicar para continuar. o El gestor de paquetes te pedir que te identiques con la clave de usuario para a acceder a los privilegios administrativos que permiten instalar aplicaciones. Una vez hecho esto, el gestor de paquetes mostrar una pantalla (gura 28) con el grado a de avance de la instalacin mientras se descargan los paquetes seleccionados del o repositorio de Internet de Ubuntu Linux.

22

Figura 26: Seleccin del paquete IDLE o

Figura 27: Conrmacin o

Cuando los paquetes se hayan descargado, el instalador iniciar automticaa a mente el proceso de instalacin en tu ordenador (gura 29). o Si todo va bien, el gestor de paquetes conrmar que ambos paquetes se instalaa ron satisfactoriamente (gura 30). Desde esta pantalla puedes ejecutar directamente IDLE haciendo doble click sobre l. O puedes pulsar el botn Cerrar para nalizar el e o gestor de paquetes. En cualquier caso, puedes lanzar la consola grca de Python siempre que a quieras seleccionando IDLE en el submen Programacin del men de Aplicaciones. u o u Es en la consola de Python (gura 31) donde pasars la mayor parte del tiempo a explorando Python. Los ejemplos de este libro asumen que eres capaz de ejecutar la consola de Python siempre que sea necesario. Contina en el apartado 0.7 u

23

Figura 28: Descarga de paquetes

Figura 29: Descarga de paquetes

Figura 30: Instalacin nalizada o

24

Figura 31: Consola de Python en Ubuntu Linux

0.6.

Instalacin en otras plataformas o

Python 3 est disponible en otras muchas plataformas. En particular, est disa a ponible prcticamente en todas las distribuciones Linux, BSD y Sun Solaris. Por a ejemplo, RedHat Linux utiliza el gestor de paquetes yum; FreeBSD tiene su propia coleccin de paquetes, y Solaris tiene el gestor de paquetes pkgadd y otros. Una o rpida bsqueda en Internet de los trminos Python 3 + emphtu sistema operativo a u e te mostrar si existe un paquete de Python 3 disponible para tu sistema, y cmo a o instalarlo.

0.7.

Uso de la consola interactiva de Python

En la consola interactiva de Python puedes explorar la sintaxis del lenguaje, solicitar ayuda interactiva sobre las sentencias del lenguaje, y depurar programas cortos. La consola grca (denominada IDLE) tambin proporciona un editor de textos a e bastante decente que resalta mediante colores la sintaxis del lenguaje Python. Si no tienes an un editor de textos de tu eleccin, puedes darle una oportunidad a IDLE. u o Vamos a comenzar! La shell de Python es un estupendo lugar para comenzar

25

a jugar con el lenguaje Python de forma interactiva. A lo largo de este libro vers a un montn de ejemplos como este: o
>>> 1 + 1 2

Los tres s mbolos de mayor que, , representan el prompt 9 de Python. No teclees nunca estos tres caracteres. Se muestran para que sepas que este ejemplo se debe teclear en la consola de Python. Lo que tienes que teclear es 1 + 1. En la consola puedes teclear cualquier expresin o sentencia vlida del lenguaje. No seas t o a mido, no muerde! Lo peor que puede pasarte es que Python muestre un mensaje de error, si tecleas algo que no entiende. Las sentencias se ejecutan inmediatamente (despus de que pulses la tecla e INTRO); las expresiones se calculan en el momento, y la consola imprime en pantalla el resultado. 2 es el resultado de la expresin. Como 1 + 1 es una expresin vlida en el o o a lenguaje Python, al pulsar la tecla INTRO Python evala la expresine imprime el u o resultado, que en este caso es 2. Vamos a probar otro ejemplo.
>>> print(Hola mundo!) Hola mundo!

Muy sencillo, no? Pero hay muchas otras cosas que puedes hacer en la consola de Python. Si en algn momento te bloqueas no recuerdas una sentencia, o no recuerdas los u argumentos que debes pasar a una funcin determinada puedes obtener ayuda en o la propia consola. Simplemente teclea help y pulsa ENTER.
>>> help Type help() for interactive help, or help(object) for help about object.

Exiten dos modos de ayuda: Puedes solicitar ayuda de un objeto concreto, lo que muestra la documentacin o del mismo y vuelve al prompt de la consola de Python.
Nota del Traductor: El prompt es el indicador que usa una consola, en este caso la consola de Python, para que el usuario sepa que puede teclear alguna sentencia. Como el uso de la palabra prompt est tan extendido para este concepto, y no existe uno en espaol de amplio uso, en este a n libro se utilizar sin traducir. a
9

26

Tambin puedes entrar en el modo ayuda, en el que en lugar de evaluar expree siones de Python, puedes teclear palabras reservadas del lenguaje o nombres de sentencias y la consola imprime lo que sepa sobre ellas. Para entrar en el modo interactivo de ayuda teclea help() y pulsa INTRO.
>>>help() Welcome to Python 3.0! This is the online help utility.

If this is your first time using Python, you should definitely check out the tutorial on the Internet at http://docs.python.org/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit". To get a list of available modules, keywords, or topics, type "modules", "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". help>

Observa que ahora el prompt cambia de a help. Este cambio sirve para recordarte que te encuentras en el modo de ayuda interactiva. Ahora puedes teclear cualquier palabra reservada, sentencia, nombre de mdulo, nombre de funcin casi o o cualquier cosa que Python entienda y leer la documentacin que haya disponible o sobre el tema tecleado.
help> print Help on built-in function print in module builtins: print(...) print(value, ..., sep= , end=\n, file=sys.stdout) Prints the values to a stream, or to sys.stdout by default. Optional keyword arguments: file: a file-like object (stream); defaults to the current sys.stdout. sep: string inserted between values, default a space. end: string appended after the last value, default a newline. help> Papaya no Python documentation found for Papaya

27

help> quit You are now leaving help and returning to the Python interpreter. If you want to ask for help on a particular object directly from the interpreter, you can type "help(object)". Executing "help(string)" has the same effect as typing a particular string at the help> prompt. >>>

En el ejemplo anterior se obtiene en primer lugar la documentacin sobre la o funcin print. Para ello se ha tecleado en el modo ayuda la palabra print y luego se ha o pulsado INTRO. Como resultado se obtiene un texto en el que se muestra el nombre de la funcin, un breve resumen de la misma, los argumentos de la funcin y sus o o valores por defecto. Si la documentacin te parece demasiado opaca, no te asustes. o Aprenders lo necesario sobre todos estos conceptos en los prximos cap a o tulos de este libro. Evidentemente el modo de ayuda no lo sabe todo. Si tecleas algo que no sea una sentencia, mdulo, funcin u otra palabra reservada de Python,el modo de ayuda o o interactiva mostrar un mensaje indicando que no encuentra documentacin alguna a o para el concepto que hayas tecleado. Por ultimo, para salir del modo de ayuda unicamente tienes que teclear quit y pulsar INTRO. El prompt vuelve de nuevo a para indicar que has abandonado el modo de ayuda interactiva y que de nuevo te encuentras en la consola de Python. IDLE, adems de servir como consola grca de Python, incluye tambin un a a e editor de textos que conoce el lenguaje Python. Vers cmo usarlo en la seccin a o o siguiente.

0.8.

Editores de texto e IDEs para Python

IDLE no es el unico entorno existente para escribir programas en Python. Aun que es muy util para comenzar a aprender el lenguaje, muchos desarrolladores pre eren utilizar otros editores de texto o Entornos Integrados de Desarrollo 10 . No los voy a abarcar aqu unicamente comentar que la comunidad de Python mantiene , e una lista de editores para el lenguaje Python sobre diversas plataformas y licencias de software.
En ingls se suele hablar de IDE, para referirse a los Integrated Development Environment, que e son aplicaciones que permiten desarrollar de forma rpida al incluir un editor de textos, compilador, a depurador e incluso herramientas de diseo de aplicaciones avanzadas. n
10

28

Tambin puede ser de inters para ti la lista de Entornos Integrados de Desae e rrollo para Python, aunque an son pocos los que sirven para Python 3. Uno de ellos u es PyDev, un plugin para Eclipse que convierte a Eclipse en un completo Entorno Integrado de Desarrollo para Python. Ambos, Eclipse y PyDev, son multiplataforma y de cdigo abierto. o Por la parte comercial, existe un entorno de desarrollo denominado Komodo IDE. Tiene una licencia que se paga por cada usuario, pero tambin ofrece descuento e para estudiantes, y una versin con licencia de prueba limitada. o Llevo programando en Python nueve aos, yo, para editar los programas, utin lizo GNU Emacs y los depuro en la shell de l nea de comando11 . No existe un modo correcto de desarrollar en Python. Encuentra lo que mejor se adapte a ti!

11

Nota del Traductor:En mi caso uso GVim y el depurador de consola pudb

29

30

Cap tulo 1 Tu primer programa en Python


Nivel de dicultad:     No entierres tu carga en un santo silencio. Tienes un problema? Estupendo. Algrate, e sumrgete en l e investiga. e e Ven. Henepola Gunarata

1.1.

Inmersin o

Los libros sobre programacin suelen comenzar con varios cap o tulos sobre los fundamentos y van, poco a poco, avanzando hasta llegar a hacer programas utiles. Vamos a saltarnos todo eso. Lo primero que vamos a ver es un programa Python completo. Probablemente no tenga ningn sentido para ti. No te preocupes por eso, u vamos a diseccionarlo l nea por l nea. Primero lelo y trata de interpretarlo. e
1 # parahumanos . py 2 3 SUFIJOS = { 1 0 0 0 : [ KB , MB , GB , TB , PB , EB , ZB , YB ] , 4 1 0 2 4 : [ KiB , MiB , GiB , TiB , PiB , EiB , ZiB , 5 YiB ] } 6 7 def tamanyo aproximado ( tamanyo , u n k i l o b y t e e s 1 0 2 4 b y t e s=True ) : 8 C o n v i e r t e un tama o de f i c h e r o en formato l e g i b l e por p e r s o n a s n 9 10 Argumentos / par metros : a 11 tamanyo tama o de f i c h e r o en b y t e s n 12 u n k i l o b y t e e s 1 0 2 4 b y t e s s i True ( por d e f e c t o ) , 13 usa m l t i p l o s de 1024 u 14 s i F a l s e , usa m l t i p l o s de 1000 u

31

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

retorna : string i f tamanyo < 0 : r a i s e V a l u e E r r o r ( e l n mero debe s e r no n e g a t i v o ) u m u l t i p l o = 1024 i f u n k i l o b y t e e s 1 0 2 4 b y t e s e l s e 1000 f o r s u f i j o in SUFIJOS [ m u l t i p l o ] : tamanyo /= m u l t i p l o i f tamanyo < m u l t i p l o : return { 0 : . 1 f } {1} . format ( tamanyo , s u f i j o ) r a i s e V a l u e E r r o r ( n mero demasiado grande ) u if name == m a i n : print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 , F a l s e ) ) print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 ) )

Antes de analizarlo paso a paso vamos a ejecutar el programa en la l nea de 1 comandos. En Linux o en Mac debes teclear: python3 parahumanos.py . El resultado ser parecido a lo siguiente: a
1 2 3 t u u s u a r i o @ t u o r d e n a d o r : / inmersionEnPython3$ python3 parahumanos . py 1 . 0 TB 9 3 1 . 3 GiB

En Windows debes teclear lo mismo: python3 parahumanos.py, unicamente var a la forma del prompt de la consola. El resultado ser parecido a: a
1 C: \ \ i n m e r s i o n e n p y t h o n 3 :> python3 parahumanos . py 2 1 . 0 TB 3 9 3 1 . 3 GiB

Qu ha pasado? Acabas de ejecutar tu primer programa Python. Has ejecutae do el intrprete de Python en la l e nea de comandos (python3), y le has pasado como parmetro el nombre del chero de script (parahumanos.py) que quer ejecutar. a as El chero de script, a su vez, dene una unica funcin de python, la funcin o o tamnyo aproximado, que toma como parmetros un tamao de chero con una precia n sin de bytes y calcula el tamao en una unidad mayor en la que el valor quede ms o n a bonito, a cambio, el resultado es aproximado. (El funcionamiento del Explorador de Windows; del Finder de Mac OS X, o de Nautilus, Dolphin o Thunar de Linux es muy parecido. Si muestras en cualquiera de ellos una carpeta de documentos en modo detalle, de forma que se vean en diferentes columnas, el icono del documento,
Para que funcione correctamente debes moverte al directorio en el que est grabado el chero e parahumanos.py.
1

32

nombre, tamao, tipo, fecha de ultima modicacin, etc. Observars que si un don o a cumento determinado ocupa 1093 bytes, en la columna de tamao no dir eso, sino n a que dir algo as como 1 KB. Esto es lo que hace la funcin tamanyo aproximado) a o Las l neas de cdigo print(tamanyo aproximado(argumentos)) del nal del script, o l neas 31 y 32, son dos llamadas a funciones primero se llama a la funcin tao manyo aproximado() pasndole unos parmetros (tambin llamados argumentos), a a e esta funcin se ejecuta y devuelve un resultado que, posteriormente, se pasa coo mo parmetro a la funcin print(). Todo ello en la misma l a o nea. La funcin print() es interna del lenguaje Python2 ; nunca vers una declaracin o a o expl cita de ella. La puedes usar cuando quieras, en cualquier parte de un programa Python3 . Porqu la ejecucin del script en la l e o nea de comandos retorna siempre la misma respuesta? Lo veremos ms adelante. Primero vamos a ver el funcionamiento a de la funcin tamanyo aproximado(). o

1.2.

Declaracin de funciones o

Python dispone de funciones como la mayor de los lenguajes, pero no tiene a cheros de cabecera como c++ o secciones de interface/implementation como en Pascal. En Python unicamente hay que declarar la funcin, como en el siguiente o ejemplo:
1 def tamanyo aproximado ( tamanyo , u n k i l o b y t e e s 1 0 2 4 b y t e s=True ) :

La palabra reservada def inicia la declaracin de la funcin, seguida del nomo o bre que le quieres dar a la misma, seguida de los parmetros de la funcin entre a o parntesis. Separndolos por comas en caso de que sean varios parmetros. e a a Observa tambin que, en Python, las fune ciones no denen un tipo de datos de retorno. No se especica el tipo de datos del valor que retornan las funciones. Es ms, ni siquiera se esa pecica si se retorna o no un valor.

En Python cuando necesitas una funcin, solamente tienes o que declararla.

En realidad, todas las funciones de Python tienen un valor de retorno; si dentro del cdigo de la funcin se ejecuta una sentencia o o return, el valor que acompaa a la sentencia ser el valor de retorno, en caso contrario n a se retorna el valor None, que es la forma de expresar el vac (null) en Python. o
En ingls built-in. e Existen montones de funciones internas del lenguaje, y muchas ms que estn separadas en a a mdulos. Lo veremos poco a poco, ten paciencia, pequeo saltamontes. o n
3 2

33

En algunos lenguajes, las funciones que retornan un valor se declaran con la palabra function, y las subrutinas que no retornan un valor con la palabra sub. En Python no existen las subrutinas. Todas son funciones, todas las funciones devuelven un valor (None si t no devuelves u algo expresamente con la palabra reservada return) y todas las funciones comienzan con la palabra def. a La funcin tamanyo aproximado() recibe dos parmetros o argumentos, tamanyo o y un kilobyte es 1024 bytes pero ninguno de ellos especica un tipo de datos. En Python, las variables nunca se tipican expl citamente, Python deduce y mantiene el tipo de datos de la variable de forma interna segn el valor que tenga asignado la u misma. En Java y otros lenguajes con tipicacin esttica, debes especicar el o a tipo de datos de los parmetros y valor de retorno de cada funcin. a o En Python nunca especicas el tipo de datos de nada de forma expl cita. Python mantiene el rastro de los tipos de datos de forma interna basndose en los valores que asignes a las variables. a

1.2.1.

Parmetros opcionales y con nombre a

Python permite que los parmetros de una funcin tengan valores por defecto; a o si la funcin se llama (para ejecutarla) si indicar el parmetro Python usar el valor o a a por defecto para asignarlo al parmetro que no se ha especicado en la llamada a a la funcin. Asimismo, los parmetros se pueden pasar en la llamada en cualquier o a orden si se utilizan parmetros con nombre. a Veamos de nuevo la declaracin de la funcin tamanyo aproximado(). o o
1 def tamanyo aproximado ( tamanyo , u n k i l o b y t e e s 1 0 2 4 b y t e s=True ) :

El segundo parmetro un kilobyte es 1024 bytes, especica un valor por defecto a igual a True. Como consecuencia, este parmetro pasa a ser opcional ; puedes llamar a a la funcin sin pasarlo en los parntesis. Python se comportar como si lo hubieras o e a llamado con el valor True como segundo parmetro. a Veamos el nal del script4 :
1 2 3 if name == m a i n : print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 , F a l s e ) ) print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 ) )
4

En Python se les suele llamar tambin script a los cheros con el cdigo fuente de los programas. e o

34

1. La primera llamada a la funcin (l o nea 2) utiliza dos parmetros. Durante la a ejecucin de la funcin tamanyo aproximado un kilobyte es 1024 bytes tendr el o o a valor False, que es lo que se pasa como segundo parmetro en la llamada a la a funcin. o 2. La segunda llamada a la funcin (l o nea 3) utiliza un unico parmetro. Pero a Python no se queja ya que el segundo es opcional. Como no se especica, el segundo parmetro utiliza su valor por defecto True, de acuerdo a lo que se a deni en la declaracin de la funcin. o o o Tambin puedes pasar los valores a una funcin utilizando nombres. Prueba lo e o siguiente en la consola:
1 2 3 4 5 6 7 8 9 10 11 12 >>> from parahumanos import tamanyo aproximado >>> tamanyo aproximado ( 4 0 0 0 , u n k i l o b y t e e s 1 0 2 4 b y t e s=F a l s e ) 4 . 0 KB >>> tamanyo aproximado ( tamanyo =4000 , u n k i l o b y t e e s 1 0 2 4 b y t e s=F a l s e ) 4 . 0 KB >>> tamanyo aproximado ( u n k i l o b y t e e s 1 0 2 4 b y t e s=F a l s e , tamanyo =4000) 4 . 0 KB >>> tamanyo aproximado ( u n k i l o b y t e e s 1 0 2 4 b y t e s=F a l s e , 4 0 0 0 ) SyntaxE rror : nonkeyword a r g a f t e r keyword a r g (< p y s h e l l#4>, l i n e 1) >>> tamanyo aproximado ( tamanyo =4000 , F a l s e ) SyntaxEr ror : nonkeyword a r g a f t e r keyword a r g (< p y s h e l l#5>, l i n e 1) >>>

1. Lnea 2: Llama a la funcin tamnyo aproximado() pasndole 4000 al primer o a parmetro (tamanyo) y el valor False en el denominado un kilobyte es 1204 bytes a (En este caso coincide que el parmetro con nombre se est pasando en la sea a gunda posicin y tambin est declarado en la funcin como segundo parmeo e a o a tro, pero esto es simplemente una coincidencia). a a 2. Lnea 4: Llama a la funcin tamanyo aproximado() pasndole 4000 al parmetro o denominado tamanyo y False al parmetro denominado un kilobyte es 1024 bytes a (Estos parmetros coinciden en orden con los de la declaracin de la funcin, a o o pero vuelve a ser una simple coincidencia). 3. Lnea 6: Llama a a la funcin tamanyo aproximado() pandole False al parme o a a tro denominado un kilobyte es 1024 bytes y 4000 al parmetro denominado taa manyo (Esta es la utilidad de usar nombres en las llamadas a una funcin, o poder pasarlos en cualquier orden, e incluso no pasar alguno de los existentes para que tomen valores por defecto mientras s que pasas uno de los ultimos parmetros de la funcin). a o

35

4. Lnea 8: Esta llamada a la funcin falla porque se usa un parmetro con o a nombre seguido de uno sin nombre (por posicin). Esta forma de llamar a la o funcin siempre falla. Python lee la lista de parmetros de izquierda a derecha, o a en cuanto aparece un parmetro con nombre, el resto de parmetros debe a a tambin proporcionarse por nombre. Los primeros pueden ser por posicin. e o 5. Lnea 10: Esta llamada tambin falla por la misma razn que la anterior. Te e o sorprende? Despus de todo, el primer parmetro se ha denominado tamanyo y e a recibe el valor 4000, es obvio que el valor False deber asignarse al parmetro a a un kilobyte es 1024 bytes. Pero Python no funciona de esa forma. Tan pronto como lee un parmetro con nombre, todos los parmetros siguientes (a la a a derecha) tienen que llevar el nombre del parmetro. a

1.3.

Cmo escribir cdigo legible o o

No te voy a aburrir con una larga charla sobre la importancia de documentar el cdigo. Solamente decir que el cdigo se escribe una vez pero se lee muchas veces, o o y que quien ms lo va a leer eres t, seis meses despus de haberlo escrito (por a u e ejemplo: cuando ya no te acuerdes de nada pero necesites corregir o aadir algo). n Python hace fcil escribir cdigo legible, aprovchate de ello. Me lo agradecers a o e a dentro de seis meses.

1.3.1.

Cadenas de texto de documentacin o

Puedes documentar una funcin proporcionndole una cadena de documentao a cin (abreviando se suele hablar de docstring). En este programa, la funcin tamano o o yo aproximado() tiene una cadena de documentacin (docstring):
1 2 3 4 5 6 7 8 9 10 11 12 def tamanyo aproximado ( tamanyo , u n k i l o b y t e e s 1 0 2 4 b y t e s=True ) : C o n v i e r t e un tama o de f i c h e r o en formato l e g i b l e por p e r s o n a s n Argumentos / par metros : a tamanyo tama o de f i c h e r o en b y t e s n u n k i l o b y t e e s 1 0 2 4 b y t e s s i True ( por d e f e c t o ) , usa m l t i p l o s de 1024 u s i F a l s e , usa m l t i p l o s de 1000 u retorna : string

La comillas triples sirven para escribir cadenas de texto que ocupen ms de a 36

una l nea. Todo lo que se escribe entre las comillas triples forma parte de una unica cadena de texto, inclu dos los espacios en blanco, retornos de carro, saltos de l nea y otras comillas sueltas. Este tipo de cadenas de texto lo puedes utilizar donde quieras dentro del cdigo Python, pero normalmente se utilizan para denir docstring o (cadenas de texto de documentacin). o Las comillas triples son la manera ms simple de escribir cadenas de a texto que incluyan, a su vez, comillas simples y/o dobles, como cuando en Perl 5 se utiliza q/.../ En este ejemplo, todo lo que se encuentra entre las comillas triples es el docstring de la funTodas las funciones se merecin, que sirve para documentar lo que hace la o cen un docstring que las explifuncin. Un docstring, si existe, debe ser lo prio que mero que aparece denido en una funcin (es o decir, se debe encontrar en la primera l nea que aparece despus de la declaracin de la funcin). Tcnicamente no necesitas escribir e o o e un docstring para cada funcin, pero deber S que lo has escuchado en las clases o as. e que programacin a las que hayas asistido, pero Python te da un incentivo mayor o para que lo hagas: los docstring estn disponibles en tiempo de ejecucin como un a o atributo de la funcin. o Muchos entornos integrados de programacin (IDEs) utilizan los docstring o para proporcionar ayuda y documentacin sensible al contexto, de forma o que cuando teclees el nombre de una funcin, aparece su docstring como o pista sobre el signicado de la funcin y de sus parmetros. Esto puede o a ser muy util, tan util como explicativos sean los docstring que escribas.

1.4.

El camino de b squeda para import u

Antes de continuar, quiero mencionar brevemente el camino5 de bsqueda de u las librer Cuando importas un mdulo, Python busca en varios lugares hasta enas. o contrarlo. En concreto, busca en todos los directorios que se encuentren denidos en la variable sys.path. Como se trata de una lista, puedes verla fcilmente o modicarla a con los mtodos estndares de manipulacin de listas. (Aprenders a trabajar con e a o a listas en el cap tulo ?? sobre Tipos de Dato Nativos).
En espaol se usa tambin ruta de bsqueda. En ingls se usa la palabra path para referirse a n e u e este concepto
5

37

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

>>> import s y s >>> s y s . path [, / u s r / l i b / python3 . 0 , / u s r / l i b / python3 . 0 / p l a t l i n u x 2 , / u s r / l i b / python3 . 0 / l i b dynload , / u s r / l i b / python3 . 0 / d i s t p a c k a g e s , / u s r / l o c a l / l i b / python3 . 0 / d i s t p a c k a g e s ] >>> s y s <module s y s ( b u i l t in)> >>> s y s . path . i n s e r t ( 0 , /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s ) >>> s y s . path [ /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s , , / u s r / l i b / python3 . 0 , / u s r / l i b / python3 . 0 / p l a t l i n u x 2 , / u s r / l i b / python3 . 0 / l i b dynload , / u s r / l i b / python3 . 0 / d i s t p a c k a g e s , / u s r / l o c a l / l i b / python3 . 0 / d i s t p a c k a g e s ] >>>

1. Lnea 1: Al importar el paquete sys de esta forma, todas sus funciones y atributos quedan a disposicin del programador para su uso. o 2. Lneas 2-8: sys.path es una variable (path) del paquete sys que contiene una lista de los directorios que constituyen el camino de bsqueda (El tuyo ser diu a ferente, ya que depende del sistema operativo, de la versin de Python que o tengas instalada, y del lugar en el que est instalada). Siempre que se haga un a import en el cdigo, Python buscar en estos directorios (por orden), hasta eno a contrar un chero cuyo nombre coincida con el valor que se usa en la sentencia import cms la extensin .py. a o 3. Lneas 9-10: En realidad te he mentido un poco, la realidad es un poco ms a compleja, no todos los mdulos se almacenan en cheros con extensin .py. o o Algunos de ellos, como el mdulo sys son mdulos internos (built-in); no exiso o ten en cheros, estn construidos internamente en el propio lenguaje. En la a prctica funcionan exactamente igual que los mdulos que estn en cheros, a o a la unica diferencia es que no existe el cdigo fuente, Porque no estn escritos o a en Python! (El mdulo sys est escrito en lenguaje c). o a 4. Lnea 11: En tiempo de ejecucin puedes aadir un nuevo directorio al ca o n mino de bsqueda de Python aadiendo un directorio a la variable sys.path, u n as Python tambin buscar en l cada vez que intentes importar un mdulo. e a e o El efecto de este cambio dura mientras se mantenga en ejecucin Python. Al o

38

nalizar, y volver a entrar en Python, el camino (la variable sys.path) volver a a tener los valores iniciales. 5. Lneas 12-19 : Al ejecutar sys.path.insert(0, path) se nsert un nuevo directorio o en la primera posicin (en Python la primera posicin se numera con el cero) o o de la lista de sys.path. Casi siempre, ser esto lo que quieras hacer. En casos a en los que exista algn conicto de nombres (por ejemplo, si Python tiene su u propia versin de una librer y es de la versin 2, pero quieres utilizar otra o a o que sea de la versin 3), as te aseguras que tus mdulos se encuentran antes o o y ejecutan en lugar de los originales.

1.5.

En Python todo es un Objeto

En caso de te lo hayas perdido, acabo de decir que las funciones de Python tienen atributos, y que esos atributos estn disponibles en tiempo de ejecucin. Una a o funcin, como todo lo dems en Python, es un objeto. o a Abre la consola interactiva de Python y ejecuta lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> import parahumanos >>> print ( parahumanos . tamanyo aproximado ( 4 0 9 6 , True ) ) 4 . 0 KiB >>> print ( parahumanos . tamanyo aproximado . d o c ) C o n v i e r t e un tama o de f i c h e r o en un formato l e g i b l e por p e r s o n a s n Argumentos / par metros : a tamanyo tama o de f i c h e r o en b y t e s n u n k i l o b y t e e s 1 0 2 4 b y t e s s i True ( por d e f e c t o ) , usa m l t i p l o s de 1024 u s i F a l s e , usa m l t i p l o s de 1000 u retorna : string

>>>

1. Lnea 1: Importa (carga en memoria) el programa parahumanos como un mdu o lo un trozo de cdigo que puedes utilizar de forma interactiva o desde un o programa Python mayor. Una vez se ha importado el mdulo, puedes utilio zar (referenciar) cualquiera de sus funciones pblicas, clases o atributos. Si u desde un mdulo se desea utilizar la funcionalidad de otro, basta con hacer o exactamente lo mismo que en esta l nea de la consola interactiva.

39

2. Lnea 2: Cuando quieres utilizar las funciones que estn denidas en los mdu e o los importados, tienes que aadir el nombre del mdulo. No es posible utilizar n o simplemente tamanyo aproximado, debes utilizar parahumanos.tamanyo aproximado. Si has utilizado Java, esta forma de utilizar una funcin deber sonarte. o a 3. Lnea 4: En este caso, en lugar de llamar a la funcin como podr esperar, o as se consulta uno de los atributos de la funcin, doc . o En Python import es equivalente al require de Perl. Cuando importas (import) un mdulo de Python puedes acceder a todas sus funciones con o la sintaxis mdulo.funcin. En Perl, cuando se requiere (require) un mduo o o lo puedes acceder a todas sus funciones con la sintaxis mdulo::funcin o o

1.5.1.

Qu es un objeto? e

En Python todo es un objeto, y todos los objetos pueden tener atributos y mtodos. Todas las funciones son objetos, y tienen el atributo doc , que retorna e el docstring que se haya denido en el cdigo fuente. El mdullo sys es tambin un o o e objeto que tiene (entre otras cosas) un atributo denominado path. Como se ha dicho: todo lo que se dena en Python es un objeto y puede tener atributos y mtodos. e Sin embargo, no hemos contestado an a la pregunta fundamental: Qu es un u e objeto? Los diferentes lenguajes de programacin denen objeto de diferente forma. o En algunos, signica que todos los objetos deben tener atributos y mtodos; en otros, e signica que todos los objetos pueden tener subclases. En Python la denicin es o ms relajada. Algunos objetos no tienen ni atributos ni mtodos, pero podran. No a e todos los objetos pueden tener subclases. Pero todo es un objeto en el sentido de que pueden asignarse a variables y pasarse como parmetro de una funcin. a o Puede que hayas o en otro contexto de programacin el trmino objeto de do o e primera clase. En Python, las funciones son objetos de primera clase. Puedes pasar una funcin como parmetro de otra funcin. Los mdulos tambin son objetos de o a o o e primera clase. Puedes pasar un mdulo completo como parmetro de una funcin. o a o Las clases son objetos de primera clase, y las instancias de las clases tambin lo son. e Esto es importante, por lo que lo voy a repetir en caso de que se te escapara las primeras veces: en Python, todo es un objeto. Las cadenas son objetos, las listas son objetos. Las funciones son objetos. Las clases son objetos. Las instancias de las clases son objetos. E incluso los mdulos son objetos. o

40

1.6.

Indentar cdigo o

Las funciones de Python no tienen begin o end, y tampoco existen llaves que marquen donde comienza y acaba el cdigo de una funcin. El unico delimitador es o o el s mbolo de los dos puntos (:) y el propio indentado del cdigo. o
1 2 3 4 5 6 7 8 9 10 11 def tamanyo aproximado ( tamanyo , u n k i l o b y t e e s 1 0 2 4 b y t e s=True ) : i f tamanyo < 0 : r a i s e V a l u e E r r o r ( El n mero debe s e r no n e g a t i v o ) u m u l t i p l o = 1024 i f u n k i l o b y t e e s 1 0 2 4 b y t e s e l s e 1000 f o r s u f i j o in SUFIJO [ m u l t i p l o ] : tamanyo /= m u l t i p l o i f tamanyo < m u l t i p l o : return { 0 : . 1 f } {1} . format ( tamanyo , s u f i j o ) r a i s e V a l u e E r r o r ( n mero demasiado grande ) u

1. Lnea 1: Los bloques de cdigo se denen por su indentado. Por bloque de o cdigo se entiende lo siguiente: funciones, sentencias if, bucles for, bucles while o y similar. Al indentar se inicia el bloque y al desindentar se naliza. No existen llaves, corchetes o palabras clave para iniciar y nalizar un bloque de forma expl cita. Esto implica que los espacios en blanco son signicativos, y deben ser consistentes. En este ejemplo, el cdigo de la funcin est indentado con o o a cuatro espacios. No es necesario que sean cuatro, pero s que sea consistente y siempre sean los mismos. La primera l nea que no est indentada deliminta el e nal de la funcin. o 2. Lnea 2: En Python, la sentencia if debe contener un bloque de cdigo. Si o 6 la expresin que sigue al if es verdadera se ejecuta el bloque indentado que o contiene el if, en caso contrario lo que se ejecuta es el bloque contenido en el else (si existe). Observa la ausencia de parntesis alrededor de la expresin. e o 3. Lnea 3: Esta l nea se encuentra dentro del bloque de cdigo del if. La sentencia o raise elevar una excepcin (del tipo ValueError, pero unicamente si tamanyo a o 0. 4. Lnea 4: Esta l nea no marca el nal de la funcin. Las l o neas que estan com pletamente en blanco no cuentan. Unicamente sirven para hacer ms legible a el cdigo, pero no cuentan como delimitadores de cdigo. La funcin contina o o o u en la l nea siguiente.
6

Si el resultado de evaluarla es True.

41

5. Lnea 6: El bucle for tambin marca el comienzo de un bloque de cdigo. Los e o bloques pueden contener mltiples l u neas, siempre que estn indentadas con e el mismo nmero de espacios. Este bucle for contiene tres l u neas de cdigo en o l. No existe ninguna otra sintxis especial para los bloques de varias l e a neas. Basta con indentar y... seguir adelante con el trabajo! Despus de algunas protestas iniciales e ine sidiosas analog con Fortran, seguro que hars as a las paces con esta forma de marcar los bloques de cdigo y comenzars a apreciar sus benecios. o a Uno de los mayores benecios es que todos los programas Python tienen un formato similar, al ser la indentacin un requisito del lenguaje y no o un elemento de estilo. La consecuencia inmediata es que los programas Python son ms fciles a a de leer y comprender por parte de una persona diferente de su programador7 .

Python utiliza los saltos de l nea para separar las sentencias y los dos puntos y la indentacin para separar los bloo ques de cdigo. C++ y Java o utilizan puntos y coma para separar sentencias y llaves para separar los bloques de cdio go.

1.7.

Excepciones

Las excepciones estn en todas partes en Python. Prcticamente todos los a a mdulos de la librer estndar las utilizan, y el propio lenguaje las lanza en muchas o a a circunstancias. Las vers una y otra vez a lo largo del libro. a Qu es una excepcin? Normalmente es un error, una indicacin de que algo e o o fue mal (No todas las excepciones son errores, pero no te preocupes por eso ahora). Algunos lenguajes de programacin fomentan que se retornen cdigos de error en o o las funciones, que los programadores tendrn que chequear. Python fomenta el uso a de las excepciones, que los programadores tienen que capturar y manejar. Cuando sucede un error se muestra en la consola de Python algunos detalles de la excepcin y cmo se produjo. A esto se le llama exo o cepcin sin capturar. Cuando la excepcin se geo o ner, Python no encontr un trozo de cdigo que o o o estuviera previsto que la capturase y respondiera en consecuencia, por eso la excepcin se fue eleo vando hasta llegar al nivel ms alto en la consola, a la cual muestra alguna informacin util para la o
7

Al contrario que Java, las funciones de Python no declaran las excepciones que podr an elevar. Te corresponde a ti determinar las excepciones que pueden suceder y necesitas capturar.

o por el propio programador despus de unos meses! e

42

depuracin del cdigo y naliza. Si esto sucede o o en la consola no es excesivamente preocupante, pero si le sucede a tu programa en plena ejecucin, el programa nalizar de forma incontrolada y no se capturase la o a excepcin. Puede que sea lo que quieras, pero puede que no. o El hecho de que suceda una excepcin no o implica necesariamente que el programa tenga Python utiliza bloques que fallar. Las excepciones se pueden manejar. try...except para manejar exAlgunas veces una excepcion sucede porque tiecepciones, y la sentencia raise nes un error en el cdigo (como por ejemplo, aco para generarlas. Java y C++ ceder al valor de una variable que no existe), peutilizan bloques try...catch ro en otras ocasiones puedes anticiparlo. Si vas para manejarlas y la sentencia a abrir un chero, puede que no exista. Si vas throw para generarlas. a importar un mdulo, puede que no est instao e lado. Si te vas a conectar a una base de datos, puede que no est disponible, o puede que no tengas las credenciales necesarias para e acceder a ella. Si sabes que una l nea de cdigo puede elevar una excepcin, deber o o as manejar la excepcin utilizando el bloque try...except. o n La funcin tamanyo aproximado() eleva excepciones por dos causas: el tamao o que se pasa es mayor que el previsto, o si es menor que cero.
1 2 i f tamanyo < 0 : r a i s e V a l u e E r r o r ( El n mero debe s e r no n e g a t i v o ) u

La sintaxis para elevar una excepcin es muy simple. Utiliza la sentencia raise, o seguida del nombre de la excepcin y, opcionalmente, se le pasa como parmetro o a una cadena de texto que sirve para propsitos de depuracin. La sintaxis es parecida o o a la de llamar a una funcin 8 . o No necesitas manejar las excepciones en la funcin que las eleva. Si no se o manejan en la funcin que las eleva, las excepciones pasan a la funcin o o que la llam, luego a la que llam a esa, y as sucesivamente a travs de o o e toda la pila de llamadas. Si una excepcin no se manejase en ninguna o funcin, el programa fallar y nalizar, Python imprimir una traza del o a a a error, y punto. Puede que fuese lo que quer o no, depende de lo que as pretendieras, que para eso eres el programador!
Las excepciones son objetos, como todo en Python recuerdas?. Para implementarlas se utilizan clases (class) de objetos. Al ejecutar en este caso la sentencia raise, en realidad se est creando una a instancia de la clase ValueError y pasndole la cadena El nmero debe ser no negativo al mtodo a u e de inicializacin. Pero nos estamos adelantando! o
8

43

1.7.1.

Capturar errores al importar

Una de las excepciones internas de Python es ImportError, que se eleva cuando intentas importar un mdulo y falla. Esto puede suceder por diversas causas, pero o la ms simple es que el mdulo no exista en tu camino de bsqueda. Puedes utilizar a o u esta excepcin para incluir caracter o sticas opcionales a tu programa. Por ejemplo, la librer chardet que aparece en el cap a tulo ?? autodetecta la codicacin de caraco teres. Posiblemente tu programa quiera utilizar esta librer si est instalada, pero a a continuar funcionando si no lo est. Para ello puedes utilizar un bloque try...except. a
1 2 3 4 try : import c h a r d e t except I m p o r t E r r o r : c h a r d e t = None

Posteriormente, en el cdigo, puedes consultar la presencia de la librer con o a una simple sentencia if:
1 2 3 4 i f chardet : # hacer algo else : # s e g u i r de t o d o s modos

Otro uso habitual de la excepcion ImportError es cuando dos mdulos impleo 9 mentan una API comn, pero existe preferencia por uno de ellos por alguna causa u (tal vez sea ms rpida, o use menos memoria). Puedes probar a importar un mdua a o lo y si falla cargar el otro. Por ejemplo, en el cap tulo ?? sobre XML se habla de dos mdulos que implementan una API comn, denominada ElementTree API. El o u primero lxml.etree, es un mdulo desarrollado por terceros que requiere descargarlo o e instalarlo t mismo. El segundo, xml.etree.ElementTree, es ms lento pero forma u a parte de la librer estndar de Python 3. a a
1 2 3 4 try : from lxml import e t r e e except I m p o r t E r r o r : import xml . e t r e e . ElementTree a s e t r e e

Al nal de este bloque try...except, has importando algn modulo y lo has u llamado etree. Puesto que ambos mdulos implementan una API comn, el resto del o u cdigo no se tiene que preocupar de qu mdulo se ha cargado10 . Asimismo, como o e o el mdulo que se haya importado termina llamndose etree, el resto del cdigo no o a o
Application Programming Interface. Interfaz de programacin de aplicaciones. o Nota del Traductor:Al implementar la misma API ambos mdulos se comportan igual por lo o que son indistingubles en cuanto a funcionamiento. As el resto del cdigo puede funcionar sin , o conocer qu mdulo se ha importado realmente. e o
10 9

44

tiene que estar repleto de sentencias if para llamar a diferentes mdulos con diferente o nombre.

1.8.

Variables sin declarar

Echale otro vistazo a la siguiente l nea de cdigo de la funcin tamanyo aproximado: o o


1 m u l t i p l o = 1024 i f u n k i l o b y t e e s 1 0 2 4 b y t e s e l s e 1000

La variable multiplo no se ha declarado en ningn sitio, simplemente se le u asigna un valor. En Python es correcto. Lo que no te dejar hacer nunca Python a es referenciar a una variable a la que nunca le has asignado un valor. Si intentas hacerlo se elevar la excepcin NameError. a o
1 >>> x 2 Traceback ( most r e c e n t c a l l l a s t ) : 3 F i l e <s t d i n > , l i n e 1 , in <module> 4 NameError : name x i s not d e f i n e d 5 >>> x = 1 6 >>> x 7 1

Le dars las gracias frecuentemente a Python por avisarte! a

1.9.

May sculas y min sculas u u

En Python, todos los nombres distinguen maysculas y minsculas: los nomu u bres de variables, de funciones, de mdulos, de excepciones. De forma que no es el o mismo nombre si cambia alguna letra de mayscula a minscula o viceversa. u u

45

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

>>> u n e n t e r o = 1 >>> u n e n t e r o 1 >>> UN ENTERO Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> NameError : name UN ENTERO i s not d e f i n e d >>> Un Entero Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> NameError : name Un Entero i s not d e f i n e d >>> un enteRo Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> NameError : name un enteRo i s not d e f i n e d

Y as siempre si pruebas todas las combinaciones posibles.

1.10.

Ejecucin de scripts o

Los mdulos de Python son objetos, por lo o que tienen propiedades muy utiles. Puedes utili Todo lo que existe en Python zar alguna de ellas para probar tus mdulos de o es un Objeto una forma sencilla. Para ello puedes incluir un bloque de cdigo especial que se ejecute cuando o arrancas el chero desde la l nea de comando. Observa las ultimas l neas de parahumanos.py:
1 2 3 if name == m a i n : print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 , F a l s e ) ) print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 ) )

Como en C, Python utiliza == para las comparaciones y = para las asignaciones. Al contrario que C, Python no permite la asignacin en o l nea, por lo que no es posible asignar un valor por accidente cuando tu intencin fuese comparar. o Qu es lo que hace este if tan especial? Como los mdulos son objetos, tienen e o propiedades, y una de las propiedades de los mdulos es name . El valor de la o propiedad name depende de la forma en la que ests utilizando el mdulo. Si e o importas el mdulo con la sentencia import el valor que contiene name es el o nombre del chero del mdulo sin la extensin. o o 46

1 >>> import parahumanos 2 >>> parahumanos . n a m e 3 parahumanos

Pero tambin puedes ejecutar directamente el mdulo como un programa e o autnomo, en cuyo caso name contiene el valor especial main . En el ejemplo, o Python evaluar la sentencia if, la expresin ser verdadera y ejecutar el bloque de a o a a cdigo contenido en el if. En este caso, imprimir dos valores: o
1 2 3 j m g a g u i l e r a @ a c e r N e t b o o k : / inmersionEnPython3 / s r c $ python3 parahumanos . py 1 . 0 TB 9 3 1 . 3 GiB

Y as queda explicado tu primer programa Python!

1.11.

Lecturas complementarias

PEP 257: Docstring Conventions Convenciones para escribir docstring. Explica lo que distingue un buen docstring de un gran docstring. Tutorial de Python: Cadenas de texto para documentacin tambin aborda la o e materia. PEP 8: Gu de estilo para codicacin en Python comenta cual es el estilo a o recomendado de indentacin. o Manual de referencia de Python explica lo que signica decir que todo en Python es un objeto, porque algunas personas son algo pedantes y les gusta discutir largo y tendido sobre ese tipo de cosas.

47

48

Cap tulo 2 Tipos de dato nativos


Nivel de dicultad:    La curiosidad es la base de toda la losof a, las preguntas alimentan su progreso, la ignorancia su n. Michel de Montaigne

2.1.

Inmersin o

Aparta tu primer programa en Python durante unos minutos, y vamos a hablar sobre tipos de dato. En Python cada valor que exista, tiene un tipo de dato, pero no es necesario declarar el tipo de las variables. Como funciona? Basado en cada asignacin a la variable, Python deduce el tipo que es y lo conserva internamente. o Python proporciona muchos tipos de dato nativos. A continuacin se muestran o los ms importantes: a 1. Booleanos: Su valor es True o False. 2. N meros: Pueden ser enteros (1, 2, 3,...), otantes (1.1, c 1.3,...)1 , fracciou 1.2, nes (1/2, 1/3, 2/3,...), o incluso nmeros complejos (i  1). u 3. Cadenas: Son secuencias de caracteres Unicode, por ejemplo, un documento HTML.
Nota del traductor: los nmeros decimales se representan utilizando punto decimal. Aunque en u espaol utilizamos la coma decimal en este libro usamos el punto decimal por ser el formato que n se requiere en Python.
1

49

4. Bytes y arrays de bytes: por ejemplo, un chero de imgenes JPEG. a 5. Listas: Son secuencias ordenadas de valores. 6. Tuplas: Son secuencias ordenadas e inmutables de valores. 7. Conjuntos: Son bolsas de valores sin ordenar. 8. Diccionarios: Son bolsas de sin ordenar de parejas clave-valor. Es posible buscar directamente por clave. Aparte de estos, hay bastantes ms tipos. Todo es un objeto en Python, por a lo que existen tipos module, function, class, method, le, e incluso compiled code 2 . Ya has visto alguno de ellos en el cap tulo anterior. En el cap tulo ?? aprenders las a clases, y en el cap tulo ?? los cheros (tambin llamados archivos). e Las cadenas y bytes son sucientemente importantes y complejas como para merecer un cap tulo aparte. Vamos a ver los otros tipos de dato en primer lugar.

2.2.

Booleanos

El tipo de datos booleano solamente tiene dos valores posibles: verdadero o fals. Python En la prctica, puedes utilizar a dispone de dos constantes denominadas True y casi cualquier expresin en un o False, que se pueden utilizar para asignar valores contexto booleano. booleanos directamente. Las expresiones tambin se pueden evaluar a un valor booleano. En e algunos lugares (como las sentencias if, Python espera una expresin que se pueda o evaluar a un valor booleano. Estos sitios se denominan contextos booleanos. Puedes utilizar casi cualquier expresin en un contexto booleano, Python intentar determio a nar si el resultado puede ser verdadero o falso. Cada tipo de datos tiene sus propias reglas para identicar qu valores equivalen a verdadero y falso en un contexto booe leano (Esto comenzar a tener un sentido ms claro para ti cuando veas algunos a a ejemplos concretos). Por ejemplo:
1 2
2

i f tamanyo < 0 : r a i s e V a l u e E r r o r ( e l n mero debe s e r no n e g a t i v o ) u Nota del traductor: Son tipos de dato del lenguaje Python que representan a: mdulos, funo ciones, clases, mtodos, cheros y cdigo compilado. e o

50

La variable tamanyo contiene un valor entero, 0 es un entero, y es un operador numrico. El resultado de la expresin es siempre un valor de tipo booleano. Puedes e o comprobarlo en la consola interactiva de Python:
1 2 3 4 5 6 7 8 9 >>> tamanyo >>> tamanyo False >>> tamanyo >>> tamanyo False >>> tamanyo >>> tamanyo True = 1 < 0 = 0 < 0 = 1 < 0

Debido a la herencia que se conserva de Python 2, los booleanos se pueden tratar como si fuesen nmeros. True es 1 y False es 0. u
1 2 3 4 5 6 7 8 9 10 >>> True + True 2 >>> True F a l s e 1 >>> True F a l s e 0 >>> True / F a l s e Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> Z e r o D i v i s i o n E r r o r : i n t d i v i s i o n or modulo by z e r o

An as no hagas esto. Olvida incluso que lo he mencionado!3 u ,

2.3.

N meros u

Los nmeros son maravillosos. Tienes un montn donde elegir. Python prou o porciona enteros y nmeros de coma otante, pero no existen declaraciones de tipo u para distinguirlos. Python los distingue por la existencia o no del punto decimal4 .
Nota del traductor: se trata de una prctica heredada de Python 2 pero que no puede consia derarse buena prctica de programacin. a o 4 Nota del traductor: En espaol se dice coma decimal, como vamos a mostrar puntos decimales n en todo el libro, por coherencia se utilizar tambin el trmino punto decimal. a e e
3

51

1 2 3 4 5 6 7 8 9 10

>>> type ( 1 ) <c l a s s i n t > >>> i s i n s t a n c e ( 1 , i n t ) True >>> 1 + 1 2 >>> 1 + 1 . 0 2.0 >>> type ( 2 . 0 ) <c l a s s f l o a t >

1. Lnea 1: la funcin type() permite consultar el tipo de cualquier valor o varia o ble. Como era de esperar 1 es un valor de tipo int. 2. Lnea 3: la funcin isinstance() permite chequear si un valor o variable es de o un tipo determinado. 3. Lnea 5: La suma de dos valores de tipo int da como resultado otro valor de tipo int. 4. Lnea 7: La suma de un valor int con otro de tipo oat da como resultado un valor de tipo oat. Python transforma el valor entero en un valor de tipo oat antes de hacer la suma. El valor que se devuelve es de tipo oat.

2.3.1.

Convertir enteros en otantes y viceversa

Como acabas de ver, algunos operadores (como la suma) convierten los nmeu ros enteros en otantes si es necesario. Tambin puedes convertirlos t mismo. e u
1 2 3 4 5 6 7 8 9 10 11 12 >>> f l o a t ( 2 ) 2.0 >>> i n t ( 2 . 0 ) 2 >>> i n t ( 2 . 5 ) 2 >>> i n t ( 2.5) 2 >>> 1 . 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1.1234567890123457 >>> type ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) <c l a s s i n t >

1. Lnea 1: Utilizando la funcin oat() puedes convertir expl o citamente un valor de tipo int en oat. 52

2. Lnea 3: Como era de prever, la conversin inversa se hace utilizando la funcin o o int(). 3. Lnea 5: La funcin int() trunca el valor otante, no lo redondea. o 4. Lnea 7: La funcin int() trunca los valores negativos hacia el 0. Es una ver o dadera funcin de truncado, no es una funcin de suelo5 . o o 5. Lnea 9: En Python, la precisin de los nmeros de punto otante alcanza 15 o u posiciones decimales. 6. Lnea 11: En Python, la longitud de los nmeros enteros no est limitada. u a Pueden tener tantos d gitos como se requieran. Python 2 ten dos tipos separados int y long. El tipo int estaba limitaa do por el sistema sys.maxint, siendo diferente segn la plataforma, pero u usualmente era 232 1. Python 3 tiene un unico tipo entero que, en su mayor parte, equivale al tipo long de Python 2. Para conocer ms detalles a consulta PEP 237.

2.3.2.

Operaciones numricas habituales e

Puedes hacer muchos tipos de clculos con nmeros. a u


1 2 3 4 5 6 7 8 9 10 11 12 >>> 5.5 >>> 5 >>> 6 >>> 5.0 >>> 121 >>> 1 11 / 2 11 // 2

11

// 2

1 1 . 0 // 2 11 2 11 % 2

1. Lnea 1: El operador / efecta una divisin en punto otante. El resultado u o siempre es de tipo oat, incluso aunque ambos operadores (dividendo y divisor) sean int.
Nota del traductor: en ingls oor function, que redondea siempre al entero menor, por lo e que el nmero -2.5 ser convertido a -3 en el caso de aplicarle una funcin de suelo u a o
5

53

2. Lnea 3: El operador // efecta una divisin entera algo extraa. Cuando el u o n resultado es positivo, el resultado es int truncado sin decimales (no redondeado). 3. Lnea 5: Cuando el operador // se usa para dividir un nmero negativo el u resultado se redondea hacia abajo al entero ms prximo (en este caso el a o resultado de la divisin ser -5.5, que redondeado es -5). o a 4. Lnea 7: El operador ** signica elevado a la potencia de. 112 es 121. 5. Lnea 9: El operador % devuelve el resto de la divisin entera. 11 dividido o entre 2 es 5 con un resto de 1, por lo que el resultado en este caso es 1. En Python 2, el operador / se usaba para representar a la divisin entera, o aunque mediante una directiva de Python 2, pod hacer que se comas portase como una divisin de punto otante. En Python 3, el operador o / siempre es una divisin de punto otante. Para consultar ms detalles o a puedes mirar PEP 238.

2.3.3.

Fracciones

Python no est limitado a nmeros enteros y de punto otante. Tambin puede a u e aplicar toda esa matemtica que aprendiste en el instituto y que luego rpidamente a a olvidaste.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>> import f r a c t i o n s >>> x = f r a c t i o n s . F r a c t i o n ( 1 , 3 ) >>> x Fraction (1 , 3) >>> x 2 Fraction (2 , 3) >>> f r a c t i o n s . F r a c t i o n ( 6 , 4 ) Fraction (3 , 2) >>> f r a c t i o n s . F r a c t i o n ( 0 , 0 ) Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> F i l e f r a c t i o n s . py , l i n e 9 6 , in new r a i s e Z e r o D i v i s i o n E r r o r ( F r a c t i o n( %s , 0 ) % numerator ) ZeroDivisionError : Fraction (0 , 0)

1. Lnea 1: Para comenzar a utilizar fracciones hay que importar el mdulo frac o tions.

54

2. Lnea 2: Para denir una fraccin crea un objeto Fraction y psale el numerador o a y denominador. 3. Lnea 5: Con las fracciones puedes efectuar los clculos matemticos habitua a a les. Estas operaciones devuelven un objeto Fraction, 2*(1/2)=(2/3). 4. Lnea 7: El objeto Fraction reduce automticamente las fracciones: (6/4) = a (3/2). 5. Lnea 9: Python tiene el buen sentido de no crear una fraccin con el denomi o nador a cero.

2.3.4.

Trigonometr a

Tambin puedes hacer clculos trigonomtricos en Python. e a e


1 2 3 4 5 6 7 >>> import math >>> math . p i 3.1415926535897931 >>> math . s i n ( math . p i / 2 ) 1.0 >>> math . tan ( math . p i / 4 ) 0.99999999999999989

1. Lnea 2: El mdulo math tiene denida una constante que almacena el valor del o nmero , la razn de la circunferencia de un c u o rculo respecto de su dimetro. a 2. Lnea 4: En el mdulo math se encuentran todas las funciones trigonomtricas o e bsicas, incluidas sin(), cos(), tan() y variantes como asin(). a 3. Lnea 6: De todos modos ten en cuenta que Python no tiene precisin innita, o tan(/4) deber devolver 1.0, no 0.99999999999999989. a

2.3.5.

N meros en un contexto booleano u

El valor cero es equivalente a falso y los valores distintos de cero son equivalentes a verdadero. Los nmeros se pueden utilizar en contextos booleanos, como en la sentencia u if. El valor cero es equivalente a falso y los valores distintos de cero son equivalentes a verdadero.

55

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

>>> ... ... ... ... ... >>> s , >>> s , >>> no , >>> s , >>> no , >>> >>> s , >>> no ,

def e s t r u e ( a n y t h i n g ) : i f anything : print ( s , e s t r u e ) else : print ( no , e s f a l s e ) es true (1) es true e s t r u e ( 1) es true es true (0) es f a l s e es true (0.1) es true es true (0.0) es f a l s e import f r a c t i o n s es true ( f r a c t i o n s . Fraction (1 , 2)) es true es true ( f r a c t i o n s . Fraction (0 , 1)) es f a l s e

1. Lnea 1: Sab que puedes denir tus propias funciones en la consola inter as activa de Python? Simplemente pulsa INTRO al nal de cada l nea, y termina pulsando un ultimo INTRO en una l nea en planco para nalizar la denicin o de la funcin. o 2. Lnea 7: En un contexto booleano, como el de la sentencia if, los nmeros u enteros distintos de cero se evalan a True; el nmero cero se evala a False. u u u 3. Lnea 13: Los nmeros en punto otante distintos de cero son True; 0.0 se u evala a False. Ten cuidado con este caso! Al ms m u a nimo fallo de redondeo (que no es imposible, como has visto en el apartado anterior) Python se encontrar comprobando el nmero 0.0000000000001 en lugar del 0 y retornar a u a True. 4. L nea 18: Las fracciones tambin se pueden utilizar en un contexto booleano. e Fraction(0, n) se evala a False para cualquier valor de n. Todas las otras u fracciones se evalan a True. u

56

2.4.

Listas

El tipo de datos List es el ms utilizado en Python. Cuando digo lista, puede a que pienses en un array6 , cuyo tamao he declarado anteriormente a su uso, que n unicamente puede contener elementos del mismo tipo. No pienses eso, las listas son mucho ms guays. a Una lista de Python es como un array de Perl 5. En Perl 5 las variables que almacenan arrays siempre comienzan con el carcter @. En Python a las variables se pueden nombrar como se quiera, ya que Python mantiene el tipo de datos internamente. Una lista de Python es mucho ms que un array de Java (aunque puede a utilizarse como si lo fuese si eso es lo que quieres). Una analog mejor a ser pensar en la clase ArrayList de Java, que puede almacenar un nmero a u arbitrario de objetos y expandir su tamao dinmicamente al aadir n a n nuevos elementos.

2.4.1.

Crear una lista

Crear una lista es fcil: utiliza unos corchetes para para delimitar una lista de a valores separados por coma.
1 2 3 4 5 6 7 8 9 10 11 >>> l i s t a = [ a , b , j m g a g u i l e r a , z , e j e m p l o ] >>> l i s t a [ a , b , jmgaguilera , z , ejemplo ] >>> l i s t a [ 0 ] a >>> l i s t a [ 4 ] ejemplo >>> l i s t a [ 1] ejemplo >>> l i s t a [ 3] jmgaguilera

1. Lneas 1 a 3: Primero denimos una lista de cinco elementos. Observa que mantiene el orden original. No es por casualidad. Una lista es un conjunto ordenado de elementos.
6

matriz de una o ms dimensiones a

57

2. Lnea 4: Se puede acceder a los elementos de la lista como en el caso de los arrays de Java, teniendo en cuenta que el primer elemento se numera como cero. El primer elemento de cualquier lista no vac es lista[0]. a 3. Lnea 6: El ultimo elemento de esta lista de cinco elementos es lista[4], puesto que los elementos se indexan contando desde cero. 4. Lnea 8: Si se usan ndices con valor negativo se accede a los elementos de la lista contando desde el nal. El ultimo elemento de una lista siempre se puede indexar utilizando lista[-1]. 5. Lnea 10: Si los nmeros negativos en los u ndices te resultan confusos, puedes pensar de esta forma: lista[-n] == lista[len(lista)-n]. Por eso, en esta lista, lista[3] == lista[5 - 3] == lista[2].

2.4.2.

Particin de listas o

lista[0] es el primer elemento de la lista. Una vez has denido una lista, puedes obtener cualquier parte de ella como una nueva lista. A esto se le llama particionado 7 de la lista.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>> [ a >>> [ b >>> [ b >>> [ a >>> [ a >>> [ z >>> [ a lista , b , jmgaguilera , z , ejemplo ] lista [1:3] , jmgaguilera ] l i s t a [1: 1] , jmgaguilera , z ] lista [0:3] , b , jmgaguilera ] lista [:3] , b , jmgaguilera ] lista [3:] , ejemplo ] lista [:] , b , jmgaguilera , z , ejemplo ]

1. Lnea 3: Puedes obtener una parte de una lista especicando dos ndices. El valor de retorno es una nueva lista que contiene los elementos de la lista original, en orden, comenzando en el elemento que estaba en la posicin del o primer ndice (en este caso lista[1]), hasta el elemento anterior al indicado por el segundo ndice (en este caso lista[3]).
7

En ingls: slicing. e

58

2. Lnea 5: El particionado de listas tambin funciona si uno o ambos e ndices son negativos. Si te sirve de ayuda puedes imaginrtelo as leyendo la lista de a : izquierda a derecha, el primer ndice siempre especica el primer elemento que quieres obtener y el segundo ndice el primer elemento que no quieres obtener. El valor de retorno es una lista con todos los elementos que estn entre ambos a ndices. 3. Lnea 7: Los ndices de las listas comienzan a contar en cero, por eso un particionado de lista[0:3] devuelve los primeros tres elementos de la lista, comenzando en lista[0], pero sin incluir lista[3]. 4. Lnea 9: Si el primer ndice es cero, puedes omitirlo. Python lo deducir. Por a eso lista[:3] es lo mismo que lista[0:3]. 5. Lnea 11: De igual forma, si el segundo ndice es la longitud de la cadena, puedes omitirlo. Por eso, en este caso, lista[3:] es lo mismo que lista[3:5], al tener esta lista cinco elementos. Existe una elegante simetr aqu En esta a . lista de cinco elementos lista[:3] devuelve los 3 primeros elementos y lista[3:] devuelve una lista con los restantes. De hecho, lista[:n] siempre retornar los n a primeros elementos y lista[n:] los restantes, sea cual sea el tamao de la lista. n 6. Lnea 13: Si se omiten ambos ndices, se obtiene una nueva lista con todos los elementos de la lista original. Es una forma rpida de hacer una copia de una a lista.

2.4.3.

A adir elementos a una lista n

Existen cuatro maneras de aadir elementos a una lista. n


1 2 3 4 5 6 7 8 9 10 11 12 13 >>> l i s t a = [ a ] >>> l i s t a = l i s t a + [ 2 . 0 , 3 ] >>> l i s t a [ a , 2.0 , 3] >>> l i s t a . append ( True ) >>> l i s t a [ a , 2 . 0 , 3 , True ] >>> l i s t a . extend ( [ c u a t r o , omega ] ) >>> l i s t a [ a , 2 . 0 , 3 , True , c u a t r o , omega ] >>> l i s t a . i n s e r t ( 0 , omega ) >>> l i s t a [ omega , a , 2 . 0 , 3 , True , c u a t r o , omega ]

1. Lnea 2: El operador + crea una nueva lista a partir de la concatenacin de o otras dos. Una lista puede contener cualquier nmero de elementos, no hay u 59

l mite de tamao (salvo el que imponga la memoria disponible). Si embargo, n si la memoria es importante, debes tener en cuenta que la concatenacin de o listas crea una tercera lista en memoria. En este caso, la nueva lista se asigna inmediatamente a la variable lista. Por eso, esta l nea de cdigo se efecta en o u dos pasos concatenacin y luego asignacin que puede (temporalmente) o o consumir mucha memoria cuando las listas son largas. 2. Lnea 3: Una lista puede contener elementos de cualquier tipo, y cada elemento puede ser de un tipo diferente. Aqu tenemos una lista que contiene una cadena de texto, un nmero en punto otante y un nmero entero. u u 3. Lnea 5: El mtodo append() aade un nuevo elemento, unico, al nal de la e n lista (Ahora ya tenemos cuatro tipos de dato diferentes en la lista!). 4. Lnea 8: Las listas son clases. Crear una lista realmente consiste en instanciar una clase. Por eso las listas tienen mtodos que sirven para operar con ellas. e El mtodo extend() toma un parmetro, una lista, y aade cada uno de sus e a n elementos a la lista original. 5. L nea 11: El mtodo insert() inserta un unico elemento a la lista original. El e primer parmetro es el a ndice del primer elemento de la lista original que se desplazar de su posicin para aadir los nuevos. Los elementos no tienen que a o n ser unicos; por ejemplo, ahora hay dos elementos separados en la lista cuyo valor es omega: el primer elemento lista[0] y el ultimo elemento lista[6]. La llamada al mtodo lista.insert(0,valor) es equivalente a la funcin unse o hift() de Perl. Aade un elemento al comienzo de la lista, y los restantes n elementos se desplazan para hacer sitio. Vamos a ver ms de cerca la diferencia entre append() y extend(). a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >>> l i s t a = [ a , b >>> l i s t a . extend ( [ d >>> l i s t a [ a , b , c , d , >>> l e n ( l i s t a ) 6 >>> l i s t a [ 1] f >>> l i s t a . append ( [ g >>> l i s t a [ a , b , c , d , >>> l e n ( l i s t a ) 7 >>> l i s t a [ 1] [ g , h , i ] , c ] , e , f ]) e , f ]

, h , i ] ) e , f , [ g , h , i ] ]

60

1. Lnea 2: El mtodo extend() recibe un unico parmetro, que siempre es una e a lista, y aade cada uno de sus elementos al nal de la lista original lista. n 2. Lnea 5: Si una lista de tres elementos se extiende con una lista de otros tres elementos, la lista resultante tiene seis elementos. 3. Lnea 9: Por otra parte, el mtodo append() recibe un unico parmetro, que e a puede ser de cualquier tipo. En este caso estamos ejecutando el mtodo pasndoe a le una lista de tres elementos. 4. Lnea 12: Si partes de una lista de seis elementos y aades otra lista a ella, n nalizas con una lista de... siete elementos. Porqu siete? Porque el ultimo e elemento (que acabas de aadir) es en s mismo una lista. Una lista puede n contener datos de cualquier tipo, inclu das otras listas. Puede que sea lo que quieras o puede que no. Pero es lo que le has pedido a Python al ejecutar append() con una lista como parmetro. a

2.4.4.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

B squeda de valores en una lista u

>>> l i s t a = [ a , b , nuevo , mpilgrim , nuevo ] >>> l i s t a . count ( nuevo ) 2 >>> nuevo in l i s t a True >>> c in l i s t a False >>> l i s t a . i n d e x ( mpilgrim ) 3 >>> l i s t a . i n d e x ( nuevo ) 2 >>> l i s t a . i n d e x ( c ) Traceback ( i n n e r m o s t l a s t ) : F i l e < i n t e r a c t i v e input > , l i n e 1 , in ? V a l u e E r r o r : l i s t . i n d e x ( x ) : x not in l i s t

1. Lnea 2: Como te puedes imaginar, el mtodo count() devuelve el nmero de e u veces que aparece un valor espec co el parmetro en la lista. a 2. Lnea 4: Si lo unico que quieres saber es si un valor se encuentra o no en la lista, el operador in es ligeramente ms rpido que el mtodo count(). El operador a a e in devuelve True o False, no indica en qu lugar de la lista se encuentra el e elemento, ni el nmero de veces que aparece. u

61

3. Lnea 8: Si necesitas conocer el lugar exacto en el que se encuentra un valor dentro de la lista debes utilizar el mtodo index(). Por defecto, este mtodo e e buscar en toda la lista, aunque es posible especicar un segundo parmetro a a para indicar el lugar de comienzo (0 es el primer ndice), e incluso, un tercer elemento para indicar el ndice en el que parar la bsqueda. u 4. Lnea 10: El mtodo index() encuentra la primera ocurrencia del valor en la e lista. En este caso el valor nuevo aparece dos veces, en la posicin 2 y en la o 4, el mtodo devuelve la posicin de la primera ocurrencia: 2. e o 5. Lnea 12: Puede que no esperases, pero el mtodo index() eleva una excepcin e o ValueError cuando no es capaz de encontrar el elemento en la lista. Espera un momento! Qu signica eso? Pues lo que he dicho: el mtodo e e index() eleva una excepcin si no es capaz de encontrar el valor en la lista. Esto o es diferente de la mayor de los lenguajes de programacin que suelen devolver a o algn u ndice no vlido, como por ejemplo, -1. Aunque al principio te pueda parecer a algo desconcertante, creo que con el tiempo llegars a apreciarlo. Signica que tu a programa fallar en la fuente del problema, en lugar de fallar ms tarde en algn otro a a u lugar por no haber contemplado la posibilidad de que un elemento no se encontrara en la lista. Recuerda que -1 es un valor de ndice vlido. Si el mtodo index() devolviera a e -1... las sesiones de depuracin ser bastante complicadas! o an

2.4.5.

Eliminar elementos de una lista

Las listas nunca tienen huecos Las listas se expanden y contraen de forma automtica. Ya has visto como a expandirlas. Existen varios modos de eliminar elementos de una lista.
1 2 3 4 5 6 7 8 >>> l i s t a = [ a , b , nuevo , mpilgrim , nuevo ] >>> l i s t a [ 1 ] b >>> del l i s t a [ 1 ] >>> l i s t a [ a , nuevo , mpilgrim , nuevo ] >>> l i s t a [ 1 ] nuevo

1. Lnea 4: Para eliminar un elemento de una lista puedes utilizar la sentencia del.

62

2. Lnea 7: Si intentas acceder al elemento en la posicin 1 despus de borrar o e el ndice 1 no da error. Despus de borrar un elemento, todos los elementos e que iban detrs de l se desplazan a la izquierda para rellenar el vac que a e o dej el elemento eliminado. o Y si no conoces la posicin del elemento? No hay problema, en vez de la o posicin, puedes utilizar el valor del elemento para eliminarlo. o
1 2 3 4 5 6 7 8 9 10 >>> l i s t a . remove ( nuevo ) >>> l i s t a [ a , mpilgrim , nuevo ] >>> l i s t a . remove ( nuevo ) >>> l i s t a [ a , mpilgrim ] >>> l i s t a . remove ( nuevo ) Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> V a l u e E r r o r : l i s t . remove ( x ) : x not in l i s t

1. Lnea 1: Puedes eliminar un elemento de una lista utilizando el mtodo re e move(). Este mtodo recibe como parmetro un valor y elimina la primera e a ocurrencia de ese valor en la lista. Como antes, todos los elementos a la derecha del eliminado, se desplazan a la izquierda para rellenar el vac puesto o, que las listas nunca tienen huecos. 2. Lnea 4: Puedes llamar al mtodo remove() tantas veces como sea necesario. e Pero si se intenta eliminar un valor que no se encuentre en la lista, el mtodo e elevar una excepcin ValueError. a o

2.4.6.

Eliminar elementos de una lista: ronda extra

Otro mtodo de inters que tiene las listas es pop(), que permite eliminar e e elementos de una lista de un modo especial.

63

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

>>> l i s t a = [ a , b , nuevo , mpilgrim ] >>> l i s t a . pop ( ) mpilgrim >>> l i s t a [ a , b , nuevo ] >>> l i s t a . pop ( 1 ) b >>> l i s t a [ a , nuevo ] >>> l i s t a . pop ( ) nuevo >>> l i s t a . pop ( ) a >>> l i s t a . pop ( ) Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> I n d e x E r r o r : pop from empty l i s t

1. Lnea 2: Cuando se llama sin parmetros, el mtodo pop() elimina el ultimo a e valor de la lista y devuelve el valor eliminado. 2. Lnea 6: Es posible extraer cualquier elemento de una lista. Para ello hay que pasar el ndice deseado al mtodo pop(). Se eliminar el elemento indicado, los e a siguientes se movern a la izquierda rellenar el vac y se devuelve el valor a o recin eliminado. e 3. Lnea 14: Si llamas al mtodo pop() con una lista vac se eleva una excepcin. e a o El mtodo pop() sin argumentos se comporta igual que la funcin pop() e o de Perl. Elimina el ultimo valor de la lista y lo devuelve. Perl dispone de otra funcin, shift(), que eliminar el primer elemento y devuelve su o valor; en Python es equivalente a lista.pop(0).

2.4.7.

Listas en contextos booleanos

Las listas vac equivalen a falso, todas las dems a verdadero. as a Puedes utilizar las listas en contextos booleanos, como en la sentencia if.

64

1 2 3 4 5 6 7 8 9 10 11 12

>>> ... ... ... ... ... >>> no , >>> s , >>> s ,

def e s t r u e ( a n y t h i n g ) : i f anything : print ( s , e s t r u e ) else : print ( no , e s f a l s e ) es es es es es es true ( [ ] ) false true ([ a ]) true true ( [ False ] ) true

1. Lnea 7: En un contexto booleano una lista vac vale False. a 2. Lnea 9: Cualquier lista con al menos un elemento vale True. 3. Lnea 11: Cualquier lista con al menos un elemento vale True. El valor de los elementos de la lista es irrelevante.

2.5.

Tuplas

Una tupla es una lista inmutable. Una tupla no se puede modicar despus de e haberla creado.
1 2 3 4 5 6 7 8 9 >>> t u p l a = ( a , b , mpilgrim , z , e j e m p l o ) >>> t u p l a ( a , b , mpilgrim , z , e j e m p l o ) >>> t u p l a [ 0 ] a >>> t u p l a [ 1] ejemplo >>> t u p l a [ 1 : 3 ] ( b , mpilgrim )

1. Lnea 1: Las tuplas se denen de la misma forma que las listas. La unica diferencia es que los elementos se cierran entre parntesis en lugar de corchetes. e 2. Lnea 4: Los elementos de una tupla estn ordenados como los de una lista. a Los ndices tambin comienzan a contar en cero, por lo que el primer elemento e de una tupla siempre es tupla[0]. 3. Lnea 6: Los ndices negativos cuentan desde el nal de la tupla como en las listas. 65

4. Lnea 8: El particionado tambin funciona como en las listas. Una particin e o de una tupla es una nueva tupla con los elementos seleccionados. Lo que diferencia a las tuplas de las listas es que las primeras no se pueden modicar. En trminos tcnicos se dice que son inmutables. En trminos prcticos e e e a esto signica que no tienen mtodos que te permitan modicarlas. Las listas tienen e mtodos como append(), extend(), insert(), remove() y pop(). Las tuplas no tienen e ninguno de estos mtodos. Puedes particionar una tupla porque en realidad se crea e una nueva tupla, y puedes consultar si contienen un valor determinado, y... eso es todo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # c o n t i n u a c i n d e l e j e m p l o a n t e r i o r o >>> t u p l a ( a , b , mpilgrim , z , e j e m p l o ) >>> t u p l a . append ( nuevo ) Traceback ( i n n e r m o s t l a s t ) : F i l e < i n t e r a c t i v e input > , l i n e 1 , in ? A t t r i b u t e E r r o r : t u p l a o b j e c t has no a t t r i b u t e append >>> t u p l a . remove ( z ) Traceback ( i n n e r m o s t l a s t ) : F i l e < i n t e r a c t i v e input > , l i n e 1 , in ? A t t r i b u t e E r r o r : t u p l a o b j e c t has no a t t r i b u t e remove >>> t u p l a . i n d e x ( e j e m p l o ) 4 >>> z in t u p l a True

1. Lnea 4: No puedes aadir elementos a una tupla. No existen los mtodos n e append() o extend(). 2. Lnea 8: No puedes eliminar elementos de una tupla. No existen los mtodos e remove() o pop(). 3. Lnea 12: S puedes buscar elementos en una tupla puesto que consultar no cambia la tupla. 4. Lnea 14: Tambin puedes utilizar el operador in para chequear si existe un e elemento en la tupla. Para qu valen las tuplas? e Las tuplas son ms rpidas que las listas. Si lo que denes es un conjunto a a esttico de valores y todo lo que vas a hacer es iterar a travs de ellos, lo mejor a e es que uses una tupla en lugar de una lista. 66

Es ms seguro, puesto que proteges contra escritura los datos que no necesitas a modicar. Algunas tuplas se pueden utilizar como claves de diccionarios como veremos ms adelante en el cap a tulo. Las listas nunca se pueden utilizar como claves de diccionarios. Las tuplas se pueden convertir en listas y viceversa. La funcin interna o tuple() puede recibir como parmetro una lista y devuelve una tupla con a los mismos elementos que tenga la lista, y la funcin list() toma como o parmetro una tupla y retorna una lista. En la prctica la funcin tuple() a a o congela una lista, y la funcin list() descongela una tupla. o

2.5.1.

Tuplas en un contexto booleano

Las tuplas tambin se pueden utilizar en un contexto booleano: e


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> def e s t r u e ( a n y t h i n g ) : ... i f anything : ... print ( s , e s t r u e ) ... else : ... print ( no , e s f a l s e ) ... >>> e s t r u e ( ( ) ) no , e s f a l s e >>> e s t r u e ( ( a , b ) ) s , e s t r u e >>> e s t r u e ( ( F a l s e , ) ) s , e s t r u e >>> type ( ( F a l s e ) ) <c l a s s b o o l > >>> type ( ( F a l s e , ) ) <c l a s s t u p l e >

1. Lnea 7: Una tupla vac siempre vale false en un contexto booleano. a 2. Lnea 9: Una tupla con al menos un valor vale true. 3. Lnea 11: Una tupla con al menos un valor vale true. El valor de los elementos es irrelevante. Pero qu hace esa coma ah e ? 4. Lnea 13: Para crear una tupla con un unico elemento, necesitas poner una coma despus del valor. Sin la coma Python asume que lo que ests haciendo e a es poner un par de parntesis a una expresin, por lo que no se crea una tupla. e o 67

2.5.2.

Asignar varios valores a la vez

A continuacin se observa una forma muy interesante de programar mltiples o u asignaciones en Python. Para ello utilizamos las tuplas:
1 2 3 4 5 6 7 8 >>> v = ( a , 2 , True ) >>> ( x , y , z ) = v >>> x a >>> y 2 >>> z True

1. Lnea 2: v es una tupla con tres elementos y (x, y, z) es una tupla con tres variables. Al asignar una tupla a la otra, lo que sucede es que cada una de las variables recoge el valor del elemento de la otra tupla que corresponde con su posicin. o Esto tiene toda clase de usos. Supn que quieres asignar nombres a un rango de o valores, puedes combinar la funcin range() con la asignacin mltiple para hacerlo o o u de una forma rpida: a
1 2 3 4 5 6 7 8 >>> ... >>> 0 >>> 1 >>> 6 (LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO) = r a n g e ( 7 ) LUNES MARTES DOMINGO

1. Lnea 1: La funcin interna range() genera una secuencia de nmeros enteros8 . o u Las variables que vas a denir son LUNES, MARTES, etc)9 . El mdulo calendar o dene unas constantes enteras para cada d de la semana). a 2. Lnea 3: Ahora cada variable tiene un valor: LUNES vale 0, MARTES vale 1, etc. Tambin puedes utilizar la asignacin mltiple para construir funciones que e o u devuelvan varios valores a la vez. Simplemente devolviendo una tupla con los valores.
Tcnicamente construye un iterador, no una lista o tupla. Lo veremos ms adelante. e a Este ejemplo procede del mdulo calendar, que es un pequeo mdulo que imprime un caleno n o dario, como el programa de UNIX cal
9 8

68

Desde el cdigo que llama a la funcin se puede tratar el valor de retorno como una o o tupla o se puede asignar los valores individuales a unas variables. Muchas librer as estndares de Python hacen esto, incluido el mdulo os, que utilizaremos en el a o siguiente cap tulo.

2.6.

Conjuntos

Un conjunto es una bolsa sin ordenar de valores unicos. Un conjunto puede contener simultneamente valores de cualquier tipo de datos. Con dos conjuntos a se pueden efectuar las t picas operaciones de unin, interseccin y diferencia de o o conjuntos.

2.6.1.

Creacin de conjuntos o

Comencemos por el principio, crear un conjunto es fcil. a


1 2 3 4 5 6 7 8 >>> u n c o n j u n t o = {1} >>> u n c o n j u n t o {1} >>> type ( u n c o n j u n t o ) <c l a s s s e t > >>> u n c o n j u n t o = { 1 , 2} >>> u n c o n j u n t o { 1 , 2}

1. Lnea 1: Para crear un conjunto con un valor basta con poner el valor entre llaves (). 2. Lnea 4: Los conjuntos son clases, pero no te preocupes por ahora de esto. 3. Lnea 6: Para crear un conjunto con varios elementos basta con separarlos con comas y encerrarlos entre llaves. Tambin es posible crear un conjunto a partir de una lista: e
1 2 3 4 5 6 >>> u n a l i s t a = [ a , b , mpilgrim , True , F a l s e , 4 2 ] >>> u n c o n j u n t o = s e t ( u n a l i s t a ) >>> u n c o n j u n t o { a , F a l s e , b , True , mpilgrim , 42} >>> u n a l i s t a [ a , b , mpilgrim , True , F a l s e , 4 2 ]

69

1. Lnea 2: Para crear un conjunto de una lista utiliza la funcin set()10 . o 2. Lnea 3: Como coment anteriormente, un conjunto puede contener valores de e cualquier tipo y est desordenado. En este ejemplo, el conjunto no recuerda a el orden en el que estaba la lista que sirvi para crearlo. Si aadieras algn o n u elemento nuevo no recordar el orden en el que lo aadiste. a n 3. Lnea 5: La lista original no se ha modicado. Tienes un conjunto vac Sin problemas. Puedes crearlo y ms tarde aadir o? a n elementos.
1 2 3 4 5 6 7 8 9 10 >>> u n c o n j u n t o = s e t ( ) >>> u n c o n j u n t o set () >>> type ( u n c o n j u n t o ) <c l a s s s e t > >>> l e n ( u n c o n j u n t o ) 0 >>> n o s e g u r o = {} >>> type ( n o s e g u r o ) <c l a s s d i c t >

1. Lnea 1: Para crear un conjunto vac debes utilizar la funcin set() sin parme o o a tros. 2. Lnea 2: La representacin impresa de un conjunto vac parece algo extraa. o o n Tal vez estabas esperando {}? Esa expresin se utiliza para representar un o diccionario vac no un conjunto vac Aprenders a usar los diccionarios ms o, o. a a adelante en este cap tulo. 3. Lnea 4: A pesar de la extraa representacin impresa se trata de un conjunto. n o 4. Lnea 6: ...y este conjunto no tiene elementos. 5. Lnea 8: Debido a razones histricas procedentes de Python 2. No puedes o utilizar las llaves para crear un conjunto vac puesto que lo que se crea es un o, diccionario vac no un conjunto vac o, o.
Aquellos que conocen cmo estn implementados los conjuntos apuntarn que realmente no se o a a trata de una llamada a una funcin, sino de la instanciacin de una clase. Te prometo que en este o o libro aprenders la diferencia. Pero por ahora basta con que sepas que set() se comporta como una a funcin que devuelve como resultado un conjunto. o
10

70

2.6.2.

Modicacin de conjuntos o

Hay dos maneras de aadir valores a un conjunto: el mtodo add() y el mtodo n e e update().
1 2 3 4 5 6 7 8 9 10 11 >>> >>> >>> {1 , >>> 3 >>> >>> {1 , >>> 3 u n c o n j u n t o = { 1 , 2} u n c o n j u n t o . add ( 4 ) un conjunto 2 , 4} len ( un conjunto ) u n c o n j u n t o . add ( 1 ) un conjunto 2 , 4} len ( un conjunto )

1. Lnea 2: El mtodo add() recibe un parmetro, que puede ser de cualquier e a tipo, cuyo resultado es aadir el parmetro al conjunto. n a 2. Lnea 5: Este conjunto tiene ahora cuatro elementos. 3. Lnea 7: Los conjuntos son bolsas de valores unicos. Por eso, si intentas aadir un valor que ya exista en el conjunto no har nada. Tampoco elevar un n a a error. Simplemente no se hace nada. 4. Lnea 10: Por eso, el conjunto an tiene tres elementos. u
1 2 3 4 5 6 7 8 9 10 11 12 >>> >>> {1 , >>> >>> {1 , >>> >>> {1 , >>> >>> {1 , un un 2, un un 2, un un 2, un un 2, c o n j u n t o = { 1 , 2 , 3} conjunto 3} c o n j u n t o . update ( { 2 , 4 , 6 } ) conjunto 3 , 4 , 6} c o n j u n t o . update ( { 3 , 6 , 9 } , { 1 , 2 , 3 , 5 , 8 , 1 3 } ) conjunto 3 , 4 , 5 , 6 , 8 , 9 , 13} c o n j u n t o . update ( [ 1 0 , 2 0 , 3 0 ] ) conjunto 3 , 4 , 5 , 6 , 8 , 9 , 1 0 , 1 3 , 2 0 , 30}

1. Lnea 4: El mtodo update() toma un parmetro, un conjunto, y aade todos e a n sus elementos al conjunto original. Funciona como si llamaras al mtodo add() e con cada uno de los elementos del conjunto que pasas como parmetro. a 71

2. Lnea 5: Los elementos duplicados se ignoran puesto que los conjuntos no pueden contener duplicados. 3. Lnea 7: Puedes llamar al mtodo update() con cualquier nmero de parme e u a tros. Cuando lo llamas con dos conjuntos, el mtodo aade todos los elementos e n de cada conjunto al conjunto original (sin incluir duplicados). 4. Lnea 10: El mtodo update() puede recibir como parmetro elementos de e a diferentes tipos de dato, incluidas las listas. Cuando se llama pasndole una a lista, el mtodo update() aade todos los elementos de la lista al conjunto e n original.

2.6.3.

Eliminar elementos de un conjunto

Existen tres formas de eliminar elementos individuales de un conjunto: Las dos primeras discard() y remove(), se diferencian de forma sutil:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> u n c o n j u n t o = { 1 , 3 , 6 , 1 0 , 1 5 , 2 1 , 2 8 , 3 6 , 45} >>> u n c o n j u n t o { 1 , 3 , 3 6 , 6 , 1 0 , 4 5 , 1 5 , 2 1 , 28} >>> u n c o n j u n t o . d i s c a r d ( 1 0 ) >>> u n c o n j u n t o { 1 , 3 , 3 6 , 6 , 4 5 , 1 5 , 2 1 , 28} >>> u n c o n j u n t o . d i s c a r d ( 1 0 ) >>> u n c o n j u n t o { 1 , 3 , 3 6 , 6 , 4 5 , 1 5 , 2 1 , 28} >>> u n c o n j u n t o . remove ( 2 1 ) >>> u n c o n j u n t o { 1 , 3 , 3 6 , 6 , 4 5 , 1 5 , 28} >>> u n c o n j u n t o . remove ( 2 1 ) Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> KeyError : 21

1. Lnea 4: El mtodo discard() toma un unico parmetro y elminia el elemento e a del conjunto. 2. Lnea 7: Si llamas al mtodo discard() con un valor que no exista en el conjunto e no se produce ningn error. Simplemente no se hace nada. u 3. Lnea 10: El mtodo remove() tambin recibe un unico parmetro y tambin e e a e elimina el elemento del conjunto. 4. Lnea 13: Aqu esta la diferencia: si el valor no existe en el conjunto, el mtodo e remove() eleva la excepcin KeyError. o 72

Como pasa con las listas, los conjuntos tambin tienen el mtodo pop(): e e
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> u n c o n j u n t o = { 1 , 3 , 6 , 1 0 , 1 5 , 2 1 , 2 8 , 3 6 , 45} >>> u n c o n j u n t o . pop ( ) 1 >>> u n c o n j u n t o . pop ( ) 3 >>> u n c o n j u n t o . pop ( ) 36 >>> u n c o n j u n t o { 6 , 1 0 , 4 5 , 1 5 , 2 1 , 28} >>> u n c o n j u n t o . c l e a r ( ) >>> u n c o n j u n t o set () >>> u n c o n j u n t o . pop ( ) Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> KeyError : pop from an empty s e t

1. Lnea 2: El mtodo pop() elimina un unico valor del conjunto y retorna el e valor. Sin embargo, como los conjuntos no estn ordenados, no hay un ltimo a u elemento, por lo que no hay forma de controlar qu elemento es el que se extrae. e Es aleatorio. 2. Lnea 10: El mtodo clear() elimina todos los valores del conjunto dejndolo e a vac Es equivalente a un conjunto = set(), que crear un nuevo conjunto o. a vac y lo asignar a la variable, eliminando el conjunto anterior. o a 3. Lnea 13: Si se intenta extraer un valor de un conjunto vac se eleva la ex o cepcin KeyError. o

2.6.4.

Operaciones t picas de conjuntos

Los conjuntos de Python permiten las operaciones habituales de este tipo de datos:

73

1 2 3 4 5 6 7 8 9 10 11 12 13 14

>>> u n c o n j u n t o = { 2 , 4 , 5 , 9 , 1 2 , 2 1 , 3 0 , 5 1 , 7 6 , 1 2 7 , 195} >>> 30 in u n c o n j u n t o True >>> 31 in u n c o n j u n t o False >>> o t r o c o n j u n t o = { 1 , 2 , 3 , 5 , 6 , 8 , 9 , 1 2 , 1 5 , 1 7 , 1 8 , 21} >>> u n c o n j u n t o . union ( o t r o c o n j u n t o ) { 1 , 2 , 1 9 5 , 4 , 5 , 6 , 8 , 1 2 , 7 6 , 1 5 , 1 7 , 1 8 , 3 , 2 1 , 3 0 , 5 1 , 9 , 127} >>> u n c o n j u n t o . i n t e r s e c t i o n ( o t r o c o n j u n t o ) { 9 , 2 , 1 2 , 5 , 21} >>> u n c o n j u n t o . d i f f e r e n c e ( o t r o c o n j u n t o ) { 1 9 5 , 4 , 7 6 , 5 1 , 3 0 , 127} >>> u n c o n j u n t o . s y m m e t r i c d i f f e r e n c e ( o t r o c o n j u n t o ) { 1 , 3 , 4 , 6 , 8 , 7 6 , 1 5 , 1 7 , 1 8 , 1 9 5 , 1 2 7 , 3 0 , 51}

1. Lnea 2: Para comprobar si un valor est contenido en un conjunto se puede a utilizar el operador in. Funciona igual que en las listas. 2. Lnea 7: El mtodo union() retorna un nuevo conjunto que contiene todos los e elementos que estn en alguno de los conjuntos originales. a 3. Lnea 9: El mtodo intersection() retorna un nuevo conjunto con los elementos e que estn en ambos conjuntos originales. a 4. L nea 11: El mtodo dierence() retorna un nuevo conjunto que contiene los e elementos que estn en un conjunto pero no en otro conjunto. a 5. Lnea 13: El mtodo symmetric dierence() retorna un nuevo conjunto que e contiene todos los elementos que estn unicamente en uno de los conjuntos a originales. Tres de estos mtodos son simtricos: e e
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # c o n t i n u a c i n d e l e j e m p l o a n t e r i o r o >>> o t r o c o n j u n t o . s y m m e t r i c d i f f e r e n c e ( u n c o n j u n t o ) { 3 , 1 , 1 9 5 , 4 , 6 , 8 , 7 6 , 1 5 , 1 7 , 1 8 , 5 1 , 3 0 , 127} >>> o t r o c o n j u n t o . s y m m e t r i c d i f f e r e n c e ( u n c o n j u n t o ) == \ . . . un conjunto . symmetric difference ( otro conjunto ) True >>> o t r o c o n j u n t o . union ( u n c o n j u n t o ) == \ . . . u n c o n j u n t o . union ( o t r o c o n j u n t o ) True >>> o t r o c o n j u n t o . i n t e r s e c t i o n ( u n c o n j u n t o ) == \ . . . un conjunto . i n t e r s e c t i o n ( otro conjunto ) True >>> o t r o c o n j u n t o . d i f f e r e n c e ( u n c o n j u n t o ) == \ . . . un conjunto . d i f f e r e n c e ( otro conjunto ) False

74

1. Lnea 2: Aunque el resultado de la diferencia simtrica de un conjunto y e otro conjunto parezca diferente de la diferencia simtrica de otro conjunto y e a un conjunto, recuerda que los conjuntos estn desordenados. Dos conjuntos con los mismos valores se consideran iguales. 2. Lnea 4: Y eso es lo que sucede aqu No te despistes por la representacin . o impresa de los conjuntos. Como contienen los mismos valores, son iguales. 3. Lnea 7: La unin de dos conjuntos tambin es simtrica. o e e 4. Lnea 10: La interseccin de dos conjuntos tambin es simtrica. o e e 5. Lnea 13: La diferencia de dos conjuntos no es simtrica, lo que tiene sentido, e es anlogo a la resta de dos nmeros; importa el orden de los operandos. a u Finalmente veamos algunas consultas que se pueden hacer a los conjuntos:
1 2 3 4 5 6 7 8 9 10 11 >>> u n c o n j u n t o = { 1 , 2 , 3} >>> o t r o c o n j u n t o = { 1 , 2 , 3 , 4} >>> u n c o n j u n t o . i s s u b s e t ( o t r o c o n j u n t o ) True >>> o t r o c o n j u n t o . i s s u p e r s e t ( u n c o n j u n t o ) True >>> u n c o n j u n t o . add ( 5 ) >>> u n c o n j u n t o . i s s u b s e t ( o t r o c o n j u n t o ) False >>> o t r o c o n j u n t o . i s s u p e r s e t ( u n c o n j u n t o ) False

1. Lnea 3: un conjunto es un subconjunto de otro conjunto Todos los miembros de un conjunto forman parte de otro conjunto. 2. Lnea 5: Pregunta lo mismo pero al revs. otro conjunto es un supercon e junto de un conjunto Todos los miembros de un conjunto forman parte de otro conjunto. 3. Lnea 7: Tan pronto como aadas un valor a un conjunto que no se encuentre n en otro conjunto ambas consultas devuelven False.

2.6.5.

Los conjuntos en contextos booleanos

Puedes utilizar conjuntos en contextos booleanos, como en una sentencia if.

75

1 2 3 4 5 6 7 8 9 10 11 12

>>> ... ... ... ... ... >>> no , >>> s , >>> s ,

def e s t r u e ( a l g o ) : i f algo : print ( s , e s t r u e ) else : print ( no , e s f a l s e ) es es es es es es true ( set ()) false t r u e ({ a }) true t r u e ({ False }) true

1. Lnea 7: En un contexto booleano los conjuntos vac valen False. os 2. Lnea 9: Cualquier conjunto con al menos un elemento vale True. 3. Lnea 11: Cualquier conjunto con al menos un elemento vale True. El valor de los elementos es irrelevante.

2.7.

Diccionarios

Un diccionario es un conjunto desordenado de parejas clave-valor. Cuando aades una clave a un diccionario, tienes que aadir tambin un valor para esa n n e clave11 . Los diccionarios de Python estn optimizados para recuperar fcilmente el a a 12 valor cuando conoces la clave, no al revs . e Un diccionario de Python, es como un hash de Perl 5. En Perl 5 las variables que almacenan hashes siempre comienzan por el carcter %. a En Python, las variables pueden tener el nombre que se quiera porque el tipo de datos se mantiene internamente.

2.7.1.

Creacin de diccionarios o

Crear diccionarios es sencillo. La sintaxis es similar a la de los conjuntos, pero en lugar de valores, tienes que poner parejas clave-valor. Una vez has creado el diccionario, puedes buscar los valores mediante el uso de su clave.
Ms tarde puedes cambiar el valor asignado a la clave si lo deseas. a Nota del Traductor: en otros lenguajes se habla de arrays asociativos o tablas hash para representar este mismo concepto
12 11

76

1 2 3 4 5 6 7 8 9 10 11

>>> u n d i c = { s e r v i d o r : db . d i v e i n t o p y t h o n 3 . o r g , b a s e d a t o s : mysql } >>> u n d i c { s e r v i d o r : db . d i v e i n t o p y t h o n 3 . o r g , b a s e d a t o s : mysql } >>> u n d i c [ s e r v i d o r ] db . d i v e i n t o p y t h o n 3 . o r g >>> u n d i c [ b a s e d a t o s ] mysql >>> u n d i c [ db . d i v e i n t o p y t h o n 3 . o r g ] Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> KeyError : db . d i v e i n t o p y t h o n 3 . o r g

1. Lnea 1: En el ejemplo creamos primero un diccionario con dos elementos y lo asignamos a la variable un dic. Cada elemento es una pareja clave-valor. El conjunto completo de elementos se encierra entre llaves. 2. Lnea 4: servidor es una clave, y su valor asociado se obtiene mediante la referencia un dic[servidor] cuyo valor es db.diveintopython3.org. 3. Lnea 6: basedatos es una clave y su valor asociado se obtiene mediante la referencia un dic[basedatos] cuyo valor es mysql. 4. Lnea 8: Puedes recuperar los valores mediante la clave, pero no puedes re cuperar las claves mediante el uso de su valor. Por eso un dic[servidor] vale db.diveintopython3.org pero un dic[db.diveintopython3.org] eleva una excepcin de tipo KeyError al no ser una clave del diccionario. o

2.7.2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Modicacin de un diccionario o

>>> u n d i c { s e r v i d o r : db . d i v e i n t o p y t h o n 3 . o r g , b a s e d a t o s : mysql } >>> u n d i c [ b a s e d a t o s ] = b l o g >>> u n d i c { s e r v i d o r : db . d i v e i n t o p y t h o n 3 . o r g , b a s e d a t o s : b l o g } >>> u n d i c [ u s u a r i o ] = mark >>> u n d i c { s e r v i d o r : db . d i v e i n t o p y t h o n 3 . o r g , u s u a r i o : mark , basedatos : blog } >>> u n d i c [ u s u a r i o ] = dora >>> u n d i c { s e r v i d o r : db . d i v e i n t o p y t h o n 3 . o r g , u s u a r i o : dora , basedatos : blog } >>> u n d i c [ U s u a r i o ] = mark >>> u n d i c { U s u a r i o : mark , s e r v i d o r : db . d i v e i n t o p y t h o n 3 . o r g , u s u a r i o : dora , b a s e d a t o s : b l o g }

77

1. Lnea 3: No puedes tener claves duplicadas en un diccionario. Al asignar un valor a una clave existente el valor anterior se pierde. 2. Lnea 6: Puedes aadir nuevas parejas clave-valor en cualquier momento. La n sintaxis es idntica a la que se utiliza para modicar valores. e 3. Lnea 8: El elemento nuevo del diccionario (clave usuario, valor mark) apa rece en la mitad. Esto es una mera coincidencia, los elementos de un diccionario no estn ordenados. a 4. Lnea 10: Al asignar un valor a una clave existente, simplemente se sustituye el valor anterior por el nuevo. 5. Lnea 14: Esta sentencia cambia el valor de la clave usuario para volver le asignar mark? No! Si lo observas atentamente vers que la U est en a a maysculas. Las claves de los diccionarios distinguen las maysculas y minscuu u u las, por eso esta sentencia crea una nueva pareja clave-valor, no sobreescribe la anterior. Puede parecerte casi lo mismo, pero en lo que a Python respecta, es totalmente diferente.

2.7.3.

Diccionarios con valores mixtos

Los diccionarios no se usan unicamente con cadenas de texto. Los valores de un diccionario pueden ser de cualquier tipo, incluidos enteros, booleanos, cualquier objeto o incluso otros diccionarios. Y en un mismo diccionario, no es necesario que todos los valores sean del mismo tipo, puedes mezclarlos segn lo necesites. Los tipos u de datos que pueden ser claves de un diccionario estn ms limitados, pero pueden a a ser cadenas de texto, enteros, y algunos tipos ms. Tambin es factible mezclar a e diferentes tipos de clave en un mismo diccionario. De hecho, ya hemos visto un diccionario con valores diferentes a cadenas de texto.
1 2 SUFIJOS = { 1 0 0 0 : [ KB , MB , GB , TB , PB , EB , ZB , YB ] , 1 0 2 4 : [ KiB , MiB , GiB , TiB , PiB , EiB , ZiB , YiB ] }

Vamos a descomponerlo en la consola interactiva de Python.

78

1 2 3 4 5 6 7 8 9 10 11 12

>>> SUFIJOS = { 1 0 0 0 : [ KB , MB , GB , TB , PB , EB , ZB , YB ] , ... 1 0 2 4 : [ KiB , MiB , GiB , TiB , PiB , EiB , ZiB , YiB ] } >>> l e n ( SUFIJOS ) 2 >>> 1000 in SUFIJOS True >>> SUFIJOS [ 1 0 0 0 ] [ KB , MB , GB , TB , PB , EB , ZB , YB ] >>> SUFIJOS [ 1 0 2 4 ] [ KiB , MiB , GiB , TiB , PiB , EiB , ZiB , YiB ] >>> SUFIJOS [ 1 0 0 0 ] [ 3 ] TB

1. Lnea 3: Como sucede con las listas y conjuntos, la funcin len() devuelve el o nmero de claves que tiene un diccionario. u 2. Lnea 5: Tambin como pasa con las listas y conjuntos puedes utilizar el ope e rador in para comprobar si una clave determinada est en el diccionario. a 3. Lnea 7: 1000 es una clave del diccionario SUFIJOS; su valor es una lista de ocho elementos (ocho cadenas de texto, por ser ms precisos). a 4. Lnea 9: De igual manera, 1024 es una clave del diccionario SUFIJOS; su valor tambin es una lista de ocho elmentos. e 5. Lnea 11: Puesto que SUFIJOS[1000] es una lista, puedes utilizar los corchetes para acceder a los elementos individuales. Recuerda que los ndices en Python comienzan a contar en cero.

2.7.4.

Diccionarios en un contexto booleano

Tambin puedes utilizar un diccionario en un contexto booleano, como en la e sentencia if. Todo diccionario vac equivale a False y todos los dems equivalen a True. o a

79

1 >>> def e s t r u e ( a l g o ) : 2 ... i f algo : 3 ... print ( s , e s t r u e ) 4 ... else : 5 ... print ( no , e s f a l s e ) 6 ... 7 >>> e s t r u e ( { } ) 8 no , e s f a l s e 9 >>> e s t r u e ( { a : 1 } ) 10 s , e s t r u e

1. Lnea 7: En un contexto booleano un diccionario vac equivale a False. o 2. Lnea 9: Cualquier diccionario con, al menos, una pareja clave-valor equivale a True.

2.8.

None

None es una constante especial de Python. Representa al valor nulo. None no es lo mismo que False. None tampoco es 0. None tampoco es la cadena vac Cualquier a. comparacin de None con otra cosa diferente de l mismo se evala al valor False. o e u None es el unico valor nulo. Tiene su propio tipo de dato (NoneType). Puedes asignar None a cualquier variable, pero no puedes crear nuevos objetos del tipo NoneType. Todas las variables cuyo valor es None son iguales entre s .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> type ( None ) <c l a s s NoneType > >>> None == F a l s e False >>> None == 0 False >>> None == False >>> None == None True >>> x = None >>> x == None True >>> y = None >>> x == y True

80

2.8.1.

None en un contexto booleano

En un contexto booleano None vale False y not None vale True.


1 2 >>> def e s t r u e ( a l g o ) : 3 ... i f algo : 4 ... print ( s , e s t r u e ) 5 ... else : 6 ... print ( no , e s f a l s e ) 7 ... 8 >>> e s t r u e ( None ) 9 no , e s f a l s e 10 >>> e s t r u e ( { not None ) 11 s , e s t r u e

2.9.

Lecturas complementarias

Operaciones booleanas Tipos numricos e Tipos secuencia Tipos conjunto Tipos mapa mdulo fractions o mdulo math o PEP 237: Unicacin de enteros largos y enteros o PEP 238: Modicacin del operador de divisin o o

81

82

Cap tulo 3 Comprensiones


Nivel de dicultad:    Nuestra imaginacin est desplegada a ms no poder, no como en la ccin, para o a a o imaginar las cosas que no estn realmente ah a , sino para entender aquellas que s lo estn. a Rychard Feynman

3.1.

Inmersin o

Este cap tulo te explicar las listas por comprensin, diccionarios por coma o prensin y conjuntos por comprensin: tres conceptos centrados alrededor de una o o tcnica muy potente. Pero antes vamos a dar un pequeo paseo alrededor de dos e n mdulos que te van a servir para navegar por tu sistema de cheros. o

3.2.

Trabajar con cheros y directorios

Python 3 posee un mdulo denominado os que es la contraccin de operating o o system1 . El mdulo os contiene un gran nmero de funciones para recuperar o u y en algunos casos, modicar informacin sobre directorios, cheros, procesos o y variables del entorno local. Python hace un gran esfuerzo por ofrecer una API unicada en todos los sistemas operativos que soporta, por lo que tus programas pueden funcionar en casi cualquier ordenador con el m nimo de cdigo espec o co posible.
1

Sistema Operativo.

83

3.2.1.

El directorio de trabajo actual

Cuando te inicias en Python, pasas mucho tiempo en la consola interactiva. A lo largo del libro vers muchos ejemplos que siguen el siguiente patrn: a o 1. Se importa uno de los mdulos de la carpeta de ejemplos. o 2. Se llama a una funcin del mdulo. o o 3. Se explica el resultado. Si no sabes cul es el directorio actual de trabajo, el primer paso probablemente a elevar la excepcin ImportError. Porqu? Porque Python buscar el mdulo en a o e a o el camino de bsqueda actual (ver cap u tulo ??), pero no lo encontrar porque la a carpeta ejemplos no est incluida en l. Para superar este problema hay dos soluciones a e posibles: 1. Aadir el directorio de ejemplos al camino de bsqueda de importacin. n u o 2. Cambiar el directorio de trabajo actual a la carpeta de ejemplos. El directorio de trabajo actual es una propiedad invisible que Python mantiene en memoria. Siempre existe un directorio de trabajo actual: en la consola interactiva de Python; durante la ejecucin de un programa desde la l o nea de comando, o durante la ejecucin de un programa Python como un CGI de algn servidor web. o u El mdulo os contiene dos funciones que te permiten gestionar el directorio de o trabajo actual.
1 2 3 4 5 6 >>> import o s >>> print ( o s . getcwd ( ) ) /home/ j m g a g u i l e r a >>> o s . c h d i r ( /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s ) >>> print ( o s . getcwd ( ) ) /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s

1. Lnea 1: El mdulo os viene instalado con Python. Puedes importarlo siempre o que lo necesites. 2. Lnea 2: Utiliza la funcin os.getcwd() para recuperar el directorio de trabajo o actual. Cuando ejecutas la consola interactiva, Python toma como directorio de trabajo actual aqul en el que te encontrases en el sistema operativo antes e de entrar en la consola; si ejecutas la consola desde una opcin de men del o u 84

sistema operativo, el directorio de trabajo ser aqul en el que se encuentre el a e programa ejecutable de Python o tu directorio de trabajo por defecto2 . 3. Lnea 4: Utiliza la funcin os.chdir() para cambiar de directorio. Conviene o utilizar la convencin de escribir los separadores en el estilo de Linux (con las o barras inclinadas adelantadas) puesto que este sistema es universal y funciona tambin en Windows. Este es uno de los lugares en los que Python intenta e ocultar las diferencias entre sistemas operativos.

3.2.2.

Trabajar con nombres de cheros y directorios

Aprovechando que estamos viendo los directorios, quiero presentarte el mdulo o os.path, que contiene funciones para manipular nombres de cheros y directorios.
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> import o s >>> print ( o s . path . j o i n ( /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / , parahumanos . py ) ) /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / parahumanos . py >>> print ( o s . path . j o i n ( /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s , parahumanos . py ) ) /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / parahumanos . py >>> print ( o s . path . expanduser ( ) ) /home/ j m g a g u i l e r a >>> print ( o s . path . j o i n ( o s . path . expanduser ( ) , i n m e r s i o n e n p y t h o n 3 , examples , humansize . py ) ) /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s \ parahumanos . py

1. Lnea 2: La funcin os.path.join() construye un nombre completo de chero o o directorio (nombre de path) a partir de uno o ms partes. En este caso a unicamente tiene que concatenar las cadenas. 2. Lnea 5: Este caso es menos trivial. La funcin aade una barra inclinada antes o n de concatenar. Dependiendo de que el ejemplo se construya en Windows o en una versin de Linux o Unix, la barra inclinada ser invertida o no. Python o a ser capaz de encontrar el chero o directorio independientemente del sentido a en el que aparezcan las barras inclinadas. En este caso, como el ejemplo lo constru en Linux, la barra inclinada es la t pica de Linux. 3. Lnea 8: La funcin os.path.expanduser() obtendr un camino completo al di o a rectorio que se exprese y que incluye como indicador el directorio ra del z
2

Esto depende del sistema operativo: windows, linux, ...

85

usuario conectado. Esto funcionar en todos los sistemas operativos que tena gan el concepto de directorio ra del usuario, lo que incluye OS X, Linux, z Unix y Windows. El camino que se retorna no lleva la barra inclinada al nal, pero, como hemos visto, a la funcin os.path.join() no le afecta. o 4. Lnea 10: Si combinamos estas tcnicas podemos construir fcilmente caminos e a completos desde el directorio ra del usuario. La funcin os.path.join() puede z o recibir cualquier nmero de parmetros. Yo me alegr mucho al descubrir esto u a e puesto que la funcin anyadirBarra() es una de las t o picas que siempre tengo que escribir cuando aprendo un lenguaje de programacin nuevo. No escribas o esta estpida funcin en Python, personas inteligentes se ha ocupado de ello u o por ti. El mdulo os.path tambin contiene funciones para trocear caminos completos, o e nombres de directorios y nombres de chero en sus partes constituyentes.
1 2 3 4 5 6 7 8 9 10 11 12 13 >>> nombrepath = /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / parahumanos . py >>> o s . path . s p l i t ( nombrepath ) ( /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s , parahumanos . py ) >>> ( nombredir , n o m b r e f i c h ) = o s . path . s p l i t ( nombrepath ) >>> nombredir /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s >>> n o m b r e f i c h parahumanos . py >>> ( nombrecorto , e x t e n s i o n ) = o s . path . s p l i t e x t ( n o m b r e f i c h ) >>> nombrecorto parahumanos >>> e x t e n s i o n . py

1. Lnea 2: La funcin split() divide un camino completo en dos partes que con o tienen el camino y el nombre de chero. Los retorna en una tupla. 2. Lnea 4: Recuerdas cuando dije que pod utilizar la asignacin mltiple para as o u devolver varios valores desde una funcin? os.path.split() hace exactamente eso. o Puedes asignar los valores de la tupla que retorna a dos variables. Cada variable recibe el valor que le corresponde al elemento de la tupla. 3. Lnea 5: La primera variable, nombredir, recibe el valor del primer elemento de la tupla que retorna os.path.split(), el camino al chero. 4. Lnea 7: La segunda variable, nombrech, recibe el valor del segundo elemento de la tupla que retorna os.path.split(), el nombre del chero.

86

5. Lnea 9: os.path tambin posee la funcin os.path.splitext() que divide el nom e o bre de un chero en una tupla que contiene el nombre y la extensin separados o en dos elementos. Puedes utilizar la misma tcnica que antes para asignarlos e a dos variables separadas.

3.2.3.

Listar directorios

El mdulo glob es otra herramienta incluida en la librer estndar de Python. o a a Proporciona una forma sencilla de acceder al contenido de un directorio desde un programa. Utiliza los caracteres comodn que suelen usarse en una consola de l nea de comandos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 >>> o s . c h d i r ( /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / ) >>> import g l o b >>> g l o b . g l o b ( e j e m p l o s / . xml ) [ e j e m p l o s \\ f e e d broken . xml , e j e m p l o s \\ f e e d ns0 . xml , e j e m p l o s \\ f e e d . xml ] >>> o s . c h d i r ( e j e m p l o s / ) >>> g l o b . g l o b ( t e s t . py ) [ a l p h a m e t i c s t e s t . py , p l u r a l t e s t 1 . py , p l u r a l t e s t 2 . py , p l u r a l t e s t 3 . py , p l u r a l t e s t 4 . py , p l u r a l t e s t 5 . py , p l u r a l t e s t 6 . py , r o m a n t e s t 1 . py , r o m a n t e s t 1 0 . py , r o m a n t e s t 2 . py , r o m a n t e s t 3 . py , r o m a n t e s t 4 . py , r o m a n t e s t 5 . py , r o m a n t e s t 6 . py , r o m a n t e s t 7 . py , r o m a n t e s t 8 . py , r o m a n t e s t 9 . py ]

1. Lnea 3: El mdulo glob utiliza comodines y devuelve el camino de todos los o cheros y directorios que coindicen con la bsqueda. En este ejemplo se busca un u directorio que contenga cheros terminados en *.xml, lo que encontrar toa dos los cheros xml que se encuentren en el directorio de ejemplos. 2. Lnea 7: Ahora cambio el directorio de trabajo al subdirectorio ejemplos. La

87

funcin os.chdir() puede recibir como parmetro un camino relativo a la posio a cin actual. o 3. Lnea 8: Puedes incluir varios comodines de bsqueda. El ejemplo encuentra u todos los cheros del directorio actual de trabajo que incluyan la palabra test en alguna parte del nombre y que, adems, terminen con la cadena .py. a

3.2.4.

Obtener metadatos de cheros

Todo sistema de cheros moderno almacena metadatos sobre cada chero: fecha de creacin, fecha de la ultima modicacin, tamao, etc. Python proporciona o o n una API unicada para acceder a estos metadatos. No necesitas abrir el chero, unicamente necesitas su nombre.
1 2 3 4 5 6 7 8 9 10 >>> import o s >>> print ( o s . getcwd ( ) ) /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s >>> metadata = o s . s t a t ( f e e d . xml ) >>> metadata . st mtime 1247520344.9537716 >>> import time >>> time . l o c a l t i m e ( metadata . st mtime ) time . s t r u c t t i m e ( tm year =2009 , tm mon=7, tm mday=13 , tm hour =17 , tm min =25 , t m s e c =44 , tm wday=0, tm yday =194 , t m i s d s t =1)

1. Lnea 2: El directorio de trabajo actual es ejemplos. 2. Lnea 4: feed.xml es un chero que se encuentra en el directorio ejemplos. La funcin os.stat() devuelve un objeto que contiene diversos metadatos sobre el o chero. 3. Lnea 5: st mtime contiene la fecha y hora de modicacin, pero en un formato o que no es muy util (Tcnicamente es el nmero de segundos desde el inicio de e u la Epoca, que est denida como el primer segundo del 1 de enero de 1970 En a serio!). 4. L nea 7: El mdulo time forma parte de la librer estndar de Python. Cono a a tiene funciones para convertir entre diferentes representaciones del tiempo, formatear valores de tiempo en cadenas y manipular las referencias a los husos horarios. 5. Lnea 8: La funcin time.localtime() convierte un valor de segundos desde el o inicio de la poca (que procede la propiedad anterior) en una estructura ms e a 88

util que contiene ao, mes, d hora, minuto, segundo, etc. Este chero se n a, modic por ultima vez el 13 de julio de 2009 a las 5:25 de la tarde. o
1 2 3 4 5 6 # c o n t i n u a c i n d e l e j e m p l o a n t e r i o r o >>> metadata . s t s i z e 3070 >>> import parahumanos >>> parahumanos . tamnyo aproximado ( metadata . s t s i z e ) 3 . 0 KiB

1. Lnea 2: La funcin os.stat() tambin devuelve el tamao de un chero en la o e n propiedad st size. El chero feed.xml ocupa 3070 bytes. 2. Lnea 5: Aprovecho la funcin tamanyo aproximado() para verlo de forma ms o a clara.

3.2.5.

Construccin de caminos absolutos o

En el apartado anterior, se observ cmo la funcin glob.glob() devolv una o o o a lista de nombres relativa. El primer ejemplo mostraba caminos como ejemplos/feed.xml, y el segundo ejemplo incluso ten nombres ms cortos como romana a test1.py. Mientras permanezcas en el mismo directorio de trabajo los path relativos funcionarn sin problemas para recuperar informacin de los cheros. No obstante, si a o quieres construir un camino absoluto Uno que contenga todos los directorios hasta el ra del sistema de archivos lo que necesitas es la funcin os.path.realpath(). z o
1 >>> import o s 2 >>> print ( o s . getcwd ( ) ) 3 /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s 4 >>> print ( o s . path . r e a l p a t h ( f e e d . xml ) ) 5 /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / f e e d . xml

3.3.

Listas por comprensin o

La creacion de listas por comprensin proporciona una forma compacta de o crear una lista a partir de otra mediante la realizacin de una operacin a cada uno o o de los elementos de la lista original.

89

1 2 3 4 5 6 7 8

>>> >>> [2 , >>> [1 , >>> >>> [2 ,

una lista = [1 , 9 , 8 , 4] [ elem 2 f o r elem in u n a l i s t a ] 18 , 16 , 8 ] una lista 9 , 8 , 4] u n a l i s t a = [ elem 2 f o r elem in u n a l i s t a ] una lista 18 , 16 , 8 ]

1. Lnea 2: Para explicar esto es mejor leerlo de derecha a izquierda. una lista es la lista origen que se va a recorrer para generar la nueva lista. El intrprete e de Python recorre cada uno de los elementos de una lista, asignando temporalmente el valor de cada elemento a la variable elem. Despus Python aplica la e operacin que se haya indicado, en este caso elem * 2, y el resultado lo aade o n a la nueva lista. 2. Lnea 4: Como se observa, la lista original no cambia. 3. Lnea 6: No pasa nada por asignar el resultado a la variable que ten la lista a original. Python primero construye la nueva lista en memoria y luego asigna el resultado a la variable. Para crear una lista de esta forma, puedes utilizar cualquier expresin vlida o a de Python, como por ejemplo las funciones del mdulo os para manipular cheros o y directorios.
1 >>> import os , g l o b 2 >>> g l o b . g l o b ( . xml ) 3 [ f e e d broken . xml , f e e d ns0 . xml , f e e d . xml ] 4 >>> [ o s . path . r e a l p a t h ( f ) f o r f in g l o b . g l o b ( . xml ) ] 5 [ /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / f e e d broken . xml , 6 /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / f e e d ns0 . xml , 7 /home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / f e e d . xml ]

1. Lnea 2: Esta llamada retorna una lista con todos los cheros terminados en .xml del directorio de trabajo. 2. Lnea 4: Esta lista generada por comprensin toma la lista original y la trans o forma en una nueva lista con los nombres completos de ruta. Las listas por comprensin tambin permiten ltrar elementos, generando una o e lista cuyo tamao sea menor que el original. n

90

1 >>> import os , g l o b 2 >>> [ f f o r f in g l o b . g l o b ( . py ) i f o s . s t a t ( f ) . s t s i z e > 6 0 0 0 ] 3 [ p l u r a l t e s t 6 . py , 4 r o m a n t e s t 1 0 . py , 5 r o m a n t e s t 6 . py , 6 r o m a n t e s t 7 . py , 7 r o m a n t e s t 8 . py , 8 r o m a n t e s t 9 . py ]

1. Lnea 2: Para ltrar una lista puedes incluir la clasula if al nal de la com u prensin. Esta expresin se evala para cada elemento de la lista original. Si o o u el resultado es verdadero, el elemento ser calculado e incluido en el resultado. a En este caso se seleccionan todos los cheros que terminan en .py que se encuentren en el directorio de trabajo, se comprueba si son de tamao mayor a n 6000 bytes. Seis de ellos cumplen este requisito, por lo que son los que aparecen en el resultado nal. Hasta el momento, todos los ejemplos de generacin de listas por comprensin o o han utilizado expresiones muy sencillas multiplicar un nmero por una constante, u llamada a una funcin o simplemente devolver el elemento original de la lista pero o no existe l mite en cuanto a la complejidad de la expresin. o
1 2 3 4 5 6 7 8 9 10 11 >>> import os , g l o b >>> [ ( o s . s t a t ( f ) . s t s i z e , o s . path . r e a l p a t h ( f ) ) f o r f in g l o b . g l o b ( . xml ) ] [ ( 3 0 7 4 , c : / home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / f e e d broken . xml ) , ( 3 3 8 6 , c : / home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / f e e d ns0 . xml ) , ( 3 0 7 0 , c : / home/ j m g a g u i l e r a / i n m e r s i o n e n p y t h o n 3 / e j e m p l o s / f e e d . xml ) ] >>> import parahumanos >>> [ ( parahumanos . tamanyo aproximado ( o s . s t a t ( f ) . s t s i z e ) , f ) f o r f in g l o b . g l o b ( . xml ) ] [ ( 3 . 0 KiB , f e e d broken . xml ) , ( 3 . 3 KiB , f e e d ns0 . xml ) , ( 3 . 0 KiB , f e e d . xml ) ]

1. Lnea 2: En este caso se buscan los cheros que nalizan en .xml en el directorio de trabajo actual, se recupera su tamao (mediante una llamada a la funcin n o os.stat()) y se construye una tupla con el tamao del chero y su ruta completa n (mediante una llamada a os.path.realpath(). 2. Lnea 7: En este caso se aprovecha la lista anterior para generar una nueva con el tamao aproximado de cada chero. n

91

3.4.
lista.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Diccionarios por comprensin o

Es similar al apartado anterior pero genera un diccionario en lugar de una


>>> import os , g l o b >>> metadata = [ ( f , o s . s t a t ( f ) ) f o r f in g l o b . g l o b ( t e s t . py ) ] >>> metadata [ 0 ] ( a l p h a m e t i c s t e s t . py , nt . s t a t r e s u l t ( st mode =33206 , s t i n o =0, s t d e v =0, s t n l i n k =0, s t u i d =0, s t g i d =0, s t s i z e =2509 , s t a t i m e =1247520344 , st mtime =1247520344 , s t c t i m e =1247520344)) >>> m e t a d a t a d i c t = { f : o s . s t a t ( f ) f o r f in g l o b . g l o b ( t e s t . py ) } >>> type ( m e t a d a t a d i c t ) <c l a s s d i c t > >>> l i s t ( m e t a d a t a d i c t . k e y s ( ) ) [ r o m a n t e s t 8 . py , p l u r a l t e s t 1 . py , p l u r a l t e s t 2 . py , p l u r a l t e s t 5 . py , p l u r a l t e s t 6 . py , r o m a n t e s t 7 . py , r o m a n t e s t 1 0 . py , r o m a n t e s t 4 . py , r o m a n t e s t 9 . py , p l u r a l t e s t 3 . py , r o m a n t e s t 1 . py , r o m a n t e s t 2 . py , r o m a n t e s t 3 . py , r o m a n t e s t 5 . py , r o m a n t e s t 6 . py , a l p h a m e t i c s t e s t . py , p l u r a l t e s t 4 . py ] >>> m e t a d a t a d i c t [ a l p h a m e t i c s t e s t . py ] . s t s i z e 2509

1. Lnea 2: Esto no genera un diccionario por comprensin, genera una lista por o comprensin. Encuentra todos los cheros terminados en .py con el texto test o en el nombre y luego construye una tupla con el nombre y los metadatos del chero (llamando a la funcin os.stat()). o 2. Lnea 3: Cada elemento de la lista resultante es una tupla. 3. Lnea 7: Esto s es una generacin de un diccionario por comprensin. La sin o o taxis es similar a la de la generacin de listas, con dos diferencias: primero, o se encierra entre llaves en lugar de corchetes; segundo, en lugar de una unica expresin para cada elemento, contiene dos expresiones separadas por dos puno tos. La expresin que va delante de los dos puntos es la clave del diccionario o y la expresin que va detrs es el valor (os.stat(f) en este ejemplo). o a 4. Lnea 8: El resultado es un diccionario. 5. Lnea 10: La claves de este caso particular son los nombres de los cheros. 6. Lnea 16: El valor asociado a cada clave es el valor que retorn la funcin o o os.stat(). Esto signica que podemos utilizar este diccionario para buscar los metadatos de un chero a partir de su nombre. Uno de los elementos de estos n metadatos es st size, el tamao de chero. Para el chero alphameticstest.py el valor es 2509 bytes. 92

Como con las listas, puedes incluir la clasula if para ltrar los elementos de u entrada mediante una expresin que se evala para cada uno de los elementos. o u
1 2 3 4 5 6 7 8 9 >>> import os , glob , parahumanos >>> d i c t = { o s . path . s p l i t e x t ( f ) [ 0 ] : parahumanos . tamanyo aproximado ( os . s t a t ( f ) . s t s i z e ) \ ... f o r f in g l o b . g l o b ( ) i f o s . s t a t ( f ) . s t s i z e > 6000} >>> l i s t ( d i c t . k e y s ( ) ) [ romantest9 , romantest8 , romantest7 , romantest6 , romantest10 , p l u r a l t e s t 6 ] >>> d i c t [ r o m a n t e s t 9 ] 6 . 5 KiB

1. Lnea 4: Este ejemplo construye una lista con todos los cheros del directorio de trabajo actual (glob.glob(*)), ltra la lista para incluir unicamente aquellos cheros mayores de 6000 bytes (if os.stat(f).s size 6000) y utiliza la lista ltrada para construir un diccionario cuyas claves son los nombres de chero menos la extensin (os.path.splitext(f)[0]) y los valores el tamao de cada uno o n de ellos (parahumanos.tamanyo aproximado(os.stat(f).st size)). 2. Lnea 5: Como viste en el ejemplo anterior son seis cheros, por lo que hay seis elementos en el diccionario. 3. Lnea 7: El valor de cada elemento es la cadena que retorna la funcin taman o yo aproximado().

3.4.1.

Trucos que se pueden hacer

Te presento un truco que puede serte de utilidad: intercambiar las claves y valores de un diccionario.
1 >>> d i c t = { a : 1 , b : 2 , c : 3} 2 >>> { v a l u e : key f o r key , v a l u e in a d i c t . i t e m s ( ) } 3 {1: a , 2: b , 3: c }

3.5.

Conjuntos por comprensin o

Por ultimo mostrar la sintaxis para generar conjuntos por comprensin. Es e o muy similiar a la de los diccionarios, con la unica diferencia de que unicamente se incluyen valores en lugar de parejas clave-valor.

93

1 2 3 4 5 6 7 8 9

>>> c o n j u n t o = s e t ( r a n g e ( 1 0 ) ) >>> c o n j u n t o { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9} >>> {x 2 f o r x in c o n j u n t o } { 0 , 1 , 4 , 8 1 , 6 4 , 9 , 1 6 , 4 9 , 2 5 , 36} >>> {x f o r x in c o n j u n t o i f x % 2 == 0} { 0 , 8 , 2 , 4 , 6} >>> {2 x f o r x in r a n g e ( 1 0 ) } { 3 2 , 1 , 2 , 4 , 8 , 6 4 , 1 2 8 , 2 5 6 , 1 6 , 512}

1. Lnea 4: Los conjuntos generados por comprensin pueden partir de otro con o junto en lugar de una lista. En este ejemlo se calcula el cuadrado de cada uno de los elementos (los nmeros del 0 al 9). u 2. Lnea 6: Como en el caso de las listas y diccionarios, puedes incluir una clasula u if para ltrar elementos antes de calcularlos e incluirlos en el resultado. 3. L nea 8: Los conjuntos por comprensin no necesitan tomar un conjunto como o entrada, pueden partir de cualquier tipo de secuencia.

3.6.

Lecturas complementarias

mdulo os o os Portabilidad en el acceso a caracter sticas espec cas del sistema operativo mdulo os.path o Manipulacin de los nombres de chero independiente de la plataforma o os.path mdulo glob o Patrones de bsqueda de cheros glob u mdulo time o Funciones para manipulacin de hora time o Listas por comprensin o Comprensiones anidadas Tcnicas para hacer bucles e

94

Cap tulo 4 Cadenas de texto


Nivel de dicultad:   Te digo esto porque eres uno de mis amigos, Mi vocabulario comienza donde el tuyo termina! Dr. Seuss, On beyond Zebra!

4.1.

Temas aburridos que debes conocer antes de la inmersin o

Sab que la gente de Bougainville tiene el alfabeto ms pequeo del mundo? as a n El alfabeto Rotokas est compuesto unicamente por 12 letras: A, E, G, I, K, O, P, a R, S, T, U y V. En el otro lado del espectro los lenguajes como el Chino, Japons e y Koreano tienen miles de caracteres. El ingls, desde luego, tiene 26 letras 52 e si cuentas las maysculas y minsculas de forma separada ms un puado de u u a n s mbolos de puntuacin !@#$ %&?. o Cuando las personas hablan sobre texto piensan en caracteres y s mbolos en la pantalla del ordenador. Pero los ordenadores no conocen ni s mbolos ni caracteres, conocen bits y bytes. Cada elemento textual que ves en la pantalla est almacenado con una codicacin de caracteres particular. Explicndolo de a o a manera informal, la codicacin de caracteres proporciona una conversin entre lo o o que ves en la pantalla y lo que el ordenador realmente almacena en memoria o en disco. Existen muchas codicaciones de caracteres diferentes, algunas optimizadas para determinados lenguajes como el ruso, el chino o el ingls, y otras que se pueden e utilizar para diferentes lenguajes.

95

En realidad es ms complicado. Muchos caracteres son comunes a diferentes a codicaciones, pero cada codicacin puede utilizar una secuencia de bytes diferente o para almacenar esos caracteres en memoria o disco. Puedes imaginarte que una codicacin de caracteres es como una especia de clave de desencriptado. Cuando tengas o una secuencia de bytes un chero, una pgina web o cualquier otra cosa y se a considere que esos bytes representan texto, necesitas conocer en qu codicacin e o de caracteres se encuentra para poder decodicar los bytes y conocer a qu carace teres representan. Si tienes una clave de decodicacin equivocada o no dispones de o ninguna, la decodicacin no ser posible o ser errnea (si se usa una decodicacin o a a o o equivocada), y el resultado ser un texto sin sentido. a Seguramente habrs visto a veces paginas a web con extraos caracteres de interrogacin o n o Todo lo que que pensabas que similar, en donde esperabas algn caracter cou sab sobre las cadenas de as mo el apstrofo o vocales acentuadas. Esto suele o texto es errneo. o indicar que el autor de la pgina no declar coa o rrectamente la codicacin de caracteres que utio liz por lo que tu navegador la tiene que adivinar y el resultado es una mezcla de o caracteres esperados e inesperados. En ingls esto es simplemente desconcertante, e pero en otros lenguajes el resultado puede ser completamente ilegible. Existen tablas de codicacin de caracteres para cada uno de los lenguajes o importantes del mundo. Puesto que cada lenguaje es diferente, y la memoria y el espacio en disco ha sido caro histricamente, cada tabla de codicacin de caracteres o o est optimizada para un lenguaje en particular. Lo que quiero decir con esto es que a cada una de las codicaciones usa los mismos nmeros (0 - 255) para representar los u caracteres de un lenguaje determinado. Por ejemplo, posiblemente ests familiarizae do con la codicacin ASCII, que almacena los caracteres del ingls como nmeros o e u que van del 0 al 127 (65 es la A, 97 es la a, etc). El ingls es un alfabeto muy e simple, por lo que puede expresarse con menos de 128 nmeros. Para aquellos que u sepan contar en base 2, eso signica 7 bits de los 8 de un byte. Algunos lenguajes de Europa como el francs, espaol y alemn necesitan ms e n a a letras que el ingls. O, para ser ms precisos, tienen letras que se combinan con e a diversas marcas diacr ticas, como el carcter n del espaol. La tabla de codicacin a n o de caracteres ms comn para estos lenguajes es CP-1252, que tambin es conocida a u e como windows-1252 porque se utiliza ampliamente en el sistema operativo Microsoft Windows. La codicacin CP-1252 comparte con ASCII los primeros 128 caracteres o (0-127), pero luego se extiende en el rango de 128 a 255 para los caracteres restantes (241 es la , 252 es la , etc). Contina siendo una tabla de codicacin de un n u u o unico byte. El valor mayor, 255, an cabe en un byte. u Adems existen lenguajes como el chino, japons y coreano, que tienen tantos a e

96

caracteres que requieren tablas de codicacin de caracteres multibyte. Esto signica o que cada carcter se representa como un nmero de dos bytes lo que abarca del 0 a u al 65535. Pero las codicaciones multibyte tambin tienen el mismo problema que e las diferentes codicaciones de un unico byte: cada una de ellas puede utilizar el mismo nmero para expresar un carcter diferente. La unica diferencia entre ellas u a es que el rango de caracteres disponible es mayor en las codicaciones multibyte. Esto no supon demasiado problema en un mundo desconectado, en donde a texto era algo que tecleabas para t y ocasionalmente imprim No exist mucho as. a texto plano. El cdigo fuente era ASCII y todo el mundo usaba procesadores o de textos que den su propo formato que ten en cuenta la informacin de an an o codicacin de caracteres junto con la informacin de estilo, etc. La gente le estos o o a documentos con el mismo programa procesador de texto que el autor original, por lo que todo funcionaba, ms o menos. a Ahora piensa en la aparicin de las redes globales y en el correo y la web. Mucho o texto plano anda suelto por el mundo, se crea en un ordenador, se transmite a un segundo y se muestra en un tercero. Los ordenadores unicamente distinguen nme u ros, pero los nmeros pueden signicar cosas diferentes. Oh no! Qu hacer? Bien, u e los sistemas tuvieron que disearse para transportar la informacin de codicacin n o o junto con el texto plano. Recuerda, se trata de las claves de descodicacin que o mapean los nmeros entendidos por el ordenador a caracteres legibles por personas. u Una clave de descodicacin perdida da lugar a texto ilegible. o Ahora piensa en intentar almacenar diversos documentos de texto en el mismo lugar, como en una tabla de una misma base de datos que almacena todo el correo electrnico que hayas recibido. An necesitas almacenar la codicacin de caracteres o u o junto con cada correo electrnico para que se pueda leer apropiadamente. Parece o dif cil? Prueba a buscar en tu base de datos de correos, eso signica convertir entre mltiples tablas de codicacin de caracteres sobre la marcha. No suena divertido?. u o Piensa ahora en la posibilidad de documentos multil ngues, en donde aparecen 1 caracteres en diferentes lenguajes . Y, por supuesto, querrs buscar el contenido de a esos documentos. Ahora llora un rato, porque todo lo que cre conocer sobre las cadenas de as texto es errneo, y no existe algo as como el texto plano. o
Pista: los programas que han intentando hacer esto utilizan habitualmente cdigos de escape o para conmutar entre modos. Si ests en modo ruso koi8-r el cdigo 241 signica R. Si cambias a o
1

a modo Griego el cdigo 241 signica . o

97

4.2.

Unicode

Entra en Unicode. Unicode es un sistema diseado para representar todos los caracteres de todos n los lenguajes. Representa cada letra, carcter o ideograma como un nmero de cuatro a u bytes. Cada nmero representa a un unico carcter que se use en al menos uno de u a los lenguajes del mundo (No se usan todos los nmeros, pero se usan ms de 65535 u a por lo que no es suciente utilizar dos bytes). Los caracteres que se utilizan en diferentes lenguajes tienen el mismo nmero generalmente, a menos que exista una u buena razn etimolgica para que no sea as De todos modos hay exactamente un o o . nmero por cada carcter y un carcter por nmero. De esta forma, cada nmero u a a u u siempre signica una unica cosa. No existen modos que rastrear, U+0041 siempre corresponde a A, incluso si tu lenguaje no usa tal s mbolo. A primera vista parece una gran idea, una tabla de codicacin de caracteres o para gobernarlos a todos. Mltiples lenguajes por documento, no ms cambios de u a modo para conmutar entre tablas de codicacin en medio de un documento. Pero o existe una pregunta obvia. Cuatro bytes? Para cada carcter? Parece un gasto a intil la mayor parte de las ocasiones, especialmente para idiomas como el ingls o u e el espaol, que necesitan menos de un byte (256 nmeros) para expresar cada uno n u de los caracteres posibles. De hecho, es un desperdicio de espacio incluso para los lenguajes basados en ideogramas como el chino, que nunca necesitan ms de dos a caracteres para cada carcter. a Existe una tabla de codicacin Unicode que utiliza cuatro bytes por cada o carcter. Se denomina UTF-32 porque 32 bits es igual a 4 bytes. UTF-32 es una a codicacin directa; toma cada carcter Unicode (un nmero de 4 bytes) y repreo a u senta al carcter con ese mismo nmero. Esto tiene varias ventajas siendo la ms a u a importante que puedes encontrar el ensimo carcter de una cadena en un tieme a po constante ya que se encuentra en a partir del byte 4 n. Tambin tiene varios e inconvenientes, siendo el ms obvio que necesita cuatro bytes para almacenar cada a carcter. a Incluso aunque existen muchos caracteres Unicode, resulta que la mayor de la a gente nunca usar nada ms all de los primeros 65535. Por eso existe otra codicaa a a cin Unicode denominada UTF-16 (16 bits son 2 bytes) que codica cada uno de los o caracteres de 0 a 65535 como dos bytes. Adems utiliza algunos trucos sucios por a si necesitas representar aquellos caracteres que se usan raramente y que estn ms a a all del 65535. La ventaja ms obvia es que esta tabla de codicacin de caracteres a a o es el doble de eciente que la de UTF-32 puesto que cada carcter requiere unicaa mente dos bytes para almacenarse, en lugar de cuatro bytes. An se puede encontrar u fcilmente el ensimo carcter de una cadena en un tiempo constante, siempre que a e a 98

se asuma que no existen caracteres especiales de los que estn por encima de 65535. a Lo que suele ser una buena asuncin... hasta el momento en que no lo es! o Tambin existen algunos inconvenientes no tan obvios tanto en UFT-32 y UTFe 8. Los ordenadores de sistemas diferentes suelen almacenar los bytes de diferentes formas. Esto signica que el carcter U+4E2D podr almacenarse en UTF-16 bien a a como 4E 2D o como 2D 4E, dependiendo de que el sistema sea big-endian o littleendian2 (para UTF-32 existen ms posibilidades de ordenacin de los bytes). Miena o tras tus documentos no dejen tu ordenador ests seguro las diferentes aplicaciones a del mismo ordenador utilizarn la misma ordenacin de bytes. Pero en el momento a o que transeras los documentos entre sistemas, tal vez a travs de Internet, vas a e necesitar una forma de indicar el orden en el que se han almacenado los bytes. De otra forma el sistema que recibe los datos no tiene forma de saber si la secuencia de dos bytes 4E 2D signica U+4E2D o U+2D4E. Para resolver este problema, las codicaciones multibyte de Unicode denen el Byte Orden Mark (BOM)3 , que es un carcter especial no imprimible que se a puede incluir al comienzo de tu documento para indica qu ordenacin de bytes e o tiene el documento. Para UTF-16 la marca de ordenacin de bytes es U+FEFF, por o lo que si recibes un documento UTF-16 que comienza con los bytes FF FE, ya sabes en qu forma vienen ordenados los bytes; si comienza con FE FF sabes que el orden e es el contrario. An as UTF-16 no es exactamente el ideal, especialmente si la mayor parte u , de los caracteres que utilizas son ASCII. Si lo piensas, incluso una pgina web china a contendr muchos caracteres ASCII todos los elementos y atributos que rodean a a los caracteres imprimibles chinos. Poder encontrar el ensimo carcter est bien, e a a pero existe el problema de los caracteres que requieren ms de dos bytes, lo que a signica que no puedes garantizar que todos los caracteres ocupan exactamente dos bytes, por lo que en la prctica no puedes encontrar el carcter de la posicin a a o ensima en un tiempo constante a no ser que mantengas un e ndice separado. Y muchacho, te aseguro que hay mucho texto ASCII por el mundo... Otras personas valoraron estas preguntas y plantearon una solucin: o

UTF-8
UTF-8 es un sistema de codicacin de longitud variable para Unicode. Eso to signica que los caracteres pueden utilizar diferente nmero de bytes. Para los u caracteres ASCII utiliza un unico byte por carcter. De hecho, utiliza exactamente a
2 3

Almacene los bytes en orden o invirtiendo el mismo. Nota del traductor: Marca de ordenacin de bytes. o

99

los mismos bytes que ASCII por lo que los 128 primeros caracteres son indistinguibles. Los caracteres latinos extendidos como la n o la o utilizan dos bytes4 . Los caracteres chinos utilizan tres bytes, y los caracteres ms raros utilizan cuatro. a Desventajas: debido a que los caracteres pueden ocupar un nmero diferente u de bytes, encontrar el carcter de la posicin ensima es una operacin de orden a o e o de complejidad O(n) lo que signica que cuanto ms larga sea la cadena, ms a a tiempo lleva encontrar un carcter espec a co. Asimismo, hay que andar codicando y decodicando entre bytes y caracteres. Ventajas: se trata de una codicacin supereciente de los caracteres ASCII. o No es peor que UTF-16 para los caracteres latinos extendidos, y es mejor que UTF32 para los caracteres chinos. Tambin (aqu tendrs que conar en mi, porque no e a te voy a mostrar la matemtica involucrada), debido a la naturaleza exacta de la a manipulacin de los bits, no existen problemas de ordenacin de bits. Un documento o o codicado en UTF-8 siempre contiene la misma cadena de bytes sea cual sea el ordenador y sistema operativo.

4.3.

Inmersin o

En Python 3 todas las cadenas de texto son secuencias de caracteres Unicode. En Python 3 no existen cadenas codicadas en UTF-8 o en CP-1252. No es correcto decir Es esta cadena una cadena codicada en UTF-8?. UTF-8 es una forma de codicar caracteres en una secuencia de bytes. Si quieres convertir una cadena de caracteres en una secuencia de bytes en una codicacin de caracteres particular, o Python 3 puede ayudarte con ello. Si quieres tomar una secuencia de bytes y convertirla en una cadena de texto, tambin te puede ayudar Python 3. Los bytes no e son caracteres, los bytes son bytes. Los caracteres son una abstraccin. Una cadena o es una secuencia de esas abstracciones.
1 2 3 4 5 6 7 >>> s = Python >>> l e n ( s ) 9 >>> s [ 0 ] >>> s + 3 Python 3

1. Lnea 1: Para crear una cadena de texto debes utilizar las comillas para deli mitarla. Se pueden utilizar comillas simples () o dobles ().
Los bytes no son unicamente la codicacin de Unicode como sucede en UTF-16, se efectan o u diversos cambios para obtener la codicacin en UTF-8. o
4

100

2. Lnea 2: La funcin interna len() devuelve la longitud de la cadena, el nmero o u de caracteres. Esta funcin es la misma que utilizas para conocer la longitud o de una lista, tupla, conjunto o diccionario. Una cadena es como una tupla de caracteres. 3. Lnea 4: De la misma forma que puedes obtener elementos individuales de una lista, puedes obtener caracteres individuales de una cadena mediante la notacin de o ndices. 4. Lnea 6: Como con las listas y tuplas, puedes contatenar las cadenas utilizando el operador +.

4.4.

Formatear cadenas
Las cadenas de texto se pueden denir utilizando comillas simples o dobles.

Vamos a echarle otro vistazo a parahumanos.py:

101

1 # parahumanos . py 2 3 SUFIJOS = { 1 0 0 0 : [ KB , MB , GB , TB , PB , EB , ZB , YB ] , 4 1 0 2 4 : [ KiB , MiB , GiB , TiB , PiB , EiB , ZiB , 5 YiB ] } 6 7 def tamanyo aproximado ( tamanyo , u n k i l o b y t e e s 1 0 2 4 b y t e s=True ) : 8 C o n v i e r t e un tama o de f i c h e r o en formato l e g i b l e por p e r s o n a s n 9 10 Argumentos / par metros : a 11 tamanyo tama o de f i c h e r o en b y t e s n 12 u n k i l o b y t e e s 1 0 2 4 b y t e s s i True ( por d e f e c t o ) , 13 usa m l t i p l o s de 1024 u 14 s i F a l s e , usa m l t i p l o s de 1000 u 15 16 retorna : string 17 18 19 i f tamanyo < 0 : 20 r a i s e V a l u e E r r o r ( e l n mero debe s e r no n e g a t i v o ) u 21 22 m u l t i p l o = 1024 i f u n k i l o b y t e e s 1 0 2 4 b y t e s e l s e 1000 23 f o r s u f i j o in SUFIJOS [ m u l t i p l o ] : 24 tamanyo /= m u l t i p l o 25 i f tamanyo < m u l t i p l o : 26 return { 0 : . 1 f } {1} . format ( tamanyo , s u f i j o ) 27 28 r a i s e V a l u e E r r o r ( n mero demasiado grande ) u 29 30 i f name == m a i n : 31 print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 , F a l s e ) ) 32 print ( tamanyo aproximado ( 1 0 0 0 0 0 0 0 0 0 0 0 0 ) )

1. Lnea 3: KB, MB, GB, ... son cadenas. 2. Lnea 8: Las cadenas de documentacin (docstrings) son cadenas de texto. o Como se expanden ms all de una l a a nea se utilizan tres comillas al comienzo y al nal para delimitarlas. 3. Lnea 18: Estas comillas triples nalizan la cadena de documentacin de esta o funcin. o 4. Lnea 20: Otra cadena que se pasa como parmetro a la excepcin con el n a o de que sea legible por una persona. 5. Lnea 26: Esto es... U! Qu car.. es esto? e

102

Python 3 permite formatear valores en cadenas de texto. Aunque este sistema permite expresiones muy complejas, su uso ms bsico consiste en insertar un valor a a en una cadena de texto en el lugar denido por un marcador.
1 >>> u s u a r i o = mark 2 >>> c l a v e = PapayaWhip 3 >>> La c l a v e de {0} e s {1} . format ( u s u a r i o , c l a v e ) 4 La c l a v e de mark e s PapayaWhip

1. Lnea 2: Realmente mi clave no es PapayaWhip. 2. Lnea 3: Aqu hay mucho que contar. Primero, se observa una llamada a un mtodo sobre una cadena de texto. Las cadenas de texto son objetos, y los e objetos tienen mtodos, como ya sabes. Segundo, la expresin completa se e o evala a una cadena. Tercero, {0} y {1} son campos de reemplazo, que se u sustituyen con los parmetros que se pasen al mtodo format(). a e

4.4.1.

Nombres de campos compuestos

En el ejemplo anterior se muestra el ejemplo ms simple, aqul en el que los a e campos de reemplazo son nmeros enteros. Los campos de reemplazo enteros se u tratan como ndices posicionales en la lista de parmetros del mtodo format(). Eso a e signica que el {0} se reemplaza por el primer parmetro (usuario en este caso), {1} a se reemplaza por el segundo (clave en este caso), etc. Puedes utilizar tantos campos de reemplazo posicional como parmetros se pasen en el mtodo format(). Pero los a e campos de reemplazo permiten mucha ms funcionalidad. a
1 2 3 4 5 6 >>> import parahumanos >>> m i s s u f i j o s = parahumanos . SUFIJOS [ 1 0 0 0 ] >>> m i s s u f i j o s [ KB , MB , GB , TB , PB , EB , ZB , YB ] >>> 1 0 0 0 { 0 [ 0 ] } = 1 { 0 [ 1 ] } . format ( m i s s u f i j o s ) 1000KB = 1MB

1. Lnea 2: En lugar de ejecutar una funcin del mdulo parahumanos unicamente o o ests capturando una de las estructuras de datos que dene; la lista de sujos a que representan las potencias de 1000. 2. Lnea 5: Esta l nea parece complicada, pero no lo es. {0} representa el primer prametro del mtodo format(), mis sujos. Por eso {0[0]} se reere al primer a e elemento de la lista que est denida como el primer parmetro del mtodo e a e format(): KB. Mientras que {0[1]} se reere al segundo elemento de la misma 103

lista: MB. Todo lo que est fuera de las llaves incluido el 1000, los signos a de igual, y los espacios quedan sin tocar. El resultado nal es: 1000KB = 1MB. El {0} se reemplaza por el primer parmetro, {1} se reemplaza por el sea gundo. Lo que este ejemplo te ensea es que los especicadores de formato pueden n utilizarse para acceder a los elementos y propiedades de las estructuras de datos utilizando (casi) sintaxis de Python. Esto se denomina nombres de campos compuestos. Estos son los nombres de campos que funcionan: Pasar una lista y acceder a un elemento de la lista utilizando un ndice (como en el ejemplo anterior). Pasar un diccionario y acceder a los valores del mismo utilizando una clave. Pasar un mdulo y acceder a sus variables y funciones por nombre. o Pasar una instancia de clase y acceder a sus propiedades y mtodos por nome bre. Cualquier combinacin de las anteriores. o Solamente para despejar tu cerebro te muestro aqu un ejemplo que combina todo lo anterior.
1 >>> import parahumanos 2 >>> import s y s 3 >>> 1MB = 1 0 0 0 { 0 . modules [ parahumanos ] . SUFIJOS [ 1 0 0 0 ] [ 0 ] } . format ( s y s ) 4 1MB = 1000KB

As es como funciona: El mdulo sys almacena informacin sobre la instancia del lenguaje Python o o que se est ejecutando en ese momento. Puesto que lo has importado, puedes a pasar el propio mdulo sys como parmetro del mtodo format(). As que el o a e campo de sustitucin {0} se reere al mdulo sys. o o sys.modules es un diccionario que almacena todos los mdulos que se han imo portando en la instancia de Python que se est ejecutando. Las claves son los a nombres de los mdulos en formato cadena de texto; los valores son propios o mdulos (objetos mdulo). Por ello {0.modules} se reere al diccionario que o o contiene todos mdulos que se han importado en Python hasta este momento. o 104

sys.modules[parahumanos] retorna el objeto parahumanos que acabas de importar. El campo de reemplazo sys.modules[parahumanos] se reere al mdulo o parahumanos. Observa que existe una ligera diferencia de sintaxis. En el cdigo o de Python, las claves del diccionario es de tipo cadena; para referirse a ellas, es necesario poner comillas alrededor del nombre del mdulo (parahumanos). o Pero dentro de los campos de sustitucin no se ponen las comillas alrededor o del nombre de la clave del diccionario (parahumanos). Segn el PEP 3101: u Formateo avanzado de cadenas: Las reglas para el parseo de la clave de un campo de sustitucin son muy simples, si comienza por un d o gito, se trata como numrica, en caso contrario se interpreta como una cadena. e sys.modules[parahumanos].SUFIJOS es el diccionario denido en el mdulo pao rahumanos. El campo de sustitucin sys.modules[parahumanos].SUFIJOS se reo ere a este diccionario. sys.modules[parahumanos].SUFIJOS[1000] es la lista de sujos mltiplos de u 1000: [KB, MB, GB, TB, PB, EB, ZB, YB] Por lo que el campo de sustitucin sys.modules[parahumanos].SUFIJOS[1000] se reere a esta lista. o sys.modules[parahumanos].SUFIJOS[1000][0] es el primer elemento de la lista de sujos: [KB]. Por lo tanto el campo de sustitucin sys.modules[parahumanos].SUFIJOS[1000][0] o se reere a la cadena KB.

4.4.2.

Especicaciones de formato

Pero espera! Hay mas! Vamos a echar otro vistazo a la l nea de cdigo ms o a extraa de parahumanos.py: n
1 2 i f tamanyo < m u l t i p l o : return { 0 : . 1 f } {1} . format ( tamanyo , s u f i j o )

Como ya sabemos, {1} se sustituye por el segundo parmetro sujo del mtodo a e format(). Pero qu es {0:.1f}? Tiene dos partes, {0} que ya conoces, y :.f que no coe noces. La segunda parte (desde los dos puntos hasta la letra f) dene el especicador de forma que ana cmo debe sustituirse la variable al formatearla. o Los especicadores de formato te permiten indicar cmo se debe efeco tuar la sustitucin del texto, como sucede con la funcin printf() en el o o lenguaje C. Puedes aadir ceros o espacios de relleno delante del nmero, n u alinear cadenas, controlar la precisin de decimales o convertir el nmero o u a hexadecimal. 105

Dentro del campo de sustitucin se utiliza el s o mbolo de dos puntos (:) para marcar el comienzo del especicador de formato. El especicador de formato .1 signica que se redondee a la dcima ms prxima (que se muestre unicamente e a o un d gito despus del punto decimal). El especicador f indica que el nmero e u debe mostrarse en formato punto jo (por oposicin a la notacin exponencial u o o otra representacin de un nmero). Si la variable tamanyo vale 698.24 y la variable o u sujo vale GB la cadena formateada resultante es 698.2 GB, porque 698.24 se redondea con un solo d gito despus del punto decimal. e
1 >>> { 0 : . 1 f } {1} . format ( 6 9 8 . 2 4 , GB ) 2 6 9 8 . 2 GB

Para conocer los detalles exactos de los especicadores de formato puedes consultar el apartado Mini-lenguaje de especicacin de formato5 de la documentacin o o ocial de Python 3.

4.5.

Otros mtodos habituales de manipulacin e o de cadenas

Adems de formatearlas, es posible hacer muchas otras cosas de utilidad con a las cadenas de texto.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >>> s = Los a r c h i v o s t e r m i n a d o s son e l re . . . s u l t a d o de a o s de e s t u d i o c i e n t n . . . f i c o combinados con l a . . . e x p e r i e n c i a de a o s . n >>> s . s p l i t l i n e s ( ) [ Los a r c h i v o s t e r m i n a d o s son e l re , s u l t a d o de a o s de e s t u d i o c i e n t , n f i c o combinados con l a , e x p e r i e n c i a de a o s . ] n >>> print ( s . l o w e r ( ) ) l o s a r c h i v o s t e r m i n a d o s son e l re s u l t a d o de a o s de e s t u d i o c i e n t n f i c o combinados con l a e x p e r i e n c i a de a o s . n >>> s . l o w e r ( ) . count ( l ) 4

1. Lnea 1: Puedes introducir cadenas multil nea en la consola interactiva de Python. Cuando inicias una cadena de texto multil nea debes pulsar la tecla
5

http://docs.python.org/3.1/library/string.html#format-specication-mini-language

106

INTRO para continuar en la siguiente l nea. Al teclear las triples comillas del nal, se cierra la cadena de texto y el siguiente INTRO que pulses ejecutar la a sentencia (en este caso asignar la cadena a la variable s). a 2. Lnea 5: El mtodo splitlines() toma una cadena multil e nea y devuelve una lista de cadenas de texto, una por cada l nea que contuviese la cadena original. Observa que las l neas no incluyen los retornos de carro o nales de l nea que tuviese la cadena original. 3. Lnea 10: El mtodo lower() convierte toda la cadena de texto a minsculas e u (El mtodo upper() convertir toda la cadena de texto a maysculas). e a u 4. Lnea 15: El mtodo count() cuenta el nmero de veces que aparece una sub e u cadena en la cadena de texto. S Hay 4 caracteres l en la cadena. ! Pongamos un caso muy comn. Supn que tienes una cadena de texto en forma u o de parejas clave-valor, clave1=valor1&clave2=valor2, y quieres dividirla y crear un diccionario de la forma {clave1: valor1, clave2: valor2}.
1 2 3 4 5 6 7 8 9 10 >>> c o n s u l t a = u s u a r i o=p i l g r i m&b a s e d e d a t o s=master&c l a v e=PapayaWhip >>> u n a l i s t a = c o n s u l t a . s p l i t ( & ) >>> u n a l i s t a [ u s u a r i o=p i l g r i m , b a s e d e d a t o s=master , c l a v e=PapayaWhip ] >>> u n a l i s t a d e l i s t a s = [ v . s p l i t ( = , 1 ) f o r v in u n a l i s t a ] >>> u n a l i s t a d e l i s t a s [ [ u s u a r i o , p i l g r i m ] , [ b a s e d e d a t o s , master ] , [ c l a v e , PapayaWhip ] ] >>> a d i c t = d i c t ( u n a l i s t a d e l i s t a s ) >>> a d i c t { c l a v e : PapayaWhip , u s u a r i o : p i l g r i m , b a s e d e d a t o s : master }

1. Lnea 2: El mtodo split() toma un parmetro, un delimitador, y divide la e a cadena en una lista de cadenas basndose en el delimitador proporcionado. En a este ejemplo, el delimitador es el carcter &. a 2. Lnea 5: Ahora tenemos una lista de cadenas, cada una de ellas con una clave seguida del s mbolo = y de un valor. Podemos utilizar las listas por comprensin para iterar sobre esta lista y dividir cada una de estas cadenas de texto o en dos cadenas utilizando el mtodo split pasndole un segundo parmetro que e a a indica que unicamente utilice la primera ocurrencia del carcter separador (En a teor una cadena podr tener ms de un s a a a mbolo igual si el valor, a su vez, contiene tambin el s e mbolo igual, por ejemplo: clave=valor=cero, con lo que clave=valor=cero.split(=) dar como resultado [clave, valor, cero]). a 3. Lnea 8: Finalmente, Python puede convertir esa lista de listas en un diccio nario con solo pasarla como parmetro a la funcin dict(). a o 107

El ejemplo anterior, explica un caso que se parece a lo que habr que a hacer para reconocer los parmetros de una URL. pero en la vida real, el a reconocimiento de los parmetros de una URL es ms complejo. Si vas a a a tener que reconocer los parmetros que recibes mediante una URL utiliza a la funcin de la librer urlib.parse denominada parse qs()6 , que reconoce o a los casos ms complejos. a

4.5.1.

Troceado de cadenas

Cuando ya has denido una cadena puedes recuperar cualquier parte de ella creando una nueva cadena de texto. A esto se denomina troceado/particionado de cadenas7 . Esto funciona de forma idntica a como funciona para las listas, lo que e tiene sentido, porque las cadenas de texto no son ms que cadenas de caracteres. a
1 2 3 4 5 6 7 8 9 10 11 >>> una cadena = Mi v o c a b u l a r i o comienza donde e l tuyo t e r m i n a >>> una cadena [ 3 : 1 4 ] vocabulario >>> una cadena [ 3 : 3 ] v o c a b u l a r i o comienza donde e l tuyo term >>> una cadena [ 0 : 2 ] Mi >>> una cadena [ : 2 3 ] Mi v o c a b u l a r i o comienza >>> una cadena [ 2 3 : ] donde e l tuyo t e r m i n a

1. Lnea 2: Puedes recuperar una parte de la cadena de texto, una parte de ella, especicando dos ndices. El valor de retorno es una nueva cadena que comienza en el primer ndice y termina en el elemento anterior al segundo ndice. 2. Lnea 4: Como sucede con las listas, puedes utilizar ndices negativos para seleccionar. 3. Lnea 6: Las cadenas tambin comienzan a contar en cero, por lo que una cadena[0:2] e devuelve los dos primeros elementos de la cadena, comenzando en la posicin o una cadena[0] hasta la posicin una cadena[2], pero sin incluirla. o 4. Lnea 8: Si el ndice de la parte izquierda vale 0 puedes omitirlo. De este modo, una cadena[:23] es lo mismo que una cadena[0:18]. Ya que en ausencia del primer ndice se asume el nmero 0. u
6 7

http://docs.python.org/3.1/library/urllib.parse.html#urllib.parse.parse qs Nota del traductor: slicing en ingls e

108

5. Lnea 10: De forma similar, si el ndice de la parte derecha de la cadena coincide con la longitud de la cadena, puedes omitirlo. As que una cadena[23:] es lo mismo que una cadena[23:45] al medir esta cadena 45 caracteres. Como ves, existe una estupenda simetr en esto, en esta cadena de 45 caracteres a una cadena[0:23] devuelve los primeros 23 caracteres, y una cadena[23:] devuelve todo lo dems, salvo los 23 caracteres iniciales. De hecho una cadena[:n] a siempre retornar los primeros n caracteres, y una cadena[n:] retornar el resto, a a independientemente de la longitud que tenga la cadena.

4.6.

Cadenas de texto y Bytes

Los bytes son bytes; los caracteres son una abstraccin. A una secuencia ino mutable de caracteres Unicode se le llama cadena de texto. Una secuencia inmutable de nmeros entre el 0 y el 255 es un objeto que se denomina bytes. u
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 >>> by = b abcd \ x65 >>> by b abcde >>> type ( by ) <c l a s s b y t e s > >>> l e n ( by ) 5 >>> by += b \ x f f >>> by b abcde \ x f f >>> l e n ( by ) 6 >>> by [ 0 ] 97 >>> by [ 0 ] = 102 Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> TypeError : b y t e s o b j e c t d o e s not s u p p o r t item a s s i g n m e n t

1. Lnea 1: Para denir un objeto bytes se usa la sintaxis de literal de bytes que es b. Cada byte dentro del literal de bytes se interpreta como un carcter a ASCII o un carcter codicado en nmero hexadecimal desde a u x00 a xFF (0-255). 2. Lnea 4: El tipo de un objeto bytes es bytes. 3. Lnea 6: Como sucede con las listas y cadenas, puedes conocer la longitud de un objeto bytes utilizando la funcin interna len(). o 109

4. Lnea 8: Como sucede con las listas y cadenas, puedes utilizar el operador + para concatenar objetos bytes. El resultado es un nuevo objeto bytes. 5. Lnea 11: Concatenar un objeto bytes de 5 bytes con uno de 1 byte da como resultado un objeto bytes de 6 bytes. 6. Lnea 13: Como sucede con las listas y cadenas, puedes utilizar la notacin o de ndices para obtener bytes individuales del objeto bytes. Los elementos individuales de una cadena son de tipo cadena; los elementos individuales de un objeto bytes son nmeros enteros. Espec u camente, enteros entre 0 y 255. 7. Lnea 15: Un objeto bytes es inmutable; no puedes asignar bytes individua les. Si necesitas modicar bytes individuales de un objeto bytes, es necesario particionar y concatener para crear un nuevo objeto bytes que contenga los elementos deseados. La alternativa es convertir el objeto bytes en un bytearray que s permite modicacin. o
1 2 3 4 5 6 7 8 9 >>> by = b abcd \ x65 >>> b a r r = b y t e a r r a y ( by ) >>> b a r r b y t e a r r a y ( b abcde ) >>> l e n ( b a r r ) 5 >>> b a r r [ 0 ] = 102 >>> b a r r bytearray (b fbcde )

1. Lnea 2: Para convertir un objeto bytes en un objeto modicable de tipo by tearray puedes utilizar la funcin interna bytearray(). o 2. Lnea 5: Todos los mtodos y operaciones que existen en el objeto bytes tam e bin estn disponibles en el objeto bytearray. e a 3. Lnea 7: Una de las diferencias es que al objeto bytearray es posible modi carle bytes individuales utilizando la notacin de o ndice. El valor que se puede asignar debe estar entre 0 y 255. Algo que no se puede hacer es mezclar bytes y cadenas.

110

1 2 3 4 5 6 7 8 9 10 11 12

>>> by = b d >>> s = abcde >>> by + s Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> TypeError : can t c o n c a t b y t e s t o s t r >>> s . count ( by ) Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n >, l i n e 1 , i n <module> TypeError : Can t c o n v e r t b y t e s o b j e c t t o s t r i m p l i c i t l y >>> s . count ( by . decode ( a s c i i ) ) 1

1. Lnea 3: No puedes concatenar bytes y cadenas. Son dos tipos de dato dife rentes. 2. Lnea 7: No puedes contar las veces que aparece una secuencia de bytes en una cadena, porque no existen bytes en una cadena. Una cadena es una secuencia de caracteres. Tal vez lo que quer contar era las veces que aparece la cadena que as obtendr despus de haber decodicado la secuencia de bytes interpretndola as e a a partir de una tabla de codicacin de caracteres particular. Si es as debes o , decirlo expl citamente. Python 3 no convertir implic a tamente bytes en cadenas o cadenas en bytes. 3. Lnea 11: Por una sorprendente coincidencia esta l nea de cdigo dice cuenta o las ocurrencias de la cadena que se obtiene despus de decodicar la secuencia e de bytes en esta tabla de caracteres particular (ASCII). Y de este modo has llegado a la relacin que existe entre las cadenas de texto o y los bytes: los objetos bytes tienen un mtodo decode() que toma como parmetro e a una tabla de codicacin de caracteres y retorna una cadena. Y las cadenas de o texto tienen un mtodo denominado encode() que toma una tabla de codicacin e o de caracteres y retorna un objeto bytes. En el ejemplo anterior, la decodicacin fue o relativamente directa convertir una secuencia de bytes que estaba en la codicacin o de caracteres ASCII en una cadena de texto. Pero el mismo proceso funciona con cualquier tabla de codicacin de caracteres siempre que dicha tabla soporte los o caracteres existentes en la cadena incluso con codicaciones heredadas (previas a Unicode).

111

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

>>> s = Python >>> l e n ( s ) 9 >>> by = s . encode ( u t f 8 ) >>> by b \ xe5 \ x b f \ xab \ xe4 \ xb9 \ x90 Python >>> l e n ( by ) 13 >>> by = s . encode ( gb18030 ) >>> by b \ x b f \ xec \ xc0 \ xd6 Python >>> l e n ( by ) 11 >>> by = s . encode ( u t f 16 ) >>> by b \ x f f \ x f e \xeb PN \x00P\ x00y \ x00t \ x00h \ x00o \ x00n \ x00 >>> l e n ( by ) 20 >>> v u e l t a = by . decode ( u t f 16 ) Python >>> v u e l t a == s True

1. Lnea 1: Esto es una cadena de texto, tiene 9 caracteres. 2. Lnea 4: El resultado de codicar la cadena en UTF-8 es un objeto bytes. Tiene 13 bytes. 3. Lnea 9: El resultado de codicar la cadena en GB18030 es un objeto bytes de 11 bytes. 4. Lnea 14: El resultado de codicar la cadena en UTF-16 es un objeto bytes de 20 bytes. 5. Lnea 19: Al decodicar el objeto bytes utilizando la codicacin adecuada (la o misma que se us al codicarlo) se obtiene una cadena de texto. En este caso o tiene 9 caracteres. Como se puede ver, es una cadena idntica a la original. e

4.7.

Postdata: Codicacin de caracteres del cdio o go fuente de Python

Python 3 asume que el cdigo fuente cada chero .py est codicado en o a UTF-8. 112

En Python 2, la codicacin de caracteres por defecto de los cheros o .py era ASCII. En Python 3, la codicacin por defecto de los cheros es o UTF-8 Si quisieras utilizar una codicacin de caracteres diferente en el chero con o el cdigo fuente, puedes incluir una declaracin de codicacin de caracteres en la o o o primera l nea cada chero. La siguiente declaracin dene que el chero se encuentra o en una codicacin windows-1252 o
1 #

c o d i n g : windows 1252

Tcnicamente la indicacin de la codicacin de caracteres puede estar en la e o o segunda l nea si la primera l nea es una declaracin de lanzador de ejecucin del o o estilo de UNIX.
1 #! / u s r / b i n / python3 2 # c o d i n g : windows 1252

Para disponer de ms informacin consulta la propuesta de mejora de Python a o 8 PEP 263 .

4.8.

Lecturas recomendadas

Sobre Unicode en Python: Unicode en Python - http://docs.python.org/3.0/howto/unicode.html Qu hay nuevo en Python 3: Texto y datos en lugar de Unicode y 8-bits e http://docs.python.org/3.0/whatsnew/3.0.html#text-vs-data-instead-of-unicodevs-8-bit Sobre Unicode en general: El m nimo absoluto que todo programador debe conocer positiva y absolutamente sobre Unicode y codicacin de caracteres (Sin excusas!): o http://www.joelonsoftware.com/articles/Unicode.html Sobre las bondades de Unicode: http://www.tbray.org/ongoing/When/200x/2003/04/06/Unicode
8

http://www.python.org/dev/peps/pep-0263/

113

Sobre cadenas de caracteres: http://www.tbray.org/ongoing/When/200x/2003/04/13/Strings Caracteres y bytes: http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF Sobre codicacin de caracteres en otros formatos: o Codicacin de caracteres en XML: o http://feedparser.org/docs/character-encoding.html Codicacin de caracteres en HTML: o http://blog.whatwg.org/the-road-to-html-5-character-encoding Sobre cadenas y formateo de cadenas: stringOperaciones comunes sobre cadenas: http://docs.python.org/3.1/library/string.html Sintaxis de formateo de cadenas de texto: http://docs.python.org/3.1/library/string.html#formatstrings Especicacin del minilenguaje de formato: o http://docs.python.org/3.1/library/string.html#format-specication-mini-language PEP 3101: Formateo avanzado de cadenas: http://www.python.org/dev/peps/pep-3101/

114

Cap tulo 5 Expresiones regulares


Nivel de dicultad:   Algunas personas, cuando se enfrentan a un problema, piensan: Ya s! usar expresiones regulares. Y as, acaban e e enfrentndose a dos problemas. a Jamie Zawinski

5.1.

Inmersin o

Todo lenguaje de programacin moderno dispone de funciones internas para o trabajar con cadenas. En Python las cadenas de texto tienen mtodos para buscar e y reemplazar: index(), nd(), split(), count(), replace(), etc. Pero esos mtodos estn e a limitados a los casos ms simples. Por ejemplo, el mtodo index() busca por una a e unica subcadena, y la bsqueda siempre distingue entre maysculas y minsculas. u u u Para poder hacer bsquedas que no distingan entre ellas debes utilizar s.lower() o u s.upper() y asegurarte de que tus cadenas de bsqueda se encuentran en el mismo u caso. Los mtodos replace() y split(). e Si tu objetivo se cumple con estos mtodos deber usarlos. Son rpidos, sime as a ples y sencillos de leer; y hay mucho que decir a favor del cdigo legible, simple o y rpido. Pero si te descubres escribiendo un montn de funciones para manipular a o cadenas con sentencias if para contemplar casos especiales, o te encuentras encadenando llamadas a split() y join() para trocear tus cadenas de texto, puede que necesites utilizar expresiones regulares. Las expresiones regualres son una forma poderosa y (en su mayor parte) estndar de bsqueda, reemplazo y anlisis de texto con patrones de caracteres a u a 115

complejos. Aunque la sintaxis de las expresiones regulares es compacta y muy diferente del cdigo normal, el resultado puede resultar ser ms legible que una solucin o a o manual que utilice un montn de funciones de cadenas de texto encadenadas. Incluso o existe un modo estndar de incluir comentarios dentro de las expresiones regulares, a por lo que puedes incluir una documentacin detallada dentro de ellas. o Si has utilizado expresiones regulares en otros lenguajes (como Perl, JavaScript o PHP), la sintaxis de Python te ser muy familiar. Puedes a limitarte a leer las funciones disponibles y sus parmetros en el resumen a de la documentacin del mdulo re1 o o

5.2.

Caso de estudio: direcciones de calles

Esta serie de ejemplos se inspira en un problema de la vida real que tuve en en el trabajo hace varios aos, cuando necesit depurar y estandarizar una lista de n e direcciones postales exportadas de un sistema heredado antes de importarlas en un nuevo sistema2 . Este ejemplo muestra la forma en la que abord el problema: e
1 2 3 4 5 6 7 8 9 10 11 >> s = 100 NORTH MAIN ROAD >>> s . r e p l a c e ( ROAD , RD. ) 100 NORTH MAIN RD. >>> s = 100 NORTH BROAD ROAD >>> s . r e p l a c e ( ROAD , RD. ) 100 NORTH BRD. RD. >>> s [ : 4 ] + s [ 4 : ] . r e p l a c e ( ROAD , RD. ) 100 NORTH BROAD RD. >>> import r e >>> r e . sub ( ROAD$ , RD. , s ) 100 NORTH BROAD RD.

1. Lnea 2: Mi objetivo es estandarizar las direcciones postales de forma que ROAD siempre se escribiera como RD.. En un primer vistazo pens que era e lo sucientemente simple como para que pudiera utilizar el mtodo replace(). e Despus de todo, las cadenas de texto estaban en maysculas por lo que no e u ser un problema la existencia de posibles minsculas. Y la cadena de bsquea u u da, ROAD, era una constante. Y en este simple ejemplo s.replace(), de hecho, funciona. 2. Lnea 5: La vida, desafortunadamente, est llena de contraejemplos, y rpida a a mente encontr este caso. El problema aqu es que ROAD aparece dos veces e
1 2

http://docs.python.org/dev/library/re.html#module-contents Como ves no me invento cosas de la nada, los ejemplos son realmente utiles.

116

en la direccin, una de ellas siendo parte del nombre de la calle BROAD y o otra por s misma. El mtodo replace() encuentra ambos casos y los reemplaza e ciegamente; destruyendo las direcciones. 3. Lnea 7: Para resolver el problema de las direcciones con ms de una ocurren a cia de la cadena de texto ROAD puedes recurrir a algo como esto: unicamente buscar y reemplazar ROAD en los ultimos cuatro caracteres de la direccin o s[-4:], y dejar el resto de la cadena igual, s[:-4]. Como ves, se est volviendo ina manejable. Por ejemplo, la forma la solucin depende del tamao de la cadena o n de bsqueda. Si intentases sustituir STREET por ST., necesitar utilizar u as s[:-6] y s[-6:].replace(...). Te gustar volver dentro de seis meses a depurar a este cdigo? S que yo no. o e 4. Lnea 9: Es el momento de pasar a las expresiones regulares. En Python esta funcionalidad se incluye en el mdulo re. o 5. Lnea 10: Echa un vistazo al primer parmetro: ROAD$. Esta simple expre a sin regular unicamente encuentra los casos en los que ROAD aparece al nal o de la l nea. El s mbolo $ signica n de la cadena. Exite otro carcter, el a circunejo: , que signica inicio de la cadena . Mediante el uso de la funcin o re.sub(), se busca en la cadena s la existencia de la expresin regular ROAD$ o para sustituirla por RD.. Esto permite encontrar ROAD al nal de la cadena s, pero no la parte contenida en BROAD puesto que se encuentra en medio de la cadena s. Continuando con mi relato sobre la depuracin de las direcciones postales, pronto deso ncuentra el comienzo de una e cubr que el ejemplo anterior, encontrar ROAD cadena. $ encuentra el nal. al nal de la direccin, no era suciente; no todas o las direcciones inclu la destinacin de la calle. an o Algunas direcciones simplemente terminaban con el nombre de la calle. La mayor parte de las veces no pasaba nada, pero si el nombre de la calle era BROAD la expresin regular encontraba ROAD al nal de la cadena como parte de la palabra, o que no era lo que quer yo. a

117

1 2 3 4 5 6 7 8 9 10 11 12

>>> s = 100 BROAD >>> r e . sub ( ROAD$ , RD. , s ) 100 BRD. >>> r e . sub ( \bROAD$ , RD. , s ) 100 BROAD >>> r e . sub ( r \bROAD$ , RD. , s ) 100 BROAD >>> s = 100 BROAD ROAD APT. 3 >>> r e . sub ( r \bROAD$ , RD. , s ) 100 BROAD ROAD APT. 3 >>> r e . sub ( r \bROAD\b , RD. , s ) 100 BROAD RD. APT 3

1. Lnea 4: Lo que yo realmente quera era buscar ROAD cuando estuviera al nal de la l nea y fuese una palabra por s misma (y no parte de una palabra mayor). Para expresar esto en una expresin regular debes utilizar zb, que o indica que un l mite de palabra debe existir en ese lugar. En Python, expresar esta cadena es algo complicado debido a que el s mbolo z suele indicar un carcter de escape, y hay que escribirlo dos veces para representarlo como tal. a Esto hay quien lo llama la plaga de las barras inclinadas invertidas, y es el argumento para decir que las expresiones regulares son ms sencillas en Perl a que en Python. En el lado negativo, Perl mezcla la sintaxis de las expresiones regulares con otra sintaxis, por lo que si tienes un error, es ms dif saber si a cil el error es en la sintaxis o en la expresin regular. o 2. Lnea 6: Para evitar la plaga de las barras inclinadas invertidas puedes utili zar lo que se llaman cadenas de texto crudas3 mediante el uso del prejo r delante de la cadena de texto. Este tipo de cadena de texto le dice a Python que nada de lo que contiene es un carcter de escape: la cadena zt represena ta al carcter tabulador, pero rzt es una cadena que contiene como primer a carcter la barrra inclinada invertida seguida de la letra t. Por eso, recomiena do que siempre utilices cadenas de texto crudas cuando vayas a escribir una expresin regular; en caso contrario, las cosas se vuelven confusas en cuanto la o expresin regular es algo compleja (y las expresiones regulares ya confunden o sucientemente por s mismas). 3. Lnea 9: Desafortunadamente rpidamente encontr ms casos que contradi a e a jeron mi razonamiento. En este caso la direccin conten la palabra ROAD o a pero no al nal de la cadena de texto, ya que conten tambin el nmero del a e u apartamento despus de la designacin de la calle. Al no encontrarse al nal e o de la cadena, no se sustituye nada porque la expresin regular no coincide. o
3

Nota del traductor: raw en ingls. e

118

4. Lnea 11: Para resolver este problema acab quitando el carcter $ y poniendo e a otro zb. De esta forma la expresin regular signica encuentra ROAD cuando o es una palabra completa en cualquier parte de la cadena, tanto si est al a principio, al nal o en cualquier otra parte.

5.3.

Caso de estudio: n meros romanos u

Es muy probable que hayas visto nmeros romanos en alguna parte incluso u aunque no los hayas reconocido. Puedes haberlos visto en los crdidos de las pel e culas antiguas o programas de televisin (Copyright MCMXLVI) o en las paredes o de las bibliotecas y universidades (Establecido en MDCCCLXXXVIII en lugar de establecido en 1888). Puede que incluso los hayas visto en referencias bibliogra cas. Es un sistema de representacin numrica que se remonta a la poca del imperio o e e romano (de ah el nombre). En los nmeros romanos existen siete caracteres que se repiten y combinan de u diferentes formas para representar nmeros: u I=1 V=5 X = 10 L = 50 C = 100 D = 500 M = 1000 Existen una reglas generales para construir nmeros romanos: u Los caracteres son aditivos, I es 1, II es 2 y III es 3. VI es 6 (literalmente 5 + 1), VII es 7 (5+1+1) y XVIII es 18 (10+5+1+1+1). Los caracteres que representan unidades, decenas, centenas y unidades de millar (I, X, C y M) pueden aparecer juntos hasta tres veces como mximo. Para a el 4 debes restar del carcter V, L D (cinco, cincuenta, quinientos) que se a o encuentre ms prximo a la derecha. No se puede representar el cuatro como a o IIII, en su lugar hay que poner IV (5-1). El nmero 40 se representa como XL u (10 menos que 50: 50-10). 41 = XLI, 42 = XLII, 43 = XLIII y luego 44 = XLIV (diez menos que cincuenta ms uno menos que cinco: 50-10+5-1). a 119

De forma similar, para el nmero 9, debes restar del nmero siguiente ms u u a prximo que represente unidades, decenas, centenas o unidades de millar (I, o X, C y M). 8 = VIII, pero 9 = IX (1 menos que 10), no 9 = VIIII puesto que el carcter I no puede repetirse cuatro veces seguidas. El nmero 90 se representa a u con XC y el 900 con CM. Los caracteres V, L y D no pueden repetirse; el nmero 10 siempre se representa u como X y no como VV. El nmero 100 siempre se representa como C y nunca u como LL. Los nmeros romanos siempre se escriben de los caracteres que representan u valores mayores a los menores y se leen de izquierda a derecha por lo que el orden de los caracteres importa mucho. {DC es el nmero 600; CD otro nmero, u u el 400 (500 - 100). CI es 101, mientras que IC no es un nmero romano vlido u a 4 porque no puedes restar I del C .

5.3.1.
.

A b squeda de coincidencias de las unidades de millar u

Qu costar conocer que una cadena de texto es un nmero romano vlido? e a u a Vamos a hacerlo d gito a d gito para facilitar la tarea y la explicacin. Puesto que o los nmeros romanos siempre se escriben del mayor al menor, vamos a comenzar u por el mayor: las unidades de millar. Para los nmeros 1000 y superiores los miles u se representan por una serie de caracteres M.
1 2 3 4 5 6 7 8 9 10 11 >>> import r e >>> p a t t e r n = M?M?M? $ >>> r e . s e a r c h ( p a t t e r n , M ) <SRE Match o b j e c t a t 0106FB58> >>> r e . s e a r c h ( p a t t e r n , M ) M <SRE Match o b j e c t a t 0106 C290> >>> r e . s e a r c h ( p a t t e r n , M M ) M <SRE Match o b j e c t a t 0106AA38> >>> r e . s e a r c h ( p a t t e r n , M M ) M M >>> r e . s e a r c h ( p a t t e r n , ) <SRE Match o b j e c t a t 0106F4A8>

1. Lnea 2: Este patrn tiene tres partes: identica el comienzo de la l o nea unicamente. Si no lo indicramos as el resto del patrn validar cualquier a , o a posicin dentro de una cadena en la que se encontrase, cosa que no quieres. Lo o que quieres es estar seguro de que los caracteres M se encuentran al comienzo
4

Para representar el 99 deber usar: XCIL (100 - 10 + 10 - 1) as

120

de la cadena. M? indica que se valide si existe un carcter M de forma opcional a en la posicin indicada. Como se repite tres veces, lo que ests diciendo es que o a se valide si existe el carcter M de cero a tres veces (al principio de la cadena a debido al ). Y por ultimo, $ valida el nal de la l nea. Cuando se combina con el carcter al comienzo, signica que el patrn debe coincidir con la cadena a o de texto completa, por lo que en este caso unicamente es posible que tenga de cero a tres caracteres M. 2. Lnea 3: La esencia del mdulo re es la funcin search(), que toma como pri o o mer parmetro una expresin regular (pattern) y como segundo una cadena a o de texto que es la que se comprobar para ver si coincide con la expresin a o regular. Si se encuentra una cadena identicada por las expresin regular, esta o funcin retorna un objeto que tiene diversos mtodos para describir la cadena o e encontrada. Si no se encuentra nada equivalente al patrn, la funcin retorna o o None. Por ahora lo unico que te interesa es conocer si una cadena cumple el patrn, y para ello basta ver qu valor retorna la funcin search. M cumple la o e o expresin regular, porque el primer M opcional coincide con el primer caracter o de la cadena y las siguientes M del patrn son ignoradas. o 3. Lnea 5: MM cumple la expresin regular porque el primer y segundo M o opcional coinciden con la primera y segunda letra M de la cadena. La tercera M opcional se ignora. 4. Lnea 7: MMM cumple la expresin regular porque los tres caracteres M o coinciden. 5. Lnea 9: MMMM no cumple la expresin regular. Los tres primeros caracteres o coinciden, pero en este momento la expresin regular insiste en que se debe o terminar la cadena (debido al carcter $), pero la cadena de texto no ha a nalizado an, existe una cuarta M. Por eso la funcin search() retorna None. u o 6. Lnea 10: La cadena de textos vac tambin cumple el patrn puesto que los a e o tres caracteres M son opcionales. ? hace que un patrn sea opcional. o

5.3.2.

A la b squeda de coincidencias de las centenas u

Las centenas son ms dif a ciles que los miles, porque existen varias formas exclusivas de representacin dependiendo del valor. o 100 = C 121

200 = CC 300 = CCC 400 = CD 500 = D 600 = DC 700 = DCC 800 = DCCC 900 = CM Por lo que existen cuatro patrones posibles: CM CD De cero a tres caracteres C (Cero si el lugar de las centenas vale cero). D, seguido de cero a tres caracteres C. Los dos ultimos patrones se pueden combinar: Una D opcional, seguida de cero a tres caracteres C. Este ejemplo muestra cmo validar las centenas de un nmero romano. o u
1 2 3 4 5 6 7 8 9 10 11 >>> import r e >>> p a t t e r n = M?M?M? (CM|CD|D?C?C?C? ) $ >>> r e . s e a r c h ( p a t t e r n , MCM ) <SRE Match o b j e c t a t 01070390 > >>> r e . s e a r c h ( p a t t e r n , MD ) <SRE Match o b j e c t a t 01073A50> >>> r e . s e a r c h ( p a t t e r n , MMMCCC ) <SRE Match o b j e c t a t 010748A8> >>> r e . s e a r c h ( p a t t e r n , MCMC ) >>> r e . s e a r c h ( p a t t e r n , ) <SRE Match o b j e c t a t 01071D98>

122

1. Lnea 2: El patrn de esta expresin regular comienza igual que el anterior, o o se valida el comienzo de la cadena (), luego de cero a tres unidades de millar (M?M?M?). Luego viene la parte nueva, se denen tres conjuntos de patrones mutuamente excluyentes. Para ello se utilizan los parntesis y la barra vertical: e CM, CD y D?C?C?C? (este ultimo representa a una D opcional seguida de cero a tres C). El analizador de expresiones regulares comprueba cada uno de estos patrones en el orden en que se muestran (de izquierda a derecha), toma el primero que coincide e ignora el resto. Si no coincide ninguno, falla la bsqueda u en la cadena de texto. 2. Lnea 3: MCM cumple el patrn porque la primera M coincide, la segunda y o la tercera del patrn se ignoran, y la CM coincide (los patrones CD y D?C?C?C? o no llegan a considerarse). MCM es la representacin romana del 1900. o 3. Lnea 5: MD cumple porque la primera M coincide, la segunda y tercera M del patrn se ignoran, y el patrn D?C?C?C? coincide en la D (los tres caracteres o o C son opcionales). MD es el nmero romano 1500. u 4. Lnea 7: MMMCCC cumple la expresin regular porque coinciden las tres M o opcionales, y el patrn D?C?C?C? coincide con CCC (la D es opcional y se o ignora). MMMCCC es el nmero romano que representa el 3300. u 5. Lnea 9: MCMC no cumple la expresin. La primera M del patrn coincide, o o las siguientes se ignoran, y CM coincide, pero al nal $ porque espera que se haya acabado la cadena pero an queda la C en la cadena de texto. La C no u coincide como parte del patrn D?C?C?C? porque es mutuamente excluyente o con el patrn CM que es el que se ha cumplido anteriormente. o 6. Lnea 10: La cadena vac an cumple este patrn. puesto que todos los ca a u o racteres M son opcionales y la cadena vac tambin coincide con el patrn a e o D?C?C?C? en el que todos los caracteres son tambin opcionales. e Vaya! Ves qu fcil es que las expresiones regulares se vayan complicando? e a Y por ahora unicamente hemos incluido las unidades de millar y las centenas de los nmeros romanos. Pero si has llegado hasta aqu ahora las decenas y las unidades u , sern fciles para t porque siguen exactamente el mismo patrn. Vamos a ver otra a a , o forma de expresar la expresin regular. o

5.4.

Utilizacin de la sintaxis {n,m} o

En la seccin anterior viste casos de caracteres que se pod repetir hasta tres o an veces. Existe otra forma de representar esto en las expresiones regulares que puede 123

resultar ms legible. Primero observa el mtodo que ya hemos usado en el ejemplo a e anterior.
1 2 3 4 5 6 7 8 9 10 11 12 >>> import r e >>> p a t t e r n = M?M?M? $ >>> r e . s e a r c h ( p a t t e r n , M ) < s r e . SRE Match o b j e c t a t 0x008EE090> >>> p a t t e r n = M?M?M? $ >>> r e . s e a r c h ( p a t t e r n , M ) M < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> p a t t e r n = M?M?M? $ >>> r e . s e a r c h ( p a t t e r n , M M ) M < s r e . SRE Match o b j e c t a t 0x008EE090> >>> r e . s e a r c h ( p a t t e r n , M M ) M M >>>

1. Lnea 3: El patrn coincide con el inicio de la cadena, luego con la primera o M, las restantes se ignoran por ser opcionales, para terminar coincidiendo el $ con el nal de la cadena. 2. Lnea 6: El patrn coincide con el inicio de la cadena, luego coinciden la o primera y segunda M, la tercera se ignora, para terminar encontrando el nal de la cadena. 3. Lnea 9: El patrn coincide con el inicio de la cadena, luego las tres M para o terminar con el nal de la cadena. 4. Lnea 11: El patrn coincide con el inicio de la cadena y las tres M, pero luego o no coincide con el nal de la cadena, que es lo que se espera, puesto que an u queda en la cadena una letra M que falta por coincidir. Por eso el patrn no o se cumple y se devuelve None.
1 2 3 4 5 6 7 8 9 >>> p a t t e r n = M{ 0 , 3 } $ >>> r e . s e a r c h ( p a t t e r n , M ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , M ) M < s r e . SRE Match o b j e c t a t 0x008EE090> >>> r e . s e a r c h ( p a t t e r n , M M ) M < s r e . SRE Match o b j e c t a t 0x008EEDA8> >>> r e . s e a r c h ( p a t t e r n , M M ) M M >>>

1. Lnea 1: Este patrn dice: Busca el comienzo de la cadena, luego busca de cero o a tres M y termina con el nal de la cadena. Los nmeros 0 y 3 del ejemplo u se pueden sustituir por cualquier combinacin; si lo que quisieras fuera que al o menos hubiera una M podr utilizar M{1,3}. as 124

2. Lnea 2: El patrn coincide con el comienzo de la cadena, luego con la M de o las tres posibles y termina encontrando el nal de la cadena. 3. Lnea 4: El patrn coincide con el comienzo de la cadena, luego con las dos M o de las tres posibles y termina encontrando el nal de la cadena. 4. Lnea 6: El patrn coincide con el comienzo de la cadena, luego con las tres o M y termina encontrando el nal de la cadena. 5. Lnea 8: El patrn coincide con el inicio de la cadena y las tres M, pero luego o no coincide con el nal de la cadena, que es lo que se espera, puesto que an u queda en la cadena una letra M que falta por coincidir. Dicho de otro modo, el patrn espera unicamente un mximo de tres M antes del nal de la cadena o a pero en este caso hay cuatro. Por eso el patrn no se cumple y se devuelve o None. {1,4} busca la coincidencia de una a cuatro veces del patrn relacionado. o

5.4.1.

Comprobacin de las decenas y las unidades o

Vamos a completar la expresin regular de bsqueda de nmeros romanos para o u u incluir a las decenas y unidades. Este ejemplo incluye las decenas.
1 2 3 4 5 6 7 8 9 10 11 >>> p a t t e r n = M?M?M? (CM|CD|D?C?C?C? ) (XC| XL | L?X?X?X? ) $ >>> r e . s e a r c h ( p a t t e r n , MCMXL ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , MCML ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , MCMLX ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , MCMLXXX ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , MCMLXXXX ) >>>

1. Lnea 2: El patrn encuentra el comienzo de la cadena, luego la primera M o opcional, luego CM, luego XL y termina detectando el nal de la cadena. Recuerda que la sintaxis (ABC) signica que se encuentre unicamente una de las tres coincidencias. Al coincidir con XL se ignoran XC y L?X?X?X?. MCMXL es el nmero romano 1940. u 2. Lnea 4: Se encuentra el comienzo de la cadena, luego la primera M opcional, seguido de CM, luego L?X?X?X?. De esta ultima coincide L y se ignoran las 125

tres X. Se naliza al encontrar el nal de la cadena. El nmero romano MCML u representa al 1950. 3. Lnea 6: Al mirar el patrn en esta cadena se encuentra el comienzo de la o misma, luego la primera M opcional, seguido de CM, luego L?X?X?X?. Del patrn L?X?X?X? coincide con la L, luego con la primera X opcional y se o ignoran la segunda y tercera X. Se termina encontrando el nal de la cadena. El nmero romano MCMLX es 1960. u 4. Lnea 8: El patrn encuentra el comienzo de la misma, luego la primera M o opcional, seguido de CM, luego L?X?X?X? sirve para identicar LXXX, terminando al encontrar el nal de la cadena. El nmero romano MCMLXXX es u 1980. 5. Lnea 10: Encuentra el comienzo de la cadena, luego la primera M opcional, luego CM, luego la L opcional y las tres X opcionales, despus de este punto e falla la comprobacin, se espera el nal de la cadena pero queda una X. Por o eso, falla toda la expresin regular y se devuelve None. MCMLXXXX no es un o nmero romano vlido. u a (A|B) coincide si la cadena contiene o el patrn A o el B o La expresin para las unidades sigue un patrn idntico. Te ahorrar los detao o e e lles mostrndote el resultado nal. a
1 >>> p a t t e r n = M?M?M? (CM|CD|D?C?C?C? ) (XC| XL | L?X?X?X? ) ( IX | IV |V? I ? I ? I ? ) $

Cmo quedar utilizando la sintaxis {n,m} En el siguiente ejemplo observas o a el resultado.


1 2 3 4 5 6 7 8 9 >>> p a t t e r n = M{ 0 , 3 } (CM|CD|D?C{ 0 , 3 } ) (XC| XL | L?X{ 0 , 3 } ) ( IX | IV |V? I { 0 , 3 } ) $ >>> r e . s e a r c h ( p a t t e r n , MDLV ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , MMDCLXVI ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , MMMDCCCLXXXVIII ) < s r e . SRE Match o b j e c t a t 0x008EEB48> >>> r e . s e a r c h ( p a t t e r n , I ) < s r e . SRE Match o b j e c t a t 0x008EEB48>

1. Lnea 2: Encuentra el comienzo de la cadena, luego una de las tres posibles M, luego D?C{0,3}. De esta ultima subexpresin, coincide con la D y con cero de o las tres posibles C. Lo siguiente que hace es coincidir con L?X{0,3} al encontrar la L y cero de tres X. Luego coincide con V?I{0,3} al encontrar la V y cero de 126

tres posibles I. Se termina con la coincidencia satisfecha al encontrar el n de la cadena. El nmero romano MDLV representa al 1555. u 2. Lnea 4: Encuentra el comienzo de la cadena, luego dos de las tres posibles M; luego D?C{0,3} encontrando D y una C; luego coincide con L?X{0,3} al encontrar L y una X; luego coincide con V?I{0,3} al encontrar V y una de las tres posibles I, y termina con al nal de la cadena. El nmero romano u MMDCLXVI es el 2666. 3. Lnea 6: Encuentra el comienzo de la cadena, luego las tres posibles M; luego D?C{0,3} encuentra D y tres C; luego coincide con L?X{0,3} al encontrar L y tres X; luego coincide con V?I{0,3} al encontrar V y las tres posibles I, y termina con al nal de la cadena. El nmero romano MMMDCCCLXXXVIII es u el 3888 y es el mayor que se puede escribir sin utilizar una sintaxis extendida. 4. Lnea 8: Observa atentamente (me siento como un mago, mirad atentamente nios, voy a sacar un conejo de mi chistera). En este caso se encuentra el n comienzo de la cadena, luego ninguna M de las tres posibles, luego coincide con D?C{0,3} a saltarse la D opcional y encontrar cero caracteres C, luego coincide con L?X{0,3} por el mismo motivo que antes, y lo mismo sucede con V?I{0,3}. Luego encuentra el nal de la cadena. Fantstico! a Si has seguido todas las explicaciones y las has entendido a la primera ya lo ests haciendo mejor que lo hice yo. Ahora imag a nate tratando de comprender las expresiones regulares que haya escrito otra persona en medio de una funcin cr o tica para tu programa. O piensa simplemente en tener que volver a ver las expresiones regulares que escribiste hace unos meses. Yo lo he tenido que hacer y no es agradable. Vamos a ver ahora una sintaxis alternativa que puede ayudarte que las expresiones regulares sean ms comprensibles. a

5.5.

Expresiones regulares detalladas

Hasta ahora has visto lo que llamar expresiones regulares compactas. Son e dif ciles de leer e incluso, aunque averiges lo que hacen, no puedes estar seguro u de acordarte seis meses despus. En realidad, unicamente necesitas documentarlas. e Para eso puedes utilizar la documentacin incrustada5 . o Python te permite hacerlo mediante el uso de las expresiones regulares detalladas. Se diferencia de una expresin regular compacta en dos cosas: o
5

Nota del Traductor: inline en ingls. e

127

Los espacios en blanco se ignoran: espacios, tabuladores y retornos de carro o saltos de l nea. No se tienen en cuenta para el cumplimiento o no de la expresin o regular. Si quieres que exista realmente tal coincidencia ser necesario que a incluyas el carcter de escape delante de ellos. a Se ignoran los comentarios. Un comentario en una expresin regular detallada o es exactamente igual que en Python: comienza en el carcter # termina al a acabarse la l nea. En este caso, el comentario est incluido en una cadena de a texto de varias l neas en lugar de estar directamente en ti cdigo fuente, pero o por lo dems es exactamente lo mismo. a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 >>> p a t t e r n = M{ 0 , 3 } (CM|CD|D?C{ 0 , 3 } ) (XC| XL | L?X{ 0 , 3 } ) ( IX | IV |V? I { 0 , 3 } ) $ >>> r e . s e a r c h ( p a t t e r n , < s r e . SRE Match o b j e c t >>> r e . s e a r c h ( p a t t e r n , < s r e . SRE Match o b j e c t >>> r e . s e a r c h ( p a t t e r n , < s r e . SRE Match o b j e c t >>> r e . s e a r c h ( p a t t e r n ,

# # # # # # # # #

comienzo de l a cadena u n i d a d e s de m i l l a r 0 a 3 M c e n t e n a s 900 (CM) , 400 (CD) , 0 300 ( 0 a 3 C) , o 500 800 (D, s e g u i d o po 0 a 3 C) d e c e n a s 90 (XC) , 40 (XL) , 0 30 ( 0 a 3 X) , o 50 80 (L , s e g u i d o de 0 a 3 X) u n i d a d e s 9 ( IX ) , 4 ( IV ) , 03 ( 0 a 3 I ) , o 58 (V, s e g u i d o de 0 a 3 I ) f i n de l a cadena

M , r e .VERBOSE) a t 0x008EEB48> MCMLXXXIX , r e .VERBOSE) a t 0x008EEB48> MMMDCCCLXXXVIII , r e .VERBOSE) a t 0x008EEB48> M )

1. Lnea 12: Lo ms importante es recordar que cuando utilizas expresiones re a gulares detalladas debes aadir un parmetro ms a la llamada a la funcin: n a a o re.VERBOSE es una constante denida en el mdulo re que permite indicar a la o funcin que el patrn debe interpretarse como una expresin regular detallao o o da. Como puedes ver, este patrn tiene muchos espacios (que son ignorados) y o varios comentarios (tambin ignorados). Una vez se han suprimido los espacios e y los comentarios, la expresin regular es exactamente la misma que viste en o la primera parte de este cap tulo, solo que mucho ms legible. a 2. Lnea 14: Esta expresin encuentra en primer lugar el comienzo de la cadena, o luego una de las tres posibles M, luego CM, luego L y las tres posibles X, luego IX y se termina con el n de la cadena.

128

3. Lnea 16: Esta expresin encuentra en primer lugar el comienzo de la cadena, o luego las tres posibles M, luego D y las tres posibles C, luego L y las tres posibles X, luego V y las tres posibles I y se termina con el n de la cadena. 4. Lnea 18: No se cumple. Porqu? Porque no se le ha pasado el parmetro e a re.VERBOSE, por lo que la funcin re.search() est tratando a la expresin o a o regular como si no fuese detallada, por lo que ha intentado encontrar en la cadena M todos los espacios y comentarios que hemos introducido en el patrn. o Python no puede detectar automticamente si una expresin es detallada o a o no. Python asume siempre que una expresin regular es compacta, a no ser o que se le diga lo contrario.

5.6.

Caso de estudio: anlisis de n meros de telfono a u e

Hasta el momento te has concentrado en identicar patrones completos. O el patrn coincide o no. Pero las expresiones regulares permiten hacer mucho ms. o a Cuando una cadena de texto coincide con el patrn de la expresin regular puedes o o recuperar trozos de la cadena a partir del objeto que se retorna. Puedes recuperar qu partes de la cadena han coincidido con qu partes de la expresin regular. e e o Este ejemplo est sacado de otro problema a real que me encontr en el trabajo. El problee zd coincide con cualquier d gima: analizar un nmero de telfono americano. u e to numrico (0-9). zD coincide e El cliente quer que el nmero se introdujese a u con cualquier carcter que no a de forma libre (en un unico campo de texto en sea d gito. pantalla), pero luego quer almacenar en la baa se de datos de la compa de forma separada na el cdigo de area, principal, nmero y opcionalmente, una extensin. Mir un poco o u o e en la web buscando ejemplos de expresiones regulares que hicieran esto, pero no encontr ninguna sucientemente permisiva. e A continuacin muestro algunos ejemplos de nmeros de telfono que necesio u e taba que se pudieran aceptar: 800-555-1212 800 555 1212 800.555.1212 (800) 555-1212 800-555-1212-1234 129

800-555-1212x1234 800-555-1212 ext. 1234 work 1-(800) 555.1212 #1234 Cunta variedad! En cada uno de los casos anteriores necesitaba identicar a el cdigo de rea 800, el troncal 500 y el resto del nmero 1212. Asimismo, para o a u aquellos que presentaban la extensin necesitaba conocer que era 1234. o
1 2 3 4 5 6 7 8 >>> phonePattern = r e . c o m p i l e ( r ( \ d{3}) (\d{3}) (\d { 4 } ) $ ) >>> phonePattern . s e a r c h ( 800 555 1212 ) . g r o u p s ( ) ( 800 , 555 , 1212 ) >>> phonePattern . s e a r c h ( 800 555 1212 1234 ) >>> phonePattern . s e a r c h ( 800 555 1212 1234 ) . g r o u p s ( ) Traceback ( most r e c e n t c a l l l a s t ) : F i l e <s t d i n > , l i n e 1 , in <module> A t t r i b u t e E r r o r : NoneType o b j e c t has no a t t r i b u t e g r o u p s

1. Lnea 1: Las expresiones regulares siempre se leen de izquierda a derecha. Esta detecta el comienzo de la l nea y luego (zd{3}). Qu es (zd{3})? Bueno, zd e signica cualquier d gito numrico (0 a 9). El {3} signica que coincida e exactamente tres veces (tres d gitos en este caso), es una variacin de la o sintaxis {n,m} que viste antes. Al ponerlo todo entre parntesis se est diciendo e a identica exactamente tres d gitos numricos y recurdalos como un grupo e e para que te pueda preguntar por ellos ms tarde a 2. Lnea 2: Para acceder a los grupos, que se guardan durante la bsqueda de la u coincidencia de la cadena con expresin regular, se utiliza el mtodo groups() en o e el objeto que devuelve el mtodo search(). Este mtod (groups()) retornar una e e a tupla con tantos elementos como grupos se denieran en la expresion regular. En este caso se han denido tres grupos, dos con tres d gitos y un tercero con cuatro. 3. Lnea 4: Esta expresin regular no es perfecta, porque no es capaz de ma o nejar nmeros telefnicos con extensiones. Por eso ser necesario expandir la u o a expresin regular. o 4. L nea 5: Y en esta l nea se observa el porqu no debes encadenar en una unica e sentencia search() y group(). Si la funcin search() no encuentra ninguna coino cidencia en la cadena devuelve None, no un objeto de coincidencia. La llamada a None.groups() eleva una excepcin perfectamente clara: None no dispone de o la funcin groups(). (Por supuesto, no ser tan fcil ni tan obvio si la excepcin o a a o sucede en lo ms profundo de tu programa. S hablo por experiencia.) a , 130

1 2 3 4 5 6 7

>>> phonePattern = r e . c o m p i l e ( r ( \ d{3}) (\d{3}) (\d{4}) (\d+)$ ) >>> phonePattern . s e a r c h ( 800 555 1212 1234 ) . g r o u p s ( ) ( 800 , 555 , 1212 , 1234 ) >>> phonePattern . s e a r c h ( 800 555 1212 1234 ) >>> >>> phonePattern . s e a r c h ( 800 555 1212 ) >>>

1. Lnea 1: Esta expresion regular es prcticamente igual a la anterior. Como a antes, coincide con el inicio de la cadena, luego con un grupo de tres d gitos decimales, luego con el guin, otro grupo de tres d o gitos decimales, otro guin, o y luego con el grupo de cuatro d gitos decimales. Lo que es nuevo es que despus debe coincidir con otro guin seguido de uno o ms d e o a gitos decimales, para terminar con el n de la cadena. 2. Lnea 2: El mtodo groups() ahora retorna una tupla de cuatro elementos, e puesto que la expresin regular ahora dene cuatro grupos a recordar. o 3. Lnea 4: Desafortunadamente esta expresin regular tampoco es la solucin o o denitiva, porque asume siempre que las diferentes partes del telfono estn e a separadas por guiones. Qu pasa si estn separadas por puntos, espacios o e a comas? Necesitas una solucin ms general para que coincida con diferentes o a tipos de separadores. 4. Lnea 6: Ups! No solamente no hace todo lo que queremos sino que en reali dad es un paso atrs, puesto que ahora no es capaz de identicar nmeros de a u telfono sin extensiones. Esto no era lo que quer si la extensin est ah quiee as, o a res conocerla, pero si no est sigues queriendo conocer las diferentes partes del a nmero de telfono. u e El siguiente ejemplo muestra una expresin regular para manejar diferentes o separadores entre las diferentes partes del nmero de telfono. u e
1 2 3 4 5 6 7 8 9 >>> phonePattern = r e . c o m p i l e ( r ( \ d { 3 } ) \D+(\d { 3 } ) \D+(\d { 4 } ) \D+(\d+)$ ) >>> phonePattern . s e a r c h ( 800 555 1212 1234 ) . g r o u p s ( ) ( 800 , 555 , 1212 , 1234 ) >>> phonePattern . s e a r c h ( 800 555 1212 1234 ) . g r o u p s ( ) ( 800 , 555 , 1212 , 1234 ) >>> phonePattern . s e a r c h ( 80055512121234 ) >>> >>> phonePattern . s e a r c h ( 800 555 1212 ) >>>

131

1. Lnea 1: Agrrate a tu sombrero. Primero se busca la coincidencia del inicio a de la cadena, luego un grupo de tres caracteres y luego zD+. Qu es eso? e Bueno, zD coincide con cualquier carcter que no sea d a gito, y + signica 1 o ms. Por eso esta expresin zD+ encuentra uno o ms caracteres que no a o a sean d gitos. Esto es lo que vamos a utilizar para intentar identicar muchos tipos diferentes de separadores (en lugar de unicamente el guin). o 2. Lnea 2: El uso de zD+ en lugar de - signica que puedes encontrar nmeros u de telfono que utilicen espacios como separadores en lugar de guiones. e 3. Lnea 4: Por supuesto an se encuentran los nmeros de telfonos que utilizan u u e como separador el guin. o 4. Lnea 6: Desafortunadamente an no tenemos la respuesta nal porque se u est asumiendo que debe haber al menos un separador. Qu pasa si el nmero a e u no tiene ningn separador? u 5. Lnea 8: Ups! Y an no se ha arreglado el problema de que sea opcional, y no u obligatoria, la existencia de las extensiones. Ahora tienes dos problemas, pero se pueden resolver ambos con la misma tcnica. e El siguiente ejemplo muestra una expresin regular para manejar nmeros o u telefnicos sin separadores. o
1 2 3 4 5 6 7 8 9 >>> phonePattern = r e . c o m p i l e ( r ( \ d { 3 } ) \D ( \ d { 3 } ) \D ( \ d { 4 } ) \D ( \ d ) $ ) >>> phonePattern . s e a r c h ( 80055512121234 ) . g r o u p s ( ) ( 800 , 555 , 1212 , 1234 ) >>> phonePattern . s e a r c h ( 8 0 0 . 5 5 5 . 1 2 1 2 x1234 ) . g r o u p s ( ) ( 800 , 555 , 1212 , 1234 ) >>> phonePattern . s e a r c h ( 800 555 1212 ) . g r o u p s ( ) ( 800 , 555 , 1212 , ) >>> phonePattern . s e a r c h ( ( 8 0 0 ) 5 5 5 1 2 1 2 x1234 ) >>>

1. Lnea 1: El unico cambio que has hecho desde el ultimo caso es cambiar + por *. En lugar de zD+ entre las partes del nmero de telfono, ahora utilizas u e zD*. Recuerdas que + signica 1 o ms? Pues * signica 0 o ms. Por eso a a ahora deber ser capaz de encontrar los nmeros de telfono incluso cuando as u e no exista ningn separador. u 2. Lnea 2: Funciona! Porqu? Encuentras el comienzo de la cadena, luego un e grupo de tres d gitos (800), luego cero caracteres no nmericos, luego otro u grupo de tres d gitos (555), luego cero caracteres no numricos, luego un grupo e de cuatro d gitos (1212), luego cero caracteres no numricos, luego un grupo e arbitrario de d gitos (1234) y luego el n de la cadena. 132

3. Lnea 4: Tambin funcionan otras variaciones: puntos en lugar de guiones, y e espacios o x antes de la extensin. o 4. Lnea 6: Tambin se ha resuelto nalmente el problema de las extensiones. e Vuelven a ser opcionales. Si no se encuentra la extensin, la funcin groups() o o sigue retornando una tupla de cuatro elementos, pero el cuarto elemento es una cadena vac a. 5. Lnea 8: Odio tener que ser el portador de malas noticias, pero an no hemos u terminado. Cul es el problema aqu Existe un carcter extra antes del cdigo a ? a o de rea pero la expresin regular asume que el primer carcter debe ser lo a o a primero de la cadena. No pasa nada, puedes utilizar la misma tcnica de cero e o ms caracteres no numricos para saltarte todos los caracteres no numricos a e e iniciales. El siguiente ejemplo muestra como manejar los caracteres previos al nmero u de telfono: e
1 2 3 4 5 6 7 >>> phonePattern = r e . c o m p i l e ( r \D ( \ d { 3 } ) \D ( \ d { 3 } ) \D ( \ d { 4 } ) \D ( \ d ) $ ) >>> phonePattern . s e a r c h ( ( 8 0 0 ) 5 5 5 1 2 1 2 e x t . 1234 ) . g r o u p s ( ) ( 800 , 555 , 1212 , 1234 ) >>> phonePattern . s e a r c h ( 800 555 1212 ) . g r o u p s ( ) ( 800 , 555 , 1212 , ) >>> phonePattern . s e a r c h ( work 1 (800) 5 5 5 . 1 2 1 2 #1234 ) >>>

1. Lnea 1: Esto es igual que en el ejemplo anterior salvo que ahora ests buscando a zD*, cero o ms caracteres numricos, antes del primero grupo (el cdigo de a e o area). Observa que no se recuerdan esos caracteres, no estn en un grupo a (no estn entre parntesis). Si aparecen, simplemente se saltan y luego se a e comienza a reconocer el codigo de area que ser almacenado por la bsqueda a u (al encontrarse entre parntesis). e 2. Lnea 2: Ahora puedes reconocer satisfactoriamente el nmero de telfono u e incluso con el parntesis de la izquierda antes del cdigo de area. El parntesis e o e de la derecha del cdigo de area ya estaba controlado, se trata como un carcter o a no numrico y se detecta con el zD* posterior al primer grupo. e 3. Lnea 4: Solamente, para tener la seguridad de que no has roto nada que fun cionase. Puesto que los caracteres iniciales son totalmente opcionales, primero detecta el comienzo de la cadena, luego cero caracteres no numricos, luego un e grupo de tres d gitos de rea (800), luego un carcter no numrico (el guin), a a e o luego un grupo de tres d gitos (555), luego un carcter no numrico (el guin), a e o 133

luego un grupo de cuatro d gitos (1212), luego cero caracteres no numricos, e luego un grupo de cero d gitos opcionales, para terminar con el nal de la cadena. 4. Lnea 6: Por eso las expresiones regulares me hacen querer sacarme los ojos con un objeto punzante. Porqu no funciona con este nmero de telfono? Porque e u e hay un 1 antes del cdigo de rea pero has asumido que todos los caracteres o a que van delante del cdigo de area sern no numricos (zD*), Aarggghhhh!!! o a e Vamos a resumir por un momento. Hasta ahora todas las expresiones regulares han buscado desde el comienzo de la cadena. Pero ahora ves que existe un nmero u indeterminado de cosas al comienzo que puede interesarte ignorar. En lugar de intentar hacer coincidir todas las combinaciones posibles lo mejor es que las ignores. Vamos a intentarlo de una forma distinta: sin expresar expl citamente el comienzo de la cadena. Esta opcin se muestra en el siguiente ejemplo. o
1 2 3 4 5 6 7 >>> phonePattern = r e . c o m p i l e ( r ( \ d { 3 } ) \D ( \ d { 3 } ) \D ( \ d { 4 } ) \D ( \ d ) $ ) >>> phonePattern . s e a r c h ( work 1 (800) 5 5 5 . 1 2 1 2 #1234 ) . g r o u p s ( ) ( 800 , 555 , 1212 , 1234 ) >>> phonePattern . s e a r c h ( 800 555 1212 ) ( 800 , 555 , 1212 , ) >>> phonePattern . s e a r c h ( 80055512121234 ) ( 800 , 555 , 1212 , 1234 )

1. Lnea 1: Observa la ausencia del en esta expresin regular, ya no vas a obligar o a que la coincidencia sea desde el comienzo de la cadena. No hay nada que diga que tienes que hacer coincidir la cadena completa. El motor de proceso de las expresiones regulares se encargar de hacer el trabajo duro descubriend a el lugar en el que la cadena de entrada comienza a coincidir. 2. Lnea 2: Ahora puedes analizar un nmero de telfono que incluya caracteres u e y un d gito previo, adems de cualquier clase de separadores alrededor de cada a parte del nmero. u 3. L nea 4: Test de seguridad. An funciona. u 4. Lnea 6: Y esto tambin. e Ves qu rpido comienza uno a perder el control de las expresiones regulares? e a Echale un vistazo a cualquiera de los ejemplos anteriores. Puedes identicar an u las diferencias entre uno y otro? Aunque puedas comprender la respuesta nal (y es la ultima respuesta, y si encuentras un caso para el que no funcione no quiero conocerlo!), vamos a escribir 134

la expresin regular de forma detallada antes de que se te olvide porqu elegiste las o e opciones que elegiste:
1 >>> phonePattern = r e . c o m p i l e ( r 2 # No busca e l i n i c i o , puede empezar en c u a l q u i e r s i t i o 3 ( zd { 3 } ) # e l c d i g o de r e a t i e n e t r e s d g i t o s ( e j . 800 ) o a 4 zD # separador opcional 5 ( zd { 3 } ) # e l t r o n c a l s i n 3 d g i t o s ( e j . 555 ) 6 zD # separador opcional 7 ( zd { 4 } ) # e l r e s t o d e l n mero : 4 d g i t o s ( e j . 1212 ) u 8 zD # separador opcional 9 ( zd ) # e x t e n s i n o p c i o n a l , c u a l q u i e r n mero de d g i t o s o u 10 $ # f i n de l a cadena 11 , r e .VERBOSE) 12 >>> phonePattern . s e a r c h ( work 1 (800) 5 5 5 . 1 2 1 2 #1234 ) . g r o u p s ( ) 13 ( 800 , 555 , 1212 , 1234 ) 14 >>> phonePattern . s e a r c h ( 800 555 1212 ) 15 ( 800 , 555 , 1212 , )

1. Lnea 12: Aparte de estar escrita en varias l neas, esta expresin es exactao mente la misma que la del ejemplo anterior, por lo que analiza las mismas cadenas. 2. Lnea 14: Validacin nal de seguridad. S an funciona. Has nalizado. o , u

5.7.

Resumen

Solamente has visto la punta ms pequea del iceberg de lo que las expresiones a n regulares pueden hacer. En otras palabras, aunque ests totalmente abrumado por e ellas ahora mismo, creme, no has visto casi nada de ellas an. e u Deber estar familiarizado con las siguientes tcnicas: as e

z coincide con el comienzo de la cadena. z$ coincide con el nal de la cadena. zb coincide con un l de palabra. mite zd coincide con cualquier d numrico. gito e zD coincide con cualquier carcter no numrico. a e
x? coincide con un carcter x 0 a 1 veces. a 135

x* coincide con un carcter x 0 o ms veces. a a x+ coincide con un carcter x 1 o ms veces. a a x{n,m} coincide con carcter x entre n y m veces. a (abc) coincide con a o b o c. (x) en general es un grupo a recordar. Puedes obtener el valor de lo que ha coincidido mediante el mtodo group() del objeto retornado por la llamada a e re.search(). Las expresiones regulares son muy potentes pero no son la solucin a todos los o problemas. Deber aprender a manejarlas de forma que sepas cundo son apropiaas a das, cundo pueden ayudarte a resolver un problema y cundo te producirn ms a a a a problemas que los que resuelven.

136

Cap tulo 6 Cierres y generadores


Nivel de dicultad:   Mi forma de deletrear es temblorosa. Deletreo bien pero me tiembla la voz as que las letras acaban en los lugares equivocados. Winnie the Pooh

6.1.

Inmersin o

Por razones que superan toda comprensin, siempre he estado fascinado por o los lenguajes. No por los lenguajes de programacin. Bueno s lenguajes de proo , gramacin, pero tambin idiomas naturales. Toma como ejemplo el ingls, es un o e e idioma esquizofrnico que toma prestadas palabras del Alemn, Francs, Espaol e a e n y lat (por decir algunos). En realidad tomar prestado es una frase equivocada, n saquea ser ms adecuada. O quizs asimila como los Borg, s eso me gusta: a a a Somos los Borg. Aadiremos tus particularidades lingu n sticas y etimolgio cas a las nuestras. Es intil que te resistas. u En este cap tulo vas a aprender sobre nombres en plural. Tambin sobre fune ciones que retornan otras funciones, expresiones regulares avanzadas y generadores. Pero primero hablemos sobre cmo crear nombres en plural. (Si no has le o do el cap tulo 5 sobre expresiones regulares ahora puede ser un buen momento; este cap tulo asume una comprensin bsica de ellas y rpidamente desciende a usos ms o a a a avanzados). 137

Si has crecido en un pa de habla inglesa o has aprendido ingls en el mbito s e a escolar, probablemente ests familiarizado con sus reglas bsicas de formacin del e a o plural: Si una palabra termina en S, X o Z adele ES. Bass se convierte en basses, na fax en faxes y waltz en waltzes. Si una palabra termina en una H sonora, aade ES, si termina en una H muda, n aade S. Qu es una H sonora? una que se combina con otras letras para n e crear un sonido que se puede escuchar. Por eso coach se convierte en coaches y rash en rashes, porque se pronuncian tanto la CH como la SH. Pero cheetah se convierte en cheetahs, puesto que la H es muda. Si una palabra termina en una Y que suene como I, se cambia la Y por IES; si la Y se combina con una vocal para de otro modo, simplemente aade una S. n Por eso vacancy se convierte en vacancies y day se convierte en days. Si todo lo dems falla, simplemente aadie uan S y cruza los dedos por que a n hayas acertado. (S que hay muchas excepciones, man se convierte en men, woman en women, e sin embargo human se convierte en humans. Mouse se convierte en mice y louse en lice, pero house se convierte en houses. Knife en knives y wife en wives, pero lowlife se convierte en lowlifes. Y todo ello sin meterme con las palabras que tienen su propio plural, como sheep, deer y haiku). Otros idiomas, por supuesto, son completamente diferentes. Vamos a disear una librer de Python que pase a plural los nombres ingleses n a de forma automtica. Vamos a comenzar con estas cuatro reglas, pero recuerda que, a inevitablemente, necesitars aadir ms. a n a

6.2.

Lo s, vamos a usar expresiones regulares! e

As que ests analizando palabras, lo que, al menos en ingls, signica que a e ests analizando cadenas de caracteres. Tienes reglas que requieren la existencida de a diferentes combinaciones de caracteres, y despus de encontrarlas necesitas hacerles e modicaciones. Esto parece un buen trabajo para las expresiones regulares!

138

1 2 3 4 5 6 7 8 9 10 11

import r e def p l u r a l ( nombre ) : i f r e . s e a r c h ( [ s x z ] $ , nombre ) : return r e . sub ( $ , e s , nombre ) e l i f r e . s e a r c h ( [ a e i o u d g k p r t ] h$ , nombre ) : return r e . sub ( $ , e s , nombre ) e l i f r e . s e a r c h ( [ a e i o u ] y$ , nombre ) : return r e . sub ( y$ , i e s , nombre ) else : return nombre + s

1. Lnea 4: Esto es una expresin regular que utiliza una sintaxis que no has o visto en el cap tulo dedicado a ellas. Los corchetes cuadrados indican que se encuentre exactamente uno de los caracteres encerrados entre ellos. Por eso [xyz] signica o s o x o z, pero unicamente uno de ellos. El s mbolo $ s deber serte familiar, coincide con el nal de la cadena. Al combinarlos esta a expresin regular comprueba si la variable nombre naliza con s, x o z. o 2. Lnea 5: La funcin re.sub() ejecuta una sustitucin de cadena de texto basndo o o a se en una expresin regular. o Vamos a ver en detalle las sustituciones de texto utilizando expresiones regulares.
1 2 3 4 5 6 7 8 9 >>> import r e >>> r e . s e a r c h ( [ abc ] , Mark ) < s r e . SRE Match o b j e c t a t 0x001C1FA8> >>> r e . sub ( [ abc ] , o , Mark ) Mork >>> r e . sub ( [ abc ] , o , r o c k ) rook >>> r e . sub ( [ abc ] , o , c a p s ) oops

1. Lnea 2: La cadena Mark contiene a, b o c? s contiene la a. , 2. Lnea 4: Ok, ahora vamos a buscar a, b o c y reemplazarlos por una o. Mark se convierte en Mork. 3. Lnea 6: La misma funcin convierte rock en rook. o 4. Lnea 8: Podr creer que caps se convierte en oaps, pero no lo hace. re.sub() as reemplaza todas las coincidencias, no solamente la primera. Por eso, esta expresin regular convierte caps en oops, porque coinciden tanto la c como la a, o as que ambas se convierten en o. 139

Y ahora volvamos a la funcin plural()... o


1 2 3 4 5 6 7 8 9 def p l u r a l ( nombre ) : i f r e . s e a r c h ( [ s x z ] $ , nombre ) : return r e . sub ( $ , e s , nombre ) e l i f r e . s e a r c h ( [ a e i o u d g k p r t ] h$ , nombre ) : return r e . sub ( $ , e s , nombre ) e l i f r e . s e a r c h ( [ a e i o u ] y$ , nombre ) : return r e . sub ( y$ , i e s , nombre ) else : return nombre + s

1. Lnea 3: Aqu ests reemplazando el nal de la cadena (que se encuentra con $) a con la cadena es. En otras palabras, ests aadiendo es al nal de la cadena. a n Podr conseguir lo mismo con la concatenacin de cadenas, por ejemplo as o nombre + es, pero he elegido utilizar expresiones regulares para cada regla, por razones que quedarn claras ms adelante. a a 2. Lnea 4: Mira atentamente, esta es otra variacin nueva. El en el primer o carcter de los corchetes indica algo especial: negacin. [bc] signica busa o a ca por un unico carcter pero que sea cualquiera salvo a, b o c. Por eso a [eioudgkprt] signica que se busque por cualquier carcter salvo los indicados. a a Luego ese carcter deber tener detrs una h y despus de ella debe venir el a a a e nal de la cadena. Estamos buscando por palabras que terminen en H sonoras. 3. Lnea 6: Aqu seguimos el mismo patrn, busca palabras que terminen en Y, o en las que delante de ella no exista una vocal. Estamos buscando por palabras que terminen en Y que suenen como I. Veamos en detalle el uso de la negacin en expresiones regulares. o
1 2 3 4 5 6 7 8 9 >>> import r e >>> r e . s e a r c h ( [ a e i o u ] y$ , vacancy ) < s r e . SRE Match o b j e c t a t 0x001C1FA8> >>> r e . s e a r c h ( [ a e i o u ] y$ , boy ) >>> >>> r e . s e a r c h ( [ a e i o u ] y$ , day ) >>> >>> r e . s e a r c h ( [ a e i o u ] y$ , p i t a ) >>>

1. Lnea 2: La palabra vacancy coincide con esta expresin regular, porque naliza o en cy, y la c no es una vocal.

140

2. Lnea 4: La palabra boy no coincide porque naliza en oy, y la expresin regular o dice expresamente que delante de la y no puede haber una o. La palabra day tampoco coincide por una causa similar, puesto que termina en ay. 3. Lnea 8: La palabra pita no coincide, puesto que no termina en y.
1 >>> r e . sub ( y$ , i e s , vacancy ) 2 vacancies 3 >>> r e . sub ( y$ , i e s , agency ) 4 agencies 5 >>> r e . sub ( ( [ a e i o u ] ) y$ , r \1 i e s , vacancy ) 6 vacancies

1. Lnea 1: Esta expresin regular convierte vacancy en vacancies y agency en o agencies, que es lo que quer Observa que tambin convierte boy en boies, as. e pero eso no pasar porque antes habremos efectuado un re.search() para desa cubrir si debemos hacer la sustitucin re.sub(). o 2. Lnea 5: Aunque sea de pasada, me gustar apuntar que es posible combinar a las dos expresiones regulares en una unica sentencia (la primera expresin o regular para descubrir si se debe aplicar una regla y la segunda para aplicarla manteniendo el texto correcto). Se muestra como quedar La mayor parte te a. debe ser familiar del cap tulo dedicado a las expresiones regulares. Utilizamos un grupo para recordar el carcter que se encuentra delante de la letra y. a Luego, en la cadena de sustitucin se utiliza una sintaxis nueva z1, que sirve o para indicar que en ese punto se debe poner el valor del grupo guardado. En este ejemplo, el valor del grupo es la letra c de delante de la letra y; cuando se efecta la sustitucin, se sustituye la c en su mismo lugar, y los caracteres u o ies en el lugar de la y. (Si se hubiesen guardado ms grupos, se podr incluir a an con z2, z3 y as sucesivamente. Las sustitucin mediante el uso de expresiones regulares es un mecanismo muy o potente, y la sintaxis 1 lo hace an ms. Pero combinar toda la operacin en una unica expresin regular u a o o la hace mucho ms dif de leer al no describir directamente la forma en la que se a cil explicaron las reglas del plural. Estas reglas dec originalmente algo as como si an la palabra termina en S, X o Z, entonces aade ES. Si se echa un vistazo al cdigo n o de la funcin, las dos l o neas de cdigo dicen casi exactemente eso mismo. o

141

6.3.

Una lista de funciones

Ahora vas a aadir un nuevo nivel de abstracin. Comenzaste por denir una n o lista de reglas: si pasa esto, haz esto oto, en caso contrario ve a la siguiente regla. Vamos a complicar un poco parte del programa para poder simplicar otra parte.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import r e def match sxz ( noun ) : return r e . s e a r c h ( [ s x z ] $ , noun ) def a p p l y s x z ( noun ) : return r e . sub ( $ , e s , noun ) def match h ( noun ) : return r e . s e a r c h ( [ a e i o u d g k p r t ] h$ , noun ) def a p p l y h ( noun ) : return r e . sub ( $ , e s , noun ) def match y ( noun ) : return r e . s e a r c h ( [ a e i o u ] y$ , noun ) def a p p l y y ( noun ) : return r e . sub ( y$ , i e s , noun ) def m a t c h d e f a u l t ( noun ) : return True def a p p l y d e f a u l t ( noun ) : return noun + s r u l e s = ( ( match sxz , a p p l y s x z ) , ( match h , a p p l y h ) , ( match y , a p p l y y ) , ( match default , apply default ) ) def p l u r a l ( noun ) : f o r m a t c h e s r u l e , a p p l y r u l e in r u l e s : i f m a t c h e s r u l e ( noun ) : return a p p l y r u l e ( noun )

1. Funcin match y: Ahora cada regla de bsqueda se convierte en una funcin o u o que devuelve el resultado de la bsqueda: re.search(). u

142

2. Funcin apply y: Cada regla de sustitucin tine su propia funcin que llama o o o a re.sub() para aplicar la regla apropiada. 3. Lnea 27: En lugar de tener una funcin plural() con mltiples reglas, tenemos o u la estructura rules, que es una secuencia formada por parejas en la que cada una de ellas est formada, a su vez, por dos funciones. a 4. Lnea 34: Puesto que las reglas se han pasado las funciones contenidas en la estructura de datos, la nueva funcin plural() puede reducirse a unas cuantas o l neas de cdigo. Mediante el uso de un bucle for puedes obtener en cada o paso las funciones de bsqueda y sustitucin de la estructura de datos rules. u o a En la primera iteracin del bucle for la variable matches rule referenciar a la o funcin match sxz y la variable apply rule referenciar a la funcin apply sxz. o a o En la segunda iteracin (asumiendo que alcanzas a ello), se le asigna match h o a matches rule y apply h a apply rule. Est garantizado que la funcin retorna a o algo en todos los caso, porque la ultima regla de bsqueda (match default) u retorna True siempre, lo que signica que se aplicar en ultima instancia la a regla correspondiente (match default). La razn por la que esta tcnica funciona o e es que todo en Python es un objeto, funciones La variable rules es una seincluidas. La estructura de datos rules contiene cuencia de pares de funciones. funciones nombres de funcin, sino objetos funo cin reales. Cuando se asignan en el bucle for o las variables matches rule y apply rule apuntan a funciones reales que puedes llamar. En la primera iteracin del bucle for esto supone que se llama la funcin mato o ches sxz(noun) y si retorna una coincidencia se llama a la funcin apply sxz(noun). o Si este nivel adicional de abstraccin te resulta confuso, intenta verlo as Este o . bucle for es equivalente a lo siguiente:
1 2 3 4 5 6 7 8 9 def p l u r a l ( noun ) : i f match sxz ( noun ) : return a p p l y s x z ( noun ) i f match h ( noun ) : return a p p l y h ( noun ) i f match y ( noun ) : return a p p l y y ( noun ) i f m a t c h d e f a u l t ( noun ) : return a p p l y d e f a u l t ( noun )

La ventaja es que ahora la funcin plural() es ms simple. Toma una secuencia o a de reglas, denidas en otra parte y cuyo nmero puede variar, e itera a travs de u e ella de forma genrica. e 143

1. Obtiene una pareja: funcin de bsqueda - funcin de sustitucin. o u o o 2. Comprueba si la funcin de bsqueda retorna True. o u 3. Coincide? Entonces ejecuta la funcin de sustitucin y devuelve el resultado. o o 4. No coincide? Vuelve al paso uno. La reglas pueden denirse en otra parte, de cualquier forma. A la funcin o plural() no le importa. Merec la pena aadir este nivel de abstraccin? Tal vez an no te lo parezca. a n o u Vamos a considerar lo que supondr aadir una nueva regla. En el primer ejemplo, a n requerir aadir una sentencia if a la funcin plural(). En este segundo ejemplo, a n o n requeriria aadir dos funciones match algo() y apply algo() y luego aadirlas a la n secuencia rules para especicar en qu orden deben llamarse estas nuevas funciones e en relacin a las reglas que ya exist o an. Pero realmente esto que hemos hecho es un hito en el camino hacia la siguiente seccin. Sigamos... o

6.4.

Una lista de patrones

Realmente no es necesario denir una funcin para cada patrn de bsqueda o o u y de sustitucin. Nunca los llamas directamente; los aades a la secuencia de reglas o n (rules) y los llamas desde ah Es ms, cada funcin sigue uno de los dos patrones. . a o Todas las funciones de bqueda llaman a re.search() y todas las funciones de sustiu tucin llaman a re.sub(). Vamos a sacar los patrones para que denir nuevas reglas o sea ms sencillo. a
1 2 3 4 5 6 7 8 import r e def b u i l d m a t c h a n d a p p l y f u n c t i o n s ( p a t t e r n , s e a r c h , r e p l a c e ) : def m a t c h e s r u l e ( word ) : return r e . s e a r c h ( p a t t e r n , word ) def a p p l y r u l e ( word ) : return r e . sub ( s e a r c h , r e p l a c e , word ) return ( m a t c h e s r u l e , a p p l y r u l e )

1. Lnea 3: build match and apply functions es una funcin que construye otras o funciones dinmicamente. Toma los parmetros y dene la funcin matches rule() a a o que llama a re.search() con el pattern que se haya pasado y el parmetro word a que se pasar a la funcin cuando se llame en el futuro. Vaya! a o 144

2. Lnea 6: La construccin de la funcin de sustitucin es similar. Es una funcin o o o o que toma un parmetro word y llama a re.sub() con l y los parmetros search a e a y replace que se pasaron a la funcin constructora. Esta tcnica de utilizar o e los valores de los parmetros exteriores a una funcin dentr ode una funcin a o o dinmica se denomina closures 1 . En el fondo se estn deniendo constantes a a que se utilizan dentro detro de la funcin que se est construyendo: la funcin o a o construida toma un unico parmetro (word) y los otros dos valores utilizados a (search y replace) son los que tuvieran almacenados en el momento en que se deni la funcin. o o 3. Lnea 8: Finalmente, la funcin retorna una tupla con las dos funciones recin o e creadas. Las constantes denidas dentro de esas funciones (pattern en la funcin o o match rule(), y search y replace en la funcin apply rule()) conservan los valores dentro de cada una de ellas, incluso despus de nalizar la ejecucin de la e o funcin constructora. Esto resulta ser muy prctico. o a Si te resulta muy confuso (y deber puesto que es algo bastante avanzado y a, extrao), puede quedarte ms claro cuando veas cmo usarlo. n a o
1 2 3 4 5 6 7 8 9 patterns = \ ( ( [ sxz ] $ , $ , ( [ a e i o u d g k p r t ] h$ , $ , ( ( qu | [ a e i o u ] ) y$ , y$ , ( $ , $ , ) rules = [ build match and apply for ( pattern , search ,

es ) , es ) , ies ) , s ) functions ( pattern , search , r e p l a c e ) r e p l a c e ) in p a t t e r n s ]

1. Lnea 1: Ahora las reglas se denen como una tupla de tuplas de cadenas (no son funciones). La primera cadena en cada tr es el patrn de bsqueda que o o u se usar en re.search() para descubrir si una cadena coincide. La segunda y la a tercera cadenas de cada grupo es la expresin de bsqueda y reemplazo que se o u utilizarn en re.sub() para modicar un nombre y ponerlo en plural. a 2. Lnea 6: Hay un ligero cambio aqu en la regla por defecto. En el ejemplo , anterior, la funcin match default() retornaba True, dando a entender que si o ninguna otra regla coincid el cdigo simplemente deber aadir una s al a, o a n nal de la palabra. Este ejemplo hacer algo que es funcionalmente equivalente. La expresin regular nal simplemente pregunta si la palabra tiene nal ($ o coincide con el nal de la cadena). Desde luego todas las cadenas tienen nal,
1

Nota del Traductor: en espaol se utiliza la palabra cierre para referirse a este trmino. n e

145

incluso la cadena vac por lo que esta expresin siempre coincide. As que sirve a, o para el mismo propsito que la funcin match default() del ejemplo anterior: o o asegura que si no coincide una regla ms espec a ca, el cdigo aade una s al o n nal de la palabra. 3. Lnea 8: Esta l nea es magia. Toma la secuencia de cadenas de patterns y la convierte en una secuencia de funciones. Cmo? mapeando las cadenas o con la funcin build match and apply functions. Toma un triplete de cadenas y o llama a la funcin con las tres cadenas como argumentos. La funcin retorna o o una tupla de dos funciones. Esto signica que las variable rules acaba siendo equivalente a la del ejemplo anterior: una lista de tuplas, en la que cada una de ellas contiene un par de funciones. La primera funcin es la funcin de o o bsqueda que llama a re.search() y la segunda que es la funcin de sustitucin u o o que llama a re.sub(). Para nalizar esta versin del programa se muestra el punto de entrada al o mismo, la funcin plural(). o
1 2 3 4 def p l u r a l ( noun ) : f o r m a t c h e s r u l e , a p p l y r u l e in r u l e s : i f m a t c h e s r u l e ( noun ) : return a p p l y r u l e ( noun )

Como la lista rules es igual que en el ejemplo anterior (realmente lo es), no deber sorprenderte al ver que la funcin plural() no ha cambiado en nada. Es as o totalmente genrica; toma una lista de funciones de reglas y las llama en orden. e No le importa cmo se han denido las reglas. En el ejemplo anterior, se denieron o funciones separadas. Ahora se han creado funciones dinmicas al mapearlas con la a funcin build match and apply functions a partir de una serie de cadenas de texto. o No importa, la funcin plural() sigue funcionando igual. o

6.5.

Un chero de patrones

Hemos eliminado todo el cdigo duplicado y aadido sucientes abstracciones o n para que las reglas de formacin de plurales del ingls queden denidas en una lista o e de cadenas. El siguiente paso lgico es extraer estas reglas y ponerlas en un chero o separado, en el que se puedan modicar de forma separada del cdigo que las utiliza. o Primero vamos a crear el chero de texto que contenga las reglas que necesitas. No vamos a crear estructuras de datos complejas, simplemente cadenas de texto separadas por espacios en blanco en tres columnas. Vamos a llamarlo plural4-rules.txt.

146

1 2 3 4

[ sxz ] $ [ a e i o u d g k p r t ] h$ [ a e i o u ] y$ $

$ $ y$ $

es es ies s

Ahora veamos cmo utilizar este chero de reglas. o


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import r e def b u i l d m a t c h a n d a p p l y f u n c t i o n s ( p a t t e r n , s e a r c h , r e p l a c e ) : def m a t c h e s r u l e ( word ) : return r e . s e a r c h ( p a t t e r n , word ) def a p p l y r u l e ( word ) : return r e . sub ( s e a r c h , r e p l a c e , word ) return ( m a t c h e s r u l e , a p p l y r u l e ) rules = [ ] with open ( p l u r a l 4 r u l e s . t x t , e n c o d i n g= u t f 8 ) a s p a t t e r n f i l e : f o r l i n e in p a t t e r n f i l e : p a t t e r n , s e a r c h , r e p l a c e = l i n e . s p l i t ( None , 3 ) r u l e s . append ( b u i l d m a t c h a n d a p p l y f u n c t i o n s ( pattern , search , r e p l a c e ))

1. Lnea 3: La funcin build match and apply functions no ha cambiado. An uti o u lizamos los cierres para construir dos funciones dinmicas por cada llamada, a que utilizan las variables denidas en la funcin externa. o 2. Lnea 11: La funcin global open() abre un chero y devuelve un objeto chero. o En este caso, el chero que estamos abriendo contiene las cadenas de texto que son los patrones de formacin de los nombres en plural La sentencia with crea o un contexto: cuando el bloque with termina, Python cerrar automticamente a a el chero, incluso si sucede una excepcin dentro del bloque with. Lo vers con o a ms detalle en el cap a tulo ?? dedicado a los cheros. 3. Lnea 12: La sentencia for lee los datos de un chero abierto: una l nea cada vez, y asigna el valor de dicha l nea a la variable line. Lo veremos en mayor detalle en el cap tulo ?? dedicado a los cheros. 4. Lnea 13: Cada l nea del chero contiene tres valores que estn separados a por espacios en blanco o tabuladores. Para obtenerlos, se utiliza el mtodo e de cadenas de texto split(). El primer parmetro del mtodo split() es None, a e que signica que trocea la cadena en cualquier espacio en blanco (tabuladores incluidos, sin distincin). El segundo parmetro es 3, que signca que trocea o a la cadena hasta 3 veces, y luego deje el resto de la l nea. Una l nea como [sxy]$ $ es se trocea en la siguiente lista [[sxy]$, $, es], lo que signica que 147

pattern contendr el valor [sxy]$, search el valor $ y replace el valor es. a Como ves, esto hace mucho para tan poco cdigo escrito. o 5. Lnea 14: Finlmente, pasas los valores pattern, search y replace a la funcin o build match and apply functions, que retorna una tupla con las dos funciones creadas. Esta tupla se aade a la lista rules, por lo que, al nalizar, la lista n rules contiene la lista de funciones de bsqueda y sustitucin que la funcin u o o plural() necesita.

6.6.

Generadores

No ser estupendo tener una funcin genrica que fuese capaz de recuperar a o e el chero de reglas? Obtener las reglas, validar si hay coincidencia, aplicar la transformacin apropiada y seguir con la siguiente regla. Esto es lo unico que la funcin o o plural() tiene que hacer.
1 2 3 4 5 6 7 8 9 10 11 def r u l e s ( r u l e s f i l e n a m e ) : with open ( r u l e s f i l e n a m e , e n c o d i n g= u t f 8 ) a s p a t t e r n f i l e : f o r l i n e in p a t t e r n f i l e : p a t t e r n , s e a r c h , r e p l a c e = l i n e . s p l i t ( None , 3 ) y i e l d build match and apply functions ( pattern , search , r e p l a c e ) def p l u r a l ( noun , r u l e s f i l e n a m e= p l u r a l 5 r u l e s . t x t ) : f o r m a t c h e s r u l e , a p p l y r u l e in r u l e s ( r u l e s f i l e n a m e ) : i f m a t c h e s r u l e ( noun ) : return a p p l y r u l e ( noun ) r a i s e V a l u e E r r o r ( no matching r u l e f o r {0} . format ( noun ) )

Cmo funciona este cdigo? Vamos a verlo primero con un ejemplo interactivo. o o

148

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

>>> def make counter ( x ) : ... print ( e n t r a n d o en make counter ) ... while True : ... yield x ... print ( incrementando x ) ... x = x + 1 ... >>> c o u n t e r = make counter ( 2 ) >>> c o u n t e r <g e n e r a t o r o b j e c t a t 0x001C9C10> >>> next ( c o u n t e r ) e n t r a n d o en make counter 2 >>> next ( c o u n t e r ) incrementando x 3 >>> next ( c o u n t e r ) incrementando x 4

1. Lnea 4: La presencia de la sentencia yield en la funcin make counter signica o que sta no es una funcin normal. Al llamarla lo que sucede es que se e o retorna un generador que puede utilizarse para generar sucesivos valores de x. 2. Lnea 8: Para crear una instancia del generador make counter simplemente hay que llamarlo como a cualquier otra funcin. Observa que esto en realidad no o ejecuta el cdigo de la funcin. Lo puedes comprobar porque la primera l o o nea o de la funcin make counter() llama a la funcin print() y en esta llamada no se o ha imprimido nada en pantalla. 3. Lnea 9: La funcin make counter() retorna un objeto generador. o 4. Lnea 11: El mtodo next() del generador retorna su siguiente valor. La primera e vez que ejecutas next() se ejecuta el cdigo de la funcin make counter() hasta o o la primera sentencia yield que se ejecute, y se retorna el valor que aparece en la sentencia yield2 . En este caso, el valor ser 2, porque originalmente se cre el a o generador con la llamdada make counter(2). 5. Lnea 14: Al llamar repetidas veces al mtodo next() del mismo objeto ge e nerador, la ejecucin del objeto se reinicia en el mismo lugar en el que se o qued (despus del yield anterior) y continua hasta que vuelve a encontrar o e
N.del T.: En espaol yield puede traducirse como ceder. En Python es como si al llegar n la ejecucin de esta sentencia, se cediera el paso devolviendo el valor que aparezca como si fuese o un return pero sin terminar la funcin. La siguiente vez que se ejecute el next() continuar por el o a lugar en el que se ced el paso. o
2

149

otra sentencia yield. Todas las variables y, en general, el estado local de la funcin queda almacenado al llegar a la sentencia yield y se recupera al llamar de o nuevo a la funcin next(). La siguiente l o nea de cdigo que se ejecuta llama a o un print() que muestra incrementando x. Despus de eso se ejecuta la sentencia e x = x + 1. Luego se ejecuta el bucle while y lo primero que sucede es que se vuelve a ejecutar yield x, lo que salva el estado en la situacin actual y devuelve o el valor que tiene x (que ahora es 3). 6. Lnea 17: La siguiente vez que llamas a next(counter), sucede lo mismo de nuevo, pero ahora el valor de x es 4. o Puesto que make counter() establece un bucle innito, tericamente se puede ejecutar innitas veces la llamada al mtodo next(), y se mantendr el incremento de e a x y la impresin de sus sucesivos valores. Pero vamos a ser un poco ms productivos o a en el uso de los generadores.

6.7.

Un generador de la serie de Fibonacci


yield pausa la funcin, next() contina desde donde se qued. o u o

1 2 3 4 5

def f i b (max ) : a, b = 0, 1 while a < max : yield a a, b = b, a + b

1. Lnea 2: La serie de Fibonacci es una secuencia nmeros en la que cada uno u de los nmeros es la suma de los dos nmeros anteriores de la serie. Comienu u za en 0 y 1. Va subiendo lentamente al principio, y luego ms rpidamente. a a Para comenzar la secuencia necesitas dos variables: a comienza valiendo 0 y b comienza en 1. 2. Lnea 4: a es el nmero actual de la secuencia, por lo que se puede ceder el u control y retornar dicho valor. 3. Lnea 5: b es el siguiente nmero de la secuencia, por lo que hay que asignarlo u a a, pero tambin hay que calcular antes el nuevo valor siguiente (a + b) y e asignarlo a b para su uso posterior. Observa que esto sucede en paralelo; si a es 3 y b es 5, entonces a, b = b, a + b har que a valga 5 (el valor previo de a b) y b valdr 8 (la suma de los valores previos de a y b). a 150

De este modo tienes una funcin que va retornando los sucesivos nmeros de la o u serie de Fibonacci. Es evidente que tambin podr hacer esto con recursin, pero e as o de este modo es ms fcil de leer. Adems, as tambin es ms fcil trabajar con los a a a e a a bucles for.
1 >>> from f i b o n a c c i import f i b 2 >>> f o r n in f i b ( 1 0 0 0 ) : 3 ... print ( n , end= ) 4 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 5 >>> l i s t ( f i b ( 1 0 0 0 ) ) 6 [ 0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , 55 , 89 , 144 , 233 , 377 , 610 , 987]

1. Lnea 2: Los generadores, como b(), se pueden utilizar directamente en los bucles for. El bucle for llamar automticamente a la funcin next() para rea a o cuperar los valores del generador b() y lo asignar a la variable del a ndice (n). 2. Lnea 3: Cada vez que se pasa por el bucle for, n guarda un nuevo valor obtenido de la sentencia yield de la funcin b(), y todo lo que hay que hacer o en el bucle es imprimirlo. Una vez la funcin b() se queda sin nmeros (a se o u hace mayor que el valor max, que en este caso es 1000), el bucle for termina sin problemas. 3. Lnea 5: Esta es una forma idiomtica de Python muy util: pasar un generador a a la funcin list() que iterar a travs de todo el generador (como en el bucle o a e for del ejemplo anterior) y retorna la lista con todos los valores.

6.8.

Un generador de reglas de plurales

Volvamos al cdigo con las reglas de formacin del plural para ver como funo o ciona plural().
1 2 3 4 5 6 7 8 9 10 11 def r u l e s ( r u l e s f i l e n a m e ) : with open ( r u l e s f i l e n a m e , e n c o d i n g= u t f 8 ) a s p a t t e r n f i l e : f o r l i n e in p a t t e r n f i l e : p a t t e r n , s e a r c h , r e p l a c e = l i n e . s p l i t ( None , 3 ) y i e l d build match and apply functions ( pattern , search , r e p l a c e ) def p l u r a l ( noun , r u l e s f i l e n a m e= p l u r a l 5 r u l e s . t x t ) : f o r m a t c h e s r u l e , a p p l y r u l e in r u l e s ( r u l e s f i l e n a m e ) : i f m a t c h e s r u l e ( noun ) : return a p p l y r u l e ( noun ) r a i s e V a l u e E r r o r ( no matching r u l e f o r {0} . format ( noun ) )

151

1. Lnea 4: No hay ninguna magia aqu Recuerda que las l . neas del chero de reglas tienen tres valores separados por espacios en blanco, por lo que utilizas line.split(None, 3) para retornar las tres columnas y asignarlas a las tres variables locales. 2. Lnea 5: Y lo siguiente es un yield. Qu es lo que se cede? las dos funciones que e se construyen dinmicamente con la ya conocida build match and apply functions, a que es idntica a los ejemplos anteriores. En otras palabras, rules() es un genee rador que va retornando funciones de bsqueda y sustitucin bajo demanda. u o 3. Lnea 8: Puesto que rules() es un generador, puedes utilizarlo directamente en un bucle for. La primera vez, el bucle for llama a la funcin rules(), que abre o el chero de patrones, lee la primera l nea, construye de forma dinmica las a funciones de bsqueda y sustitucin de los patrones de esa l u o nea y cede el control devolviendo ambas funciones. La segunda vuelta en el bucle for contina u en el lugar exacto en el que se cedi el control por parte del generador rules(). o Lo primero que har es leer la siguiente l a nea del chero (que contina abieru to), construir dinmicamente otras dos funciones de bsqueda y sustitucin a a u o basadas en los patrones de esa l nea del chero y, de nuevo, ceder el control a devolviendo las dos nuevas funciones. Qu es lo que hemos ganado con respecto de la versin anterior? Tiempo e o de inicio. En la versin anterior, cuando se importaba el mdulo, se le el chero o o a completo y se constru una lista con todas las reglas posibles. Todo ello, antes de a que se pudiera ejecuta la funcin plural(). Con los generadores, puedes hacero todo de o forma perezosa: primero lees la primera regla, creas las funciones y las pruebas, si con ello se pasa el nombre a plural, no es necesario seguir leyendo el resto del chero, ni crear otras funciones. Qu se pierde? Rendimiento! Cada vez que llamas a la funcin plural(), el e o generador rules() vuelve a iniciarse desde el principio (se genera un nuevo objeto cada vez que se llama a la funcin generador rules()) lo que signica que se reabre o el chero de patrones y se lee desde el comienzo, una l nea cada vez. Cmo podr o amos tener lo mejor de los dos mundos?: coste m nimo de inicio (sin ejecutar ningn cdigo en el import), y mximo rendimiento (sin construir las u o a mismas funciones una y otra vez). Ah! y todo ello manteniendo las reglas en un chero separado (porque el cdigo es cdigo y los datos son datos) de forma que no o o haya que leer la misma l nea del chero dos veces. Para hacer eso, necesitas construir un iterador. Pero antes de hacerlo, es necesario que aprendas a manejar las clases de objetos en Python.

152

6.9.

Lecturas recomendadas

Generadores simples (PEP 255): http://www.python.org/dev/peps/pep-0255/ Comprendiendo la sentencia with de Python: http://ebot.org/zone/pythonwith-statement.htm Cierres en Python: http://ynniv.com/blog/2007/08/closures-in-python.html Nmeros de Fibonacci: http://en.wikipedia.org/wiki/Fibonacci number u Nombres plurales irregulares en ingls: http://www2.gsu.edu/wwwesl/egw/crump.htm e

153

Das könnte Ihnen auch gefallen