PYTHON para todos

Nov 15, 2011 | Publisher: @lmartinezh | Category: Technology |  

Python PARA TODOS Ral Gonzlez Duque Python PARA TODOS Ral Gonzlez Duque Python para todos por Ral Gonzlez Duque Este libro se distribuye bajo una licencia Creative Commons Reconocimien- to 2.5 Espaa. Usted es libre de: copiar, distribuir y comunicar pblicamente la obra hacer obras derivadas Bajo las condiciones siguientes: Reconocimiento. Debe reconocer y dar crdito al autor original (Ral Gonzlez Duque) Puede descargar la versin ms reciente de este libro gratuitamente en la web http://mundogeek.net/tutorial-python/ La imgen de portada es una fotografa de una pitn verde de la especie Morelia viridis cuyo autor es Ian Chien. La fotografa est licenciada bajo Creative Commons Attribution ShareAlike 2.0 Contenido Introduccin 7 Qu es Python? 7 Por qu Python? 8 Instalacin de Python 9 Herramientas bsicas 10 Mi primer programa en Python 12 Tipos bsicos 15 Nmeros 16 Cadenas 21 Booleanos 22 Colecciones 24 Listas 24 Tuplas 26 Diccionarios 27 Control de flujo 29 Sentencias condicionales 29 Bucles 32 Funciones 36 Orientacin a Objetos 42 Clases y objetos 42 Herencia 45 Herencia mltiple 46 Polimorfismo 47 Encapsulacin 48 Clases de "nuevo-estilo" 50 Mtodos especiales 50 Revisitando Objetos 53 Diccionarios 53 Cadenas 54 Listas 55 Programacin funcional 57 Funciones de orden superior 57 Iteraciones de orden superior sobre listas 59 Funciones lambda 60 Comprensin de listas 61 Generadores 62 Decoradores 63 Excepciones 65 Mdulos y Paquetes 72 Mdulos 72 Paquetes 75 Entrada/Salida Y Ficheros 77 Entrada estndar 77 Parmetros de lnea de comando 78 Salida estndar 78 Archivos 82 Expresiones Regulares 85 Patrones 85 Usando el mdulo re 89 Sockets 92 Interactuar con webs 96 Threads 102 Qu son los procesos y los threads? 102 El GIL 103 Threads en Python 104 Sincronizacin 106 Datos globales independientes 111 Compartir informacin 111 Serializacin de objetos 113 Bases de Datos 117 DB API 117 Otras opciones 124 Documentacin 125 Docstrings 125 Pydoc 126 Epydoc y reStructuredText 127 Pruebas 135 Doctest 135 unittest / PyUnit 139 Distribuir aplicaciones Python 143 distutils 143 setuptools 147 Crear ejecutables .exe 152 ndice 155 7 introduCCin Qu es Python? Python es un lenguaje de programacin creado por Guido van Rossum a principios de los aos 90 cuyo nombre est inspirado en el grupo de cmicos ingleses "Monty Python". Es un lenguaje similar a Perl, pero con una sintaxis muy limpia y que favorece un cdigo legible. Se trata de un lenguaje interpretado o de script, con tipado dinmico, fuertemente tipado, multiplataforma y orientado a objetos. Lenguaje interpretado o de script Un lenguaje interpretado o de script es aquel que se ejecuta utilizando un programa intermedio llamado intrprete, en lugar de compilar el cdigo a lenguaje mquina que pueda comprender y ejecutar directa- mente una computadora (lenguajes compilados). La ventaja de los lenguajes compilados es que su ejecucin es ms rpida. Sin embargo los lenguajes interpretados son ms flexibles y ms portables. Python tiene, no obstante, muchas de las caractersticas de los lengua- jes compilados, por lo que se podra decir que es semi interpretado. En Python, como en Java y muchos otros lenguajes, el cdigo fuente se traduce a un pseudo cdigo mquina intermedio llamado bytecode la primera vez que se ejecuta, generando archivos .pyc o .pyo (bytecode optimizado), que son los que se ejecutarn en sucesivas ocasiones. Tipado dinmico La caracterstica de tipado dinmico se refiere a que no es necesario declarar el tipo de dato que va a contener una determinada variable, Python para todos 8 sino que su tipo se determinar en tiempo de ejecucin segn el tipo del valor al que se asigne, y el tipo de esta variable puede cambiar si se le asigna un valor de otro tipo. Fuertemente tipado No se permite tratar a una variable como si fuera de un tipo distinto al que tiene, es necesario convertir de forma explcita dicha variable al nuevo tipo previamente. Por ejemplo, si tenemos una variable que contiene un texto (variable de tipo cadena o string) no podremos tra- tarla como un nmero (sumar la cadena "9" y el nmero 8). En otros lenguajes el tipo de la variable cambiara para adaptarse al comporta- miento esperado, aunque esto es ms propenso a errores. Multiplataforma El intrprete de Python est disponible en multitud de plataformas (UNIX, Solaris, Linux, DOS, Windows, OS/2, Mac OS, etc.) por lo que si no utilizamos libreras especficas de cada plataforma nuestro programa podr correr en todos estos sistemas sin grandes cambios. Orientado a objetos La orientacin a objetos es un paradigma de programacin en el que los conceptos del mundo real relevantes para nuestro problema se tras- ladan a clases y objetos en nuestro programa. La ejecucin del progra- ma consiste en una serie de interacciones entre los objetos. Python tambin permite la programacin imperativa, programacin funcional y programacin orientada a aspectos. Por qu Python? Python es un lenguaje que todo el mundo debera conocer. Su sintaxis simple, clara y sencilla; el tipado dinmico, el gestor de memoria, la gran cantidad de libreras disponibles y la potencia del lenguaje, entre otros, hacen que desarrollar una aplicacin en Python sea sencillo, muy rpido y, lo que es ms importante, divertido. La sintaxis de Python es tan sencilla y cercana al lenguaje natural que Introduccin 9 los programas elaborados en Python parecen pseudocdigo. Por este motivo se trata adems de uno de los mejores lenguajes para comenzar a programar. Python no es adecuado sin embargo para la programacin de bajo nivel o para aplicaciones en las que el rendimiento sea crtico. Algunos casos de xito en el uso de Python son Google, Yahoo, la NASA, Industrias Light & Magic, y todas las distribuciones Linux, en las que Python cada vez representa un tanto por ciento mayor de los programas disponibles. Instalacin de Python Existen varias implementaciones distintas de Python: CPython, Jython, IronPython, PyPy, etc. CPython es la ms utilizada, la ms rpida y la ms madura. Cuando la gente habla de Python normalmente se refiere a esta implementacin. En este caso tanto el intrprete como los mdulos estn escritos en C. Jython es la implementacin en Java de Python, mientras que IronPython es su contrapartida en C# (.NET). Su inters estriba en que utilizando estas implementaciones se pueden utilizar todas las libreras disponibles para los programadores de Java y .NET. PyPy, por ltimo, como habris adivinado por el nombre, se trata de una implementacin en Python de Python. CPython est instalado por defecto en la mayor parte de las distribu- ciones Linux y en las ltimas versiones de Mac OS. Para comprobar si est instalado abre una terminal y escribe python. Si est instalado se iniciar la consola interactiva de Python y obtendremos parecido a lo siguiente: Python 2.5.1 (r251:54863, May 2 2007, 16:56:35) [GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> Python para todos 10 La primera lnea nos indica la versin de Python que tenemos ins- talada. Al final podemos ver el prompt (>>>) que nos indica que el intrprete est esperando cdigo del usuario. Podemos salir escribiendo exit(), o pulsando Control + D. Si no te muestra algo parecido no te preocupes, instalar Python es muy sencillo. Puedes descargar la versin correspondiente a tu sistema ope- rativo desde la web de Python, en http://www.python.org/download/. Existen instaladores para Windows y Mac OS. Si utilizas Linux es muy probable que puedas instalarlo usando la herramienta de gestin de paquetes de tu distribucin, aunque tambin podemos descargar la aplicacin compilada desde la web de Python. Herramientas bsicas Existen dos formas de ejecutar cdigo Python. Podemos escribir lneas de cdigo en el intrprete y obtener una respuesta del intrprete para cada lnea (sesin interactiva) o bien podemos escribir el cdigo de un programa en un archivo de texto y ejecutarlo. A la hora de realizar una sesin interactiva os aconsejo instalar y uti- lizar iPython, en lugar de la consola interactiva de Python. Se puede encontrar en http://ipython.scipy.org/. iPython cuenta con caractersticas aadidas muy interesantes, como el autocompletado o el operador ?. (para activar la caracterstica de autocompletado en Windows es nece- sario instalar PyReadline, que puede descargarse desde http://ipython. scipy.org/ moin/PyReadline/Intro) La funcin de autocompletado se lanza pulsando el tabulador. Si escribimos fi y pulsamos Tab nos mostrar una lista de los objetos que comienzan con fi (file, filter y finally). Si escribimos file. y pulsamos Tab nos mostrar una lista de los mtodos y propiedades del objeto file. El operador ? nos muestra informacin sobre los objetos. Se utiliza aadiendo el smbolo de interrogacin al final del nombre del objeto del cual queremos ms informacin. Por ejemplo: In [3]: str? Introduccin 11 Type: type Base Class: String Form: Namespace: Python builtin Docstring: str(object) -> string Return a nice string representation of the object. If the argument is a string, the return value is the same object. En el campo de IDEs y editores de cdigo gratuitos PyDEV (http:// pydev.sourceforge.net/) se alza como cabeza de serie. PyDEV es un plu- gin para Eclipse que permite utilizar este IDE multiplataforma para programar en Python. Cuenta con autocompletado de cdigo (con informacin sobre cada elemento), resaltado de sintaxis, un depurador grfico, resaltado de errores, explorador de clases, formateo del cdigo, refactorizacin, etc. Sin duda es la opcin ms completa, sobre todo si instalamos las extensiones comerciales, aunque necesita de una canti- dad importante de memoria y no es del todo estable. Otras opciones gratuitas a considerar son SPE o Stani's Python Editor (http://sourceforge.net/projects/spe/), Eric (http://die-offenbachs.de/eric/), BOA Constructor (http://boa-constructor.sourceforge.net/) o incluso emacs o vim. Si no te importa desembolsar algo de dinero, Komodo (http://www. activestate.com/komodo_ide/) y Wing IDE (http://www.wingware.com/) son tambin muy buenas opciones, con montones de caractersticas interesantes, como PyDEV, pero mucho ms estables y robustos. Ade- ms, si desarrollas software libre no comercial puedes contactar con Wing Ware y obtener, con un poco de suerte, una licencia gratuita para Wing IDE Professional :) 12 Mi priMer prograMa en python Como comentbamos en el captulo anterior existen dos formas de ejecutar cdigo Python, bien en una sesin interactiva (lnea a lnea) con el intrprete, o bien de la forma habitual, escribiendo el cdigo en un archivo de cdigo fuente y ejecutndolo. El primer programa que vamos a escribir en Python es el clsico Hola Mundo, y en este lenguaje es tan simple como: print "Hola Mundo" Vamos a probarlo primero en el intrprete. Ejecuta python o ipython segn tus preferencias, escribe la lnea anterior y pulsa Enter. El intr- prete responder mostrando en la consola el texto Hola Mundo. Vamos ahora a crear un archivo de texto con el cdigo anterior, de forma que pudiramos distribuir nuestro pequeo gran programa entre nuestros amigos. Abre tu editor de texto preferido o bien el IDE que hayas elegido y copia la lnea anterior. Gurdalo como hola.py, por ejemplo. Ejecutar este programa es tan sencillo como indicarle el nombre del archivo a ejecutar al intrprete de Python python hola.py Mi primer programa en Python 13 pero vamos a ver cmo simplificarlo an ms. Si utilizas Windows los archivos .py ya estarn asociados al intrprete de Python, por lo que basta hacer doble clic sobre el archivo para eje- cutar el programa. Sin embargo como este programa no hace ms que imprimir un texto en la consola, la ejecucin es demasiado rpida para poder verlo si quiera. Para remediarlo, vamos a aadir una nueva lnea que espere la entrada de datos por parte del usuario. print "Hola Mundo" raw_input() De esta forma se mostrar una consola con el texto Hola Mundo hasta que pulsemos Enter. Si utilizas Linux (u otro Unix) para conseguir este comportamiento, es decir, para que el sistema operativo abra el archivo .py con el intrprete adecuado, es necesario aadir una nueva lnea al principio del archivo: #!/usr/bin/python print "Hola Mundo" raw_input() A esta lnea se le conoce en el mundo Unix como shebang, hashbang o sharpbang. El par de caracteres #! indica al sistema operativo que dicho script se debe ejecutar utilizando el intrprete especificado a continuacin. De esto se desprende, evidentemente, que si esta no es la ruta en la que est instalado nuestro intrprete de Python, es necesario cambiarla. Otra opcin es utilizar el programa env (de environment, entorno) para preguntar al sistema por la ruta al intrprete de Python, de forma que nuestros usuarios no tengan ningn problema si se diera el caso de que el programa no estuviera instalado en dicha ruta: #!/usr/bin/env python print "Hola Mundo" raw_input() Por supuesto adems de aadir el shebang, tendremos que dar permi- sos de ejecucin al programa. Python para todos 14 chmod +x hola.py Y listo, si hacemos doble clic el programa se ejecutar, mostrando una consola con el texto Hola Mundo, como en el caso de Windows. Tambin podramos correr el programa desde la consola como si trata- ra de un ejecutable cualquiera: ./hola.py 15 tipos bsiCos En Python los tipos bsicos se dividen en: Nmeros, como pueden ser 3 (entero), 15.57 (de coma flotante) o 7 + 5j (complejos) Cadenas de texto, como "Hola Mundo" Valores booleanos: True (cierto) y False (falso). Vamos a crear un par de variables a modo de ejemplo. Una de tipo cadena y una de tipo entero: # esto es una cadena c = "Hola Mundo" # y esto es un entero e = 23 # podemos comprobarlo con la funcin type type(c) type(e) Como veis en Python, a diferencia de muchos otros lenguajes, no se declara el tipo de la variable al crearla. En Java, por ejemplo, escribira- mos: String c = "Hola Mundo"; int e = 23; Este pequeo ejemplo tambin nos ha servido para presentar los comentarios inline en Python: cadenas de texto que comienzan con el carcter # y que Python ignora totalmente. Hay ms tipos de comenta- rios, de los que hablaremos ms adelante. Python para todos 16 Nmeros Como decamos, en Python se pueden representar nmeros enteros, reales y complejos. Enteros Los nmeros enteros son aquellos nmeros positivos o negativos que no tienen decimales (adems del cero). En Python se pueden repre- sentar mediante el tipo int (de integer, entero) o el tipo long (largo). La nica diferencia es que el tipo long permite almacenar nmeros ms grandes. Es aconsejable no utilizar el tipo long a menos que sea necesario, para no malgastar memoria. El tipo int de Python se implementa a bajo nivel mediante un tipo long de C. Y dado que Python utiliza C por debajo, como C, y a dife- rencia de Java, el rango de los valores que puede representar depende de la plataforma. En la mayor parte de las mquinas el long de C se almacena utilizando 32 bits, es decir, mediante el uso de una variable de tipo int de Python podemos almacenar nmeros de -231 a 231 - 1, o lo que es lo mismo, de -2.147.483.648 a 2.147.483.647. En plataformas de 64 bits, el rango es de -9.223.372.036.854.775.808 hasta 9.223.372.036.854.775.807. El tipo long de Python permite almacenar nmeros de cualquier preci- sin, estando limitados solo por la memoria disponible en la mquina. Al asignar un nmero a una variable esta pasar a tener tipo int, a menos que el nmero sea tan grande como para requerir el uso del tipo long. # type(entero) devolvera int entero = 23 Tambin podemos indicar a Python que un nmero se almacene usan- do long aadiendo una L al final: # type(entero) devolvera long entero = 23L Tipos bsicos 17 El literal que se asigna a la variable tambin se puede expresar como un octal, anteponiendo un cero: # 027 octal = 23 en base 10 entero = 027 o bien en hexadecimal, anteponiendo un 0x: # 017 hexadecimal = 23 en base 10 entero = 017 Reales Los nmeros reales son los que tienen decimales. En Python se expre- san mediante el tipo float. En otros lenguajes de programacin, como C, tenemos tambin el tipo double, similar a float pero de mayor precisin (double = doble precisin). Python, sin embargo, implementa su tipo float a bajo nivel mediante una variable de tipo double de C, es decir, utilizando 64 bits, luego en Python siempre se utiliza doble precisin, y en concreto se sigue el estndar IEEE 754: 1 bit para el signo, 11 para el exponente, y 52 para la mantisa. Esto significa que los valores que podemos representar van desde 2,2250738585072020 x 10-308 hasta 1,797693134862315710308. La mayor parte de los lenguajes de programacin siguen el mismo esquema para la representacin interna. Pero como muchos sabris esta tiene sus limitaciones, impuestas por el hardware. Por eso desde Python 2.4 contamos tambin con un nuevo tipo Decimal, para el caso de que se necesite representar fracciones de forma ms precisa. Sin embargo este tipo est fuera del alcance de este tutorial, y slo es necesario para el mbito de la programacin cientfica y otros rela- cionados. Para aplicaciones normales podeis utilizar el tipo float sin miedo, como ha venido hacindose desde hace aos, aunque teniendo en cuenta que los nmeros en coma flotante no son precisos (ni en este ni en otros lenguajes de programacin). Para representar un nmero real en Python se escribe primero la parte entera, seguido de un punto y por ltimo la parte decimal. real = 0.2703 Python para todos 18 Tambin se puede utilizar notacin cientfica, y aadir una e (de expo- nente) para indicar un exponente en base 10. Por ejemplo: real = 0.1e-3 sera equivalente a 0.1 x 10-3 = 0.1 x 0.001 = 0.0001 Complejos Los nmeros complejos son aquellos que tienen parte imaginaria. Si no conocas de su existencia, es ms que probable que nunca lo vayas a necesitar, por lo que puedes saltarte este apartado tranquilamente. De hecho la mayor parte de lenguajes de programacin carecen de este tipo, aunque sea muy utilizado por ingenieros y cientficos en general. En el caso de que necesitis utilizar nmeros complejos, o simplemen- te tengis curiosidad, os dir que este tipo, llamado complex en Python, tambin se almacena usando coma flotante, debido a que estos nme- ros son una extensin de los nmeros reales. En concreto se almacena en una estructura de C, compuesta por dos variables de tipo double, sirviendo una de ellas para almacenar la parte real y la otra para la parte imaginaria. Los nmeros complejos en Python se representan de la siguiente forma: complejo = 2.1 + 7.8j Operadores Veamos ahora qu podemos hacer con nuestros nmeros usando los operadores por defecto. Para operaciones ms complejas podemos recurrir al mdulo math. Operadores aritmticos Operador Descripcin Ejemplo + Suma r = 3 + 2 # r es 5 - Resta r = 4 - 7 # r es -3 Tipos bsicos 19 Operador Descripcin Ejemplo - Negacin r = -7 # r es -7 * Multiplicacin r = 2 * 6 # r es 12 ** Exponente r = 2 ** 6 # r es 64 / Divisin r = 3.5 / 2 # r es 1.75 // Divisin entera r = 3.5 // 2 # r es 1.0 % Mdulo r = 7 % 2 # r es 1 Puede que tengis dudas sobre cmo funciona el operador de mdulo, y cul es la diferencia entre divisin y divisin entera. El operador de mdulo no hace otra cosa que devolvernos el resto de la divisin entre los dos operandos. En el ejemplo, 7/2 sera 3, con 1 de resto, luego el mdulo es 1. La diferencia entre divisin y divisin entera no es otra que la que indica su nombre. En la divisin el resultado que se devuelve es un nmero real, mientras que en la divisin entera el resultado que se devuelve es solo la parte entera. No obstante hay que tener en cuenta que si utilizamos dos operandos enteros, Python determinar que queremos que la variable resultado tambin sea un entero, por lo que el resultado de, por ejemplo, 3 / 2 y 3 // 2 sera el mismo: 1. Si quisiramos obtener los decimales necesitaramos que al menos uno de los operandos fuera un nmero real, bien indicando los decimales r = 3.0 / 2 o bien utilizando la funcin float (no es necesario que sepais lo que significa el trmino funcin, ni que recordeis esta forma, lo veremos un poco ms adelante): r = float(3) / 2 Esto es as porque cuando se mezclan tipos de nmeros, Python con- Python para todos 20 vierte todos los operandos al tipo ms complejo de entre los tipos de los operandos. Operadores a nivel de bit Si no conocis estos operadores es poco probable que vayis a necesi- tarlos, por lo que podis obviar esta parte. Si an as tenis curiosidad os dir que estos son operadores que actan sobre las representaciones en binario de los operandos. Por ejemplo, si veis una operacin como 3 & 2, lo que estais viendo es un and bit a bit entre los nmeros binarios 11 y 10 (las representacio- nes en binario de 3 y 2). El operador and (&), del ingls "y", devuelve 1 si el primer bit operando es 1 y el segundo bit operando es 1. Se devuelve 0 en caso contrario. El resultado de aplicar and bit a bit a 11 y 10 sera entonces el nmero binario 10, o lo que es lo mismo, 2 en decimal (el primer dgito es 1 para ambas cifras, mientras que el segundo es 1 slo para una de ellas). El operador or (|), del ingls "o", devuelve 1 si el primer operando es 1 o el segundo operando es 1. Para el resto de casos se devuelve 0. El operador xor u or exclusivo (^) devuelve 1 si uno de los operandos es 1 y el otro no lo es. El operador not (~), del ingls "no", sirve para negar uno a uno cada bit; es decir, si el operando es 0, cambia a 1 y si es 1, cambia a 0. Por ltimo los operadores de desplazamiento (>) sirven para desplazar los bits n posiciones hacia la izquierda o la derecha. Operador Descripcin Ejemplo & and r = 3 & 2 # r es 2 | or r = 3 | 2 # r es 3 ^ xor r = 3 ^ 2 # r es 1 ~ not r = ~3 # r es -4 Tipos bsicos 21 Desplazamiento der. r = 3 >> 1 # r es 1 Cadenas Las cadenas no son ms que texto encerrado entre comillas simples ('cadena') o dobles ("cadena"). Dentro de las comillas se pueden aadir caracteres especiales escapndolos con \, como \n, el carcter de nueva lnea, o \t, el de tabulacin. Una cadena puede estar precedida por el carcter u o el carcter r, los cuales indican, respectivamente, que se trata de una cadena que utiliza codificacin Unicode y una cadena raw (del ingls, cruda). Las cade- nas raw se distinguen de las normales en que los caracteres escapados mediante la barra invertida (\) no se sustituyen por sus contrapartidas. Esto es especialmente til, por ejemplo, para las expresiones regulares, como veremos en el captulo correspondiente. unicode = u"" raw = r"\n" Tambin es posible encerrar una cadena entre triples comillas (simples o dobles). De esta forma podremos escribir el texto en varias lneas, y al imprimir la cadena, se respetarn los saltos de lnea que introdujimos sin tener que recurrir al carcter \n, as como las comillas sin tener que escaparlas. triple = """primera linea esto se vera en otra linea""" Las cadenas tambin admiten operadores como +, que funciona reali- zando una concatenacin de las cadenas utilizadas como operandos y *, en la que se repite la cadena tantas veces como lo indique el nmero utilizado como segundo operando. a = "uno" b = "dos" c = a + b # c es "unodos" c = a * 3 # c es "unounouno" Python para todos 22 Booleanos Como decamos al comienzo del captulo una variable de tipo boolea- no slo puede tener dos valores: True (cierto) y False (falso). Estos valores son especialmente importantes para las expresiones condicio- nales y los bucles, como veremos ms adelante. En realidad el tipo bool (el tipo de los booleanos) es una subclase del tipo int. Puede que esto no tenga mucho sentido para t si no conoces los trminos de la orientacin a objetos, que veremos ms adelante, aunque tampoco es nada importante. Estos son los distintos tipos de operadores con los que podemos traba- jar con valores booleanos, los llamados operadores lgicos o condicio- nales: Operador Descripcin Ejemplo and se cumple a y b? r = True and False # r es False or se cumple a o b? r = True or False # r es True not No a r = not True # r es False Los valores booleanos son adems el resultado de expresiones que utilizan operadores relacionales (comparaciones entre valores): Operador Descripcin Ejemplo == son iguales a y b? r = 5 == 3 # r es False != son distintos a y b? r = 5 != 3 # r es True < es a menor que b? r = 5 < 3 # r es False > es a mayor que b? r = 5 > 3 # r es True Tipos bsicos 23 = 3 # r es True 24 ColeCCiones En el captulo anterior vimos algunos tipos bsicos, como los nmeros, las cadenas de texto y los booleanos. En esta leccin veremos algunos tipos de colecciones de datos: listas, tuplas y diccionarios. Listas La lista es un tipo de coleccin ordenada. Sera equivalente a lo que en otros lenguajes se conoce por arrays, o vectores. Las listas pueden contener cualquier tipo de dato: nmeros, cadenas, booleanos, y tambin listas. Crear una lista es tan sencillo como indicar entre corchetes, y separa- dos por comas, los valores que queremos incluir en la lista: l = [22, True, "una lista", [1, 2]] Podemos acceder a cada uno de los elementos de la lista escribiendo el nombre de la lista e indicando el ndice del elemento entre corchetes. Ten en cuenta sin embargo que el ndice del primer elemento de la lista es 0, y no 1: l = [11, False] mi_var = l[0] # mi_var vale 11 Si queremos acceder a un elemento de una lista incluida dentro de otra lista tendremos que utilizar dos veces este operador, primero para in- dicar a qu posicin de la lista exterior queremos acceder, y el segundo para seleccionar el elemento de la lista interior: l = ["una lista", [1, 2]] Colecciones 25 mi_var = l[1][0] # mi_var vale 1 Tambin podemos utilizar este operador para modificar un elemento de la lista si lo colocamos en la parte izquierda de una asignacin: l = [22, True] l[0] = 99 # Con esto l valdr [99, True] El uso de los corchetes para acceder y modificar los elementos de una lista es comn en muchos lenguajes, pero Python nos depara varias sorpresas muy agradables. Una curiosidad sobre el operador [] de Python es que podemos utili- zar tambin nmeros negativos. Si se utiliza un nmero negativo como ndice, esto se traduce en que el ndice empieza a contar desde el final, hacia la izquierda; es decir, con [-1] accederamos al ltimo elemento de la lista, con [-2] al penltimo, con [-3], al antepenltimo, y as sucesivamente. Otra cosa inusual es lo que en Python se conoce como slicing o parti- cionado, y que consiste en ampliar este mecanismo para permitir selec- cionar porciones de la lista. Si en lugar de un nmero escribimos dos nmeros inicio y fin separados por dos puntos (inicio:fin) Python interpretar que queremos una lista que vaya desde la posicin inicio a la posicin fin, sin incluir este ltimo. Si escribimos tres nmeros (inicio:fin:salto) en lugar de dos, el tercero se utiliza para determi- nar cada cuantas posiciones aadir un elemento a la lista. l = [99, True, "una lista", [1, 2]] mi_var = l[0:2] # mi_var vale [99, True] mi_var = l[0:4:2] # mi_var vale [99, "una lista"] Los nmeros negativos tambin se pueden utilizar en un slicing, con el mismo comportamiento que se coment anteriormente. Hay que mencionar as mismo que no es necesario indicar el principio y el final del slicing, sino que, si estos se omiten, se usarn por defecto las posiciones de inicio y fin de la lista, respectivamente: l = [99, True, "una lista"] mi_var = l[1:] # mi_var vale [True, "una lista"] Python para todos 26 mi_var = l[:2] # mi_var vale [99, True] mi_var = l[:] # mi_var vale [99, True, "una lista"] mi_var = l[::2] # mi_var vale [99, "una lista"] Tambin podemos utilizar este mecanismo para modificar la lista: l = [99, True, "una lista", [1, 2]] l[0:2] = [0, 1] # l vale [0, 1, "una lista", [1, 2]] pudiendo incluso modificar el tamao de la lista si la lista de la parte derecha de la asignacin tiene un tamao menor o mayor que el de la seleccin de la parte izquierda de la asignacin: l[0:2] = [False] # l vale [False, "una lista", [1, 2]] En todo caso las listas ofrecen mecanismos ms cmodos para ser mo- dificadas a travs de las funciones de la clase correspondiente, aunque no veremos estos mecanismos hasta ms adelante, despus de explicar lo que son las clases, los objetos y las funciones. Tuplas Todo lo que hemos explicado sobre las listas se aplica tambin a las tuplas, a excepcin de la forma de definirla, para lo que se utilizan parntesis en lugar de corchetes. t = (1, 2, True, "python") En realidad el constructor de la tupla es la coma, no el parntesis, pero el intrprete muestra los parntesis, y nosotros deberamos utilizarlos, por claridad. >>> t = 1, 2, 3 >>> type(t) type "tuple" Adems hay que tener en cuenta que es necesario aadir una coma para tuplas de un solo elemento, para diferenciarlo de un elemento entre parntesis. >>> t = (1) >>> type(t) Colecciones 27 type "int" >>> t = (1,) >>> type(t) type "tuple" Para referirnos a elementos de una tupla, como en una lista, se usa el operador []: mi_var = t[0] # mi_var es 1 mi_var = t[0:2] # mi_var es (1, 2) Podemos utilizar el operador [] debido a que las tuplas, al igual que las listas, forman parte de un tipo de objetos llamados secuencias. Permitirme un pequeo inciso para indicaros que las cadenas de texto tambin son secuencias, por lo que no os extraar que podamos hacer cosas como estas: c = "hola mundo" c[0] # h c[5:] # mundo c[::3] # hauo Volviendo al tema de las tuplas, su diferencia con las listas estriba en que las tuplas no poseen estos mecanismos de modificacin a travs de funciones tan tiles de los que hablbamos al final de la anterior seccin. Adems son inmutables, es decir, sus valores no se pueden modificar una vez creada; y tienen un tamao fijo. A cambio de estas limitaciones las tuplas son ms "ligeras" que las listas, por lo que si el uso que le vamos a dar a una coleccin es muy bsico, puedes utilizar tuplas en lugar de listas y ahorrar memoria. Diccionarios Los diccionarios, tambin llamados matrices asociativas, deben su nombre a que son colecciones que relacionan una clave y un valor. Por ejemplo, veamos un diccionario de pelculas y directores: d = {"Love Actually ": "Richard Curtis", "Kill Bill": "Tarantino", Python para todos 28 "Amlie": "Jean-Pierre Jeunet"} El primer valor se trata de la clave y el segundo del valor asociado a la clave. Como clave podemos utilizar cualquier valor inmutable: podramos usar nmeros, cadenas, booleanos, tuplas, pero no listas o diccionarios, dado que son mutables. Esto es as porque los diccio- narios se implementan como tablas hash, y a la hora de introducir un nuevo par clave-valor en el diccionario se calcula el hash de la clave para despus poder encontrar la entrada correspondiente rpidamente. Si se modificara el objeto clave despus de haber sido introducido en el diccionario, evidentemente, su hash tambin cambiara y no podra ser encontrado. La diferencia principal entre los diccionarios y las listas o las tuplas es que a los valores almacenados en un diccionario se les accede no por su ndice, porque de hecho no tienen orden, sino por su clave, utilizando de nuevo el operador []. d["Love Actually "] # devuelve "Richard Curtis" Al igual que en listas y tuplas tambin se puede utilizar este operador para reasignar valores. d["Kill Bill"] = "Quentin Tarantino" Sin embargo en este caso no se puede utilizar slicing, entre otras cosas porque los diccionarios no son secuencias, si no mappings (mapeados, asociaciones). 29 Control de flujo En esta leccin vamos a ver los condicionales y los bucles. Sentencias condicionales Si un programa no fuera ms que una lista de rdenes a ejecutar de forma secuencial, una por una, no tendra mucha utilidad. Los con- dicionales nos permiten comprobar condiciones y hacer que nuestro programa se comporte de una forma u otra, que ejecute un fragmento de cdigo u otro, dependiendo de esta condicin. Aqu es donde cobran su importancia el tipo booleano y los operadores lgicos y relacionales que aprendimos en el captulo sobre los tipos bsicos de Python. if La forma ms simple de un estamento condicional es un if (del ingls si) seguido de la condicin a evaluar, dos puntos (:) y en la siguiente lnea e indentado, el cdigo a ejecutar en caso de que se cumpla dicha condicin. fav = "mundogeek.net" # si (if) fav es igual a "mundogeek.net" if fav == "mundogeek.net": print "Tienes buen gusto!" print "Gracias" Como veis es bastante sencillo. Eso si, aseguraros de que indentis el cdigo tal cual se ha hecho en el ejemplo, es decir, aseguraros de pulsar Tabulacin antes de las dos r- denes print, dado que esta es la forma de Python de saber que vuestra intencin es la de que los dos print se ejecuten slo en el caso de que Python para todos 30 se cumpla la condicin, y no la de que se imprima la primera cadena si se cumple la condicin y la otra siempre, cosa que se expresara as: if fav == "mundogeek.net": print "Tienes buen gusto!" print "Gracias" En otros lenguajes de programacin los bloques de cdigo se determi- nan encerrndolos entre llaves, y el indentarlos no se trata ms que de una buena prctica para que sea ms sencillo seguir el flujo del progra- ma con un solo golpe de vista. Por ejemplo, el cdigo anterior expresa- do en Java sera algo as: String fav = "mundogeek.net"; if (fav.equals("mundogeek.net")){ System.out.println("Tienes buen gusto!"); System.out.println("Gracias"); } Sin embargo, como ya hemos comentado, en Python se trata de una obligacin, y no de una eleccin. De esta forma se obliga a los progra- madores a indentar su cdigo para que sea ms sencillo de leer :) if else Vamos a ver ahora un condicional algo ms complicado. Qu hara- mos si quisiramos que se ejecutaran unas ciertas rdenes en el caso de que la condicin no se cumpliera? Sin duda podramos aadir otro if que tuviera como condicin la negacin del primero: if fav == "mundogeek.net": print "Tienes buen gusto!" print "Gracias" if fav != "mundogeek.net": print "Vaya, que lstima" pero el condicional tiene una segunda construccin mucho ms til: if fav == "mundogeek.net": print "Tienes buen gusto!" print "Gracias" else: print "Vaya, que lstima" Control de flujo 31 Vemos que la segunda condicin se puede sustituir con un else (del ingls: si no, en caso contrario). Si leemos el cdigo vemos que tiene bastante sentido: "si fav es igual a mundogeek.net, imprime esto y esto, si no, imprime esto otro". if elif elif else Todava queda una construccin ms que ver, que es la que hace uso del elif. if numero < 0: print "Negativo" elif numero > 0: print "Positivo" else: print "Cero" elif es una contraccin de else if, por lo tanto elif numero > 0 puede leerse como "si no, si numero es mayor que 0". Es decir, primero se evala la condicin del if. Si es cierta, se ejecuta su cdigo y se con- tina ejecutando el cdigo posterior al condicional; si no se cumple, se evala la condicin del elif. Si se cumple la condicin del elif se ejecuta su cdigo y se continua ejecutando el cdigo posterior al condicional; si no se cumple y hay ms de un elif se contina con el siguiente en orden de aparicin. Si no se cumple la condicin del if ni de ninguno de los elif, se ejecuta el cdigo del else. A if C else B Tambin existe una construccin similar al operador ? de otros lengua- jes, que no es ms que una forma compacta de expresar un if else. En esta construccin se evala el predicado C y se devuelve A si se cumple o B si no se cumple: A if C else B. Veamos un ejemplo: var = "par" if (num % 2 == 0) else "impar" Y eso es todo. Si conocis otros lenguajes de programacin puede que esperarais que os hablara ahora del switch, pero en Python no existe esta construccin, que podra emularse con un simple diccionario, as que pasemos directamente a los bucles. Python para todos 32 Bucles Mientras que los condicionales nos permiten ejecutar distintos frag- mentos de cdigo dependiendo de ciertas condiciones, los bucles nos permiten ejecutar un mismo fragmento de cdigo un cierto nmero de veces, mientras se cumpla una determinada condicin. while El bucle while (mientras) ejecuta un fragmento de cdigo mientras se cumpla una condicin. edad = 0 while edad < 18: edad = edad + 1 print "Felicidades, tienes " + str(edad) La variable edad comienza valiendo 0. Como la condicin de que edad es menor que 18 es cierta (0 es menor que 18), se entra en el bucle. Se aumenta edad en 1 y se imprime el mensaje informando de que el usuario ha cumplido un ao. Recordad que el operador + para las cadenas funciona concatenando ambas cadenas. Es necesario utilizar la funcin str (de string, cadena) para crear una cadena a partir del nmero, dado que no podemos concatenar nmeros y cadenas, pero ya comentaremos esto y mucho ms en prximos captulos. Ahora se vuelve a evaluar la condicin, y 1 sigue siendo menor que 18, por lo que se vuelve a ejecutar el cdigo que aumenta la edad en un ao e imprime la edad en la pantalla. El bucle continuar ejecutndose hasta que edad sea igual a 18, momento en el cual la condicin dejar de cumplirse y el programa continuara ejecutando las instrucciones siguientes al bucle. Ahora imaginemos que se nos olvidara escribir la instruccin que aumenta la edad. En ese caso nunca se llegara a la condicin de que edad fuese igual o mayor que 18, siempre sera 0, y el bucle continuara indefinidamente escribiendo en pantalla Has cumplido 0. Esto es lo que se conoce como un bucle infinito. Control de flujo 33 Sin embargo hay situaciones en las que un bucle infinito es til. Por ejemplo, veamos un pequeo programa que repite todo lo que el usua- rio diga hasta que escriba adios. while True: entrada = raw_input("> ") if entrada == "adios": break else: print entrada Para obtener lo que el usuario escriba en pantalla utilizamos la funcin raw_input. No es necesario que sepais qu es una funcin ni cmo funciona exactamente, simplemente aceptad por ahora que en cada iteracin del bucle la variable entrada contendr lo que el usuario escribi hasta pulsar Enter. Comprobamos entonces si lo que escribi el usuario fue adios, en cuyo caso se ejecuta la orden break o si era cualquier otra cosa, en cuyo caso se imprime en pantalla lo que el usuario escribi. La palabra clave break (romper) sale del bucle en el que estamos. Este bucle se podra haber escrito tambin, no obstante, de la siguiente forma: salir = False while not salir: entrada = raw_input() if entrada == "adios": salir = True else: print entrada pero nos ha servido para ver cmo funciona break. Otra palabra clave que nos podemos encontrar dentro de los bucles es continue (continuar). Como habris adivinado no hace otra cosa que pasar directamente a la siguiente iteracin del bucle. edad = 0 while edad < 18: Python para todos 34 edad = edad + 1 if edad % 2 == 0: continue print "Felicidades, tienes " + str(edad) Como veis esta es una pequea modificacin de nuestro programa de felicitaciones. En esta ocasin hemos aadido un if que comprueba si la edad es par, en cuyo caso saltamos a la prxima iteracin en lugar de imprimir el mensaje. Es decir, con esta modificacin el programa slo imprimira felicitaciones cuando la edad fuera impar. for in A los que hayis tenido experiencia previa con segn que lenguajes este bucle os va a sorprender gratamente. En Python for se utiliza como una forma genrica de iterar sobre una secuencia. Y como tal intenta facilitar su uso para este fin. Este es el aspecto de un bucle for en Python: secuencia = ["uno", "dos", "tres"] for elemento in secuencia: print elemento Como hemos dicho los for se utilizan en Python para recorrer secuen- cias, por lo que vamos a utilizar un tipo secuencia, como es la lista, para nuestro ejemplo. Leamos la cabecera del bucle como si de lenguaje natural se tratara: "para cada elemento en secuencia". Y esto es exactamente lo que hace el bucle: para cada elemento que tengamos en la secuencia, ejecuta estas lneas de cdigo. Lo que hace la cabecera del bucle es obtener el siguiente elemento de la secuencia secuencia y almacenarlo en una variable de nombre ele- mento. Por esta razn en la primera iteracin del bucle elemento valdr "uno", en la segunda "dos", y en la tercera "tres". Fcil y sencillo. En C o C++, por ejemplo, lo que habramos hecho sera iterar sobre las Control de flujo 35 posiciones, y no sobre los elementos: int mi_array[] = {1, 2, 3, 4, 5}; int i; for(i = 0; i < 5; i++) { printf("%d\n", mi_array[i]); } Es decir, tendramos un bucle for que fuera aumentando una variable i en cada iteracin, desde 0 al tamao de la secuencia, y utilizaramos esta variable a modo de ndice para obtener cada elemento e imprimir- lo. Como veis el enfoque de Python es ms natural e intuitivo. Pero, qu ocurre si quisiramos utilizar el for como si estuviramos en C o en Java, por ejemplo, para imprimir los nmeros de 30 a 50? No os preocupis, porque no necesitarais crear una lista y aadir uno a uno los nmeros del 30 al 50. Python proporciona una funcin llamada range (rango) que permite generar una lista que vaya desde el primer nmero que le indiquemos al segundo. Lo veremos despus de ver al fin a qu se refiere ese trmino tan recurrente: las funciones. 36 funCiones Una funcin es un fragmento de cdigo con un nombre asociado que realiza una serie de tareas y devuelve un valor. A los fragmentos de cdigo que tienen un nombre asociado y no devuelven valores se les suele llamar procedimientos. En Python no existen los procedimien- tos, ya que cuando el programador no especifica un valor de retorno la funcin devuelve el valor None (nada), equivalente al null de Java. Adems de ayudarnos a programar y depurar dividiendo el programa en partes las funciones tambin permiten reutilizar cdigo. En Python las funciones se declaran de la siguiente forma: def mi_funcion(param1, param2): print param1 print param2 Es decir, la palabra clave def seguida del nombre de la funcin y entre parntesis los argumentos separados por comas. A continuacin, en otra lnea, indentado y despus de los dos puntos tendramos las lneas de cdigo que conforman el cdigo a ejecutar por la funcin. Tambin podemos encontrarnos con una cadena de texto como primera lnea del cuerpo de la funcin. Estas cadenas se conocen con el nombre de docstring (cadena de documentacin) y sirven, como su nombre indica, a modo de documentacin de la funcin. def mi_funcion(param1, param2): """Esta funcion imprime los dos valores pasados como parametros""" print param1 print param2 Esto es lo que imprime el opeardor ? de iPython o la funcin help Funciones 37 del lenguaje para proporcionar una ayuda sobre el uso y utilidad de las funciones. Todos los objetos pueden tener docstrings, no solo las funciones, como veremos ms adelante. Volviendo a la declaracin de funciones, es importante aclarar que al declarar la funcin lo nico que hacemos es asociar un nombre al fragmento de cdigo que conforma la funcin, de forma que podamos ejecutar dicho cdigo ms tarde referencindolo por su nombre. Es decir, a la hora de escribir estas lneas no se ejecuta la funcin. Para llamar a la funcin (ejecutar su cdigo) se escribira: mi_funcion("hola", 2) Es decir, el nombre de la funcin a la que queremos llamar seguido de los valores que queramos pasar como parmetros entre parntesis. La asociacin de los parmetros y los valores pasados a la funcin se hace normalmente de izquierda a derecha: como a param1 le hemos dado un valor "hola" y param2 vale 2, mi_funcion imprimira hola en una lnea, y a continuacin 2. Sin embargo tambin es posible modificar el orden de los parmetros si indicamos el nombre del parmetro al que asociar el valor a la hora de llamar a la funcin: mi_funcion(param2 = 2, param1 = "hola") El nmero de valores que se pasan como parmetro al llamar a la fun- cin tiene que coincidir con el nmero de parmetros que la funcin acepta segn la declaracin de la funcin. En caso contrario Python se quejar: >>> mi_funcion("hola") Traceback (most recent call last): File "", line 1, in TypeError: mi_funcion() takes exactly 2 arguments (1 given) Tambin es posible, no obstante, definir funciones con un nmero va- riable de argumentos, o bien asignar valores por defecto a los parme- tros para el caso de que no se indique ningn valor para ese parmetro al llamar a la funcin. Python para todos 38 Los valores por defecto para los parmetros se definen situando un signo igual despus del nombre del parmetro y a continuacin el valor por defecto: def imprimir(texto, veces = 1): print veces * texto En el ejemplo anterior si no indicamos un valor para el segundo parmetro se imprimir una sola vez la cadena que le pasamos como primer parmetro: >>> imprimir("hola") hola si se le indica otro valor, ser este el que se utilice: >>> imprimir("hola", 2) holahola Para definir funciones con un nmero variable de argumentos coloca- mos un ltimo parmetro para la funcin cuyo nombre debe preceder- se de un signo *: def varios(param1, param2, *otros): for val in otros: print val varios(1, 2) varios(1, 2, 3) varios(1, 2, 3, 4) Esta sintaxis funciona creando una tupla (de nombre otros en el ejemplo) en la que se almacenan los valores de todos los parmetros extra pasados como argumento. Para la primera llamada, varios(1, 2), la tupla otros estara vaca dado que no se han pasado ms parmetros que los dos definidos por defecto, por lo tanto no se imprimira nada. En la segunda llamada otros valdra (3, ), y en la tercera (3, 4). Tambin se puede preceder el nombre del ltimo parmetro con **, en cuyo caso en lugar de una tupla se utilizara un diccionario. Las claves de este diccionario seran los nombres de los parmetros indicados al Funciones 39 llamar a la funcin y los valores del diccionario, los valores asociados a estos parmetros. En el siguiente ejemplo se utiliza la funcin items de los diccionarios, que devuelve una lista con sus elementos, para imprimir los parmetros que contiene el diccionario. def varios(param1, param2, **otros): for i in otros.items(): print i varios(1, 2, tercero = 3) Los que conozcis algn otro lenguaje de programacin os estaris preguntando si en Python al pasar una variable como argumento de una funcin estas se pasan por referencia o por valor. En el paso por referencia lo que se pasa como argumento es una referencia o puntero a la variable, es decir, la direccin de memoria en la que se encuentra el contenido de la variable, y no el contenido en si. En el paso por valor, por el contrario, lo que se pasa como argumento es el valor que conte- na la variable. La diferencia entre ambos estriba en que en el paso por valor los cambios que se hagan sobre el parmetro no se ven fuera de la fun- cin, dado que los argumentos de la funcin son variables locales a la funcin que contienen los valores indicados por las variables que se pasaron como argumento. Es decir, en realidad lo que se le pasa a la funcin son copias de los valores y no las variables en si. Si quisiramos modificar el valor de uno de los argumentos y que estos cambios se reflejaran fuera de la funcin tendramos que pasar el par- metro por referencia. En C los argumentos de las funciones se pasan por valor, aunque se puede simular el paso por referencia usando punteros. En Java tambin se usa paso por valor, aunque para las variables que son objetos lo que se hace es pasar por valor la referencia al objeto, por lo que en realidad parece paso por referencia. En Python tambin se utiliza el paso por valor de referencias a objetos, Python para todos 40 como en Java, aunque en el caso de Python, a diferencia de Java, todo es un objeto (para ser exactos lo que ocurre en realidad es que al objeto se le asigna otra etiqueta o nombre en el espacio de nombres local de la funcin). Sin embargo no todos los cambios que hagamos a los parmetros dentro de una funcin Python se reflejarn fuera de esta, ya que hay que tener en cuenta que en Python existen objetos inmutables, como las tuplas, por lo que si intentramos modificar una tupla pasada como parmetro lo que ocurrira en realidad es que se creara una nueva ins- tancia, por lo que los cambios no se veran fuera de la funcin. Veamos un pequeo programa para demostrarlo. En este ejemplo se hace uso del mtodo append de las listas. Un mtodo no es ms que una funcin que pertenece a un objeto, en este caso a una lista; y append, en concreto, sirve para aadir un elemento a una lista. def f(x, y): x = x + 3 y.append(23) print x, y x = 22 y = [22] f(x, y) print x, y El resultado de la ejecucin de este programa sera 25 [22, 23] 22 [22, 23] Como vemos la variable x no conserva los cambios una vez salimos de la funcin porque los enteros son inmutables en Python. Sin embargo la variable y si los conserva, porque las listas son mutables. En resumen: los valores mutables se comportan como paso por refe- rencia, y los inmutables como paso por valor. Con esto terminamos todo lo relacionado con los parmetros de las funciones. Veamos por ltimo cmo devolver valores, para lo que se utiliza la palabra clave return: Funciones 41 def sumar(x, y): return x + y print sumar(3, 2) Como vemos esta funcin tan sencilla no hace otra cosa que sumar los valores pasados como parmetro y devolver el resultado como valor de retorno. Tambin podramos pasar varios valores que retornar a return. def f(x, y): return x * 2, y * 2 a, b = f(1, 2) Sin embargo esto no quiere decir que las funciones Python puedan de- volver varios valores, lo que ocurre en realidad es que Python crea una tupla al vuelo cuyos elementos son los valores a retornar, y esta nica variable es la que se devuelve. 42 orientaCin a objetos En el captulo de introduccin ya comentbamos que Python es un lenguaje multiparadigma en el se poda trabajar con programacin es- tructurada, como venamos haciendo hasta ahora, o con programacin orientada a objetos o programacin funcional. La Programacin Orientada a Objetos (POO u OOP segn sus siglas en ingls) es un paradigma de programacin en el que los conceptos del mundo real relevantes para nuestro problema se modelan a travs de clases y objetos, y en el que nuestro programa consiste en una serie de interacciones entre estos objetos. Clases y objetos Para entender este paradigma primero tenemos que comprender qu es una clase y qu es un objeto. Un objeto es una entidad que agrupa un estado y una funcionalidad relacionadas. El estado del objeto se define a travs de variables llamadas atributos, mientras que la funcionalidad se modela a travs de funciones a las que se les conoce con el nombre de mtodos del objeto. Un ejemplo de objeto podra ser un coche, en el que tendramos atri- butos como la marca, el nmero de puertas o el tipo de carburante y mtodos como arrancar y parar. O bien cualquier otra combinacin de atributos y mtodos segn lo que fuera relevante para nuestro progra- ma. Una clase, por otro lado, no es ms que una plantilla genrica a partir Orientacin a objetos 43 de la cul instanciar los objetos; plantilla que es la que define qu atri- butos y mtodos tendrn los objetos de esa clase. Volviendo a nuestro ejemplo: en el mundo real existe un conjunto de objetos a los que llamamos coches y que tienen un conjunto de atribu- tos comunes y un comportamiento comn, esto es a lo que llamamos clase. Sin embargo, mi coche no es igual que el coche de mi vecino, y aunque pertenecen a la misma clase de objetos, son objetos distintos. En Python las clases se definen mediante la palabra clave class segui- da del nombre de la clase, dos puntos (:) y a continuacin, indentado, el cuerpo de la clase. Como en el caso de las funciones, si la primera lnea del cuerpo se trata de una cadena de texto, esta ser la cadena de documentacin de la clase o docstring. class Coche: """Abstraccion de los objetos coche.""" def __init__(self, gasolina): self.gasolina = gasolina print "Tenemos", gasolina, "litros" def arrancar(self): if self.gasolina > 0: print "Arranca" else: print "No arranca" def conducir(self): if self.gasolina > 0: self.gasolina -= 1 print "Quedan", self.gasolina, "litros" else: print "No se mueve" Lo primero que llama la atencin en el ejemplo anterior es el nombre tan curioso que tiene el mtodo __init__. Este nombre es una conven- cin y no un capricho. El mtodo __init__, con una doble barra baja al principio y final del nombre, se ejecuta justo despus de crear un nuevo objeto a partir de la clase, proceso que se conoce con el nombre de instanciacin. El mtodo __init__ sirve, como sugiere su nombre, para realizar cualquier proceso de inicializacin que sea necesario. Como vemos el primer parmetro de __init__ y del resto de mtodos Python para todos 44 de la clase es siempre self. Esta es una idea inspirada en Modula-3 y sirve para referirse al objeto actual. Este mecanismo es necesario para poder acceder a los atributos y mtodos del objeto diferenciando, por ejemplo, una variable local mi_var de un atributo del objeto self. mi_var. Si volvemos al mtodo __init__ de nuestra clase Coche veremos cmo se utiliza self para asignar al atributo gasolina del objeto (self.gaso- lina) el valor que el programador especific para el parmetro gasoli- na. El parmetro gasolina se destruye al final de la funcin, mientras que el atributo gasolina se conserva (y puede ser accedido) mientras el objeto viva. Para crear un objeto se escribira el nombre de la clase seguido de cual- quier parmetro que sea necesario entre parntesis. Estos parmetros son los que se pasarn al mtodo __init__, que como decamos es el mtodo que se llama al instanciar la clase. mi_coche = Coche(3) Os preguntareis entonces cmo es posible que a la hora de crear nues- tro primer objeto pasemos un solo parmetro a __init__, el nmero 3, cuando la definicin de la funcin indica claramente que precisa de dos parmetros (self y gasolina). Esto es as porque Python pasa el primer argumento (la referencia al objeto que se crea) automgicamen- te. Ahora que ya hemos creado nuestro objeto, podemos acceder a sus atributos y mtodos mediante la sintaxis objeto.atributo y objeto. metodo(): >>> print mi_coche.gasolina 3 >>> mi_coche.arrancar() Arranca >>> mi_coche.conducir() Quedan 2 litros >>> mi_coche.conducir() Quedan 1 litros >>> mi_coche.conducir() Quedan 0 litros >>> mi_coche.conducir() Orientacin a objetos 45 No se mueve >>> mi_coche.arrancar() No arranca >>> print mi_coche.gasolina 0 Como ltimo apunte recordar que en Python, como ya se coment en repetidas ocasiones anteriormente, todo son objetos. Las cadenas, por ejemplo, tienen mtodos como upper(), que devuelve el texto en maysculas o count(sub), que devuelve el nmero de veces que se encontr la cadena sub en el texto. Herencia Hay tres conceptos que son bsicos para cualquier lenguaje de pro- gramacin orientado a objetos: el encapsulamiento, la herencia y el polimorfismo. En un lenguaje orientado a objetos cuando hacemos que una clase (subclase) herede de otra clase (superclase) estamos haciendo que la subclase contenga todos los atributos y mtodos que tena la supercla- se. No obstante al acto de heredar de una clase tambin se le llama a menudo "extender una clase". Supongamos que queremos modelar los instrumentos musicales de una banda, tendremos entonces una clase Guitarra, una clase Batera, una clase Bajo, etc. Cada una de estas clases tendr una serie de atribu- tos y mtodos, pero ocurre que, por el mero hecho de ser instrumentos musicales, estas clases compartirn muchos de sus atributos y mtodos; un ejemplo sera el mtodo tocar(). Es ms sencillo crear un tipo de objeto Instrumento con las atributos y mtodos comunes e indicar al programa que Guitarra, Batera y Bajo son tipos de instrumentos, haciendo que hereden de Instrumento. Para indicar que una clase hereda de otra se coloca el nombre de la cla- se de la que se hereda entre parntesis despus del nombre de la clase: class Instrumento: def __init__(self, precio): Python para todos 46 self.precio = precio def tocar(self): print "Estamos tocando musica" def romper(self): print "Eso lo pagas tu" print "Son", self.precio, "$$$" class Bateria(Instrumento): pass class Guitarra(Instrumento): pass Como Bateria y Guitarra heredan de Instrumento, ambos tienen un mtodo tocar() y un mtodo romper(), y se inicializan pasando un parmetro precio. Pero, qu ocurrira si quisiramos especificar un nuevo parmetro tipo_cuerda a la hora de crear un objeto Guitarra? Bastara con escribir un nuevo mtodo __init__ para la clase Guitarra que se ejecutara en lugar del __init__ de Instrumento. Esto es lo que se conoce como sobreescribir mtodos. Ahora bien, puede ocurrir en algunos casos que necesitemos sobrees- cribir un mtodo de la clase padre, pero que en ese mtodo queramos ejecutar el mtodo de la clase padre porque nuestro nuevo mtodo no necesite ms que ejecutar un par de nuevas instrucciones extra. En ese caso usaramos la sintaxis SuperClase.metodo(self, args) para llamar al mtodo de igual nombre de la clase padre. Por ejemplo, para llamar al mtodo __init__ de Instrumento desde Guitarra usaramos Instru- mento.__init__(self, precio) Observad que en este caso si es necesario especificar el parmetro self. Herencia mltiple En Python, a diferencia de otros lenguajes como Java o C#, se permite la herencia mltiple, es decir, una clase puede heredar de varias clases a la vez. Por ejemplo, podramos tener una clase Cocodrilo que heredara de la clase Terrestre, con mtodos como caminar() y atributos como velocidad_caminar y de la clase Acuatico, con mtodos como nadar() y atributos como velocidad_nadar. Basta con enumerar las clases de Orientacin a objetos 47 las que se hereda separndolas por comas: class Cocodrilo(Terrestre, Acuatico): pass En el caso de que alguna de las clases padre tuvieran mtodos con el mismo nombre y nmero de parmetros las clases sobreescribiran la implementacin de los mtodos de las clases ms a su derecha en la definicin. En el siguiente ejemplo, como Terrestre se encuentra ms a la iz- quierda, sera la definicin de desplazar de esta clase la que prevale- cera, y por lo tanto si llamamos al mtodo desplazar de un objeto de tipo Cocodrilo lo que se imprimira sera "El animal anda". class Terrestre: def desplazar(self): print "El animal anda" class Acuatico: def desplazar(self): print "El animal nada" class Cocodrilo(Terrestre, Acuatico): pass c = Cocodrilo() c.desplazar() Polimorfismo La palabra polimorfismo, del griego poly morphos (varias formas), se re- fiere a la habilidad de objetos de distintas clases de responder al mismo mensaje. Esto se puede conseguir a travs de la herencia: un objeto de una clase derivada es al mismo tiempo un objeto de la clase padre, de forma que all donde se requiere un objeto de la clase padre tambin se puede utilizar uno de la clase hija. Python, al ser de tipado dinmico, no impone restricciones a los tipos que se le pueden pasar a una funcin, por ejemplo, ms all de que el objeto se comporte como se espera: si se va a llamar a un mtodo f() del objeto pasado como parmetro, por ejemplo, evidentemente el objeto tendr que contar con ese mtodo. Por ese motivo, a diferencia Python para todos 48 de lenguajes de tipado esttico como Java o C++, el polimorfismo en Python no es de gran importancia. En ocasiones tambin se utiliza el trmino polimorfismo para referirse a la sobrecarga de mtodos, trmino que se define como la capacidad del lenguaje de determinar qu mtodo ejecutar de entre varios mto- dos con igual nombre segn el tipo o nmero de los parmetros que se le pasa. En Python no existe sobrecarga de mtodos (el ltimo mtodo sobreescribira la implementacin de los anteriores), aunque se puede conseguir un comportamiento similar recurriendo a funciones con va- lores por defecto para los parmetros o a la sintaxis *params o **params explicada en el captulo sobre las funciones en Python, o bien usando decoradores (mecanismo que veremos ms adelante). Encapsulacin La encapsulacin se refiere a impedir el acceso a determinados m- todos y atributos de los objetos estableciendo as qu puede utilizarse desde fuera de la clase. Esto se consigue en otros lenguajes de programacin como Java utili- zando modificadores de acceso que definen si cualquiera puede acceder a esa funcin o variable (public) o si est restringido el acceso a la propia clase (private). En Python no existen los modificadores de acceso, y lo que se suele hacer es que el acceso a una variable o funcin viene determinado por su nombre: si el nombre comienza con dos guiones bajos (y no termina tambin con dos guiones bajos) se trata de una variable o funcin pri- vada, en caso contrario es pblica. Los mtodos cuyo nombre comien- za y termina con dos guiones bajos son mtodos especiales que Python llama automticamente bajo ciertas circunstancias, como veremos al final del captulo. En el siguiente ejemplo slo se imprimir la cadena correspondiente al mtodo publico(), mientras que al intentar llamar al mtodo __pri- vado() Python lanzar una excepcin quejndose de que no existe (evidentemente existe, pero no lo podemos ver porque es privado). Orientacin a objetos 49 class Ejemplo: def publico(self): print "Publico" def __privado(self): print "Privado" ej = Ejemplo() ej.publico() ej.__privado() Este mecanismo se basa en que los nombres que comienzan con un doble guin bajo se renombran para incluir el nombre de la clase (caracterstica que se conoce con el nombre de name mangling). Esto implica que el mtodo o atributo no es realmente privado, y podemos acceder a l mediante una pequea trampa: ej._Ejemplo__privado() En ocasiones tambin puede suceder que queramos permitir el acceso a algn atributo de nuestro objeto, pero que este se produzca de forma controlada. Para esto podemos escribir mtodos cuyo nico cometido sea este, mtodos que normalmente, por convencin, tienen nombres como getVariable y setVariable; de ah que se conozcan tambin con el nombre de getters y setters. class Fecha(): def __init__(self): self.__dia = 1 def getDia(self): return self.__dia def setDia(self, dia): if dia > 0 and dia < 31: self.__dia = dia else: print "Error" mi_fecha = Fecha() mi_fecha.setDia(33) Esto se podra simplificar median

Python para todos.pdf

Comments

You must log in to comment