7
SOLO PROGRAMADORES Introducción En este primer artículo nos dedicaremos a intro- ducir la sintaxis de Python y a iniciarnos en la programación orientada a objetos a través de Python. En un segundo artículo hablaremos de las facilidades provistas por Python para la pro- gramación de interfaces gráficas. En la tercera entrega explicaremos las bondades de Python para la programación de aplicaciones web con acceso a bases de datos. Finalmente, concluire- mos este curso de Python en una cuarta entrega con la descripción de su primo hermano Jython. Python, el otro lenguaje de programación libre que empieza con 'P' y que no es ni Perl ni PHP, fue creado por Guido van Rossum (http://www- .python.org/~guido/) en 1991. Dio este nombre al lenguaje inspirado por el popular grupo cómi- co británico Monty Python. Guido creó Python durante unas vacaciones de navidad en las que (al parecer) se estaba aburriendo. Hola Mundo en Python Como con cualquier otro lenguaje de programa- ción, comencemos el aprendizaje de Python con el más simple de los ejemplos: print "Hola Mundo" # "Hola Mundo" En este primer extracto de código ya podemos observar la simplicidad de Python. Probable- mente este es el ejemplo del programa "Hola Mundo" más sencillo que jamás has visto. La sentencia print imprime una cadena de caracte- res a consola. Las cadenas de caracteres en Python se pueden denotar bien entre comillas dobles o comillas simples, por ejemplo 'Hola mundo'. Nótese que los comentarios de línea se indican con el símbolo #, mientras que los blo- ques de código pueden comentarse entre '"' y '"'. Características de Python Tras ver el primer extracto de código en Python, enumeremos sus principales características: Sintaxis elegante, minimalista y densa: En Python todo aquello innecesario no hay que escribirlo (;, {, }, \n). Además como veremos pocas líneas de código revierten en mucha funcionalidad. Moderno: Soporta objetos y estructuras de datos de alto nivel tales como cadenas de caracteres (strings), listas, diccionarios. Multi-paradigma: En vez de forzar a los pro- gramadores a adoptar un paradigma de pro- gramación único, Python permite el uso de programación orientada a objetos, programa- ción estructurada o procedural e incluso pro- gramación funcional. Organizado y extendible: Dispone de múltiples formas de organizar código tales como funcio- nes, clases, módulos, y paquetes. Si hay áreas que son lentas se pueden reemplazar por plu- gins en C o C++, siguiendo la API para exten- der o empotrar Python en una aplicación. Interpretado: No es necesario declarar cons- tantes y variables antes de utilizarlas y no requiere paso de compilación/linkaje. La pri- mera vez que se ejecuta un script de Python se compila y genera bytecode que es luego interpretado. Python es dinámico, encuentra errores de uso de tipos de datos en tiempo de ejecución y usa un recolector de basura para la gestión de memoria. Multiplataforma: Python genera código interoperable, que se puede ejecutar en múl- tiples plataformas (más aún que Java). Además, es posible embeber Python dentro de una JVM, como veremos en la cuarta entrega de esta serie. 20 MIDDLEWARE Pensando en Python (I): 3 en raya en modo texto Pensando en Python (I): 3 en raya en modo texto En la serie de artículos que aquí comenzamos describiremos el lenguaje de programación Python. Para ilustrar sus virtudes desarrollaremos un juego de tres en raya, que según transcurra esta serie irá haciéndose cada vez más sofisticado. Pasará de ser un simple juego con interfaz en modo texto, a tener una interfaz gráfica, y de éste a ser una aplicación web que accede a una base de datos. DIEGO LZ. DE IPIÑA GZ. DE ARTAZA (Profesor del Departa- mento de Ingeniería del Software de la Facultad de Ingeniería (ESIDE) de la Universidad de Deusto)

Pens and Oen Python i

Embed Size (px)

Citation preview

  • SOLO PROGRAMADORES

    Introduccin

    En este primer artculo nos dedicaremos a intro-ducir la sintaxis de Python y a iniciarnos en laprogramacin orientada a objetos a travs dePython. En un segundo artculo hablaremos delas facilidades provistas por Python para la pro-gramacin de interfaces grficas. En la terceraentrega explicaremos las bondades de Pythonpara la programacin de aplicaciones web conacceso a bases de datos. Finalmente, concluire-mos este curso de Python en una cuarta entregacon la descripcin de su primo hermano Jython.Python, el otro lenguaje de programacin libreque empieza con 'P' y que no es ni Perl ni PHP,fue creado por Guido van Rossum (http://www-.python.org/~guido/) en 1991. Dio este nombreal lenguaje inspirado por el popular grupo cmi-co britnico Monty Python. Guido cre Pythondurante unas vacaciones de navidad en las que(al parecer) se estaba aburriendo. Hola Mundo en PythonComo con cualquier otro lenguaje de programa-cin, comencemos el aprendizaje de Python conel ms simple de los ejemplos:

    print "Hola Mundo" # "Hola Mundo"

    En este primer extracto de cdigo ya podemosobservar la simplicidad de Python. Probable-mente este es el ejemplo del programa "HolaMundo" ms sencillo que jams has visto. Lasentencia print imprime una cadena de caracte-res a consola. Las cadenas de caracteres enPython se pueden denotar bien entre comillasdobles o comillas simples, por ejemplo 'Holamundo'. Ntese que los comentarios de lnea seindican con el smbolo #, mientras que los blo-ques de cdigo pueden comentarse entre '"' y '"'.

    Caractersticas de Python

    Tras ver el primer extracto de cdigo en Python,enumeremos sus principales caractersticas:z Sintaxis elegante, minimalista y densa: En

    Python todo aquello innecesario no hay queescribirlo (;, {, }, \n). Adems como veremospocas lneas de cdigo revierten en muchafuncionalidad.

    z Moderno: Soporta objetos y estructuras dedatos de alto nivel tales como cadenas decaracteres (strings), listas, diccionarios.

    z Multi-paradigma: En vez de forzar a los pro-gramadores a adoptar un paradigma de pro-gramacin nico, Python permite el uso deprogramacin orientada a objetos, programa-cin estructurada o procedural e incluso pro-gramacin funcional.

    z Organizado y extendible: Dispone de mltiplesformas de organizar cdigo tales como funcio-nes, clases, mdulos, y paquetes. Si hay reasque son lentas se pueden reemplazar por plu-gins en C o C++, siguiendo la API para exten-der o empotrar Python en una aplicacin.

    z Interpretado: No es necesario declarar cons-tantes y variables antes de utilizarlas y norequiere paso de compilacin/linkaje. La pri-mera vez que se ejecuta un script de Pythonse compila y genera bytecode que es luegointerpretado. Python es dinmico, encuentraerrores de uso de tipos de datos en tiempo deejecucin y usa un recolector de basura parala gestin de memoria.

    z Multiplataforma: Python genera cdigointeroperable, que se puede ejecutar en ml-tiples plataformas (ms an que Java).Adems, es posible embeber Python dentrode una JVM, como veremos en la cuartaentrega de esta serie.

    20

    MIDDLEWARE

    Pensando en Python (I):3 en raya en modo textoPensando en Python (I):3 en raya en modo texto

    En la serie de artculos que aqucomenzamos describiremos ellenguaje de programacin Python.Para ilustrar sus virtudesdesarrollaremos un juego de tres enraya, que segn transcurra esta serieir hacindose cada vez mssofisticado. Pasar de ser un simplejuego con interfaz en modo texto, atener una interfaz grfica, y de ste aser una aplicacin web que accede auna base de datos.

    DIEGO LZ. DE IPIA GZ. DE ARTAZA (Profesor del Departa-mento de Ingeniera del Software de la Facultad deIngeniera (ESIDE) de la Universidad de Deusto)

    python_Middleware.qxd 26/01/1998 6:38 Pgina 20

  • SOLO PROGRAMADORES

    z Open source: Razn por la cual la librera demdulos de Python (http://docs.python-.org/lib/lib.html) contiene un sinfn de mdulosde utilidad y sigue creciendo continuamente.

    z De propsito general: Toda aplicacin progra-mable con C# o Java tambin puede ser pro-gramada con Python.

    Peculiaridades sintcticasPython presenta unas diferencias sintcticasnotables con respecto a otros lenguajes de pro-gramacin. Usa tabulacin (o espaciado) paramostrar una estructura de bloques. Se tabulauna vez para indicar el comienzo de bloque y sedes-tabula para indicar el final del bloque.Adems, Python no usa el smbolo ';' para indi-car el final de una sentencia sino simplementeun retorno de carro. El cuadro "C/Java vs.Python" compara un extracto de cdigo enC/Java con otro de cdigo en Python. Obsrveseque las peculiaridades sintcticas de Pythontraen consigo una reduccin de los caracteresutilizados y lneas de cdigo. Adems, comoefecto lateral, estas peculiaridades sintcticasobligan a diferentes programadores a escribir elcdigo del mismo modo. No hace falta definirmanuales de referencia de programacin, paraasegurarte que todos los programadores queintervienen en un proyecto utilizan las mismasconvenciones. Como nota positiva, comentarque la mayora de las palabras claves utilizadaspor Python coinciden con las usadas en C o Java.Dominios de aplicacin de PythonTodo ingeniero de software, como buen artesano,debera dominar varios lenguajes de programa-cin. Es inviable concebir que con un slo lengua-je de programacin podemos llevar a cabo todotipo de desarrollos. Hay aplicaciones o parte deellas que se adecuarn ms a las caractersticasde un lenguaje de programacin que otro. En esteapartado vamos a resaltar las situaciones en lascuales deberamos considerar el uso de Python yen cuales otras lo deberamos desdear.Python, al ser un lenguaje de scripting e inter-pretado no es adecuado para la programacin debajo nivel o de sistemas. Por ejemplo, la progra-macin de drivers y kernels, dado que Python alser de demasiado alto nivel, no tiene controldirecto sobre memoria y otras reas de bajonivel. Tampoco es adecuado para aplicaciones

    que requieren una alta capa-cidad de computo, tal es elcaso de sistemas de procesa-miento de imgenes. Paraeste tipo de aplicaciones el"viejo" C o C++ nunca podrser superado.Python es ideal, sin embargo,como lenguaje "pegamento"para combinar varios compo-nentes juntos, para llevar acabo prototipos de sistemas, para la elaboracinde aplicaciones cliente web o con interfaz grfi-ca, el desarrollo de sistemas distribuidos o laprogramacin de tareas cientficas, en las quehay que simular y prototipar rpidamente.Python ha sido utilizado para desarrollar muchosgrandes proyectos de software como el servidorde aplicaciones Zope, el sistema de comparticinde ficheros Mnet o parte de la implementacinde Google. Actualmente, Python es uno de lostres lenguajes de programacin que se usan enla framework de desarrollo de servidores de apli-caciones libres LAMP (Linux Apache MySQL yPython, Perl o PHP).

    Programando en Python

    Una vez conocidas las caractersticas de Pythones momento de empezar a usarlo. Para ellohabremos de descargar una versin del mismo(actualmente 2.3.4) de la seccin Download delportal de Python (http://www.python.org), mos-trado en la figura 1 (tambin puede obtenersedel CD-ROM que acompaa la revista). La insta-lacin para Windows es tan sencilla como hacerdoble clic en el ejecutable descargado. ParaLinux, podremos usar los rpms disponibles enhttp://www.python.org/2.3.3/rpms.html. El co-mando que te permitir su instalacin ser algosimilar a:rpm -iv python2.3-2.3.4-pydotorg.i386.rpm

    Modos de programacin Python se puede usar de dos modos diferentes:interactivamente o en modo script. Para arrancarPython en modo interactivo todo lo que se nece-sita es ejecutar en una consola de comandos(cmd en Windows o xterm en Linux) el intrpre-te de Python, esto es, el ejecutable python. Unavez arrancado el intrprete podrs introducircualquier sentencia en Python. La figura 2 mues-

    21

    MIDDLEWAREPensando en Python (I): 3 en raya en modo texto

    C/Java vs Python

    Cdigo en C/Java

    if (x) {if (y) {

    f1();}f2();

    }

    Cdigo en Python

    if x:if y:

    f1() f2()

    Figura 1. Pgina principal de www.python.org.

    Figura 2. Python en modo interactivo.

    python_Middleware.qxd 26/01/1998 6:38 Pgina 21

  • SOLO PROGRAMADORES

    tra dos sesiones interactivas de Python. En la pri-mera se ha codificado el ejemplo "Hola Mundo"mostrado con anterioridad. Para salir del intr-prete se ha pulsado Ctrl-Z. Para realizar lo mismoen UNIX deberamos haber pulsado Ctrl-D.Alternativamente, se podran haber usado lasdos sentencias mostradas en la segunda sesininteractiva de la figura 2. La primera importa elmdulo sys (ms detalles luego) y la segundaejecuta el mtodo exit() de ese mdulo, que haceque el hilo de ejecucin del programa finalice.Para utilizar Python en modo script, se guardanlas sentencias del programa en un fichero yluego se ejecuta el mismo escribiendo python. Por ejemplo, en UNIXpodramos hacer lo siguiente para crear el fiche-ro holamundo.py y luego ejecutarlo:$ cat > holamundo.py

    #!/usr/bin/env python

    print "Hello World"

    Ctrl^D

    $ python holamundo.py

    Hello World

    Ntese que la sentencia:#!/usr/bin/env python

    se usara en entornos UNIX para indicar al siste-ma que el intrprete Python se debera utilizarpara ejecutar un fichero que tenga atributos deejecucin. En Windows es ignorada.Sentencias y bloquesPara realizar un programa til es necesario agru-par grupos de sentencias en unidades lgicas obloques. Recuerda que en Python las sentenciasse delimitan por el salto de lnea y los bloques seindican por tabulacin que sigue a una senten-cia acabada en ':'. Por ejemplo, el cdigo del lis-tado 1 contiene la comparacin de una variablecon un valor que imprime diferentes mensajessegn el resultado de su evaluacin. La ejecucin del programa del listado 1 median-te el comando:python bloque.py

    generara la siguiente salida:Quin eres?

    No eres Diego!

    IdentificadoresLos identificadores sirven para nombrar varia-bles, funciones y mdulos. Deben empezar conun carcter no numrico y contener letras,nmeros y '_'. Python es sensible al uso demaysculas y minsculas en identificadores. Lassiguientes son palabras reservadas y no se pue-den utilizar como identificadores: and, elif, glo-bal, or, assert, else, if, len, pass, break, except,import, print, class, exec, in, raise, continue,finally, is, return, def, for, lambda, try, del, from,not, while. Existen unos cuantos identificadoresespeciales con prefijo '__' para variables y fun-ciones que corresponden a smbolos implcita-mente definidos:z __name__: nombre de funcinz __doc__: documentacin sobre una funcinz __init__(): constructor de una claseVariables y tipos de datosPara declarar una variable en Python solamentees necesario darle un nombre y asignarle unvalor. La variable es del tipo del valor asignado.Por defecto las variables son locales y accesiblessolamente dentro del bloque de cdigo dondehan sido declaradas, para acceder a variablesglobales, es necesario preceder el nombre de lavariable con el identificador global. Si no sequiere asignar ningn valor a una variable, se lepuede asignar el valor None, equivalente a nullen Java.Numricos. Python define los siguientes tiposnumricos: integer, long integer, floating-point,y complex. Sobre los valores numricos se pue-den aplicar los mismos operadores que en Java oC++, esto es, +, -, *, / y % (resto). Su uso se ilus-tra en los siguientes comandos escritos en modointeractivo:>>> x = 4

    >>> int (x) # convierte x a entero4

    >>> long(x) # convirtelo a long4L

    >>> float(x) # a float4.0

    >>> complex (4, .2) (4+0.2j)

    Strings. Python soporta las cadenas de caracte-res que son delimitadas por un par de ' o ". Dosstrings juntos separados por un espacio se unen,y los separados por comas aparecen separadospor un espacio:>>> print "Hola" "Iigo" # imprime HolaIigo

    >>> print "Hola", "Iigo" # imprime Hola Iigo

    Se utilizan los mismos cdigos de escape que enC y Java. Por ejemplo, para imprimir una nueva

    22

    MIDDLEWARE

    LISTADO 1 Nuestro primer bloque# bloque.pyname = "Diego1" # asignacin de valor a variable if name == "Diego":

    print "Aupa Diego" else:

    print "Quin eres?" print "No eres Diego!"

    python_Middleware.qxd 26/01/1998 6:38 Pgina 22

  • SOLO PROGRAMADORES

    lnea utilizaramos print '\n'. Las cadenas decaracteres cuyos caracteres especiales no quere-mos que sean interpretados se indican con elprefijo 'r' de raw.Las cadenas de caracteres son objetos en Pythona los cuales se les pueden aplicar algunas de lasfunciones predefinidas por Python, como len,que devuelve el nmero de elementos en unasecuencia o los mtodos que define tales comoupper para convertir a maysculas y find paraencontrar sub-cadenas en una cadena, entreotros muchos. Para ms informacin tanto sobrela clase String como cualquier otra clase omdulo de Python es recomendable revisar ladocumentacin de la librera estndar de Python(http://docs.python.org/lib/lib.html), cuya tablade contenidos se muestra en la figura 3. A con-tinuacin mostramos algunas sentencias quehacen uso de strings:>>> len('La vida es mucho mejor con Python.')>>> 34

    >>> 'La vida es mucho mejor con Python.'.upper() 'LA VIDA ES MUCHO MEJOR CON PYTHON'

    >>> "La vida es mucho mejor con Python".find("Python")27

    >>> "La vida es mucho mejor con Python".find('Perl') -1

    >>> 'La vida es mucho mejor con Python'.replace('Python', 'Jython') 'La vida es mucho mejor con Jython'

    El carcter '%' representa al operador de forma-teo de cadenas, que se usa de una manera muysimilar a los formateadores en C para la senten-cia printf, tales como d para decimal, f para floato, x para hexadecimal:>>> provincia = 'lava'

    >>> "La capital de %s es %s" % (provincia,"Vitoria-Gasteiz")'La capital de lava es Vitoria-Gasteiz'

    Booleanos. Las constantes booleanas definidaspor Python son True y False. El resultado de unacondicin siempre devuelve uno de esos dosvalores.Listas. Una lista representa una secuencia din-mica que puede crecer, y est indexada por unentero que comienza con el valor 0. Python defi-ne el operador ':' u operador de rodajas que per-mite indicar dando el ndice inicial y final frag-mentos del string a recuperar. Una lista es unaclase definida por Python y por tanto tienemtodos para aadir (add) o insertar (insert)valores. Para borrar un elemento se utiliza la

    funcin predefinida del:>>> meses = ["Enero", "Febrero"] >>> print meses[0] Enero

    >>> meses.append("Marzo") >>> print meses[1:2]['Febrero']>>> del meses[0]>>> meses

    ['Febrero', 'Marzo']

    Tuplas. Las tuplas son como laslistas, pero no se pueden modifi-car. Son convenientes cuandoqueremos devolver varios valorescomo resultado de invocar a unafuncin. Se definen con el opera-dor (, por ejemplo, (1,2).Diccionarios. Los diccionarios son arrays asocia-tivos o mapas, indexados por una clave en vez deun ndice numrico. La clave puede ser cualquierobjeto Python, aunque normalmente es unatupla. Como se trata de una clase define unaserie de mtodos que podemos invocar talescomo has_key. El operador in se utiliza paracomprobar si un elemento forma parte de unasecuencia:>>> mydict = {"altura" : "media", "habilidad": "intermedia"} >>> print mydict

    {'altura': 'media', 'habilidad': 'intermedia'} >>> print mydict["habilidad"] intermedia

    >>>if mydict.has_key('altura'):>>> print 'Nodo encontrado'

    Nodo encontrado

    >>> if 'altura' in mydict:

    >>> print 'Nodo encontrado'

    Nodo encontrado

    Control de flujoCondicionales. La sentencia if se utiliza para ladefinicin de condiciones y puede ir seguida devarias partes elif y una else. En Python los opera-dores boleanos definidos son: or, and y not. Losoperadores relacionales definidos son ==, >, < y =.q = 4

    h = 5

    d = 3

    if q < h:

    print "primer test pasado"

    elif d

  • SOLO PROGRAMADORES

    else:

    print "tercer test pasado"

    >>> python condicional.py

    primer test pasado

    Bucles. Para la definicin de bucles podemosusar el operador for o while. for se utiliza princi-palmente para iterar sobre los miembros de unasecuencia: listas, tuplas o diccionarios. for se uti-liza a menudo con la funcin predefinida range,que crea una secuencia descrita por ([start,] end[,step]), donde los campos start y step son opcio-nales. start es 0 y step es 1 por defecto:>>> for x in range(1,5):>>> print x

    >>> 1 2 3 4

    La sentencia while es otra sentencia de repeti-cin. Se utiliza para ejecutar un bloque de cdi-go hasta que una condicin sea falsa. La senten-cia break se utiliza a menudo dentro de un buclewhile y sirve para salir del bucle:>>> reply = 'repite'

    >>> while reply == 'repite':

    ... print 'Hola'

    ... reply = raw_input('Introduce "repite" para hacerlo de nuevo: ')...

    Hola

    Introduce "repite" para hacerlo de nuevo:

    adis

    >>>

    FuncionesUna funcin se declara usando la palabra clavedef, seguida del nombre de la funcin y entreparntesis una lista de argumentos. Los argu-mentos si corresponden a tipos numricos, bole-anos o strings se pasan por valor y si correspon-den a secuencias por referencia. A una funcinse le pueden asignar parmetros por defecto,preasignado un valor a cada parmetro de unafuncin. Por ejemplo:def myfunc(a,b=2):

    sum = a + b

    return sum

    print myfunc(2) # devuelve el valor 4

    A una funcin se le puede pasar un nmerovariable de argumentos (argumento con prefijo*) y argumentos basados en palabras clave nopredefinidas (argumento con prefijo **):def testArgLists_1(*args, **kwargs):

    print 'args:', args

    print 'kwargs:', kwargs

    testArgLists_1('aaa', 'bbb', arg1='ccc', arg2='ddd')

    que visualizara:args: ('aaa', 'bbb') kwargs: {'arg1': 'ccc', 'arg2': 'ddd'}

    ClasesLas clases en Python son creadas usando la sen-tencia class. Una clase contiene una coleccin demtodos. Cada mtodo contiene como primerparmetro (self) que hace referencia a la instan-cia de la clase, es equivalente al this de C++ oJava. Python soporta mltiple herencia de clases.Existe un soporte limitado para variables priva-das, usando una tcnica llamada name mangling.Todo identificador de la forma __spam es tex-tualmente reemplazado por _classname__spam.Sin embargo, el identificador todava podra seraccedido por cdigo que usa la instancia de laclase mediante _classname__spam. El listado 2muestra un simple ejemplo de herencia.ExcepcionesCada vez que un error ocurre se lanza unaexcepcin, visualizndose un extracto de la piladel sistema. La ejecucin de la ltima sentenciadel ejemplo anterior producira:Traceback (most recent call last):

    File "clasesherencia.py", line 28, in ?

    print obj2.__upper

    AttributeError: Special instance has no

    attribute '__upper'

    Para capturar una excepcin se usa except ypara lanzar una excepcin se usa raise. Sepueden crear excepciones personalizadas cre-

    24

    MIDDLEWARE

    LISTADO 2 Un simple ejemplo de herencia# clasesherencia.pyclass Basic:

    def __init__(self, name): self.__name = name

    def show(self): print 'Basic -- name: %s' % self.__name

    class Special(Basic): # entre parntesis la clase basedef __init__(self, name, edible):

    Basic.__init__(self, name) self.__upper = name.upper()self.__edible = edible

    def show(self): Basic.show(self) print 'Special -- upper name: %s.' % self.__upper, if self.__edible:

    print "It's edible." else:

    print "It's not edible." def edible(self):

    return self.__edible

    obj1 = Basic('Manzana')obj1.show() print '=' * 30 obj2 = Special('Naranja', 1) obj2.show()print obj2._Basic__nameprint obj2.__upper # lanzar una excepcin

    python_Middleware.qxd 26/01/1998 6:39 Pgina 24

  • SOLO PROGRAMADORES

    ando una nueva clase que derive de laclase RuntimeError definida por Python.El siguiente fragmento ilustra el uso deexcepciones:# excepcion.py

    try:

    fh=open("new.txt", "r")except IOError, e:

    print e

    $ python excepcion.py

    [Errno 2] No such file or directory: 'new.txt'

    Mdulos y paquetesLas libreras de mtodos y clases seagrupan en Python en mdulos. Unmdulo es una coleccin de mtodos oclases en un fichero que acaba en .py.El nombre del fichero determina elnombre del mdulo en la mayora delos casos. Para usar un mdulo se usa lasentencia:import

    que hace que un mdulo y su conteni-do sean disponibles para su uso.Alternativamente se puede usar lasentencia:from import

    Por ejemplo, un mdulo se podra definircomo:# modulo.py

    def one(a): print "in one"

    def two (c): print "in two"

    Este modulo se usara como sigue. Ntesela diferencia que existe entre el uso de laclusula import y la from:>>> import modulo

    >>> modulo.one(2)in one

    >>> from modulo import *

    >>> one(2)in one

    >>>

    Un conjunto de mdulos puede agru-parse como una unidad representadapor un paquete. En la siguiente entregaveremos un ejemplo de creacin y usode paquetes.

    Desarrollando tu primera aplicacin

    Para poner en prctica la sintaxis del len-guaje Python vamos a desarrollar una sim-ple aplicacin de tres en raya. Aparte depermitirnos jugar contra la mquina, estejuego requiere que el jugador se autentifi-que antes de jugar y adems guarda esta-dsticas en memoria sobre las partidasganadas, perdidas o empatadas por cadajugador. Por el momento la mquina usa unalgoritmo sencillsimo para la eleccin de lacasilla a tachar por la mquina, la elige demanera aleatoria. En prximas entregas deesta serie discutiremos algoritmos mejoresbasados en inteligencia artificial. El listado3 muestra la clase RegistroJugadores quees utilizada para mantener las estadsticasde las partidas de los jugadores.El constructor de RegistroJugadores definedos atributos privados de tipo diccionarioque guardan los jugadores registrados(self.__jugadores) y las estadsticas de laspartidas (self.__estadisticas). Se carga unslo jugador con nombre de usuario "solop"y contrasea "solop", e inicializamos lasestadsticas para el jugador 'solop', con la

    lista [0,0,0] que indica que el usuario no haganado, ni empatado, ni perdido ningnjuego todava. La clase RegistroJugadoresdefine el mtodo registarJugador que per-mita registrar los detalles de login de unnuevo jugador. Si ya existe un usuario conel nombre de usuario pasado, se lanza unaexcepcin y si no se crea una nueva entra-da en el atributo self.__jugadores. El mto-do login permite la autenticacin de unusuario, y en caso de proveerse un nombrede usuario o clave errneas se lanza unaexcepcin. Por su parte, los mtodosregistrarVictoria, registrarEmpate yregistrarPerdida sirven para modificar elatributo self.__estadisticas con los resulta-dos de las partidas de cada jugador.Finalmente el mtodo getEstadisticasdevuelve una lista con los resultados obte-nidos por un jugador.La clase JuegoTresEnRaya (vase la figura 4),que define la lgica principal de la aplicacin,no se ha incluido en estas pginas por razonesde espacio, sin embargo el cdigo de dichaclase puede encontrarse en el CD-ROM. Elconstructor de esta clase recibe como parme-tros una referencia al registro de jugadores, elnombre de usuario y la clave del jugador que

    25

    MIDDLEWAREPensando en Python (I): 3 en raya en modo texto

    LISTADO 3 La clase RegistroJugadores# imports para toda la aplicacinimport osimport sysimport randomfrom types import *

    class RegistroJugadores:def __init__(self):

    self.__jugadores = {'solop':'solop'}self.__estadisticas = {'solop':[0, 0, 0]} # jugador -> [ganados, empa

    tados, perdidos]

    def registrarJugador(self, jugador, clave):if len(trim(jugador)) == 0 or len(trim(clave)) == 0:

    raise "Los campos jugador y clave no pueden estar vacios"if self.__jugadores.has_key(jugador):

    raise "Jugador " + jugador + " ya ha sido registrado!"self.__jugadores[jugador] = claveself.__estadisticas[jugador] = [0, 0, 0]

    def login(self, jugador, clave):if not self.__jugadores.has_key(jugador):

    raise "Jugador " + jugador + " no registrado!"

    if not self.__jugadores[jugador] == clave:raise "Clave de jugador " + jugador + " es invalida"

    return True

    def registrarVictoria(self, userName):self.__estadisticas[userName][0] += 1

    def registrarEmpate(self, userName):self.__estadisticas[userName][1] += 1

    def registrarPerdida(self, userName):self.__estadisticas[userName][2] += 1

    def getEstadisticas(self, userName):return self.__estadisticas[userName]

    python_Middleware.qxd 26/01/1998 6:40 Pgina 25

  • SOLO PROGRAMADORES

    quiere competircon la mquina.El constructor enprimer lugarguarda la referen-cia al registro enla variable privadaself.__registro yvalida que losdatos de autenti-ficacin del juga-

    dor son correctos.A continuacin,

    declara las constantes self.__combiGanadorascon las combinaciones ganadoras del juego,self.__marcaJugador con el carcter 'o' queindica la marca de un jugador yself.__marcaMaquina con el valor 'x' quedenota las casillas marcadas por la mquina.Finalmente, el constructor declara las variablesself.__userName donde memoriza el identifi-cador del jugador, self.__casillasMarcadasdonde cuenta cuntas casillas estn marcadashasta el momento y el array bidimensionalself.__casillero que recoge los valores marca-dos en cada casilla, inicialmente ninguno. Estaclase tambin declara los siguientes mtodosde ayuda privados: __elegirMarcaMaquina,__verTablero y __hayGanador. El mtodo

    __elegirMarcaMaquina hace uso del mdulorandom para elegir de manera aleatoria una delas casillas no marcadas. El mdulo__verTablero visualiza en modo texto el table-ro. Finalmente, el mtodo __hayGanadordetermina si alguna de las combinacionesganadoras ha sido alcanzada.La clase JuegoTresEnRaya slo define elmtodo pblico jugar() que define toda lalgica del juego de tres en raya entre unusuario y la mquina. Asume que el usuariosiempre comienza. La partida no concluyehasta que se ha encontrado una combina-cin ganadora o se han tachado las nuevecasillas del tablero. Mientras el usuario nointroduce los datos de una casilla correcta-mente el mtodo itera sobre un bucle. Pararecoger la entrada del usuario se utiliza lafuncin raw_string(). Ademsdado que se pretende que la entrada tengael formato (x, y), se evala si los datosintroducidos corresponden a una tupla,mediante la funcin eval que convierte unstring al tipo de datos representado.Adems se valida si el valor interpretadocorresponde a una tupla haciendo uso delmtodo type del mdulo types y del opera-dor is que permite la comparacin entre unvalor y su tipo: if not type(casillaCoords) isTupleType. Adems en cada iteracin secomprueba que el valor de la celda intro-

    ducida est dentro del rango de valo-res validos y adems no haya sido yamarcado. Despus de que el usuariointroduzca una casilla vlida se evalasi ha ganado invocando el mtodo__hayGanador. Si es as se registra lavictoria del usuario invocandoself.__registro.registrarVictoria-(self.__userName). Si todava no sehan marcado las nueve casillas deltablero se pasa el turno a la mquina,eligindose la casilla a marcarmediante la llamada al mtodo priva-do __elegirMarcaMaquina. A conti-nuacin, se comprueba si tras marcarla ltima casilla la mquina ha ganado

    la partida y si es as seregistra que el usuariola ha perdido. Cuandolas casillas marcadas

    sean nueve y no hahabido ningn ganadorse registrar el hecho deque el juego ha acabadoen empate.El listado 4 muestra elbloque de entrada delprograma. Todo bloqueque comience con if__name__ == '__ma-

    in__':, es equivalente a un bloque main enC o Java. El bloque main, en primer lugar,obtiene una referencia al registro. En futu-ras entregas recuperaremos ese registrobien de un fichero o de una base de datos.Por el momento, esto se consigue invocan-do al constructor de RegistroJugadores quemantiene un diccionario en memoria conlos jugadores registrados y otro con lasestadsticas de juego de los mismos. Ensegundo lugar, el bloque main crea una ins-tancia de la clase JuegoTresEnRaya, pasan-do como referencia el registro obtenido y elnombre y contrasea del jugador. Estos dosltimos valores son recuperados a partir delos parmetros pasados en la invocacindel programa, mediante la sentenciasys.argv[x], donde x indica el orden delparmetro, apuntando el ndice 0 al nom-bre del script. A continuacin, se permiteque el usuario inicie una partida llamandoal mtodo jugar() de la instancia deJuegoTresEnRaya. Al finalizar esta partidase pregunta al usuario si quiere seguirjugando y se repite este proceso hasta queel usuario no responda s. Finalmente,antes de terminar el programa se muestranlas estadsticas de resultados de los enfren-tamientos entre la mquina y el usuarioindicado. La figura 5 muestra una sesindel juego de tres en raya.

    Conclusines

    Este artculo ha mostrado la sintaxis dellenguaje Python y ha ilustrado su uso a tra-vs de la elaboracin de un simple juego detres en raya. A travs de la elaboracin deeste pequeo programa hemos podidocomprobar la simplicidad de Python y suscapacidades para construir de manera rpi-da cualquier tarea de programacin quetengamos en mente. En la siguiente entre-ga de esta serie veremos cmo proporcio-nar una interfaz grfica a este juego ycmo mantener el registro de jugadores ysus estadsticas en varios ficheros.

    26

    MIDDLEWARE

    Figura 4. La clase JuegoTresEnRaya

    Figura 5. Ejecucin del juego tres en raya.

    LISTADO 4 El bloque mainif __name__ == '__main__':

    registro = RegistroJugadores()juego = JuegoTresEnRaya(registro, sys.argv[1], sys.argv[2])juego.jugar()while True:

    s = raw_input("Quieres jugar otra vez? (s) o (n): ")if s.strip().lower() == 's':

    juego = JuegoTresEnRaya(registro, 'solop', 'solop')juego.jugar()

    else:print 'Gracias por jugar al tres en raya!'print 'Estadsticas de juego de solop: victorias (' + str(registro.getEstadisticas('solop')[0]) +\

    ') - empates (' + str(registro.getEstadisticas('solop')[1]) + \') - derrotas (' + str(registro.getEstadisticas('solop')[2]) + ')'

    break

    python_Middleware.qxd 26/01/1998 6:40 Pgina 26