Aprenda a Pensar Como un Programador

con Python

Aprenda a Pensar Como un Programador
con Python

Allen Downey Jeffrey Elkner Chris Meyers Traducido por ´ Miguel Angel Vilella ´ Angel Arnal Iv´n Juanes a Litza Amurrio Efrain Andia C´sar Ballardini e

Green Tea Press
Wellesley, Massachusetts

Copyright c 2002 Allen Downey, Jeffrey Elkner, y Chris Meyers.

Corregido por Shannon Turlington y Lisa Cutler. Dise˜o de la cubierta por Rebecca Gimenez. n Green Tea Press 1 Grove St. P.O. Box 812901 Wellesley, MA 02482 Se permite copiar, distribuir, y/o modificar este documento bajo los t´rminos de e la GNU Free Documentation License, Versi´n 1.1 o cualquier versi´n posterior o o publicada por la Free Software Foundation; siendo las Secciones Invariantes “Pr´logo”, “Prefacio”, y “Lista de Colaboradores”, sin texto de cubierta, y o sin texto de contracubierta. Se incluye una copia de la licencia en el ap´ndice e titulado “GNU Free Documentation License”. La GNU Free Documentation License est´ disponible en www.gnu.org o escria biendo a la Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
A La forma original de este libro es c´digo fuente L TEX. La compilaci´n de este o o A X tiene el efecto de generar una representaci´n independiente del fuente L TE o dispositivo de un libro de texto, que puede convertirse a otros formatos e imprimirse. A El fuente L TEX de este libro y m´s informaci´n sobre el proyecto de Libro de a o Texto de C´digo Abierto est´n disponibles en o a

http://www.thinkpython.com
A La composici´n de este libro se realiz´ utilizando L TEX y LyX. Las ilustraciones o o se hicieron con xfig. Todos ellos son programas gratuitos de c´digo abierto. o

Historia de la impresi´n: o Abril 2002: Primera edici´n. o ISBN 0-9716775-0-6

Pr´logo o
Por David Beazley Como educador, investigador, y autor de libros, estoy encantado de ver la finalizaci´n de este libro. Python es un lenguaje de programaci´n divertido y o o extremadamente f´cil de usar que en los ultimos a˜os se ha hecho muy popua ´ n lar. Desarrollado hace diez a˜os por Guido van Rossum, su sintaxis simple y la n sensaci´n general se deriva en gran parte del ABC, un lenguaje desarrollado en o los 1980s para la ense˜anza. Sin embargo, Python tambi´n se cre´ para resolver n e o problemas reales y presenta una variedad amplia de caracter´ ısticas de lenguajes de programaci´n como C++, Java, Modula-3 y Scheme. Debido a esto, una de o las caracter´ ısticas notables de Python es su atractivo para los desarrolladores profesionales de progamaci´n, cient´ o ıficos, investigadores, artistas, y educadores. A pesar del atractivo de Python para muchas comunidades diferentes, puede que a´n se pregunte “¿por qu´ Python?” o “¿por qu´ ense˜ar programaci´n u e e n o con Python?”No es tarea f´cil responder a estas preguntas, en especial cuando a la opini´n popular est´ del lado de alternativas m´s masoquistas como C++ y o a a Java. Sin embargo, pienso que la respuesta m´s directa es que la progrmaci´n a o en Python es simplemente m´s divertida y m´s productiva. a a Cuando imparto cursos de inform´tica, quiero cubrir conceptos importantes, a hacer el material interesante y enganchar a los estudiantes. Desgraciadamente, hay una tendencia en los cursos de introducci´n a la programaci´n a prestar o o demasiada atenci´n a la abstracci´n matem´tica que hace que los estudiantes o o a se frustren con problemas farragosos relacionados con detalles nimios de la sintaxis, compilaci´n, y la aplicaci´n de reglas aparentemente arcanas. Aunque o o tal abstraci´n y formalismo son importantes para ingenieros profesionales de la o programaci´n y estudiantes que planean continuar sus estudios de inform´tica, o a decidirse por este enfoque en un curso introductorio s´lo tiene ´xito en hacer o e aburrida la inform´tica. Cuando imparto un curso, no quiero tener un aula de a estudiantes sin inspiraci´n. Quisiera verlos intentando resolver problemas ino teresantes, explorando ideas diferentes, probando enfoques no convencionales,

vi

Pr´logo o

rompiendo las reglas, y aprendiendo de sus errores. Al hacerlo, no quiero perder la mitad del semestre tratando de sortear problemas con una sintaxis abstrusa, mensajes de error del compilador incomprensibles, o los varios cientos de maneras que un programa puede generar un error de proteci´n general. o Una de las razones por las que me gusta Python es por que proporciona un equilibrio muy bueno entre lo pr´ctico y lo conceptual. Puesto que Python es un a lenguaje interpretado, los principiantes pueden tomar el lenguaje y empezar a hacer cosas interesantes casi inmediato, sin perderse el los problemas de compilaci´n y enlazado. Adem´s, Python viene con una gran biblioteca de m´dulos que o a o se pueden usar para hacer toda clase de tareas que abarcan desde programaci´n o para web a gr´ficos. Este enfoque pr´ctico es una buena manera de enganchar a a a estudiantes y permite que completen proyectos significativos. Sin embargo, Python tambi´n puede servir como una base excelente para intruducir conceptos e importantes de inform´tica. Puesto que Python soporta completamente procea dimientos y clases, los estudiantes pueden introducirse gradualmente en temas como abstracci´n procedural, estructuras de datos, y programaci´n orientada a o objetos, que son aplicables a cursos posteriores en Java o C++. Python incluso toma prestada cierta cantidad de caracter´ ısticas de lenguajes de programaci´n o funcionales y puede usarse para intruducir conceptos que pudieran ser cubiertos en mas detalle en cursos de Scheme o Lisp.
2

Leendo, el prefacio de Jeffrey, me sorprenden sus comentarios sobre que Python le permite ver un “m´s alto nivel de ´xito y un bajo nivel de frustraci´n a e o que puede “avanzar r´pido con mejores resultados”. Aunque estos comentarios a se refieren a sus cursos introductorios, a veces uso Python por estas mismas razones en cursos de inform´tica avanzada en la Universidad de Chicago. En a estos cursos me enfrento constantemente con la desalentadora tarea de cubrir un mont´n de material dif´ en un agotador trimestre de nueve semanas. Auno ıcil que es ciertamente posible para m´ infligir mucho dolor y sufrimiento usando un ı lenguaje como C++, he visto a menudo que ese estilo es ineficaz, especialmente cuando el curso se trata de un asunto sin relaci´n apenas con la “programaci´n”. o o Encuentro que usar Python me permite dedicarme m´s al asunto en cuesti´n a o mientras permito a los estudiantes completar proyectos utiles. ´

Aunque Python es todav´ un lenguaje joven y en desarollo, creo que tiene ıa un futuro brillante en la educaci´n. Este libro es un paso importante en esa o direcci´n. o David Beazley Universidad de Chicago Autor de Python Essential Reference

Sus tres autores. un profesor de instituto y un programador profesional. Al seguir con n la pr´ctica anterior de dar a los estudiantes dos a˜os de exposici´n al mismo a n o lenguaje. tambi´n es extremadamente dif´ de aprender y ense˜ar. cuyo marco han establecido Richard Stallman y la o Free Software Foundation. pero hemos sido capaces de colaborar estrechamente y hemos recibido la ayuda de mucha gente maravillosa que han donado su tiempo y esfuerzo para ayudar a mejorar este libro.Prefacio Por Jeff Elkner Este libro debe su existencia a la colaboraci´n hecha posible por la Internet y o al movimiento de software libre. donde doy clase. todav´ tienen que conocerse ıa cara a cara. el lenguaje de ense˜anza n era Pascal tanto en nuestro curso de primer a˜o como en el AP. y como consecuencia perd´ muchos estudiantes sin ıa . Como en muchos o o institutos en todo el pa´ la decisi´n de cambiar de lenguaje tuvo un impacto ıs. un profesor universitario. o directo sobre el curriculum de inform´tica en el Insituto de Yorktown en Ara lington. Virgina. Aunque es un lenguaje de programaci´n a o muy poderoso. el examen de Advanced Placement (AP) de Ciencias de la Computaci´n del Claustro Escolar se realiz´ por primera vez en C++. C´mo y por qu´ vine a usar Python o e En 1999. me convenc´ de que C++ era una mala elecci´n para iniciar n a ı o a los estudiantes en la inform´tica. n Dos a˜os m´s tarde. tomamos la decisi´n de cambiar a C++ en el aula de primer a˜o del o n curso 1997-98 de modo que estar´ ıamos en sinton´ con el cambio del Claustro ıa Escolar para el curso AP del a˜o siguiente. Hasta ese momento. Me e ıcil n encontr´ luchando constantemente con la dif´ sintaxis de C++ y sus m´ltiples e ıcil u formas de hacer las cosas. Creemos que este libro es un testamento a los beneficios y futuras posibilidades de este tipo de colaboraci´n.

suger´ que Python era o ıa la soluci´n que buscaba. Anteriormente en ese a˜o. Su lectura me hizo inmediatamente un maestro mejor. Sab´ que Matt no pod´ terminar una o ıa ıa aplicaci´n de tal escala en tan poco tiempo con C++. n Necesitaba un lenguaje que funcionase tanto en las m´quinas de nuestro laboa ratorio de Linux como en las plataformas Windows y Macintosh que la mayor´ ıa de los estudiantes ten´ en casa. Y lo m´s importante. y este logro. Convencido de que deb´ de haber una elecci´n mejor para el lenguaje ıa o de nuestro curso de primer a˜o. combinado o con la positiva valoraci´n de Python por parte de Matt. para que ıan ıa o los estudiantes pudieran usarlo en casa sin importar su nivel econ´mico. o Encontrar un libro de texto Una vez decidido a usar Python tanto en mis clases de inform´tica b´sica como a a en el a˜o siguiente. Ten´ que soportar tanto la ıa programaci´n procedural como la orientada a objetos. se me ocurri´ que podr´ traducir la versi´n original ı o ıa o en Java del libro de Allen al nuevo lenguaje. me puse a buscar una alternativa para C++. El contenido libre vino al rescate. Una vez que decid´ usar Python. En dos meses. Python destac´ como el mejor candidato. Era el libro de inform´tica m´s claro y pr´ctico que hab´ visto. sino que o ıa escribi´ una aplicaci´n llamada pyTicket que permit´ a nuestro personal inforo o ıa mar de problemas tecnol´gicos via Web. Quer´ o ıa un lenguaje utilizado por programadores profesionales. Quer´ que fuera de c´digo abierto. How to Think Like a Coma n puter Scientist. lo que significaba que pod´ usarse y o u ıa modificarse libremente para ajustarse a las necesidades de su usuario. tener el libro de Allen para trabajar a . o a ten´ que ser f´cil de aprender y de ense˜ar. Allen ya hab´ escrito e ıa un libro de texto de inform´tica de primer a˜o. Matt Ahrens. que ı a probase Python.viii Prefacio necesidad. el problema m´s acuciante era la falta de un libro de texto n a disponible. a a a ıa Pon´ el ´nfasis en los procesos de pensamiento involucrados en la programaci´n ıa e o m´s que en las caracter´ a ısticas de un lenguaje en particular. y que tuviera una comunidad activa de desarrolladores a su alrededor. Cuando le´ ese libro. Richard Stallman n me present´ a Allen Downey. Ambos hab´ o ıamos escrito a Richard expresando nuestro inter´s en desarrollar conenidos educativos libres. Cuando investigu´ las opciones con ıa a n e estos obejetivos en mente. sino que o se public´ bajo la licencia p´blica GNU. How to Think Like a Computer Scientist no era s´lo un libro excelente. no s´lo hab´ aprendido el lenguaje. supe inmediatamente que quer´ usarlo ı ıa en mi clase. Aunque no hubiera sido capaz de escribir un libro de texto por mi cuenta. o Ped´ a uno de los estudiantes m´s talentosos de Yorktown.

los anim´ a buscar errores en el libro e d´ndoles un punto extra cada vez que hac´ una sugerencia que terminaba a ıan como un cambio en el texto. dirigi´ndoe les m´s all´ de donde yo pod´ llevarles. a a ıa Presentando la programaci´n con Python o El proceso de traducir y usar How to Think Like a Computer Scientist durante los dos ultimos a˜os ha confirmado la idoneidad de Python para ense˜ar a ´ n n estudiantes principiantes. mostrando al mismo tiempo que el modelo e cooperativo de desarrollo que tan buenos resultados hab´ dado en el software ıa pod´ funcionar tambi´n para el contenido educativo. o o Recib´ un correo electr´nico de Chris Meyers expresando su inter´s en el liı o e bro. o n en Eugene. ıa e El trabajo en este libro durante los dos ultimos a˜os ha sido gratificante para mis ´ n estudiantes y para m´ y mis estudiantes desempe˜aron un importante papel en ı. Esto tuvo el doble beneficio de animarlos a leer el texto con m´s atenci´n y tener el texto revisado en profundidad por sus cr´ a o ıticos m´s importantes: los estudiantes que lo usan para aprender inform´tica. La perspectiva de impartir el curso llev´ a Chris haso ta el libro.org/obp llamado Python for Fun y estaba trabajando con algunos de mis estudiantes aventajados como profesor magistral. Oregon. n el proceso. o n o . y empez´ a colaborar con ´l inmediatamente. Python simplifica enormemente los ejemplos de programaci´n y facilita la ense˜anza de los conceptos importantes en programaci´n.ix partir de ´l me hizo posible hacerlo. a a Para la segunda mitad del libro. Chris es un programador profesional que empez´ a impartir un curso de o programaci´n con Python el a˜o pasado en el Colegio de Lane Community. Como pod´ hacer cambios instant´neos cuando alguien encontraba ıa a un error ortogr´fico o un pasaje dif´ a ıcil. Hacia el final del o e a˜o escolar hab´ creado un proyecto complementario en nuesto sitio web en n ıa http://www.ibiblio. acerca de la programaci´n orientada a objetos. El libro se estanc´ en un estado inacabado ıa o durante buena parte de un a˜o hasta que la comunidad de c´digo abierto de n o nuevo proporcion´ los medios necesarios para su terminaci´n. o sab´ que necesitar´ a alguien con m´s experiencia real en programaci´n de ıa ıa a o la que yo ten´ para hacerlo bien.

present´ndoles de esta forma o a el entorno de programaci´n. En C++ una variable es un nombre para un lugar que contiene una cosa. Algunos de a ellos est´n sin duda un poco nerviosos. El curso de Inform´tica I en Yorktown no tiene prerrequisitos. P´rrafos enteros desapareciendo de la versi´n Python del texto porque la a o sintaxis clara de Python los hace innecesarios. Las variables deben declararse seg´n su tipo en parte porque el tama˜o del lugar al u n que apuntan tiene que determinarse de antemano. La programaci´n con Python tiene exactamente lo o o que necesito para hacer estas cosas. tras haber o´ que programar compua ıdo tadores es algo dif´ de aprender.h> void main() { cout << "Hola. En la a o o versi´n Python s´lo hay dos. Es el tradicional programa o “hola. Los objetivos educativos en este momento a del curso son exponer a los estudiantes a la idea de una sentencia de programaci´n y llevarles a escribir su primer programa. Uno de o los mejores ejemplos de ello es la manera en la cual Python maneja las variables. Hay trece p´rrafos de explicaci´n de “¡Hola. as´ que muchos de los estua ı diantes que ven este ejemplo est´n mirando su primer programa. } en la versi´n Python se convierte en: o print "Hola. void main(). El uso de un lenguaje de muy alto nivel como Python permite que el profesor deje para m´s tarde hablar sobre los detalles de bajo nivel de la m´quina hasta a a que los estudiantes tengan el fondo necesario para entender los detalles. {. Mundo" Aunque es un ejemplo trivial. El concepto poderoso y fundamental de a a . De este modo crea la habilidad de poner pedag´gicamente “antes lo primero”. mundo" << endl. mundo”. a La comparaci´n del texto explicativo de este programa para cada versi´n del o o libro ilustra mejor lo que esto significa para los estudiantes principiantes. que en la versi´n C++ del libro es as´ o ı: #include <iostream. hablaremos de ello m´s tarde”. destacan las ventajas de Python. La versi´n C++ siempre me ha obligado a ıcil o elegir entre dos opciones insatisfactorias: explicar las sentencias #include. sino las o minucias de la sintaxis de C++. Encontr´ que esto mismo suced´ por todo el e ıa libro. y arriesgarme a lo mismo. est´ ligada al hardware de la m´quina. y } y arriesgarme a confundir o intimidar a algunos estudiantes desde el principio. A´n m´s importante: los once p´rrafos que faltan o o u a a no tocan las “grandes ideas” de la programaci´n de computadores.x Prefacio El primer ejemplo del texto ilustra esta cuesti´n. o decirles “No te preocupes de todo eso ahora. mundo!” en la versi´n C++. y nada m´s. As´ la idea de una variable ı.

com. Ha emn pezando a surgir una comunidad de usuarios. Octetos y direcciones no ayudan a la a a comprensi´n. Este o n es un concepto mucho m´s intuitivo para estudiantes principiantes y est´ m´s a a a cerca del significado de “variable” que aprendieron en su clase de matem´ticas. Otro ejemplo de c´mo Python ayuda en la ense˜anza y aprendizaje de la proo n gramaci´n es en su sintaxis para las funciones. Veo un mayor nivel general de ´xito y un menor e nivel de frustraci´n del que experiment´ durante los dos a˜os que ense˜´ C++. y simplemente digo a mis o o estudiantes: “cuando definas una funci´n. La emergencia de esta comunidad de usuarios y la posibilidad que sugiere para colaboraciones similares entre educadores han sido para m´ las partes m´s excitantes de trabajar en este ı a proyecto. por lo que ahora soy capaz de ense˜ar funciones n en la mitad de tiempo que antes. espero que continue y se o acelere el crecimiento de la comunidad de usuarios.xi lo que es una variable ya es suficientemente dif´ para estudiantes principiantes ıcil (tanto de inform´tica como de ´lgebra). El problema principal se centra alrededor de la diferencia entre la definici´n de una funci´n y la llamao o da a una funci´n. Los par´metros van con las definiciones. y la distinci´n asociada entre un par´metro y un argumento. cuando llames a una funci´n. M´s estudiantes terminan el curso a a a con la habilidad de crear programas utiles y con la actitud positiva hacia la ´ experiencia de programaci´n que esto engendra. los argumentos a con las llamadas. seguido del nombre o de la funci´n que est´s definiendo. o par´metro por a a referencia y valor de por medio. Con la publicaci´n de este libro en forma impresa. con mejor comprensi´n. y pas´ menos tiempo ayud´ndoles con los problemas derivados e a de su uso. o o a Python viene al rescate con una sintaxis a la que no le falta belleza. o Formar una comunidad He recibido correos electr´nicos de todos los rincones del planeta de parte o de gente que usa este libro para aprender o enese˜ar a programar. a Este a˜o tuve muchas menos dificultades ense˜ando lo que son las variables que n n en el anterior. simplemente di o e o (escribe) su nombre”. Mis estudiantes siempre han o tenido una gran dificultad comprendiendo las funciones. La definici´n de una funci´n empieza con la palabra clave def. o e n ne Avanzo m´s r´pido con mejores resultados. En Python una variable es un nombre que se˜ala una cosa.thinkpython. tipos de par´metros. podemos incrementar la calidad de los materiales . No hay tipo de retorno. y muchas personas han contribuido al proyecto mandando materiales a trav´s del sitio web complementario e http://www. o El uso de Python ha mejorado la eficacia de nuestro programa de inform´tica a para todos los estudiantes. empieza con def. Trabajando juntos.

Jeffrey Elkner Escuela Secundaria Yortown Arlington.com. escriban a los autores a feedback@thinkpython.xii Prefacio disponibles para nuestro uso y ahorrar un tiempo valioso. Les invito a unirse a nuestra comunidad y espero con impaciencia saber algo de ustedes. Por favor. Virginia .

4. As´ que queremos agradecer a la Free ı Software Foundation por desarrollar esta licencia y. todav´ puede haber ıa errores en el libro. ver´ que cada una de las a personas que aparecen le ha ahorrado a usted y a los lectores que le sucedan la confusi´n de un error t´cnico o una explicaci´n poco clara simplemente eno e o vi´ndonos una nota. a Si se toma el tiempo de echar un vistazo a la lista. Desgraciadamente. decidimos expresar nuestra gratitud en la forma de una lista de colaboradores. por supuesto. o o o Yvon Boulianne envi´ una correcci´n de un error sem´ntico en el Cap´ o o a ıtulo 5. aparecer´ en la siguiente versi´n de la lista de colaboradores (a no ser que pida a o quedar omitido). a Pos imposible que parezca tras tantas correcciones. Fred Bremmer comunic´ una correcci´n de la Secci´n 2.Lista de Colaboradores Parafraseando la filosof´ de la Free Software Foundation. o o o A Jonah Cohen escribi´ los scripts en Perl para convertir la fuente L TEX del o libro en hermoso HTML. pero hacemos lo que podemos para mantenerla actualizada. . Si cambiamos algo a partir de su sugerencia. La direcci´n de correo es o feedback@thinkpython. Si se encontrara con una. o Se hizo realidad a causa de una colaboraci´n que no habr´ sido posible sin o ıa la GNU Free Documentation License. o Tambi´n nos gustar´ dar las gracias a los m´s de cien lectores de aguda vista e ıa a que se han preocupado de enviarnos sugerencias y correcciones en los dos ulti´ mos a˜os. Siguiendo el esp´ n ıritu del software libre. este libro es libre ıa como la libre expresi´n.1. ponerla a nuestra disposici´n. esperamos que se tome un minuto para ponerse en contacto con nosotros. pero no necesariamente gratis como la pizza gratis.com. esta listo no est´ completa. ¡Gracias! Lloyd Hugh Allen envi´ una correcci´n de la Secci´n 8.

ıa del texto.10. o David Pool envi´ un error tipogr´fico en el glosario del Cap´ o a ıtulo 1. o o o Courtney Gleason y Katherine Smith escribieron horsebet. Lee Harr comunic´ m´s correcciones de las que tenemos sitio para enumeo a rar aqu´ y de verdad deber´ aparecer como uno de los principales editores ı.6. que se us´ como un caso de estudio en una versi´n temprana del libro. e inici´ una discusi´n sobre aspectos o o t´cnicos de los int´rpretes.4. e a . e e Benoit Girard envi´ una correcci´n de un divertido error de la Secci´n 5. 2 y 3.9 y 3.10. Tambi´n arregl´ el Makefile de forma que crea un ´ e o ındice la primera vez que se ejecuta y nos ayud´ a preparar un esquema de versiones. y tambi´n amables palabras de ´nimo. o Man-Yong Lee envi´ una correcci´n del c´digo de ejemplo de la Secci´n o o o o 2. Su proo o grama puede encontrarse en el sitio web. Tambi´n encontr´ errores en e o la funci´n incrementa del Cap´ o ıtulo 13.py. David Kershaw arregl´ la funci´n catTwice que no funcionaba en la Seco o ci´n 3. o Matthew J. Kevin Parks envi´ valiosos comentarios y sugerencias acerca de c´mo meo o jorar la distribuci´n del libro.xiv Lista de Colaboradores Michael Conlon envi´ una correcci´n gramatical del Cap´ o o ıtulo 2 y una mejora del estilo del Cap´ ıtulo 1. ıa Chris McAloon envi´ varias correciones de las Secciones 3. James Kaylin es un estudiante que us´ el texto. o Eddie Lam ha enviado numerosas correcciones de los Cap´ ıtulos 1. Simon Dicon Montford inform´ de una definici´n de funci´n faltante y o o o varios errores tipogr´ficos en el Cap´ a ıtulo 3. Envi´ numerosas correco o ciones. David Mayo se˜al´ que la palabra “unconscientemente”en el Cap´ n o ıtulo 1 deb´ cambiarse por “subconscientemente”. John Ouzts corrigi´ la definici´n de “valor de retorno”del Cap´ o o ıtulo 3. Moelter ha sido un colaborador durante mucho tiempo y ha enviado numerosas correcciones y sugerencias.

donde la funci´n imprin o o o meHora se usaba en un ejemplo sin haberla definido. o . o James Mayer envi´ un cargamento de errores tipogr´ficos y ortogr´ficos. o Son los primeros en probar los Cap´ ıtulos de la segunda mitad del libro. o o y explic´ la diferencia entre gleich y selbe. Craig T. Snydal est´ poniendo a prueba el texto en un curso en la Unia versidad de Drew. Robin Shaw se˜al´ un error en la Secci´n 13. a partir de L TEX genera. Adem´s a de escribir el primer borrador del Cap´ ıtulo sobre diccionarios. Moshe Zadka ha hecho contribuciones inestimables al proyecto. o a a incluyendo dos en la lista de colaboradores. Peter Winstanley nos hizo saber de un persistente error en nuestro lat´ ın del Cap´ ıtulo 3. o Tauhidul Hoque y Lex Berezhny crearon las ilustraciones del Cap´ ıtulo 1 y mejoraron muchas de las otras ilustraciones.xv Michael Schmitt envi´ una correcci´n del Cap´ o o ıtulo sobre archivos y excepciones. Michele Alzetta pill´ un error en el Cap´ o ıtulo 8 y envi´ varios comeno tarios y sugerencias pedag´gicas interesantes sobre Fibonacci y La Mona.1. y han hecho numerosas correcciones y sugerencias. Ian Thomas y sus estudiantes usan el texto en un curso de programaci´n. Keith Verheyden envi´ una correcci´n del Cap´ o o ıtulo 3. Ha contribuido con varias sugerencias y correcciones de importancia. ´ Angel Arnal es parte de un equipo internacional de traductores que trabajan en la versi´n en espa˜ol del texto. Tambi´n ha encontrado varios o n e errores en la versi´n inglesa. Hayden McAfee pill´ una inconsistencia potencialmente confusa entre dos o ejemplos. proporcion´ una gu´ continuada en las primeras etapas del libro. o ıa Christoph Zwerschke envi´ varias correcciones y sugerencias pedag´gicas. el HTML. Paul Sleigh encontr´ un error en el Cap´ o ıtulo 7 y un error en el script Perl A de Jonah Cohen que. Chris Wrobel hizo correcciones al c´digo del Cap´ o ıtulo sobre E/S de archivos y excepciones. Dr.

y pill´ un par de errores o a o graves en el Cap´ ıtulo 5. o a o Gregor Lingl ense˜a Python en un instituto de Viena. o David Hutchins pill´ un error tipogr´fico en el Pr´logo. Julie Peters encontr´ un error tipogr´fico en el Prefacio. o a . Est´ tran a bajando en una traducci´n del libro al alem´n. Smith encontr´ varios errores tipogr´ficos y nos est´ ayuo a a dando a preparar la actualizaci´n del libro para Python 2.xvi Lista de Colaboradores Andy Mitchell pill´ un error tipogr´fico en el Cap´ o a ıtulo 1 y un ejemplo err´neo en el Cap´ o ıtulo 2.2. a Christopher P. Austria. Kalin Harvey sugiri´ una clarificaci´n al Cap´ o o ıtulo 7 y detect´ varios errores o tipogr´ficos.

. . . . . . . 1. . . . Glosario . . . . Evaluar expresiones . . . 2. . . . . .6. . . . . . . . .5. . . . . . . El lenguaje de programaci´n Python . v vii xiii 1 1 3 4 6 8 9 11 11 12 13 14 15 16 2. . . . . . . . . . . . . . e o Lenguajes formales y lenguajes naturales . . Variables . .6. . . . .4. . . . . e ¿Qu´ es la depuraci´n (debugging)? . . . . . . .2. . . 1. . . . .´ Indice general Pr´logo o Prefacio Lista de Colaboradores 1. . . . . . Sentencias . . . . . . . . . . . . . . El primer programa . . . . . . . 1. . . . . 2. . . . . . 2. . . . . . . . . . . . . . . . 1. . . . . .1. . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . o ¿Qu´ es un programa? . .4. . . . . El Camino del Programa 1. . . . . . . . . . 2. . . . . . . .5. . . . . . . . . Nombres de variables y palabras reservadas . . . . . . . . . . . . . . . . . . . . . Variables. . . . . . . . . . . . . . . . Operadores y expresiones . . . . . Valores y tipos . . . . . . . . . . . . . . . . 2. . 1.1. expresiones y sentencias 2. . . . . . . . . . . . . .2. . . . . . . . .3. . .

.6. . . . . . . . . . . .10. . . . . . . . . . . . . 3. . . . . . . . . . . . . . . . . . . . . . . . . . . El operador m´dulo .5. 3. . . 3. . . . . 2. . . . . . . . . . Operadores l´gicos . o Ejecuci´n alternativa . Glosario . . . . . . . . 3. a Composici´n . . . . . . 3. . . . . . . . . . . . . . .11. . . . . .3. . . .3. . . . . . . . 2. . . . . . . . . . 4. . . . . . . . . . . . . . . . . . Los comentarios . .8. . . . . . . . . . . . . . . . . . . . . . 2. . . . . . o Funciones matem´ticas .7. . . . . . . . . . . . . . . . . 3. . . . . . . . .9. . . . . . . . . . . . 3. . o Condiciones encadenadas . . . . . . . . . . . . . . . . . 4. . . . . . . . . . . . Conversi´n de tipos . . . . . . . . . . . . . . . . . . . . . . .4. . . . . . . . . . . . . . . . . . . . . . . 4. . . . . . . 3. . . . . . . . Funciones con resultado . .xviii ´ Indice general El orden de las operaciones . . . . .10. . . . . . .9. . . . Composici´n . . . . . . . . . . . . . Funciones 3. . . . o 17 17 18 19 19 21 21 22 22 23 24 24 26 27 28 29 30 31 32 35 35 36 36 37 37 38 2. . . . . . Condicionales y recursividad 4. . . . o Par´metros y argumentos . . . . . . . . . . . . . . . . .6. . . . . . . . 3. . . . . . . . . . Diagramas de pila . . . a 3. . Las operaciones sobre cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o Ejecuci´n condicional . . . . . . . .7. . . . . . . . . . . . . . . . . . . . . . . .12. . . . . . .4. . . . . . . . . . . 4. o Expresiones booleanas . . . o Coerci´n de tipos . n Las definiciones y el uso . . . . . . . . . . . . . . . . . 4. . 3. . .1. . . . .5.1. . . . . . . . . . . . . . 3. . . 4. . . . a 3. . . . .2. . . . . . . . . . . . . . . . . . . . . .13. . . .8. . Flujo de ejecuci´n . . . . . . . . . Llamadas a funciones . . .11. . o A˜adir funciones nuevas . . . . . . . . . . . . . . . . . . Glosario . . . . 2. . .2. . . . Las variables y los par´metros son locales .

5. . . Desarrollo de programas . . . . . . . .5. . . . . . . . . . Iteraci´n o 6. . . . . . . . . . . . . . . . . . . 4. . . . . . . . . . Un ejemplo m´s . . 6. . . . . 5. . . . . . .9. . 6.7. . . 5. . . 6. . . 5. 6. o u La sentencia while . . . . . . . . . . . . . . . 5. . . . . . . . . . . . .5. . . .13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o Funciones booleanas . . .8. . . . . . . . Encapsulado y generalizaci´n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6. . . . . . . . . . . . . . . . . . . . . . . . . . .10. . . . 6. . . . . . . . . . Condiciones anidadas . . . . . . . . . . . . . . . . . . . . . . . . . . 5. . . . . . . . . . . . . xix 39 40 40 42 43 44 45 47 47 48 51 52 53 55 56 57 58 61 61 62 64 66 67 68 69 70 71 72 4. .1. . . . . . 4. . . . . . . . . Asignaci´n m´ltiple . . . . . Composici´n . . . . . . . . . .´ Indice general 4. . . . . . a o Variables locales . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . .10.6. . . . . 6. 5. . o M´s encapsulaci´n . Recursividad infinita . . . . . . . . .8. . . . . . . . . . a Acto de fe . 4. . . . . . . .9. . . . . . . . . . . 6. . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . .7. . . . . Tablas . . . . . . . . . . . . . . . . . . . .2.4. . . . .12. . . . . . . . Glosario . Entrada por teclado . . . . . . . . M´s recursividad . . . . . . . . . . . . Recursividad . . . . La sentencia return . . . . . . . . . . . . .8. . .3. . . . . . . . o Glosario . . . a o Funciones . . . . . . . . . . . . a Comprobaci´n de tipos . . . . . . . . . . .11. . . . . . . . . . . . . . . .4. . . . . . . . . . . . . . . . . . .9. . .7. . . Valores de retorno . . . Glosario . . . . . . 4. . . . . . . 6. . M´s generalizaci´n . . . . 4. . . . . . . . . . . . . . . 6. . . . . .6. . . . . . . . .1. . . . . . . . . . . . . Tablas de dos dimensiones . . . . . . Funciones productivas 5. . . . . . . . . . . Diagramas de pila para funciones recursivas . . . . . . . . . . . . . 5. . . . 5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . Porciones de cadenas . . . . Alias (poner sobrenombres) . . . . .8. . Glosario . . . . . . . 8. . . 8. . . . . . Objetos y valores . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . .7. . . . . . 8. . . . . . . . . . . . . o Bucles y conteo . . . . .3. . . Una funci´n “encuentra” . . . . . Borrado en una lista . . . . . . . . . . . . . . . . . . . . . Listas y bucles for . . . . 8. . Longitud . . . . .6. . . Porciones (slices) . . . . . . . . . Operaciones con listas . . Clonar listas . . . . . Las listas son mutables . .11. Cadenas 7. . . . Un tipo de datos compuesto . . . . . . . 8. . . . Acceso a los elementos . . . . . . . . . . . . . Listas 8. . . . . . . . . . . . . . . . .6. . . . . . . Listas como par´meteros . . 7. . . . . . . .9.12. . . . . .13. Clasificaci´n de caracteres . . 7. . . . . . . .10. . . . . . . . . . . . . . . . . . . . . . . . 8. . . . . . 7. . . . . . . 7. . . .8. . . . a 8. 8. . . . El m´dulo “string” . . . . . . . . . . . . . . . . . . . . . . . .10. . . . . . . . . . . . . . n Pertenencia a una lista . . . . . . . . . . Listas anidadas . . . . . . . . . . . . . . . . . . .2. . . . . . Longitud (tama˜o) de una lista . . . . . . . . .11. . . 7. . . . . . . . . . Recorrido y el bucle for . . . . . . . . . . . . . . . . . . . 8. . . . . . . . . . . . . . . . . .4. . . . . . . . . . . . 8. . .1.5. . . . . 8. . . . . . . . . . . . . . . . . . . .4. . . . . . . . . . . 7. 8. . . . . . . . . . . .xx ´ Indice general 75 75 76 76 78 78 79 80 80 81 82 83 85 Valores de una lista . . o Las cadenas son inmutables . . . . .3. . . 85 86 87 88 88 89 90 90 91 91 92 93 94 95 7. . . . . . . . . . . . . . . .7. . . . . . . . . . . . . . . .5. . . . .14. 7. . . . . . . . . . . . . o 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8. . . . . .9. . . . . . . . . . Comparaci´n de cadenas . 8. . . . . . . . o 7. . . .2. . . . . . 7. . . . . . . . . . . . . . . . . .

. . 112 o 10. . . . . . . . . . . . . Mutabilidad y tuplas . . . . . . . . . . xxi 95 96 97 99 99 Asignaci´n de tuplas . 9. . .15. . . . . . . . . . . . . . . . . . . . . . . . 101 N´meros aleatorios . .2. . . . . . . . 123 11. .5. . . . . Directorios . . . . . . 115 10.7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . Matrices dispersas . . . . . . . . . . . . Matrices .4. . . . . Glosario . . . . . . . .6. . . . . .7. . 104 Una soluci´n en una sola pasada . . . . . . . . . . . . . . . . . . . . . .Diccionarios 10. . . . . . . . .2. . . . . . . . . . . . . . . . .3. 113 10. . . . . . . . . . . . . . . 116 10. . M´todos del diccionario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9. . . . . . . . . . . . . . . . . . 125 . . . 9. . . . . . . . . . . . . . . . . . . . 102 u Conteo . . . . . . . 116 11. . . Asignaci´n de alias y copiado . . . . . . . . . . . . . . . . . . . . . . . . . . .17. 9. . . . . . . 107 109 10. . . . . . . . . . . . . . . . .8. . . . . . . . . . . . . . . . . . . . . . . . . . .´ Indice general 8. . . . .1. . . . . . . . . . . . 9. . . 9. . . . Escribir variables . . . . . . . 111 e 10.Archivos y excepciones 119 11. . . . . . . . . . Operaciones sobre diccionarios . . . . . . Tuplas 9. . . . 8. . . 100 o Tuplas como valor de retorno . . . . . 9. . 106 o Glosario . . . . . . . .1. 110 10. . . . . . . . Archivos de texto . . . . . Cadenas y listas . . . . . . . . . . . . . . . . 9. . . . . . . . . . . . . . . . . .1. . . . . . . . 121 11. . .4. Enteros largos . . . . . . . . . . .16. . . . . . . . . . 103 Muchos baldes . . . . . . 9. . . .6. . . . . . . . . . . . . . . . . Pistas . .9. . . . . . . . . . 112 10. 8. . . . . .2. . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . Glosario . . . . . . Contar letras . .3. . . . . . . 101 u Lista de n´meros aleatorios . .8. . . . . . . .

. . . . . . . . . . . . . . .4. . . . . . .2. . . . . . . . Modificadores . . . . . . 137 12. . . . . . . . . . . . . . . . . . . . . . .2. . Tipos compuestos definidos por el usuario . . . . . . . . . . . Atributos . . .4. . 143 13. Funciones puras . Excepciones . . . . . . . . . 146 13. . . . . . . . . . . . . . . . . . . . . . . . .7. . . . . . . . . . . . . . . . . . . .1. . . . . . . . 141 13. . . . ¿Qu´ es mejor? . Generalizaci´n o . . . . . . . . . . . . . . . . 133 a 12. . .5. . . . . . . .Clases y objetos 131 12. . . . . . . . . . Instancias como valores de retorno . . . . . . . . . . . . . . . 135 a 12. . Caracter´ ısticas de la orientaci´n a objetos . . . . . . Algoritmos . . . . . . . . . . . . 151 . . . . . . 146 13. . . . . . . Hora . . . . . . . Mismidad . . . . . Glosario .Clases y funciones 141 13. . . . . . . . . . . . . . . . . .3. .6. . . . . . .9. . .8. . . . . . . . . . . . . . . . . . . . . .xxii ´ Indice general 11. . Otro ejemplo . . . . . . . . . . . . . . 147 14. . . . . . . . . . . . . .8. . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . .Clases y m´todos e 149 14. . . . . . . . . . 136 12. . . . . . . . . . . . . . . . 144 e 13. . . . . . . . . . . . Glosario . . . 149 o 14. . . . . . . . . . 128 12. Glosario . . Instancias como par´metro . .3. 142 13. .5. . . . . . . . . . . . . . . . . . . . . . Desarrollo de prototipos frente a planificaci´n . . . . . .6. . . . . . . . . . . . . . . . . . . . . . . . . . . . Rect´ngulos . . . . . . . .1. . 139 13. 134 12. . . . . . . . . . . . . . . . . . . 131 12. Copiado . . . . . . . . . . . . . . imprimeHora . . . . .1. . 150 14. . . . . . . . . . . . . . . . . . . .2. 145 o 13. . . . . . . . . . . . . . . 125 11. . . . . . . . . . 136 12. . . . . Encurtido . . . . . . . . . . . . . . . . . . . . . . . . . Los objetos son mudables . . . . . .3.6. . . . . . . . . . . . . 126 11. . .7. . . . . . . . . . 132 12.4. . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . 169 16.6. .5. . . . . . 153 14. . La clase JuegoDeLaMona . . . . . .5. . . 175 16. . . . . . . . .7. . . . . . . . 164 o 15. . 174 16. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 o 15. . . . . . . . . . . . . . . . . . . . .1. .3. Una mano de cartas . . Un ejemplo m´s complicado . . . . . 167 15. . . . . . . . . . . . . . . . . . . Polimorfismo . 160 15. . . .Herencia 171 16. . . . . . . . . . . . .9. . . . . . . . . . . . . . Sobrecarga de operadores . . . . . . . . . .4. . . . . . . . . La clase JuegoDeCartas .6. . . . . . Mazos de naipes . . 171 16. . . 161 15. . . . . . . . . . . . . . . 176 16. . . . . . . Composici´n . . . . . . . . Objetos Carta . . . . . . . . . . . . . .7. . . . . . . . . . . . . 181 . .´ Indice general xxiii 14. . .3. . Glosario . . . .2. . . . . Barajar el mazo . . 173 16. . . 161 o 15. . . . . . . .8. . .1. . . . . . . .10. . . . . .Conjuntos de objetos 161 15. . . . . . . . . Herencia . . . . . . . . .4. . . . . 156 14. . Impresi´n del mazo de naipes . .8. Glosario . . . . . . . . . La clase ManoDeLaMona . . . . . . . . . . . . . . . 158 14. 168 o 15. . . . . . . . . . . . . 152 a 14. . . . . . 163 15. . . . . . . . . . . . . . . . . El m´todo de inicializaci´n . . . . . . . . . . . . . . . . 177 16. . . . Eliminaci´n y reparto de los naipes . . . . . . . . . . . . . . .4. . . . . . . 165 15. . . . Comparaci´n de naipes .2. . . . . .5. 172 16. . . . . . . . . . . . Revisi´n de los Puntos . . . . . . . . . . . . . . . . . . . . . . .9. . 155 o 14. Argumentos opcionales . . . . . . . . . . 154 e o 14. . . . . . . . . . . . . . . . . . . . . . . . . . . .7. . . . . . . . . . . . . . . . . . . . . . . . .8. . . . . . . . . . . Atributos de clase y el m´todo e str . . . . Mostremos la mano . . . . . . . . . . . . . . . . . El reparto de los naipes . . . . . . Glosario . . . . . . . . . . . . . . . . . . .6. . . . . . . . . . . . . . . . . .

. . Uso de push y pop . . . . . . . . . . . . . . . . . . . . . . La clase Nodo . . . . . . . . . 198 18. . . . Listas como colecciones . . . . . . . .9. .6. . . . . . . . . . . . . . . . . . .8. . . . . . . 199 a a 18. . . . . . . . . . . . 195 18. . 196 o 18. . . . . . . . . . . . Listas infinitas . . . . . . . . . . . . . . . . . 188 u 17. . . .6.3. . . . . . . . . . . Rendimiento t´ ıpico . . . . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . Listas y recursividad . . . . . . . . . . . . . . . .Listas enlazadas 17. 186 17. 183 17.10. . . . . . . 196 18. . . . . . . . . . . . . . . . . . . . . . .2. . . . . . .1. El TAD Pila . . .4. . . . . . . . . An´lisis sint´ctico . . . . . . . . . . 191 17. . C´mo implementar pilas con listas de Python . . . . . . . . . . . . Evaluar un postfijo . . . . . . . . . . . Clientes y proveedores . 199 18. Glosario . . . . . .9. . . . . . . . .3. . . . . . . . . . . .5.1. . . .11. . . . . . . . . . El TAD Cola . . . . . . . Usar una pila para evaluar postfijo . . . . . . .2. . . . .7. . Glosario . . . . . . Teorema fundamental de la ambig¨edad . . . . . . . . . . . . . . . .8. 200 18.1. Invariantes . . . . . . . . . . . . . . . . . . . . . . . .Colas 203 19. . . . . . 197 18. . . . . Modificar listas . . . Cola Enlazada . . 183 17.xxiv ´ Indice general 183 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 19. . . . . . . 187 17. . . 190 17. . . . . .2. . . . . . Envoltorios y ayudantes . . . 204 19. . . . . . . . . . . . . . . .4. . . . . . . . .3. . . . . 201 19. . . . . . . . . . . . . . Tipos abstractos de datos . . . . . . 205 . . 192 18. . . . . .Pilas 195 18. . . . La clase ListaEnlazada . . . . . . . 185 17. 189 17. . . . . . . . . . . . . . . . . 190 17. . . . . . . . .7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Referencias incrustadas .

. . . . . 213 ´ 20. . .7. . . 225 Errores en tiempo de ejecuci´n .5. . . . . Glosario . . . Construir un ´rbol de expresi´n . .1. . . . 214 a 20. . Glosario . . 238 Comparar fracciones . . . . . . . . . . .6. . . . . . . . . . . . . . .4.4. . . . . . . . . . . . Arboles de expresi´n . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . 231 a 235 B. . . . . . . 237 Algoritmo de Euclides . . . . . . B. . . . . . . .3. . . .8. . . . . . . . . . . . . . . B. . . . . . . A. . . . . . . . . 241 . . . . . . . . . . . . . . . . . . .6. . . . . . . . . . . 216 a o 20. . . . . . . . 225 Errores de sintaxis . . . . . . . .4. . . . . . . . . . . . . . . . . . . . . . . 227 o Errores sem´nticos . . . . . . . . . . . . 239 Forzando la m´quina . . . . . . . . .3.6. B. . . 213 o 20.7. . . . . . . 224 A. . . . . . . . . . 220 20. . .1. . . . . . . . . . . . . . . . . . . . 205 19. . . . . .´ Indice general xxv 19. . . . . .3. . . . . . . . . . . . . . 240 a Glosario . . . . 212 a 20. . . . . B. . . . . . A. . . . . . . . . . . . Multiplicaci´n de fracciones . . . . . . . . . . . . . . La clase Golfista . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Crear un nuevo tipo de datos B. . . . . . . . . .2. . . . . 209 19. . . . . . . . . . . . . . . . . . . . . . Crear ´rboles . . . . . . Arboles 211 20. . . . . Cola Enlazada Mejorada . . . . . . . . . . . . . . . . Recorrer ´rboles a .2. . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . 210 ´ 20. B. . . . Manejar errores . . . . . . . . . . . . . . . . . Recorrido de un ´rbol . . . . 236 o Suma de fracciones . . . . 207 19. . El ´rbol de animales . . . . . . . . . . . . . . . . Depuraci´n o A. . . . . . . . . 221 a 20. . . Cola priorizada . . . .5. . . . . . . . . .

. . 254 o Adivina el animal . . . . .1. . D. . . . . . . . . . . . Fraction class . . . . . . . . . 269 Aggregation with Independent Works . . . . . .2. 261 a 263 E. . . . . Future Revisions of This License . . . . . .6. .4. . . . . . C. . . E. . .2. . . . . . . . . . . . .xxvi ´ Indice general 243 C. . . . .7. . . . . . . . . . . . . . . 249 Clase Pila . .8. . . . C. 255 C. . 264 Verbatim Copying . . . . . . . . . . E. . . .10. . . . . . . . . . . .9. . . . E. 270 E. . . . . . . . Applicability and Definitions . . . . . . .6. 266 Combining Documents . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . .11. . . . . . . . . . . . . . . . . . . . . . . 268 Collections of Documents . Lecturas recomendadas D. . . . . 253 ´ Arboles de expresi´n . . . . . . . 251 ´ Arboles . . . . . . . . . . . . . . . . 269 Termination . 265 Modifications . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . Addendum: How to Use This License for Your Documents . . . . . . . . . . . . . . C. . . . . . . . . . . .5. .8. . . . . . . . . . . . . . . . . . . . . . 245 Lists Enlazadas . . . . . . . . . . C. . . . . . . 270 E. . . . . . . . . . . . . . . . . . . . . .4. . Listados Completos de Python C. . . . . . . . . . . . 270 . . Clase Punto . . . . . . . . . E. GNU Free Documentation License E. . . . . E. . . . . . 243 Clase Hora . . . . . . . . . . . . . . . . 259 Libros y sitios web sobre Python . . 244 Cartas. . . . . . . . . . . . . . . . . . . . 250 Colas y colas priorizadas . . . . . . .7. . . . . . . . . . . . . E. . . C. . .10. . . E. . . . . . C. . . . . . . . . . . . . 269 Translation . . . . . . . . . . mazos y juegos . C. . . . . . . . . 256 D. . .2. . . . . . . . .1. . .5. . . . . . . . . . . . . 265 Copying in Quantity .3. . . . . . . . . . . . . . .9. . . E. C. . . . . 260 Libros recomendados sobre inform´tica en general . . . . . . . . . . . . . . . . . . . . . .

Cap´ ıtulo 1

El Camino del Programa
El objetivo de este libro es ense˜arle a pensar como lo hacen los cient´ n ıficos inform´ticos. Esta manera de pensar combina las mejores caracter´ a ısticas de la matem´tica, la ingenier´ y las ciencias naturales. Como los matem´ticos, los a ıa, a cient´ ıficos inform´ticos usan lenguajes formales para designar ideas (espec´ a ıficamente, computaciones). Como los ingenieros, ellos dise˜an cosas, ensamblando n sistemas a partir de componentes y evaluando ventajas y desventajas de cada una de las alternativas. Como los cient´ ıficos, ellos observan el comportamiento de sistemas complejos, forman hip´tesis, y prueban sus predicciones. o La habilidad m´s importante del cient´ a ıfico inform´tico es la soluci´n de proa o blemas. La soluci´n de problemas incluye poder formular problemas, pensar en o la soluci´n de manera creativa, y expresar una soluci´n con claridad y precisi´n. o o o Como se ver´, el proceso de aprender a programar es la oportunidad perfecta a para desarrollar la habilidad de resolver problemas. Por esa raz´n este cap´ o ıtulo se llama “El Camino del programa”. A cierto nivel, usted aprender´ a programar, lo cual es una habilidad muy util a ´ por s´ misma. A otro nivel, usted utilizar´ la programaci´n para obtener alg´n ı a o u resultado. Ese resultado se ver´ m´s claramente durante el proceso. a a

1.1.

El lenguaje de programaci´n Python o

El lenguaje de programaci´n que aprender´ es Python. Python es un ejemplar o a de un lenguaje de alto nivel; otros ejemplos de lenguajes de alto nivel son C, C++, Perl y Java.

2

El Camino del Programa

Como se puede deducir de la nomenclatura “lenguaje de alto nivel”, tambi´n e existen lenguajes de bajo nivel, a los que tambi´n se califica como lenguae jes de m´quina o lenguajes ensambladores. A prop´sito, los computadores s´lo a o o ejecutan programas escritos en lenguajes de bajo nivel. Los programas de alto nivel tienen que traducirse antes de ejecutarse. Esta traducci´n lleva tiempo, lo o cual es una peque˜a desventaja de los lenguajes de alto nivel. n Aun as´ las ventajas son enormes. En primer lugar, la programaci´n en lenguajes ı o de alto nivel es mucho m´s f´cil; escribir programas en un lenguaje de alto nivel a a toma menos tiempo, los programas son m´s cortos y m´s f´ciles de leer, y es m´s a a a a probable que estos programas sean correctos. En segundo lugar, los lenguajes de alto nivel son portables, lo que significa que pueden ejecutarse en tipos diferentes de computadores sin modificaci´n alguna o con pocas modificaciones. o Los programas escritos en lenguajes de bajo nivel s´lo pueden ser ejecutarse en o un tipo de computador y deben reescribirse para ejecutarlos en otro. Debido a estas ventajas, casi todos los programa se escriben en un lenguaje de alto nivel. Los lenguajes de bajo nivel s´lo se usan para unas pocas aplicaciones o especiales. Hay dos tipos de programas que traducen lenguajes de alto nivel a lenguajes de bajo nivel: int´rpretes y compiladores. Un int´rprete lee un programa de e e alto nivel y lo ejecuta, lo que significa que lleva a cabo lo que indica el programa. Traduce el programa poco a poco, leyendo y ejecutando cada comando.

CODIGO FUENTE

INTERPRETER

SALIDA

Un compilador lee el programa y lo traduce todo al mismo tiempo, antes de ejecutar cualquiera de las instrucciones. En este caso, al programa de alto nivel se le llama el c´digo fuente, y al programa traducido el c´digo de objeo o to o el c´digo ejecutable. Una vez compilado el programa, puede ejecutarlo o repetidamente sin volver a traducirlo.

CODIGO FUENTE

COMPILADOR

CODIGO OBJETO

EJECUTOR

SALIDA

Python se considera como lenguaje interpretado porque los programas de Python se ejecutan por medio de un int´rprete. Existen dos maneras de usar el e

1.2 ¿Qu´ es un programa? e

3

int´rprete: modo de comando y modo de gui´n. En modo de comando se escrie o ben sentencias en el lenguaje Python y el int´rprete muestra el resultado. e $ python Python 1.5.2 (#1, Feb 1 2000, 16:32:16) Copyright 1991-1995 Stichting Mathematish Centrum, Amsterdam >>> print 1 + 1 2 La primera l´ ınea de este ejemplo es el comando que pone en marcha el int´rprete e Python. Las dos l´ ıneas siguientes son mensajes del int´rprete. La tercera l´ e ınea comienza con >>>, que es la invitaci´n del int´rprete para indicar que est´ listo. o e a Escribimos print 1 + 1 y el int´rprete contest´ 2. e o Alternativamente, se puede escribir el programa en un archivo y usar el int´rpree te para ejecutar el contenido de dicho archivo. El archivo se llama, en este caso, un gui´n. Por ejemplo, en un editor de texto se puede crear un archivo o latoya.py que contenga esta l´ ınea: print 1 + 1 Por acuerdo un´nime, los archivos que contienen programas de Python tienen a nombres que terminan con .py. Para ejecutar el programa, se le tiene que indicar el nombre del gui´n al int´rpreo e te. $ python latoya.py 2 En otros entornos de desarrollo los detalles de la ejecuci´n de programas pueden o ser diferentes. Aem´s, la mayor´ de programas son m´s interesantes que el a ıa a mencionado. La mayor´ de ejemplos en este libro se ejecutan desde en la l´ ıa ınea de comando. La l´ ınea de comando es muy apropiada para el desarrollo de programas y para pruebas r´pidas porque se pueden teclear las instrucciones de Python y se puea den ejecutar inmediatamente. Una vez que un programa est´ completo, puede a archivarse en un gui´n para ejecutarlo o modificarlo en el futuro. o

1.2.

¿Qu´ es un programa? e

Un programa es una secuencia de instrucciones que especifican c´mo ejecutar o una computaci´n. La computaci´n puede ser algo matem´tico, como solucionar o o a

4

El Camino del Programa

un sistema de ecuaciones o determinar las ra´ de un polinomio, pero tambi´n ıces e puede ser una computaci´n simb´lica, como buscar y reemplazar el texto de un o o documento o (aunque parezca raro) compilar un programa. Las instrucciones (comandos, ´rdenes) tienen una apariencia diferente en leno guajes de programaci´n diferentes, pero existen algunas funciones b´sicas que o a se presentan en casi todo lenguaje: entrada: Recibir datos del teclado, o un archivo u otro aparato. salida: Mostrar datos en el monitor o enviar datos a un archivo u otro aparato. matem´ticas: Ejecutar operaciones b´sicas de matem´ticas como la adici´n y a a a o la multiplicaci´n. o operaci´n condicional: Probar la veracidad de alguna condici´n y ejecutar o o una secuencia de instrucciones apropiada. repetici´n: Ejecutar alguna acci´n repetidas veces, normalmente con alguna o o variaci´n. o Lo crea o no, eso es todo. Todos los programas que existen, por complicados que sean, est´n formulados exclusivamente con tales instrucciones. As´ una manera a ı, de describir la programaci´n es: El proceso de romper una tarea en tareas cada o vez m´s peque˜as hasta que estas tareas sean suficientemente simples para ser a n ejecutadas con una de estas instrucciones simples. Quiz´s esta descripci´n sea un poco ambigua. No se preocupe. Lo explicaremos a o con m´s detalle con el tema de los algoritmos. a

1.3.

¿Qu´ es la depuraci´n (debugging)? e o

La programaci´n es un proceso complejo y, por ser realizado por humanos, a o menudo desemboca en errores. Por razones caprichosas, esos errores se llaman bugs y el proceso de buscarlos y corregirlos se llama depuraci´n (en ingl´s o e “debugging”). Hay tres tipos de errores que pueden ocurrir en un programa, de sintaxis, en tiempo de ejecuci´n y sem´nticos. Es muy util distinguirlos para encontrarlos o a ´ mas r´pido. a

1.3 ¿Qu´ es la depuraci´n (debugging)? e o

5

1.3.1.

Errores sint´cticos a

Python s´lo puede ejecutar un programa si el programa es correcto sint´cticao a mente. En caso contrario, es decir si el programa no es correcto sint´cticamente, a el proceso falla y devuelve un mensaje de error. El t´rmino sintaxis se refiere a e la estructura de cualquier programa y a las reglas de esa estructura. Por ejemplo, en espa˜ol la primera letra de toda oraci´n debe ser may´scula, y todas las n o u oraciones deben terminar con un punto. esta oraci´n tiene un error sint´ctico. o a Esta oraci´n tambi´n o e Para la mayor´ de lectores, unos pocos errores sint´cticos no son significatvos, ıa a y por eso pueden leer la poes´ de e. e. cummings sin anunciar errores de sinıa taxis. Python no es tan permisivo. Si hay aunque sea un solo error sint´ctico a en el programa, Python mostrar´ un mensaje de error y abortar´ la ejecuci´n a a o del programa. Durante las primeras semanas de su carrera como programador pasar´, seguramente, mucho tiempo buscando errores sint´cticos. Sin embargo, a a tal como adquiera experiencia tendr´ menos errores y los encontrar´ mas r´pido. a a a

1.3.2.

Errores en tiempo de ejecuci´n o

El segundo tipo de error es un error en tiempo de ejecuci´n. Este error no aparece o hasta que se ejecuta el programa. Estos errores tambi´n se llaman excepciones e porque indican que algo excepcional (y malo) ha ocurrido. Con los programas que vamos a escribir al principio, los errores en tiempo de ejecuci´n ocurrir´n con poca frecuencia, as´ que puede pasar bastante tiempo o a ı hasta que vea uno.

1.3.3.

Errores sem´nticos a

El tercer tipo de error es el error sem´ntico. Si hay un error de l´gica en su a o programa, el programa se ejecutar´ sin ning´n mensaje de error, pero el resula u tado no ser´ el deseado. Ser´ cualquier otra cosa. Concretamente, el programa a a har´ lo que usted le dijo. a A veces ocurre que el programa escrito no es el programa que se ten´ en mente. ıa El sentido o significado del programa (su sem´ntica) no es correcto. Es dif´ haa ıcil llar errores de l´gica, porque requiere trabajar al rev´s, observando el resultado o e del programa para averiguar lo que hace.

6

El Camino del Programa

1.3.4.

Depuraci´n experimental o

Una de las t´cnicas m´s importantes que usted aprender´ es la depuraci´n. Aune a a o que a veces es frustrante, la depuraci´n es una de las partes m´s intelectualmente o a ricas, interesantes y estimulantes de la programaci´n. o La depuraci´n es una actividad parecida a la tarea de un investigador: se tieo nen que estudiar las claves para inducir los procesos y eventos llevaron a los resultados que tiene a la vista. La depuraci´n tambi´n es una ciencia experimental. Una vez que se tiene la o e idea de cu´l es el error, se modifica el programa y se intenta nuevamente. Si su a hip´tesis fue la correcta se pueden predecir los resultados de la modificaci´n y o o estar´ m´s cerca de un programa correcto. Si su hip´tesis fue err´nea tendr´ que a a o o a idearse otra hip´tesis. Como dijo Sherlock Holmes, “Cuando se ha descartado o lo imposible, lo que queda, no importa cuan inveros´ ımil, debe ser la verdad.” (A. Conan Doyle, The Sign of Four) Para algunas personas, la programaci´n y la depuraci´n son lo mismo: la proo o gramaci´n es el proceso de depurar un programa gradualmente hasta que haga o lo que usted quiera. La idea es que deber´ usted comenzar con un programa ıa que haga algo y hacer peque˜as modificaciones, depur´ndolas sobre la marcha, n a de modo que siempre tenga un programa que funcione. Por ejemplo, Linux es un sistema operativo que contiee miles de l´ ıneas de c´digo, o pero Linus Torvalds lo comenz´ como un programa para explorar el microproceo sador Intel 80836. Seg´n Larry Greenfield, “Uno de los proyectos tempranos de u Linus fue un programa que alternaba la impresi´n de AAAA con BBBB. Este o programa evolucion´ en Linux” (de The Linux Users’Guide Versi´n Beta 1). o o Otros cap´ ıtulos tratar´n m´s acerca del tema de depuraci´n y otras t´cnicas de a a o e programaci´n. o

1.4.

Lenguajes formales y lenguajes naturales

Los lenguajes naturales son los lenguajes hablados por seres humanos, como el espa˜ol, el ingl´s y el franc´s. No los han dise˜ados personas (aunque se n e e n intente poner cierto orden en ellos), sino que se han desarrollado naturalmente. Los lenguajes formales son lenguajes dise˜ados por humanos y que tienen n aplicaciones espec´ ıficas. La notaci´n matem´tica, por ejemplo, es un lenguaje o a formal ya que se presta a la representaci´n de las relaciones entre n´meros y o u s´ ımbolos. Los qu´ ımicos utilizan un lenguaje formal para representar la estructura qu´ ımica de las mol´culas. Y lo m´s importante: e a

lo que quiere decir que cualquier u sentencia tiene s´lo un significado. a Al leer una oraci´n. a a Por ejemplo cuando usted escucha la oraci´n “El otro zapato cay´”. pero 3 = +6$ no lo es. o Aunque existen muchas cosas en com´n entre los lenguajes naturales y los u lenguajes formales—por ejemplo las unidades. Las a unidades son los elementos b´sicos de un lenguaje. o la sem´ntica.4 Lenguajes formales y lenguajes naturales Los lenguajes de programaci´n son lenguajes formales deo sarrollados para expresar computaciones. entender´ el o a significado de la oraci´n. Similarmente. sea en un lenguaje natural o una sentencia en un lenguaje o t´cnico. Por ejemplo. Suponiendo que sepa lo ques es un zapato y lo que es caer. la estructura. Cuando se ha analizado o la oraci´n sint´cticamente. o tanto como sea posible. pero 2 Zz no lo es. Similarmente. La segunda clase de regla sint´ctica est´ relacionada con la estructura de un a a elemento. se puede deducir el significado. en 3=+6$. entiende o o que “el otro zapato” es el sujeto y “cay´” es el verbo. o sea. 3 + 3 = 6 es una expresi´n matem´tica correcta. de la o a a oraci´n. trate de producir una oraci´n con estructura a o aceptada pero que est´ compuesta de unidades irreconocibles.1. la sintaxis y la sem´ntica—tambi´n existen muchas diferencias: a e ambig¨ edad: Los lenguajes naturales tienen much´ u ısimas ambig¨edades. $ no es una unidad matem´tica aceptada (al menos hasta donde nosotros sabemos. Los o lenguajes formales se dise˜an para estar completamente libres de amn big¨edades. los a n´meros y los elementos qu´ u ımicos. Por ejema plo. que u los hablantes sortean usando claves contextuales y otra informaci´n. el orden de las unidades. H2 0 es una nomenclatura qu´ ımica correcta. En un lenguaje natural e o este proceso. e A manera de pr´ctica. 7 Los lenguajes formales casi siempre tienen reglas sint´cticas estrictas. La estructura de la sentencia 3=+6$ no se acepta porque no se puede escribir el s´ ımbolo de igualdad seguido de un s´ ımbolo positivo. a u 2 Zz no es formal porque no hay ning´ n elemento con la abreviatura Zz. o . las f´rmulas moleculares tienen que mostrar el o n´mero de sub´ u ındice despu´s del elemento. De o a la misma manera. en cuanto a unidades y estructura. Luego e escriba otra oraci´n con unidades aceptables pero con estructura no o v´lida. llamado an´lisis sint´ctico ocurre subconscientemente. no antes. Existen dos clases de reglas sint´cticas. se debe discernir la estructura de la oraci´n. sin importar el contexto. como lo son las palabras.

la estructura es muy importante. Los que aprenden a hablar un lenguaje natural—es decir. ponga atenci´n a los detalles. La prosa se presta al an´lisis m´s que la poes´ pero a u a a ıa. En vez de eso. mundo” (Hello world!) porque s´lo muestra las palabras “Hola a todo el mundo”. El primer programa Tradicionalmente el primer programa en un lenguaje nuevo se llama “Hola. Los lenguajes formales son menos redundantes y m´s concisos. todav´ contiene ambig¨edad. Los fallos de puntuaci´n o o y la ortograf´ que puede obviar en el lenguaje natural. Tama bi´n. produce un efecto o reacci´n emocional. aprenda a separar las diferentes partes en su mente. de izquierda a derecha. a literalidad: Los lenguajes naturales tienen muchas met´foras y frases hechas. o La ambig¨edad no es solo com´n sino utilizada a prop´sito. u u o Prosa: El significado literal de la palabra es mas importante y la estructura da m´s significado a´n. es diferente al significado de sus sustantivos y verbos. a El significado de un dicho. pueden suponer una ıa. por ejemplo “Estirar la pata”. He aqu´ unas sugerencias para la lectura de un programa (y de otros lenguajes ı formales). mundo" . recuerde que los lenguajes formales son mucho m´s densos a que los lenguajes naturales. las lenguas nau turales utilizan bastante redundancia. A veces la diferencia entre los lenguajes formales y los naturales es comparable a la diferencia entre la prosa y la poes´ ıa: Poes´ Se utiliza una palabra por su cualidad auditiva tanto como por su signiıa: ficado. 1. identificar las unidades e interpretar la estructura. Finalmente. as´ que entonces no es una buena idea e ı leerlo de pies a cabeza. y es entendido en su totalidad analizando las unidades y la estructura. en su totalidad. ıa u Programas: El significado de un programa es inequ´ ıvoco y literal. todo el mundo— muchas veces tienen dificultad en adaptarse a los lenguajes formales. Los lenguajes formales no difieren de su significado literal.8 El Camino del Programa redundancia: Para reducir la ambig¨edad y los malentendidos. Como resultado suelen ser prolijos. o En Python es as´ ı: print "Hola. El poema. Primero.5. En este ejemplo. gran diferencia en un lenguaje formal. la oraci´n no tiene o nada que ver con un pie y significa ’morirse’. y por consecuente lleva m´s tiempo leerlos.

En este caso. o programa: Un conjunto de instrucciones que especifica una computaci´n. m´s bien muestra un valor. programa ejecutable: Otro nombre para el c´digo de objeto que est´ listo o a para ejecutarse.6. 1.1. o algoritmo: Un proceso general para resolver una clase completa de problemas. portabilidad: La cualidad de un programa que le permite ser ejecutado en m´s de un tipo de computador. el resultado es las palabras a Hola. no aparecen en el resultado. lenguaje de bajo nivel: Un lenguaje de programaci´n dise˜ado para ser f´cil o n a de ejecutar para un computador. n Alguna gente eval´a la calidad de un lenguaje de programaci´n por la simpliciu o dad del programa “Hola. . o o lenguaje de alto nivel: Un lenguaje como Python dise˜ado para ser f´cil de n a leer y escribir para la gente. Glosario soluci´n de problemas: El proceso de formular un problema. Si seguimos ese criterio. Python cumple con todas sus metas. tambi´n se lo llama “lenguaje de m´quie a na” o “lenguaje ensamblador”. a interpretar: Ejecutar un programa escrito en un lenguaje de alto nivel traduci´ndolo l´ e ınea por l´ ınea compilar: Traducir un programa escrito en un lenguaje de alto nivel a un lenguaje de bajo nivel todo al mismo tiempo. c´digo de objeto: La salida del compilador una vez que ha traducido el proo grama. en preparaci´n para la ejecuci´n o o posterior. hallar la soluo ci´n y expresar esa soluci´n. mundo”. gui´n: Un programa archivado (que va a ser interpretado).6 Glosario 9 Este es un ejemplo de una sentencia print. la cual no imprime nada en papel. mundo Las comillas se˜alan el comienzo y el final del valor. c´digo fuente: Un programa escrito en un lenguaje de alto nivel antes de ser o compilado.

o o error sem´ntico: Un error en un programa que hace que ejecute algo que no a era lo deseado.10 error (bug): Un error en un programa. . error sint´ctico: Un error en un programa que hace que el programa sea ima posible de analizar sint´cticamente (e imposible de interpretar). como la representaci´n de ideas matem´ticas o proo a gramas de computadores. a an´lisis sint´ctico: La examinaci´n de un programa y el an´lisis de su estruca a o a tura sint´ctica. sem´ntica: El significado de un programa. o sintaxis: La estructura de un programa. u excepci´n: Otro nombre para un error en tiempo de ejecuci´n. todos los lenguajes de programaci´n son lenguao jes formales. a sentencia print: Una instrucci´n que causa que el int´rprete Python muestre o e un valor en el monitor. unidad: Uno de los elementos b´sicos de la estructura sint´ctica de un prograa a ma. a error en tiempo de ejecuci´n: Un error que no ocurre hasta que el prograo ma ha comenzado a ejecutarse e impide que el programa contin´e. an´logo a una palabra en un lenguaje natural. El Camino del Programa depuraci´n: El proceso de hallazgo y eliminaci´n de los tres tipos de errores o o de programaci´n. a language natural: Cualquier lenguaje hablado que evolucion´ de forma natuo ral. lenguaje formal: Cualquier lenguaje dise˜ado por humanos que tiene un n prop´sito espec´ o ıfico.

mundo es una cadena. puede pregunt´rselo a a al int´rprete de Python.Cap´ ıtulo 2 Variables. Los valores que hemos visto hasta el u momento son 2 (el resultado de sumar 1 + 1) y Hola.1. Usted (y el ı int´rprete) puede identificar las cadenas porque est´n encerradas entre comie a llas. expresiones y sentencias 2. llamada as´ porque contiene una “cadena” de letras. mundo") <type ’string’> >>> type(17) <type ’int’> No es sorprendente que las cadenas sean de tipo string (cadena en ingl´s) y e los enteros sean de tipo int (por integer en ingl´s). Estos valores son de distintos tipos: 2 es un entero y Hola. La sentencia print tambi´n funciona con enteros: e >>> print 4 4 Si no est´ seguro del tipo que tiene un determinado valor. mundo. Valores y tipos El valor es uno de los elementos fundamentales (como por ejemplo una letra o un n´mero) que manipula un programa. e >>> type("Hola. los e . De forma menos obvia.

La sentencia de asignaci´n crea nuevas variables y les asigna un valor: o >>> mensaje = "Que onda?" >>> n = 17 >>> pi = 3.000 como una lista de tres n´meros que debe imprimir. pero es una expresi´n legal: o >>> print 1. como en 1.2"? Parecen n´meros.000. pero est´n e u a entre comillas como las cadenas. Variables Una de las caracter´ ısticas m´s potentes de los lenguajes de programaci´n es a o la capacidad de manipular variables. Cuando escriba un entero largo. 1 2.2) <type ’float’> ¿Qu´ ocurre con los valores como "17" y "3.12 Variables. podr´ estar tentado de usar comas entre grupos ıa ´ de tres d´ ıgitos.000. de nombre mensaje. La segunda le da el uso de la coma y el punto en n´mero es en ingl´s el contrario al uso espa˜ol. como se u e n apunt´ en una nota anterior o 1 El . >>> type(3. La primera de ellas asigna el valor "Que onda?" a una variable nueva. no era eso lo que quer´ ıamos.2.000. Este no es un entero legal en Python. Una variable es un nombre que hace referencia a un valor. Python interpreta 1. >>> type("17") <type ’string’> >>> type("3.14159 Este ejemplo muestra tres asignaciones. As´ que recuerde no insertar comas en u ı sus enteros. expresiones y sentencias n´meros con decimales (separados por medio de un punto en ingl´s) son de tipo u e float debido a la representaci´n de estos n´meros en el formato llamado de o u coma flotante (floating-point).000.000 1 0 0 En fin.2") <type ’string’> Son cadenas.

2. pero deben comenzar con una letra. Este tipo de representaci´n n o se llama diagrama de estado. los programadores eligen nombres significativos para sus variables: esto permite documentar para qu´ se usa la variable. Una forma habitual de representar variables sobre el papel es escribir el nombre con una flecha se˜alando al valor de la variable.3 Nombres de variables y palabras reservadas 13 valor entero 17 a n. e >>> print mensaje "Que onda?" >>> print n 17 >>> print pi 3. Aunque es u . ya que muestra en qu´ estado se halla cada e una de las variables (consid´relo como el “estado de ´nimo” de la variable”). y la tercera le da el valor de n´mero en coma flotante u 3.14159 La sentencia print tambi´n funciona con variables. De nuevo. e >>> type(mensaje) <type ’string’> >>> type(n) <type ’int’> >>> type(pi) <type ’float’> El tipo de una variable es el tipo del valor al que se refiere. e a El siguiente diagrama muestra el efecto de las tres sentencias de asignaci´n o anteriores: mensaje n pi "Que onda?" 17 3. e Los nombres de las variables pueden tener una longitud arbitraria. podemos preguntar al int´rprete lo que son.14159 a pi.14159 En cada caso.2. Nombres de variables y palabras reservadas Como norma general. el resultado es el valor de la variable. Las variables tambi´n tienen e tipo. Pueden estar formados por letras y n´meros.3.

obtendr´ un error de sintaxis. o Cuando usted escribe una sentencia en la l´ ınea de comandos. Si hay m´s de una o a sentencia.4. o El gui´n bajo ( ) tambi´n es legal y se utiliza a menudo para separar nombres o e con m´ltiples palabras. recuerde u o que la distinci´n es importante: Bruno y bruno son dos variables diferentes. Si lo hace. Si el int´rprete se queja de alguno e de sus nombres de variable.14 Variables. Python tiene 28 palabras reservadas: and assert break class continue def del elif else except exec finally for from global if import in is lambda not or pass print raise return try while Tal vez quiera mantener esta lista a mano. El lenguaje usa las palabras reservadas para definir sus reglas y estructura. y usted no sabe por qu´. Pero ¿qu´ tiene de malo class? a o e Resulta que class es una de las palabras reservadas de Python. Python la ejecuta y muestra el resultado. El resultado de una sentencia print es un valor. Las sentencias de asignaci´n no entregan ning´n resultado. u Si intenta darle a una variable un nombre ilegal. o u Normalmente un gui´n contiene una secuencia de sentencias. compruebe si est´ en esta e a lista. mas$ es ilegal porque contiene un car´cter ilegal. y no pueden usarse como nombres de variables. 2. como mi nombre o precio del cafe colombiano. los resultados aparecen de uno en uno tal como se van ejecutando las sentencias. el signo del d´lar. expresiones y sentencias aceptable usar may´sculas. Sentencias Una sentencia es una instrucci´n que puede ejecutar el int´rprete de Python. . o e Hemos visto dos tipos de sentencias: print y la asignaci´n. a >>> 76trombones = "gran desfile" SyntaxError: invalid syntax >>> mas$ = 1000000 SyntaxError: invalid syntax >>> class = "Curso de Programaci´n 101" o SyntaxError: invalid syntax 76trombones es ilegal porque no comienza por una letra. si lo hay. por convenci´n no lo hacemos.

una expresi´n sin m´s es una sentencia v´lida.5. variables y operadores. >>> mensaje = "Que onda?" >>> mensaje "Que onda?" >>> print mensaje Que onda? Cuando Python muestra el valor de una expresi´n. e o ı >>> 17 17 >>> x 2 Para complicar las cosas. evaluar una expresi´n no es del todo lo mismo que o imprimir un valor.2. el int´rprete la eval´ a y muestra el e u resultado: >>> 1 + 1 2 Un valor. usa el mismo formato que o usted usar´ para introducir un valor. eso significa que ıa incluye las comillas. o o a a El gui´n o . Pero la sentencia print imprime el valor de la expresi´n.5 Evaluar expresiones Por ejemplo. En el caso de las cadenas. pero no hace nada. o 15 2. Evaluar expresiones Una expresi´n es una combinaci´n de valroes. En un gui´n. lo o que en este caso es el contenido de la cadena. Si teclea o o una expresi´n en la l´ o ınea de comandos. se considera una expresi´n por s´ mismo. el gui´n o print 1 x = 2 print x prsenta la salida 1 2 De nuevo. la sentencia de asignaci´n no produce ninguna salida. y tambi´n una variable.

/. o Cuando ambos operandos son enteros. incluso en o o casos como estos en los que el siguiente entero est´ muy pr´ximo.6. como a la suma y la multiplicaci´n. pero la divio o si´n le puede sorprender. Los valores que usa el operador se llaman operano dos. e por convenci´n.16 17 3. resta. el resultado ha de ser tambi´n un entero. se sustituye con su valor antes de realizar la operaci´n. expresiones y sentencias no presenta ninguna salida. o La suma. El motivo de la discrepancia reside en que Python est´ llevando a cabo una a divisi´n de enteros.2 "Hola. y el uso de los par´ntesis para el agrupamiento.98333 y no 0. mundo" 1 + 1 Variables. o Cuando aparece el nombre de una variable en el lugar de un operando. multiplicaci´n y exponenciaci´n hacen lo esperado. Las siguientes expresione son legales en Python y su significado es m´s o menos a claro: 20+32 hora-1 hora*60+minuto minuto/60 5**2 (5+9)*(15-7) Los s´ ımbolos +. a o Una alternativa posible en este caso es el c´lculo de un porcentaje y no el de a una fracci´n: o >>> minuto*100/60 98 . El asterisco (*) es el signo de a multiplicaci´n y ** el s´ o ımbolo para exponenciaci´n. se usan e todos de la misma forma que en matem´ticas. Operadores y expresiones Los operadores son s´ ımbolos especiales que representan c´lculos simples. la divisi´n de enterios simpre se redondea a la baja. ¿C´mo cambiar´ usted el gui´n para mostrar los o ıa o valores de estas cuatro expresiones? 2. La operaci´n que sigue tiene un resultado inesperado: o o >>> minuto = 59 >>> minuto/60 0 El valor de la variable minuto es 59. -. y 59 dividido entre 60 es 0.

aunque el o a resultado no cambie de todas formas. 2 * (3-1) es igual a 4.2. el orden de evaluaci´n a o o depende de las reglas de precedencia. as´ pues 2**1+1 o a ı es igual a 3 y no a 4. devolviendo tt 5900/60. que es m´s o o a alta que la de la Adici´n y la Sustracci´n. que tienen tambi´n la misma o o e precedencia.7 El orden de las operaciones 17 De nuevo se redondea el resultado a la baja. o Los operadores que tienen la misma precedencia se eval´an de izquierda u a derecha. Exponenciaci´n tiene la siguiente precedencia m´s alta. tiene lugar primero la ı.8. 2. Tambi´n puede usar par´ntesis para que una e e expresi´n sea m´s legible. por ejemplo (minuto * 100) / 60.7. y 3*1**3 es igual a 3 y no a 27. incluso si a las cadenas parecen n´meros. el resultado habr´ sido 59/1 que da 59. Por tanto 2*3-1 devuelve 5 y no 4. El orden de las operaciones Cuando aparece m´s de un operador en una expresi´n. a a Los ingleses usan el acr´nimo PEMDAS como regla parea recordar el orden de o las operaciones: Par´ntesis: tienen la precedencia m´s alta y pueden usarse para forzar que e a una expresi´n se eval´e en el orden que queramos nosotros. Las siguientes sentencias son ilegales (suponiendo u que mensaje sea de tipo string) mensaje-1 "Hola"/123 mensaje*"Hola" "15"+2 . y e u (1+1)**(5-2) es igual a 8. y no 1 (recuerde que en la divisi´n de enteros 2/3 da 0). Puesto que las o u expresiones entre par´ntesis se eval´an primero. pero al menos ahora la respuesta es aproximadamente correcta. Python sigue las mismas reglas de precedencia que los propios matem´ticos para sus operaciones matem´ticas. y 2/3-1 da -1. o multiplicaci´n. y que es incorrecto. o que veremos en el Cap´ ıtulo 3. Si las operaciones se hubiesen realizado de derecha a izquierda. La Multiplicaci´n y la Divisi´n tienen la misma precedencia. Las operaciones sobre cadenas En general no es posible realizar operaciones matem´ticas con cadenas. que a su vez da como resultado o 98. Otra alternativa es la divisi´n de coma flotante. ıa 2. As´ en la expresi´n minuto*100/60.

expresiones y sentencias Es curioso que el operador + funcione con cadenas. y as´ es. lleva a cabo la repetici´n.18 Variables. Por e o ejemplo ’Chiste’*3 es ’ChisteChisteChiste’. el operador + representa la concatenaıa. Por ı otro lado. el otro ha de ser un entero. esperamos o que ’Chiste’*3 sea lo mismo que ’Chiste’+’Chiste’+’Chiste’. ¿Puede encontrar una propiedad que o o tienen la suma y la multiplicaci´n de enteros y que no tengan la concatenaci´n o o y la repetici´n de cadenas? o 2. expresiones y sentencias) por separado. Igual que 4*3 es equivalente a 4+4+4. Por n o ejemplo. no debemos decir “al mismo tiempo”. Por un lado. El operador * tambi´n funciona con cadenas. hora*60+minuto u . la concatenaci´n y la repetici´n son de alguna manera muy diferentes o o de la adici´n y la multiplicaci´n de enteros. sabemos c´mo sumar n´meros y c´mo imprimirlos. y es necesario para introducir el espacio que separa las cadenas concatenadas. lo que significa que se unen los dos operandos uni´ndolos extremo con o e extremo. Ya hemos visto un ejemplo de ello: print "N´mero de minutos desde la medianoche: ". cadenas y variables puede usarse dentro de o u una sentencia print. El espacio delante de pan a es parte de la cadena. Uno de los operandos ha de ser una cadena. pero la cuesti´n es que cualquier o o expresi´n relacionada con n´meros. o Una de las caracter´ ısticas m´s utiles de los lenguajes de programaci´n es su a ´ o capacidad de tomar peque˜os bloques de construcci´n y ensamblarlos. Por ejemplo: fruta = "pl´tano" a bizcochoBueno = " pan de leche" print fruta + bizcochoBueno La salida del programa es pl´tano pan de leche. ci´n.9. sin hablar de c´mo combinarlos. aunque no haga exactamente lo que usted esperar´ Para cadenas. resulta que podeo u o mos hacer las dos cosas a un tiempo: >>> 20 print 17 + 3 En realidad. esta interpretaci´n de + y * cobra sentido por analog´ con la o ıa suma y la multimplicaci´n. Composici´n o Hasta ahora hemos examinado los elementos de un programa (variables. puesto que en realidad la suma tiene que realizarse antes de la impresi´n.

qu´ hace el programa. la parte izquierda de una sentencia de asignaci´n tiene que ser un o nombre de variable. Los lenguajes formales son densos y con frecuencia es a dif´ observar un trozo de c´digo y averiguar lo que hace. pero ya veremos otros ejemplos donde la composici´n hace posible expresar c´lculos complejos con o a limpieza y brevedad. ıcil o e Por ello es una buena idea a˜adir notas a su programa que expliquen. ´ ATENCION: Hay l´ ımites al lugar donde pueden usarse ciertas expresiones. 2. se vuelven n a m´s complicados de leer. o 2.2.10 Los comentarios 19 Y tambi´n puede poner expresiones arbitrarias en la parte derecha de una sene tencia de asignaci´n: o porcentaje = (minuto * 100) / 60 Esta capacidad puede no resultar muy sorprendente. Tambi´n puede poner e comentarios al final de otras l´ ıneas: porcentaje = (minuto * 100) / 60 # ojo: divisi´n de enteros o Todo lo que va del # al final de la l´ ınea se ignora (no tiene efecto sobre el programa). o por qu´ lo hace. Por ejemplo. o a futuros programaa dores que podr´ tener que usar el c´digo. en un n lenguaje natural. El mensaje est´ destinado al programador.10. Los comentarios Conforme los programas van creciendo de tama˜o y complic´ndose. el comentario aparece en una l´ ınea propia.11. o . no una exrpresi´n. Estas notas se llaman comentarios y e se marcan con el s´ ımbolo #: # calcula el porcentaje de la hora que ha pasado ya porcentaje = (minuto * 100) / 60 En este caso. En este caso avisa al lector sobre el ıan o sorprendente comportamiento de la divisi´n de enteros. Glosario valor: un n´mero o cadena (o cualquier otra cosa que se especifique posteu riormente) que puede almacenarse en una variable o calcularse en una expresi´n. Por tanto es ilegal lo siguiente: minute+1 o = hour.

como la sua ma. operadores y valores. destinado a otros o programadores (o cualquiera que lea el c´digo fuente) y que no tiene efecto o sobre la ejecuci´n del programa. ´ divisi´n de enteros: es una operaci´n que divide un entero entre otro y deo o vuelve un entero. las sentencias que hemos vistos son las asignaciones y las sentencias print. La divisi´n de enteros devuelve s´lo el n´mero entero o o u de veces que el numerador es divisible por en denominador. reglas de precedencia: la serie de reglas que especifican el orden en el que las expresiones con m´tiples operadores han de evaluarse. El tipo de un valor determina c´mo puede usarse o en las expresiones.20 Variables. palabra reservada: es una palabra clave que usa el compilador para analizar sint´cticamente los programas. Hasta o o o ahora. u concatenar: unir dos operandos extremo con extremo. sentencia: es una porci´n de c´digo que representa una orden o acci´n. u coma flotante: un formato para representar n´meros con decimales. asignaci´n: sentencia que asigna un valor a una variable. a comentario: un segmento de informaci´n en un programa. composici´n: la capacidad de combinar expresiones sencillas y sentencias haso ta crear sentencias y expresiones compuestas. operador: un s´ ımbolo especial que representa un c´lculo sencillo. o ´ evaluar: simplificar una expresi´n ejecutando las operaciones para entregar un o valor unico. No pueden usarse palabras reservadas. u variable: nombre que hace referencia a un valor. Hasta ahora. o diagrama de estado: representaci´n gr´fica de un conjunto de variables y de o a los valores a los que se refiere. la multiplicaci´n o la concatenaci´n de cadenas. y descarta el resto. def y while como nombres de variables. Dicha combio o naci´n representa un unico valor como resultado. los tipos que hemos visto son enteros (tipo int). por a ejemplo if. o . u expresi´n: una combinaci´n de variables. expresiones y sentencias tipo: un conjunto de valores. con el fin de representar c´lculos complejos de forma concisa. o o operando: uno de los valores sobre los que act´a un operador. n´meros de coma flotante (tipo float) y cadenas (tipo string).

o El valor o variable. u ´ >>> id(3) 134882108 >>> yanira = 3 >>> id(yanira) 134882108 Cada valor tiene un id. llamado el argumento de la funci´n. a >>> nereida = type("32") >>> print nereida <type ’string’> Otro ejemplo m´s: la funci´n id toma como argumento un valor o una variable a o y devuelve un entero que act´a como identificador unico de ese valor.Cap´ ıtulo 3 Funciones 3. Es habitual decir que una funci´n “toma” un argumento y e o “devuelve” un resultado.1. El resultado se llama valor de retorno. Llamadas a funciones Ya hemos visto un ejemplo de una llamada a una funci´n: o >>> type("32") <type ’string’> El nombre de la funci´n es type. El id de una variable es el id del valor al que hace referencia. que es un valor unico relacionado con d´nde se almacena ´ o en la memoria del computador. En lugar de imprimir el valor de retorno. . y muestra el tipo de un valor o de una variable. ha de estar encerrado o entre par´ntesis. podemos asign´rselo a una variable.

El motivo es que se representan de forma distinta dentro del computador.22 Funciones 3. tenemos otra forma de enfrentarnos a la divisi´n de enteros. pero recuerde que e siempre redondea hacia abajo: >>> int(3. minuto / 60.14149) ’3. Conversi´n de tipos o Python proporciona una colecci´n de funciones internas que convierten valores o de un tipo a otro.2.14149’ Pudiera parecer extra˜o que Python distinga entre el valor entero 1 y el valor n de coma flotante 1.14159 Finalmente.14159") 3. si o es posible.3. pero pertenecen u a tipos distintos. Volviendo al ejemplo del cap´ o ıtulo anterior.99999) 3 La funci´n float que convierte enteros y cadenas en n´meros en coma flotante: o u >>> float(32) 32. La funci´n int toma un valor y lo convierte a un entero. suponga que queremos calcular qu´ fracci´n de una hora hab´ transcurrido. Coerci´n de tipos o Ahora que ya sabemos convertir entre tipos. La expresi´n e o ıa o m´s obvia. incluso 59 minutos despu´s de la hora. por lo que el resultado a o es siempre 0. est´ la funci´n str. >>> int("32") 32 >>> int("Hola") ValueError: invalid literal for int(): Hola int tambi´n convierte valores de coma flotante a enteros.0 >>> float("3. que convierte a tipo string: a o >>> str(32) ’32’ >>> str(3. realiza una divisi´n de enteros. o da un error si no es posible. Tal vez representen el mismo n´mero.0. e Una alternativa es convetir minuto a tipo float (coma flotante) y luego efectuar una divisi´n de coma flotante: o . 3.

sin(angulo) . o Antes de poder usar las funciones de un m´dulo. y el log de 0.4 Funciones matem´ticas a >>> minuto = 59 >>> float(minuto) / 60. Primero evaluamos el argumento de la funci´n m´s interna.0 0.4. si uno de o a los operandos matem´ticos es tipo float. obligamos a Python a hacer divisi´n de o coma flotante.1 es -1 a (suponiendo que log indique el logaritmo de base 10). tenemos que especificar el nombre del m´dulo o y el nombre de la funci´n. 3. Luego eval´a la funci´n en s´ misma.571 es 1.571. Un m´dulo es un archivo que contiene una a o colecci´n de funciones agrupadas juntas.log10 (17.1 (si x es igual a 10. Por ejemplo.0) angulo = 1.0). el otro se convierte autom´ticamente a a en float.983333333333 23 O bien podemos sacar provecho de las reglas de la conversi´n autom´tica de o a tipos. El sin (seno) de 1. luego se eval´a la funci´n. (el argumento). Para los operadores matem´ticos. y as´ sucesivamente. A esto se le llama notaci´n o o de punto: decibelio = math. y que haya aprendido a evaluar expresiones como sin(pi/2) y log(1/x). y 1/x es 0.0 0. >>> minuto = 59 >>> minuto / 60. Primero eval´a la expresi´n entre par´ntesis.3. bien mir´ndola en una tabla. tenemos que importarlo: o >>>import math Para llamar a una de las funciones. llamada coerci´n de tipos. bien llevando u o ı a a cabo diversos c´lculos. Este proceso puede aplicarse repetidamente para evaluar expresiones m´s coma plicadas como log(1/sin(pi/2)). o a u o ı Python dispone de un m´dulo matem´tico que proporciona la mayor´ de las o a ıa funciones matem´ticas habituales.983333333333 Al usar un denomidador que es float.5 altura = math. Funciones matem´ticas a Es posible que ya haya visto usted en matem´ticas funciones como sin (seno) y a log. separados por un punto. pi/2 u o e es aproximadamente 1.

log(10. lo divide entre dos y le a˜ade el resultado n al valor de angulo. e Para convertir de grados a radianes. calcule primero el ´ngulo a en radianes y luego halle el seno: grados = 45 angulo = grados * 2 * math. sin y las otras funciones trigonom´tricas (cos.cos(angulo + pi/2) Esta sentencia toma el valor de pi.exp(math. 3.0 math. e o La tercera sentencia halla el seno del valor de la variable angulo. A˜ adir funciones nuevas n Hasta ahora s´lo hemos usado las funciones que vienen incluidas con Python. en base 10.707106781187 3.0)) Esta sentencia encuentra el logaritmo en base e de 10 y luego eleva e a ese exponente. >>> math. Por ejemplo. La creaci´n de nuevas funciones e n o para resolver sus problemas partigulares es una de las cosas m´s utiles de los a ´ lenguajes de programaci´n de prop´sito general.pi / 360.5.sqrt(2) / 2. las funciones de Python se pueden a componer. dividida entre a ız 2. o o .24 Funciones La primera sentencia da a decibelio el valor del logaritmo de 17. puede dividir por 360 y multiplicar por 2*pi. La suma se pasa luego como argumento a la funci´n cos. Hay tambi´n una funci´n llamada log que toma logaritmos en base e. tan. eso quiere decir que se usa una expresi´n como parte de otra.0 0. puede usar cualquier expresi´n como argumento de una funci´n: o o x = math.) toman sus argumentos en radianes. Composici´n o Igual que con las funciones matem´ticas. etc. verificar el resultado compar´ndolo con el de la ra´ cuadrada de 2.6. o Tambi´n puede tomar el resultado de una funci´n y pas´rselo como argumento e o a a otra: x = math. Por o ejemplo.sin(angulo) La constante pi tambi´n es parte del m´dulo math. Si se sabe la geometr´ puede e o ıa. o pero tambi´n es posible a˜adir nuevas funciones. El resultado queda asignado a x. para hallar el seno de 45 grados.

Esta operaci´n se especifica en o o una definici´n de funci´n. que muestra como salida un car´cter a ´ a de nueva l´ ınea (es lo que sucede cuando utiliza una orden print sin argumentos). ya que nos a permite usar funciones sin preocuparnos sobre los detalles de sus definiciones. con la excepci´n de o o que no puede usar las palabras reservadas de Python. ha de proporcionar para usar la e o funci´n nueva. La lista de par´metros a especifica qu´ informaci´n. que lleva a cabo la operaci´n deseada. pero tienen u o que estar indentadas desde el margen izquierdo.6 A˜ adir funciones nuevas n 25 En contextos de programaci´n. Observe el espacio a˜adido que hay entre las dos l´ n ıneas. Las funciones que hemos usado hsta ahora las han o o definido por nosotros. Eso es bueno. Segunda linea. o Puede haber cualquier n´mero de sentencias dentro de la funci´n." The output of this program is Primera linea. entre las l´ ıneas. Llamamos entonces a la funci´n nueva usando la misma sintaxis que usamos o para las funciones internas: print "Primera linea. Contiene una unica sentencia. Si quisi´ramos m´s e a espacios. La sintaxis de la definici´n de una funci´n es: o o def NOMBRE( LISTA DE PARAMETROS ): SENTENCIAS Puede inventarse el nombre que desee para su funci´n. y esas definiciones est´n ocultas. de manera a que su sintaxis es: def nueva_linea(): print Esta funci´n se llama nueva linea." . En los ejemplos de este libro se usar´ una indentaci´n de dos espacios. ¿qu´ har´ e ıamos? Podemos llamar varias veces a la misma funci´n: o print "Primera linea. funci´n es una secuencia de instrucciones con o o nombre.3." nueva_linea() nueva_linea() nueva_linea() print "Segunda linea. en caso de haberla." nueva_linea() print "Segunda linea. Los par´ntesis vac´ indican que no tiene o e ıos par´metros. a o El primer par de funciones que escribiremos no tienen par´metros.

una manera de imprimir nueve l´ o ıneas consecutivas es llamar a tresLineas tres veces. y que o imprima tres nuevas l´ ıneas: def tresLineas(): nueva_linea() nueva_linea() nueva_linea() print "Primera Linea. 2. las cuales est´n todas indentadas con dos o a espacios. adem´s de habitual. y usar palabras de su propia lengua a o en vez de c´digo arcano." tresLineas() print "Segunda Linea. pero este ejemplo demuestra dos: Crear una nueva funci´n le da la oportunidad de dar un nombre a un grupo o de sentencias. ¿C´mo imprio mir´ 27 l´ ıa ıneas nuevas? 3. o Crear una nueva funci´n hace que el programa sea m´s peque˜o. Hasta ahora puede no haber quedar claro por qu´ vale la pena crear todas e estas funciones nuevas. escriba una funci´n llamada nueveLineas que use o tresLineas para imprimir nueve l´ ıneas en blanco.7. Por ejemplo. Puesto que la siguiente sentencia no est´ indentada. Se puede llamar al mismo procedimiento repetidamente. Las funciones simplifican su programa al ocultar c´lculos a complejos detr´s de ´rdenes sencillas." Esta funci´n contiene tres sentencias. o Observe los siguientes puntos con respecto a este programa: 1.26 Funciones O bien podemos escribir una nueva funci´n que llamaremos tresLineas. ´ a Se puede llamar a una funci´n desde dentro de otra funci´n: en este caso o o tresLineas llama a nueva linea. al elimio a n nar c´digo repetitivo. De hecho es bastante util hacerlo. el programa completo o o queda de la siguiente manera: . Como actividad. Python sabe que a no es parte de la funci´n. En realidad hay much´ ısimas razones. Las definiciones y el uso Juntando los fragmentos de c´digo de la secci´n anterior.

8 Flujo de ejecuci´n o def nueva_linea(): print def tresLineas(): nueva_linea() nueva_linea() nueva_linea() print "Primera Linea. Aunque no es habitual. ¿Qu´ ocurre cuando ejecuta el o e programa? 3.3. Las seno tencias se ejecutan a raz´n de una cada vez. Registre qu´ mensaje ´ e de error obtiene usted. a esto se le llama flujo de ejecuci´n. pruebe a tomar la versi´n del programa o que funcionaba y a mover la definci´n de nueva linea m´s abajo o a que la definici´n de tresLineas . Como actividad. la definici´n de la funci´n tiene que ejecutarse antes de la o o primera vez que se la invoque. hasta que se alcanza una o llamada a una funci´n." tresLineas() print "Segunda Linea. o La ejecuci´n comienza siempre por la primera sentencia del programa. Como segunda actividad. pero o recuerde que las sentencias que hay dentro de la funci´n no se ejecutan hasta o que se hace la llamada a la funci´n. tiene que o conocer el orden en el que se ejecutan las sentencias." 27 El presente programa contiene dos definiciones de funciones: nueva linea y tresLineas. en orden. pero el efecto es crear una nueva funci´n. puede definir una o . o Las definiciones de funciones no alteran el flujo de ejecuci´n del programa. Las definiciones de funciones se ejecutan como el resto de sentencias. tiene que crear una funci´n antes de poder ejecutarla. y la definici´n de la o o o funci´n no genera salida. Las sentencias del interior de o la funci´n no se ejecutan hasta que se llama a la funci´n. pruebe a ejecutar este programa moviendo las tres ultimas sentencias al principio del programa. Flujo de ejecuci´n o Para asegurarse de que una funci´n se define antes de su primer uso.8. o Como era de esperar. o En otras palabras.

o o Esto suena bastante sencillo. a e no lo lea desde la parte superior a la inferior. si o o desea encontrar el seno de un n´mero. siga el flujo de ejecuci´n. el flujo salta hasta la primera l´ ınea de la funci´n o a la que se llama. Par´metros y argumentos a Algunas de las funciones internas que hemos usado precisan de argumentos. retomar la ejecuci´n en el punto donde lo dej´. El nombre paso se eligi´ para sugerir que el nombre que le d´ a un par´metro depende de o e a usted. que toma un par´meı o a tro: def imprimeDoble(paso): print paso.9. a . En lugar de eso. podr´ o ıamos vernos obligados a abandonarla e ir a ejecutar sentencias en otra funci´n m´s. Dentro de la funci´n. En lugar ıo o de ir a la siguiente sentencia. sin toma como argumento un valor num´rico. la definici´n de funci´n interior no se o o o ejecuta hasta que no se llama a la funci´n exterior. Pero o a mientras estamos en esta nueva funci´n. o o termina. hasta que se acuerda de que una funci´n puede o llamar a otra. los valores que se le han o pasado se asignan a variables llamadas par´metros. de manera o a que cada vez que se completa una funci´n. ¡podr´ o ıamos salirnos y ejecutar otra funci´n m´s! o a Afortunadamente. ¿Cu´l es la moraleja de toda esta historia? Cuando est´ leyendo un programa. En este caso. o 3. a Python se le da bien tomar nota de d´nde est´. el programa retoma el punto en donde o lo dej´ en la funci´n que hizo la llamada.. ejecuta todas las sentencias que encuentre all´ y vuelve a ı. como pow. u e u As´ pues. Por ejemplo. ı e Algunas funciones toman m´s de un argumento. Mientras estamos en medio de una funci´n. Cuando llega al final del programa..28 Funciones funci´n dentro de otra. tiene que indicar de qu´ n´mero se trata. paso Esta funci´n toma un unico argumento y se lo asigna a un par´metro llamado o ´ a paso. o Las llamadas a funciones son como un desv´ en el flujo de ejecuci´n. a He aqu´ un ejemplo de una funci´n definida por el usuario. El valor del par´metro (en este punto todav´ no tenemos ni idea de cu´l a ıa a ser´) se imprime dos veces. que toma dos argua mentos: la base y el exponente. pero en general es mejor que elija un nombre m´s ilustrativo que paso. seguido por un car´cter de nueva l´ a a ınea. los valores que controlan c´mo la funci´n lleva a cabo su tarea.

Dafne. o >>> imprimeDoble(’Jam´n’*4) o Jam´nJam´nJam´nJam´n Jam´nJam´nJam´nJam´n o o o o o o o o >>> imprimeDoble(math. es mitad laurel mitad ninfa.0 -1. u Las mismas reglas de composici´n que se aplican a las funciones internas se o aplican tambi´n a las funciones definidas por el usuario.. Las variables y los par´metros son locales a Cuando crea una variable dentro de una funci´n.3. aqu´ en imprimeDoble llamamos a todo el mundo o ı paso. Observe un aspecto realmente importante en este caso: el nombre de la variable que pasamos como argumento (latoya) no tiene nada que ver con el nombre del par´metro (paso). la funci´n o o >>> def catDoble(parte1. as´ que puede usar e ı cualquier tipo de expresi´n como argumento de imprimeDoble. parte2): . es mitad laurel mitad ninfa.14159) 3. en la segunda o es un entero. No importa c´mo se llamaba el valor en su lugar original (el a o lugar desde donde se invoc´).10.0 Como de costumbre. >>> . se eval´a la expresi´n antes de ejecutar la funci´n. el argumento es una cadena.. cat = parte1 + parte2 .. y en la tercera es un n´mero de coma flotante.14159 En la primera llamada a la funci´n. Por ejemplo.. es mitad laurel mitad ninfa’ >>> imprimeDoble(latoya) Dafne. de modo u o o que imprimeDoble devuelve Jam´nJam´nJam´nJam´n Jam´nJam´nJam´nJam´n o o o o o o o o en lugar de ’Jam´n’*4’Jam´n’*4. y no puede usarla fuera de ella.cos(math.. o o Asimismo podemos usar una variable como argumento: >>> latoya = ’Dafne. s´lo existe dentro de dicha o o funci´n. 3.10 Las variables y los par´metros son locales a 29 La funci´n imprimeDoble sirve con cualquier tipo (de dato) que se pueda imo primir: >>> imprimeDoble(’Jam´n’) o Jam´n Jam´n o o >>> imprimeDoble(5) 5 5 >>> imprimeDoble(3.pi)) -1.14159 3.. imprimeDoble(cat) .

imprimeDoble fue llamado o por catDoble y a catDoble lo invoc´ main . a 3. Si trat´semos de impria mirla. Die Jesu domine." "Pie Jesu domine." "Pie Jesu domine.11. los concatena y luego imprime el resultado dos veces. Si trata de usarla. pero tambi´n muestran la funci´n a e o la que cada variable pertenece. que es un nombre especial de la o . obtendr´ ıamos un error: >>> print cat NameError: cat Los par´metros tambi´n son locales. Dona eis requiem." El orden de la pila muestra el flujo de ejecuci´n. Dona eis requiem. Cada funci´n se representa por una caja con el nombre de la funci´n junto a o o ´l. Diagramas de pila Para mantener el rastro de qu´ variables pueden usarse y d´nde. Como los diagramas de estado. Dona eis requiem." catDoble(cantus1. Cuando catDoble termina. a veces es util e o ´ dibujar un diagrama de pila. los diagramas de pila muestran el valor de cada variable. Los par´metros y variables que pertenecen a una funci´n van dentro. una vez fuera de la funci´n a e o imprimeDoble. Python se quejar´. el diagrama de stack para el programa anterior tiene este aspecto: __main__ chant1 chant2 catTwice part1 part2 cat printTwice bruce "Pie Jesu domine." "Pie Jesu domine. la variable cat se destruye. Por ejemplo.30 Funciones toma dos argumentos." "Dona eis requiem." "Dona eis requiem. " cantus2 = "Dona eis requiem. no existe nada llamado paso. Dona eis requiem. cantus2) Jesu domine. Podemos llamar a la funci´n con dos cadenas: o >>> >>> >>> Die cantus1 = "Die Jesu domine. Por e a o ejemplo.

12. line 9.py". Cuando crea una variable fuera de cualquier funci´n. Le dice a usted en qu´ archivo de programa sucedi´ el error. pertenece o a o a main .12 Funciones con resultado 31 funci´n m´s alta. Tambi´n muestra la l´ e ınea de c´digo que caus´ el o o error. Si sucede un error durante la llamada a una funci´n. o e ı Por ejemplo. e o o por ejemplo nueva linea() + 7? 2.py". a como nueva linea. provocaremos un NameError: Traceback (innermost last): File "test. Ello o suscita varias preguntas: 1. 3. Funciones con resultado Seguramente ha notado ya que algunas de las funciones que estamos usando. F´ ıjese en la similaridad entre la traza inversa y el diagrama de pila. As´ que parte1 en catDoble tiene el mismo valor que cantus1 en ı main . y as´ hasta main . Otras funciones. in catDoble imprimeDoble(cat) File "test. line 5. y en qu´ l´ e o e ınea. el par´metro se refiere al mismo valor que el argumento corresa pondiente. no lo asigna a una variable ni lo usa como parte de una expresi´n o m´s amplia)? a ¿Qu´ sucede si usa una funci´n sin resultado como parte de una expresi´n. devuelven un resultado. llevan a cabo una acci´n pero no devuelven un valor. ¿Qu´ sucede si llama usted a uana funci´n y no hace nada con el resultado e o (es decir. No es una coincidencia. line 13. cantus2) File "test. si intentamos acceder a cat desde imprimeDoble. y el nombre de la funci´n o o o o que llam´ a ´sa.py". in imprimeDoble print cat NameError: cat Esta lista de funciones de llama traceback (traza inversa). igual que las funciones matem´ticas. Python imprime el nombre o de la funci´n y el nombre de la funci´n que la llam´. En cada caso. y qu´ funciones se e ejecutaban en ese momento.3. . in __main__ catDoble(cantus1.

Glosario llamada a funci´n: Una sentencia que ejecuta una funci´n. perguntar al int´rprete ser´ una buena e a manera de averiguarlo.32 3. o debemos limitarnos a funcinoes simples como nueva linea e imprimeDoble? La respuesta a la tercera pregunta es “s´ puede escribir funciones que devuelvan ı. o o notaci´n de punto: La sintaxis para llamar a una funci´n de otro m´dulo. e argumento: Valor que se le pasa a una funci´n cuando se la llama. y lo haremos en el cap´ ıtulo 5. o o o conversi´n de tipo: Una sentencia expl´ o ıcita que toma un valor de un tipo y calcula el valor correspondiente de otro tipo. o . especificando o o o su nombre. Cada vez que tenga una duda sobre lo que a es legal o ilegal en Python. y o a pueden producir un resultado o no. seguido por un punto y el nombre de o la funci´n. Si se usa una llamada a o funci´n a modo de expresi´n. coerci´n: Conversi´n tipos que ocurre autom´ticamente de acuerdo con las o o a reglas de coerci´n de Python. a o valor de retorno: Es el resultado de una funci´n. valores”. a flujo de ejecuci´n: Orden en el que se ejecutan las sentencias durante la ejeo cuci´n de un programa.13. Como actividad final. o m´dulo: Fichero que contiene una colecci´n de funciones y clases relacionadas. 3. El valor se o asigna al par´metro correspondiente de la funci´n. Est´ compuesta o o a por el nombre de la funci´n m´s una lista de argumentos encerrados entre o a par´ntesis. definici´n de funci´n: Sentencia que crea una nueva funci´n. o funci´n: Secuencia de sentencias etiquetadas que llevan a cabo determinada o operaci´n de utilidad. el valor de retorno es el valor de la expresi´n. Las funciones pueden tomar par´metros o no. Funciones ¿Se pueden escribir funciones que devuelvan resultados. o o o especificando el nombre del m´dulo. consteste a las otras dos preguntas intentando hacerlas en la pr´ctica. par´metros y las sentencias que ejecuta.

3. Las variables locales o s´lo pueden usarse dentro de su funci´n. sus variao a bles y los valores a los que se refieren. presentadas cuando sucede un error en tiempo de ejecuci´n.13 Glosario 33 par´metro: Nombre que se usa dentro de una funci´n para referirse a el valor a o que se le pasa como argumento. variable local: variable definida dentro de una funci´n. o o notaci´n de punto o traza inversa . traza inversa: (traceback en ingl´s) Una lista de las funciones en curso de e ejecuci´n. o o diagrama de pila: Representaci´n gr´fica de una pila de funciones.

.

el operador de m´dulo es el signo de tanto por ciento ( %).1. ı. .Cap´ ıtulo 4 Condicionales y recursividad 4. En Python. La sintaxis es la misma de los o otros operadores: >>> >>> 2 >>> >>> 1 cociente = 7 / 3 print cociente resto = 7 % 3 print resto As´ 7 dividido entre 3 da 2 con 1 de resto. Por ejemplo. El operador m´dulo o El operador m´dulo funciona con enteros (y expresiones enteras). x % 100 devuelve los dos ultimos d´ ´ ıgitos. Tambi´n puede usar el operador m´dulo para extraer el d´ e o ıgito m´s a la derecha a de un n´mero. x % 10 devuelve el d´ u ıgito m´s a la derecha de x (en a base 10). Por ejemplo. El operador de m´dulo resulta ser soprendentemente util. y devuelve o el resto de dividir el primer operando entre el segundo. entonces x es u divisible entre y. De forma similar. puede o ´ comprobar si un n´mero es divisible entre otro: si x % y es cero.

36 Condicionales y recursividad 4. los dos operandos son iguales. Operadores l´gicos o Hay tres operadores l´gicos: and. u Finalmente. no existen =< ni =>. as´ que la expresi´n se ı o eval´a como 1 (verdadero). y una expresi´n que es falsa tiene o o el valor 0. los otros son: o x x x x x != y > y < y >= y <= y # # # # # x x x x x no es es es es es igual a y mayor que y menor que y mayor o igual que y menor o igual que y Aunque probablemente estas operaciones le resulten familiares. o sea. y not. 5 no es igual a 6. Recuerde que = es un operador de asignaci´n y == es un operador de comparaci´n. as´ que u ı obtenemos 0 (falso). El operador == compara dos valores y entrega una expresi´n booleana: o >>> 5 == 5 1 >>> 5 == 6 0 En la primera sentencia. Cualqueir n´mero que u no sea cero se interpreta como “verdadero”.3. x >0 and e x <10 es verdadero s´lo si x es mayor que 0 y menor que 10. los s´ ımbolos en Python son diferentes de los matem´ticos. Por ejemplo. pero Python no es muy estricto. o o a 4. en la segunda sentencia. . el operador not niega una expresi´n booleana. los operandos de los operadores l´gicos deber´ ser o ıan expresiones booleanas. La sem´ntica (significado) de o a estos operadores es similar a sus significados en ingl´s. Expresiones booleanas Una expresi´n booleana es una expresi´n que es cierta o falsa. si x es menor o igual que y. de forma que not(x o >y) es cierto si (x >y) es falso. Un error habitual es utilizar un signo a igual sencillo (=) en lugar del doble (==).2. si el n´mero es divisible por 2 o por 3. En Python. o n %2 == 0 or n %3 == 0 es verdadero si cualquiera de las condiciones es verdadera. Adem´s. o o una expresi´n que es cierta tiene el valor 1. o sea. Hablando estrictamente. El operador == es uno de los operadores de comparaci´n. or.

ıa que no hace nada. En tales casos. y la condici´n determina cu´l de ellas se ejecuta.4.. Las sentencias condicionales nos dan esta capacidad. 4. if consta de una cabecera y un bloque de sentencias: CABECERA: PRIMERA SENTENCIA . La sintaxis o a . Ejecuci´n alternativa o Una segunda forma de la sentencia if es la ejecuci´n alternativa. pero debe haber al menos una. Si es verdadera.4 Ejecuci´n condicional o >>> >>> 1 >>> >>> 0 x = 5 x and 1 y = 0 y and 1 37 En general. Ejecuci´n condicional o Para escribir programas utiles. Los elementos indentados que siguen se llaman bloque de la sentencia. Si quiere comparar un valor con cero. No hay l´ ımite a la cantidad de sentencias que pueden aparecer en el cuerpo de una sentencia if. entonces o o la sentencia indentada se ejecuta. (normalmente como reserva de espacio para algo de c´digo que o todav´ no ha escrito).. o Como otras sentencias compuestas. Un bloque de sentencias dentro de una sentencia compuesta recibe el nombre de cuerpo de la sentencia. puede usted utilizar la sentencia pass.5. en la que hay o dos posibilidades. Si la condici´n no es verdadera. La forma m´s a sencilla es la sentencia if: if x > 0: print "x es positivo" La expresi´n booleana tras el if se llama condici´n. 4. este tipo de cosas no se considera buen estilo. ULITMA SENTENCIA La cabecera comienza con una nueva l´ ınea y termina con el signo de dos puntos. La primera sentencia no indentada marca el fin del bloque. A veces. no pasa nada. deber´ hacerlo expl´ ıa ıcitamente.4. casi siempre necesitamos la capacidad de com´ probar ciertas condiciones y cambiar el comportamiento del programa en consonancia. es util tener un cuerpo ´ sin sentencias.

quiz´ desee “envolver” este c´digo en una funci´n: u a o o def imprimeParidad(x): if x%2 == 0: print x. "es par" else: print x. "es mayor que". Llame a esta funci´n de la u o manera siguiente: >>> imprimeParidad(17) >>> imprimeParidad(y+1) 4. y elif x > y: print x. entonces sabemos que x es par. De nuevo. No o a hay l´ ımite al n´mero de sentencias elif. se ejecutar´ exactamente una de las alternativas. pero s´lo se permite una sentencia u o else (que puede omitirse) y debe ser la ultima rama de la sentencia: ´ if eleccion == ’A’: funcionA() elif eleccion == ’B’: . si piensa que querr´ comprobar con frecuencia la paridad de a n´meros. Una a a forma de expresar tal computaci´n es un conditional encadenado: o if x < y: print x. "es impar" Condicionales y recursividad Si el resto cuando se divide x entre 2 es cero. "y". Llamamos ramas a a las posibilidades porque son ramas del flujo de ejecuci´n.6. Si la condici´n es falsa.38 tiene este aspecto: if x%2 == 0: print x. se o ejecuta el segundo lote de sentencias. "es menor que". y. o Como un aparte. "es par" else: print x. "son iguales" elif es una abreviatura de ”else if”. y else: print x. Puesto que la condici´n debe ser verdadera o o falsa. Condiciones encadenadas A veces hay m´s de dos posibilidades y necesitamos m´s de dos ramas. "es impar" Ahora tiene una funci´n llamada imprimeParidad que muestra el mensaje aproo piado para cada n´mero entero que usted le pase. y este programa muestra un mensaje a tal efecto. s´lo se ejecutar´ una rama.

y as´ Si una de ellas es cierta. envuelva estos ejemplos en funciones llamadas compara(x.4. y ~~~~else: ~~~~~~print x. Los operadores l´gicos suelen facilitar un modo de simplificar las sentencias o condicionales anidadas. y) y resuelve(eleccion). aunque podr´ ser igualmente sentencias condicionales. La primera rama contiene una o sentencia simple de salida. Pod´ o ıamos haber escrito as´ el ı ejemplo de tricotom´ ıa: ~~if x == y: ~~~~print x. y La condici´n externa que contiene dos ramas. o as´ que podemos usar el operador and: ı . se ejecuta la rama correspondiente ı. La segunda rama contiene otra sentencia if. las condio ciones anidadas en seguida se vuelven dif´ ıciles de leer. s´lo se ejecuta a o o la primera rama verdadera. se comprueba la siguiente. y. "y". y termina la sentencia. ıan Aunque la indentaci´n de las sentencias hace la estructura evidente.7. 4. "son iguales" ~~else: ~~~~if x < y: ~~~~~~print x. que tiene dos ramas en s´ misma. "es menor que"." u ı La sentencia print s´lo se ejecuta si conseguimos superar ambos condicionales. Condiciones anidadas Una condici´n puede estar anidada dentro de otra." Las condiciones se comprueban en orden. Por ejemplo. Si la primera es falsa. podemos reescribir el c´digo siguiente con o un s´lo condicional: o if 0 < x: if x < 10: print "x es un n´mero positivo de un d´gito. "es mayor que". Incluso si es cierta m´s de una condici´n. Estas dos ramas son ambas sentencias de salida ı de datos. En general es una buena idea evitarlas cuando pueda.7 Condiciones anidadas 39 funcionB() elif eleccion == ’C’: funcionC() else: print "Eleccion no valida. Como ejercicio.

por lo que Python nos proporciona una sintaxis alternativa similar a la notaci´n matem´tica: o a if 0 < x < 10: print "x es un n´mero positivo de un d´gito.8. Puede no resultar evidente por qu´ es bueno esto. Recursividad Ya mencionamos que es legal que una funci´n llame a otra. en cuyo caso muestra un mensaje de error y luego usa return para salir de la funci´n. y de ello hemos visto o ya varios ejemplos." u ı Esta condici´n es sem´nticamente la misma que la expresi´n booleana compueso a o ta y que el condicional anidado. por favor. Una raz´n para usarla es detectar una condici´n de error: o o import math def imprimeLogaritmo(x): if x <= 0: print "Solo numeros positivos. El flujo de la o ejecuci´n vuelve inmediatamente al llamante y no se ejecutan las l´ o ıneas restantes de la funci´n.40 Condicionales y recursividad if 0 < x and x < 10: print "x es un n´mero positivo de un d´gito. La sentencia return La sentencia return le permite terminar la ejecuci´n de una funci´n antes de o o alcanzar su final." u ı Estos tipos de condiciones son habituales.9.log(x) print "El log de x es". Examine por ejemplo la siguiente funci´n: o . o Recuerde que para usar una funci´n del m´dulo math tiene que importarlo. result La funci´n imprimeLogaritmo toma un par´metro llamado x. pero ı e viene a resultar una de las cosas m´s interesantes y curiosas que puede hacer a un programa. o o 4. Lo primero que o a hace es comprobar si x es menor o igual que cero. 4. Olvidamos mencionar que tambi´n es legal que una funci´n e o se llame a s´ misma." return result = math.

sea un entero positivo. muestra el valor 1.. La cuenta atras que dio n=1 retorna. def nuevaLinea(): print . La cuenta atras que dio n=3 retorna. De manera que la a salida completa presenta el siguiente aspecto: 3 2 1 Despegando! Como segundo ejemplo. o y puesto que n es cero. muestra n y luego llama a la funci´n llamada cuenta atras (ella misma) pas´ndole como arguo a mento n-1. y luego se llama a s´ misma . Y entonces ya est´ de vuelta en main (menudo viaje). muestra el valor 2 y luego se llama a s´ misma . y luego se llama a s´ misma. ı La ejecuci´n de cuenta atras comienza con n=0.. muestra la palabra “Despegando!” y luego retorna.4. ¿Qu´ sucede si llamamos a la funci´n de la siguiente manera? e o >>> cuenta_atras(3) La ejecuci´n de cuenta atras comienza con n=3. da o como salida el valor 3. ı La ejecuci´n de cuenta atras comienza con n=1. y puesto que n no es cero... n. consideremos de nuevo las funciones nuevaLinea and tresLineas.. Si n el par´mea a tro es cero. muestra la palabra “Despegando!”.. La cuenta atras que dio n=2 retorna. En otro caso.9 Recursividad def cuenta_atras(n): if n == 0: print "Despegando!" else: print n cuenta_atras(n-1) 41 cuenta atras espera que su par´metro. y puesto o que n no es cero. y puesto que n no o es cero. ı La ejecuci´n de cuenta atras comienza con n=2.

el n´mero total de nuevas l´ a u ıneas es 1 + (n-1). que si rescata su ´lgebra ver´ que es n. invocada con n = 3: . o ı y dichas funciones se denominan recursivas. En el caso de una o a funci´n recursiva. De esta manera. mientras n sea mayor que cero.42 def tresLineas(): nuevaLinea() nuevaLinea() nuevaLinea() Condicionales y recursividad Aunque todas funcionan. muestra una nueva l´ ınea.10. que contiene sus variables locales y par´metros. a a o Cada vez que se llama a una funci´n. no ser´ de mucha ayuda si quisiera mostrar 2 l´ ıan ıneas nuevas o 106. Diagramas de pila para funciones recursivas El la Secci´n 3. puede haber m´s de un marco en la pila al mismo tiempo. El mismo tipo de diagrama o puede hacer m´s f´cil interpretar una funci´n recursiva.11 utilizamos un diagrama de pila para representar el estado de o un programa durante la llamada de una funci´n. Python crea un nuevo marco para la o funci´n. y luego se llama a s´ misma para mostrar >n-1 nuevas ı l´ ıneas m´s. o a La figura muestra un diagrama de pila para cuenta atras. Una mejor alternativa ser´: a def nLineas(n): if n > 0: print nLineas(n-1) Este programa es parecido a cuenta atras. 4. a a El proceso por el que una funci´n se llama a s´ misma se llama recursividad.

de manera que no hay m´s marcos. y generalmente no se la considera una buena idea.11. a Como actividad.4. line 2. donde n=0. No hace una llamada recursiva. Este es un programa m´ ınimo con recursividad infinita: def recurre(): recurre() El la mayor´ de los entornos de programaci´n. line 2. in recurse RuntimeError: Maximum recursion depth exceeded . Est´ vac´ a a ıa porque no hemos ninguna variable sobre main ni le hemos pasado ning´n u par´metro. un programa con recursividad ıa o infinita no se ejecutar´ realmente para siempre. a Los cuatro marcos de cuenta atras tienen valores diferentes para el par´metro a n.11 Recursividad infinita __main__ countdown countdown countdown countdown n n n n 3 2 1 0 43 Como es habitual. en lo alto de la pila est´ el marco de main . Esta circunstancia se conoce como a recursividad infinita. Python informar´ de un mensaje a a de error cuando se alcance el nivel m´ximo de recursividad: a File "<stdin>". dibuje un diagrama de pila para nLineas. in recurse (98 repetitions omitted) File "<stdin>". invocada con el par´metro n=4. se llama caso base. El fondo de la pila. seguir´ haciendo llamadas reo a cursivas para siempre y nunca terminar´. Recursividad infinita Si una recursi´n no alcanza nunca el caso base. a 4.

se convertir´ en un entero y se u a asignar´ a velocidad. e Puede proporcionarle un indicador a raw input como argumento: >>> nombre = raw_input ("C´mo te llamas? ") o C´mo te llamas? H´ctor. utilice la funci´n input. el proa o grama se detiene y espera a que el usuario escriba algo.. Por desgracia.44 Condicionales y recursividad Esta traza inversa es un poco mayor que la que vimos en el cap´ ıtulo anterior. Simplemente hacen lo mismo siempre. Cuando el usuario pulsa la tecla Return o Enter. Por ejemplo: o >>> indicador = \ . La m´s sencilla se llama raw input. u e 4. escriba una funci´n con recursividad infinita y o ejec´tela en el int´rprete de Python.12. h´roe de los Troyanos! e e Si espera que la entrada sea un entero. hay 100 marcos recurre en la pila! Como actividad. Python proporciona funciones internas que obtienen entradas desde el teclado. generalmente es buena idea usar raw input para obtener una cadena y usar entonces las funciones de conversi´n para convertir o a otros tipos. Cuando llamamos a esta funci´n. si el usuario escribe algo que no sea un a d´ ıgito. . ¡Cuando sucede el error. el programa se reanuda y raw input devuelve lo que el usuario escribi´ como tipo string: o >>> entrada = raw_input () A qu´ est´s esperando? e a >>> print entrada A qu´ est´s esperando? e a Antes de llamar a raw input es conveniente mostrar un mensaje que le pida al usuario el dato solicitado.. el programa dar´ un error: a >>> velocidad = input (indicador) Cu´l es la velocidad de una golondrina sin carga? a Se refiere usted a la golondrina europea o a la africana? SyntaxError: invalid syntax Para evitar este tipo de error. Este mensaje se llama indicador (prompt en ingl´s). h´roe de los Troyanos! o e e >>> print nombre H´ctor. Entrada por teclado Los programas que hemos escrito hasta ahora son un poco maleducados en el sentido de que no aceptan entradas de datos del usuario. "Cu´l es la velocidad de una golondrina sin carga?\n" a >>> velocidad = input (indicador) Si el usuario teclea una cadena de n´meros.

expresi´n booleana: Una exprersi´n que es cierta o falsa. e a sentencia compuesta: Estructura de Python que est´ formado por una cabea cera y un cuerpo. >= y <=. por ejemplo. se˜alado con un signo de tanto por ciento ( %). sentencia condicional: Sentencia que controla el flujo de ejecuci´n de un proo grama dependiendo de cierta condici´n. operador l´gico: Uno de los operadores que combinan expresiones booleanas: o and. o indicador: indicador visual que invita al usuario a introducir datos.13 Glosario 45 4. !=. la rama de una sentencia condicional que o no ocasiona una llamada recursiva. La cabecera termina en dos puntos (:). cuerpo: En una sentencia compuesta.4. ıa bloque: Grupo sentencias consecutivas con el mismo sangrado. Glosario operador m´dulo: Operador. o o operador de comparaci´n: Uno de los operadores que comparan dos valores: o ==. o condici´n: La expresi´n booleana de una sentencia condicional que determina o o qu´ rama se ejecutar´. anidamiento: Una estructura de programa dentro de otra. recursividad: El proceso de volver a llamar a la funci´n que se est´ ejecutando o a en ese momento. or y not. A la larga una recursi´n infinita provocar´ un o a error en tiempo de ejecuci´n.13. o n que trabaja sobre enteros y devuelve el resto cuando un n´mero se divide u entre otro. el bloque de sentencias que sigue a la cabecera de la sentencia. una sentencia condidional dentro de una o ambas ramas de otra sentencia condicional. caso base: En una funci´n recursiva. >. El cuerpo tiene una sangr´ con respecto a la cabecera. recursividad infinita: Funci´n que se llama a s´ misma recursivamente sin o ı alcanzar nunca el caso base. <. .

.

ninguna de las funciones que hemos escrito ha devuelto un valor. que llamaremos funciones productivas. El primer ejemplo es area.1. que devuelve el ´rea de un c´ a ırculo con un radio dado: import math def area(radio): temporal = math.0) altura = radio * math.pi * radio**2 return temporal Ya hemos visto antes la sentencia return. a falta de un nombre mejor.sin(angulo) Pero hasta ahora. o ı podr´ ıamos haber escrito esta funci´n m´s concisamente: o a . han producido resultados.Cap´ ıtulo 5 Funciones productivas 5. como las funciones math o funciones matem´ticas. En este cap´ ıtulo escribiremos funciones que devuelvan valores. pero en una funci´n productiva la o sentencia return incluye un valor de retorno. La expresi´n dada puede ser arbitrariamente complicada. Valores de retorno Algunas de las funciones internas que hemos usado. Llamar a la funci´n genera un a o nuevo valor. que normalmente asignamos a una variable pasa usar como parte de una expresi´n. Esta sentencia quiere decir “retorna inmediatamente de la funci´n y usa la siguiente expresi´n como valor de o o retorno”. as´ pues.exp(1. o import math e = math.

habr´ escrito algue e a nas funcioncillas.2. 5. Desarrollo de programas Llegados a este punto. entonces no se cumple ninguna de ambas condiciones y la funci´n termina sin alcanzar la setencia o return. Tal como vaya escribiendo funciones mayores puede empezar . recibe el nombre de c´digo muerto. si ha hecho los ejercicios. En cuanto se ejecuta una de ellas. a A veces es util disponer de varias sentencias de retorno. y -1 si x <y . una en cada rama de ´ una condici´n: o def valorAbsoluto(x): if x < 0: return -x else: return x Puesto que estas sentencias return est´n en una condici´n alternativa.pi * radio**2 Funciones productivas Por otra parte. la funci´n termina sin a o ejecutar ninguna de las sentencias siguientes. escriba una funci´n comparar que devuelva 1 si x o >y . las variables temporales como temporal suelen hacer m´s a f´cil el depurado. El c´digo que aparece despu´s de una sentencia return o en cualquier otro lugar o e donde el flujo de ejecuci´n no pueda llegar. s´lo se a o o ejecutar´ una de ellas. 0 si x == y . el valor de retorno es un valor especial llamado None: >>> print valorAbsoluto(0) None Como actividad. En este caso. Tambi´n. Por ejemplo: def valorAbsoluto(x): if x < 0: return -x elif x > 0: return x Este programa no es correcto porque si resulta que x vale 0. o o En una funci´n productiva es una buena idea asegurarse de que cualquier posible o recorrido del programa alcanza una sentencia return.48 def area(radio): return math. tendr´ que poder mirar a funciones Python completas ıa y adivinar qu´ hacen.

x2. es util saber la respuesta a o ´ correcta. hemos comprobado que la funci´n es sint´cticamente correco a ta. as´ que podemos empezar a a˜adir l´ ı n ıneas de c´digo..0 Obviamente.. la funci´n no calcula distancias.2 Desarrollo de programas 49 a experimentar m´s dificultades. que es un valor en coma a flotante. Cuando se comprueba una funci´n. especialmente con los errores en tiempo de a ejecuci´n y los sem´nticos. y1 ) y (x2 . return 0. x2. y2): return 0.0 >>> Elegimos estos valores de tal forma que la distancia horizontal sea igual a 3 y la distancia vertical sea igual a 4. Hasta el momento. y2 ).. de esa manera el resultado es 5 (la hipotenusa del tri´ngulo 3-4-5). y2): . vamos a sugerirle una t´cnie ca que llamaremos desarrollo incremental. supongamos que desea encontrar la distancia entre dos puntos. siempre devuelve cero. y1. El objetivo del desarrollo incremental es sustituir largas sesiones de depuraci´n por la adici´n y prueba de o o peque˜as porciones de c´digo en cada vez. dados por las coordenadas (x1 . Pero es o sint´cticamente correcta y se ejecutar´. Por el teorema de Pit´goras. Despu´s de cada cambio o e . tenemos que llamarla con valores de ejemplo: o >>> def distancia(x1. 6) 0. Ya podemos escribir un bosquejo de la funci´n: o def distancia(x1. En otras palabras.0 .5. los dos puntos son los par´metros. podemos a escribir la distancia es: distancia = (x2 − x1 )2 + (y2 − y1 )2 (5. y1. ¿cu´les son las entradas (par´metros) y cu´l es la a a a salida (valor de retorno)? En este caso. lo que significa que podemos probarla a a antes de complicarla m´s. 2. que podemos representar usando a cuatro par´metros.1) El primer paso es considerar qu´ aspecto tendr´ una funci´n distancia en e ıa o Python. n o Por ejemplo. El valor de retorno es la distancia.. a Para comprobar la nueva funci´n. o a Para lidiar con programas de complejidad creciente. >>> distancia(1. 4.

n El siguiente paso en el c´lculo es encontrar las diferencias entre x2 −x1 y y2 −y1 . si hemos importado el m´dulo math. podemos usar la funci´n sqrt ´ o o para calcular y devolver el resultado: def distancia(x1.0 Si la funci´n funciona. def distancia(x1. valga la redundancia. x2.y1 dalcuadrado = dx**2 + dy**2 resultado = math.x1 dy = y2 .0 F´ ıjese en que hemos eliminado las sentencias print que escribimos en el paso anterior. ıa Por ultimo. o a correctamente el primer c´lculo. y1.x1 dy = y2 . las salidas deber´ ser 3 y 4.sqrt(dalcuadrado) return resultado Si esto funciona correctamente. Este c´digo se llama andamiaje porque es util para construir el o ´ programa pero no es parte del producto final. comprobamos de nuevo la funci´n. y2): dx = x2 . Si no. x2. dy return 0.x1 dy = y2 . Ahora calculamos la suma de los cuadarados de dx y dy: def distancia(x1. y1. dalcuadrado return 0. dx print "dy es".50 Funciones productivas incremental. ha terminado. x2. y2): dx = x2 . y2): dx = x2 .y1 dalcuadrado = dx**2 + dy**2 print "dalcuadrado es: ". Si en un momento dado apareo ce un error. a Almacenaremos dichos valores en variables temporales llamadas dx y dy y las imprimiremos. y1. podr´ ser que quisiera ıa usted imprimir el valor de resultado antes de la sentencia return. sabremos d´nde est´ exactamente: en la ultima l´ o a ´ ınea que hayamos a˜adido. . De nuevo querremos ejecutar el programa en este estado y comprobar la salida (que deber´ dar 25). s´lo hay unas pocas l´ a o ıneas que revisar.y1 print "dx es". Si no. Si o ıan es as´ sabemos que la funci´n recibe correctamente los par´metros y realiza ı.

yc. 3. Una vez que el programa est´ funcionando. yp) El segundo paso es encontrar el ´rea de un c´ a ırculo con ese radio y devolverla: resultado = area(radio) return resultado Envolviendo todo esto en una funci´n. Supongamos que el punto central est´ almacenado en las variables xc e yc. Esta habilidad se llama composici´n . se puede llamar a una funci´n a o desde dentro de otra. sabr´ exactamente d´nde est´. utilice el desarrollo incremental para escribir una funci´n de nombre hipotenusa que devuelva la longitud de la hipoo tenusa de un tri´ngulo rect´ngulo. Afortunadamente hay una funci´n.3 Composici´n o 51 Al principio. tal vez prefiera eliminar parte e del andamiaje o aglutinar m´ltiples sentencias en expresiones compuestas. 5. xp. u pero s´lo si eso no hace que el programa sea dif´ de leer. xp. puede que se encuentre escribiendo y depurando trozos mayores. Los aspectos fundamentales del proceso son: 1. El primer paso es hallar el radio a del c´ ırculo. escribiremos una funci´n que tome dos puntos. Composici´n o Como seguramente a estas alturas ya supondr´. Registre cada estado del desarrollo incremental seg´n vaya u avanzando. Si hay un error. a o a Use variables temporales para mantener valores intermedios. deber´ a˜adir solamente una o dos l´ ıa n ıneas de c´digo cada vez. que es la distancia entre los dos puntos.3. o Conforme vaya ganando experiencia. y calcule el ´rea del c´ a ırculo. o Como ejemplo. que realiza esta tarea: o radio = distancia(xc. Comience con un programa que funcione y h´gale peque˜os cambios ina n crementales. obtenemos: o def area2(xc. yc. 2.5. dando como par´metros los dos a a a catetos. distancia. Sin embargo. yc. el proceso de desarrollo incremental puede ahorrarle mucho tiempo de depurado. yp): radio = distancia(xc. xp. el centro del o c´ ırculo y un punto del per´ ımetro. o ıcil Como actividad. yp) resultado = area(radio) return resultado . y a que el punto del per´ ımetro lo est´ en xp e yp. de tal manera que pueda mostrarlos por pantalla y comprobarlos.

podemos hacerlo m´s a a conciso integrando las llamadas a las funciones en una sola l´ ınea: def area2(xc. y2). xp. xp. o Las variables temporales radio y area son utiles para el desarrollo y el depu´ rado. Podemos devolverla directamente. x2. yc. evitando a la vez la sentencia if: def esDivisible(x. y1. escriba una funci´n pendiente(x1. y1) y (x2.4. Funciones booleanas Las funciones pueden devolver valores booleanos. yc. y2) o que devuelva la pendiente de la l´ ınea que atraviesa los puntos (x1. pero una vez que el programa est´ funcionando. e 5. yp): return area(distancia(xc. x2. lo que a menudo es conveniente para ocultar complicadas comprobaciones dentro de funciones. Por ejemplo: def esDivisible(x. Es habitual dar a las funciones booo leanas nombres que suenan como preguntas s´ ı/no. y): return x % y == 0 La siguiente sesi´n muestra a la nueva funci´n en acci´n: o o o >>> 0 >>> 1 esDivisible(6. y2). y): if x % y == 0: return 1 # it’s true else: return 0 # it’s false La funci´n lleva por nombre esDivisible. S´lo puede haber una unica funci´n con un determinado nombre o ´ o dentro de un m´dulo. Podemos reducir el tama˜o de la funci´n aprovech´ndonos del hecho de que n o a la sentencia condicional que hay despu´s del if es en s´ misma una expresi´n e ı o booleana. y2) que devuelva la [[y-intercepta]] de la l´ ınea a trav´s de los puntos (x1. 3) El uso m´s com´n para las funciones booleanas es dentro de sentencias condia u cionales: .52 Funciones productivas Hemos llamado a esta funci´n area2 para distinguirla de la funci´n area definida o o anteriormente. yp)) Como actividad. 4) esDivisible(6. y1. Devuelve 1 ´ 0 para indicar o si la x es o no divisibelo por y. Luego use esta funci´n en una funci´n que se llame o o intercepta(x1. y1) y (x2.

uno de los primeros cient´ ıficos inform´ticos (algunos argumena tar´n que era un matem´tico. etc.5. M´s recursividad a Hasta ahora. se quedar´ confuso. se la conoce como la a tesis de Turing. y): print "x es divisible entre y" else: print "x no es divisible entre y" Puede parecer tentador escribir algo como: if esDivisible(x. Por otra parte. y. Una o definici´n verdaderamente circular no es muy util: o ´ frangoso: adjetivo que describe algo que es frangoso Si usted viera esa definici´n en el diccionario. pero muchos de los cient´ a a ıficos inform´ticos pionea ros comenzaron como matem´ticos). Si estudia un curso de Teor´ de la Computaci´n. los discos. y) == 1: Pero la comparaci´n extra es innecesaria. Una definici´n recursiva es semejante a una definici´n circular. n pero puede que le interese saber que ese subconjunto es ya un lenguaje de programaci´n completo. evaluaremos una serie de funciones matem´ticas que se definen a recursivamente. escriba una funci´n estaEntre(x.5. Probar tal afirmaci´n es un ejercicio nada trivial. o Como actividad. necesitar´ algunas ıa ´rdenes para controlar dispositivos como el teclado. o o en el sentido de que la definici´n contiene una referencia a lo que se define. con esto queremos decir que cualquier cosa que pueda o computarse se puede expresar en este lenguaje. completado por primera vez o por Alan Turing. Para darle una idea de lo que puede hacer con las herramientas que ha aprendido hasta ahora. 53 5. Cualquier programa que se haya escrito alguna vez puede reescribirse utilizando unicamente las caracter´ ´ ısticas del lenguaje que ha aprendido hasta el momento (de hecho. o ıa si ha buscado la definici´n de la funci´n matem´tica factorial. habr´ visto algo o o a a sejemante a lo siguiente: . pero o o eso es todo).5 M´s recursividad a if esDivisible(x. z) que deo vuelva 1 en caso de que y <= x <= z y que devuelva 0 en cualquier otro caso. tendr´ oporıa o a tunidad de ver la prueba. En correspondencia. el rat´n. usted ha aprendido solamente un peque˜o subconjunto de Python.

As´ pues. Junt´ndolos todos. tomamos la segunda rama y calculamos el factorial de n-1. tomamos la primera rama y devolvemos el valor 1 sin hacer m´s llamadas rea cursivas.54 Funciones productivas 0! = 1 n! = n · (n − 1)! Esta definici´n establece que el factoral de 0 es 1. tenemos que hacer una llamada ı recursiva para hallar el factorial de n − 1 y luego multiplicarlo por n: def factorial(n): if n == 0: return 1 else: recursivo = factorial(n-1) resultado = n * recursivo return resultado El flujo de ejecuci´n de este programa es similar al de cuenta atras de la o Secci´n 4.. 3! es 3 veces 2!. tomamos la segunda rama y calculamos el factorial de n-1. que es 6. normalmente podr´ escribir o a un programa de Python para evaluarlo. que es una vez 0!. y que el factorial de cualquier o otro valor... Puesto que 1 no es 0. que es 2 veces 1!. .9. n. y he aqu´ la parte interesante. tomamos la segunda rama y calculamos el factorial de n-1. Si llamamos a factorial con el valor 3: o Puesto que 3 no es 0. Si puede escribir una definici´n recursiva de algo. es n multiplicado por el factorial de n − 1. Puesto que 0 es 0. El primer paso es decidir cu´les son los a par´metros para esta funci´n. 3! es igual a 3 veces 2 veces 1 vez 1. Puesto que 2 no es 0.. todo lo que hemos de hacer es devolver 1: def factorial(n): if n == 0: return 1 En otro caso... Con poco esfuerzo llegar´ a la conclusi´n de que a o a o factorial toma un unico par´metro: ´ a def factorial(n): Si resultase que el argumento fuese 0. ı a .

se convierte en el valor de retorno de la llamada a la funci´n que comenz´ todo el proceso. usted ya practica dicho salto de fe cuando usa funciones internas. Acto de fe Seguir el flujo de ejecuci´n es una de las maneras de leer programas.cos o a math. y el resultado 6. El valor de retorno (1) se multiplica por n. que es 2.6 Acto de fe El valor de retorno (1) se multiplica por n. que es el producto de n por recursivo. En cada marco.exp. 55 El valor de retorno (2) se multiplica por n. Cuando llama a math. y se devuelve el resultado.6. que es 3. De hecho. y se devuelve el resultado. o o He aqu´ el aspecto que tiene el diagrama de pila para esta secuencia de llamadas ı a funci´n: o __main__ 6 factorial factorial factorial factorial n n n n 3 2 1 0 recurse recurse recurse 2 1 1 return return return 6 2 2 1 1 1 Los valores de retorno se muestran seg´n se pasan hacia la parte superior de u la pila. La alternativa es lo que llamamos el “acto de fe”. N´tese que en el ultimo marco las variables locales recursivo y resultado no o ´ existen porque la rama que las crea no se ejecuta. no examina la implementaci´n de o . 5. damos por sentado que la funci´n trabaja correctamente y devuelve o o el valor apropiado. en lugar de seguir el flujo de o ejecuci´n. el valor de retorno es el valor de resultado. que es 1. Cuando llegamos a una funci´n. pero puede o volverse r´pidamente una tarea laber´ a ınitca.5.

Por ejemplo en la Secci´n 5. Cuando lo tenga funcionando. tenderemos a usar la versi´n m´s concisa.4. Lo mismo vale para los programas recursivos. Un ejemplo m´s a En el ejemplo anterior. usamos variables temporales para ir apuntando los resultados y para hacer que el c´digo fuese m´s f´cil de depurar. pero precisamente por eso se llama acto de fe. est´ claro que s´ puede. en lugar de seguir el flujo de ejecuci´n. podremos usar la funci´n sin tener siquiera que volver a mirar el c´digo o o o otra vez. Una vez que nos hayamos u convencido de que dicha funci´n es correcta. es un tanto extra˜o dar por supuesto que la funci´n est´ bien n o a cuando ni siquiera ha acabado de escribirla. multiplic´ndolo por n. el ejemplo m´s com´n de una funci´n matem´tica ree a u o a cursivamente definida es fibonacci. Cuando llegue a la llamada recursiva. devuelve el resultado correcto) y luego preguntarse: “suponiendo que puedo hallar el factorial de n − 1. escribimos una funci´n llamada esDivisible o o que determina si un n´mero es divisible por otro. Traducido a Python. pero podr´ o a a ıamos habernos ahorrado unas cuantas l´ ıneas: def factorial(n): if n == 0: return 1 else: return n * factorial(n-1) De ahora en adelante. comprobando y examinando el o c´digo.7. lo podr´ acortar. ¿puedo hallar el factorial de n?” En este caso. tendr´ que dar por supuesto que o ıa la llamada recursiva funciona (es decir. 5. Lo mismo se aplica cuando llama a una de las funciones programadas por usted. a ı a Por supuesto. pero le recoo a mendamos que utilice la versi´n m´s expl´ o a ıcita mientras se halle desarrollando c´digo.56 Funciones productivas dichas funciones. Simplemente da por sentado que funcionan porque los que escribieron las bibliotecas internas de Python son buenos programadores. que presenta la siguiente definici´n: o f ibonacci(0) = 1 f ibonacci(1) = 1 f ibonacci(n) = f ibonacci(n − 1) + f ibonacci(n − 2). si se siente inspirado. o a Despu´s de factorial. es como sigue: .

Pero si confiamos en el acto de n fe. a a a ı Podemos usar la funci´n type para comparar el tipo del par´metro con el tipo o a de un valor entero conocido (por ejemplo 1). Comprobaci´n de tipos o ¿Qu´ sucede si llamamos a factorial y le damos 1. a a n a Tenemos dos opciones." return -1 elif n == 0: return 1 else: return n * factorial(n-1) . ¿c´mo ha podido ocurrir? o o Hay una condici´n de salida o caso base: cuando n == 0. A partir de ah´ se vuelve m´s y m´s peque˜o. En la primera llamada recursiva. tomemos la segunda.8 Comprobaci´n de tipos o def fibonacci (n): if n == 0 or n == 1: return 1 else: return fibonacci(n-1) + fibonacci(n-2) 57 Si intenta seguir el flujo de ejecuci´n aqu´ incluso para valores relativamente o ı. o podemos hacer que factorial u compruebe el tipo de su par´metro. pero nunca ser´ 0. Pero.5. ı. si da por supuesto que las dos llamadas recursivas funcionan correctamente. podemos asegurarnos de que el par´metro sea positivo: a def factorial (n): if type(n) != type(1): print "El factorial est´ definido s´lo para enteros. El problema es que el o valor de n yerra el caso base.5 como argumento? e >>> factorial (1. En la siguiente vez su valor es -0." a o return -1 elif n < 0: print "El factorial est´ definido s´lo para enteros\ a o positivos. le puede dar un dolor de cabeza. peque˜os de n. a o o y est´ m´s all´ del objetivo de este libro. La primera opci´n se llama funci´n gamma. Podemos intentar generalizar la funci´n factorial para o que trabaje con n´meros de coma flotante. el valor de n es 0.8.5) RuntimeError: Maximum recursion depth exceeded Tiene todo el aspecto de una recursi´n infinita. As´ pues.5. Ya que estamos en ello.5. a 5. entonces estar´ claro que obtiene el resultado correcto al sumarlas juntas.

para indicar a quien hizo la llamada a la funci´n que algo fue mal: o >>> factorial (1. None: Valor especial de Python que devuelven funciones que o bien no tienen sentencia de return o bien tienen una sentencia de return sin argumento. -1 >>> factorial (-2) El factorial esta definido solo para enteros positivos. -1 >>> factorial ("paco") El factorial esta definido solo para enteros. El segundo evita los enteros negativos. o Este programa muestra un patr´n que se llama a veces guardi´n. -1.5) El factorial esta definido solo para enteros.58 Funciones productivas Ahora tenemos tres condiciones de salida o casos base. o o valor de retorno: El valor obtenido como resultado de una llamada a una funci´n. entonces sabemos que n es un entero positivo y podemos probar que la recursi´n termina. a meo a nudo debido a que aparece tras una sentencia de return. andamiaje: El c´digo que se usa durante el desarrollo del programa pero que o no es parte de la versi´n final. En ambos casos. o . a c´digo muerto: Parte de un programa que no podr´ ejecutarse nunca. o o 5. Los guardianes hacen posible demostrar la correcci´n del c´digo. -1 Si pasamos ambas comprobaciones. o variable temporal: Variable utilizada para almacenar un valor intermedio en un c´lculo complejo.9. Las primeras o a dos condicionales act´an como guardianes. desarrollo incremental: Un m´todo de desarrollo de programas que busca e evitar el depurado a˜adiendo y probando una peque˜a cantidad de c´digo n n o en cada paso. Glosario funci´n productiva: Funci´n que devuelve un valor de retorno. se u muestra un mensaje de error y se devuelve un valor especial. El primero filtra los n´meros no enteros. protegiendo al c´digo que sigue de u o los valores que pudieran causar errores.

.9 Glosario 59 guardi´n: Una condici´n que comprueba y maneja circunstancias que pudieran a o provocar un error.5.

.

Asignaci´n m´ ltiple o u Es posible que haya descubierto que es posible hacer m´s de una asignaci´n a a o una misma variable. por eso ambos valores aparecen en la misma l´ ınea.1. . Pero no lo es. es especialmente importante u distinguir entre una sentencia de asignaci´n y una sentencia de igualdad. He aqu´ el aspecto de una asignaci´n m´ltiple en un diagrama de estado: ı o u bruce 5 7 Cuando hay asignaciones m´ltiples a una variable. El efecto de la nueva asignaci´n es redirigir la variable de o manera que deje de remitir al valor antiguo y empieze a remitir al valor nuevo. ya que la primera vez que imprimimos bruno su valor es 5. bruno print bruno print = 5 bruno. Puesto o que Python usa el s´ ımbolo = para la asignaci´n. = 7 bruno La salida del programa es 5 7. es tentador interpretar una o sentencia como a = b como sentencia de igualdad.Cap´ ıtulo 6 Iteraci´n o 6. La coma al final de la primera sentencia print impide que se imprima una nueva l´ ınea en ese punto. y la segunda vez su valor es 7.

La sentencia while Una de las tareas para las que los computadores se usan con frecuencia es la automatizaci´n de tareas repetitivas. pero no o tienen por qu´ quedarse as´ e ı. podr´ suceder que el c´digo sea dif´ de leer y mantener. que tambi´n se llama iteraci´n. entonces a siempre ser´ igual a b. muestra e a la palabra “Despegando!”. Por ejemplo o en matem´ticas si a = 7 entonces 7 = a. en matem´ticas. debe usarla con cuidado. La primera caracter´ a a ıstica que vamos a considerar es la sentencia while.62 Iteraci´n o Para empezar. o Casi podr´ leer una sentencia while como si fuera ingl´s (castellano “mienıa e tras”). ıa o ıcil 6. y por lo tanto ya dejan de ser iguales.o como :=. una sentencia de igualdad es verdadera todo a a el tiempo. Por ser la o e o iteraci´n tan habitual. ´ Este es el aspecto de cuenta atras con una sentencia while: def cuenta_atras(n): while n > 0: print n n = n-1 print "Despegando!" Como eliminamos la llamada recursiva. Hemos visto dos programas. y 7 = a no lo es. En Python. a = 5 b = a a = 3 # a y b son ahora iguales # a y b ya no son iguales La tercera l´ ınea cambia el valor de a pero no cambia el valor de b. la igualdad es commutativa. nLineas y cuenta atras. Pero en Python la sentencia a = 7 es a legal. como <. Cuando llegues a cero. que usan la recursividad para llevar a cabo la repetici´n. se usa para la o asignaci´n un s´ o ımbolo distinto. Quiere decir que “Mientras n sea mayor que cero. Si los o u ´ valores de las variables van cambiando constantemente en distintas partes del programa. contin´a mostrando el u valor de n y despu´s rest´ndole 1 al valor de n.2. una a sentencia de asignaci´n puede hacer que dos variables sean iguales. Python proporciona como lenguaje varias caracter´ o ısticas que la hacen m´s f´cil. para evitar la confusi´n. . o Aunque la asignaci´n m´ltiple es util a menudo. En algunos lenguajes de programaci´n. y la asignaci´n no lo es. Si a = b ahora. esta funci´n no es recursiva. Repetir tareas similares o id´nticas es algo o e que los computadores hacen bien y las personas no hacen tan bien. Y lo que es m´s.

o . Evaluar la condici´n. y luego volver al paso 1. u En el caso de cuenta atras. 2. la secuencia resultante es 3. o el bucle se repetir´ para siempre. 3. Si es par. El cuerpo del bucle debe cambiar el valor de una o m´s variables de manera que. no hay una prueba obvia de que n alcance alguna vez el valor 1. 10. o de que el programa vaya a terminar. a o En cada iteraci´n. podemos probar que el bucle terminar´ porque a sabemos que el valor de n es finito. repetir”. N´tese que si la condici´n es falsa la primera vez que se atraviesa el bucle. Puesto que n a veces aumenta y a veces disminuye. salir de la sentencia while y continuar la o ejecuci´n en la siguiente sentencia.2 La sentencia while 63 M´s formalmente. 1. if n%2 == 0: n = n/2 else: n = n*3+1 # n es par # n es impar La condici´n de este bucle es n != 1. el valor de n se divide entre dos. que es lo que se llama bucle infinito. En caso contrario. son un bucle infinito. aclarar. Si es impar. Este tipo de flujo de llama bucle porque el tercer paso vuelve de nuevo arriba. el valor se sustituye por 3n+1. Por ejemplo. 8. Por ejemplo. el flujo de ejecuci´n de una sentencia while es el siguiente: a o 1. El cuerpo est´ formado por todas las sentencias bajo el encabezado que tienen a el mismo sangrado. 4. 5. Una a infinita fuente de diversi´n para los cient´ o ıficos inform´ticos es la observaci´n de a o que las instrucciones del champ´ “lavar. de manera que el bucle continuar´ hasta o a que n sea 1. Para algunos valores particulares de n. podemos probar la terminaci´n.6. 2. que har´ que la condici´n sea falsa. el programa muestra como salida el valor de n y luego como prueba si es par o impar. la condici´n sea falsa y el bucle termine. En otros casos no es tan f´cil decirlo: a def secuencia(n): while n != 1: print n. o Si la condici´n es falsa (0). y podemos ver que el valor de n disminuye cada vez que se atraviesa el bucle (cada iteraci´n). si el valor de comienzo (el argumento pasado a la secuencia) es 3. devolviendo 0 o 1. las o o sentencias del interior del bucle no se ejecutan nunca. de manera que ea la larga o tenemos que llegar a cero. a llegado el momento. ejecutar cada una de las sentencias en el o cuerpo del bucle while. 16. o Si la condici´n es verdadera (1).

64

Iteraci´n o

si el valor de inicio es una potencia de dos, entonces el valor de n ser´ par cada a vez que se pasa a trav´s del bucle, hasta que lleguemos a 1. El ejemplo anterior e acaba con dicha secuencia, empezando por 16. Dejando aparte valores particulares, la pregunta interesante es si podemos probar que este programa terminar´ para todos los valores de n. Hasta la fecha, a nadie ha sido capaz de probarlo o negarlo. Como actividad, reescriba la funci´n nLines de la secci´n 4.9 utilio o zando iteraci´n en lugar de recursividad. o

6.3.

Tablas

Una de las cosas para las que resultan buenos los bucles es para generar datos tabulares. Antes de que los computadores estuvieran disponibles de forma masiva, la gente ten´ que calcular a mano logaritmos, senos, cosenos y otras funciones ıa matem´ticas. Para facilitarlo, los libros de matem´ticas conten´ largas tablas a a ına donde aparec´ los valores de estas funciones. Confeccionar estas tablas era ıan una tarea lenta y pesada, y el resultado estaba lleno de erratas. Cuando los computadores aparecieron en escena, una de las primeras reacciones fue “¡Qu´ bueno! Podemos usar los computadores para generar las tablas, as´ no e ı habr´ errores”. Result´ cierto (casi), pero no se vio m´s all´. Poco despu´s los a o a a e computadores y las calculadoras cient´ ıficas se hicieron tan ubicuas que las tablas resultaron obsoletas. Bueno, casi. Resulta que para ciertas operaciones, los computadores usan tablas para obtener un valor aproximado, y luego ejecutan c´lculos para mejorar la a aproximaci´n. En algunos casos, ha habido errores en las tablas subyacentes; el o m´s famoso estaba en la tabla que el Pentium de Intel usaba para llevar a cabo a la divisi´n de coma flotante. o Aunque una tabla logar´ ıtmica ya no es tan util como lo fuera anta˜o, todav´ ´ n ıa constituye un buen ejemplo de iteraci´n. El siguiente programa muestra una o secuencia de valores en la columna izquierda y sus logaritmos en la columna derecha: x = 1.0 while x < 10.0: print x, ’\t’, math.log(x) x = x + 1.0 El \t representa un car´cter de tabulaci´n. a o

6.3 Tablas

65

Tal como se van mostrando en la pantalla caracteres y cadenas, un se˜alador n invisible llamado cursor lleva la cuenta de d´nde ir´ el pr´ximo car´cter. Tras o a o a una sentencia print, el cursor va normalmente al principio de la l´ ınea siguiente. El car´cter de tabulaci´n hace que el cursor se desplace a la derecha hasta que a o alcance uno de los marcadores de tabulaci´n. Los tabuladores son utiles para o ´ alinear columnas de texto, como en la salida del programa anterior: 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 0.0 0.69314718056 1.09861228867 1.38629436112 1.60943791243 1.79175946923 1.94591014906 2.07944154168 2.19722457734

Si estos valores le parecen raros, recuerde que la funci´n log usa como base e. o Debido a que las potencias de dos son muy importantes en las ciencias de la computaci´n, generalmente querremos hallar los logaritmos en relaci´n con la o o base dos. Para llevarlo a cabo, podemos usar la siguiente f´rmula: o log2 x = Cambiar la sentencia de salida a: print x, ’\t’, devuelve 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 0.0 1.0 1.58496250072 2.0 2.32192809489 2.58496250072 2.80735492206 3.0 3.16992500144 math.log(x)/math.log(2.0) loge x loge 2 (6.1)

Podemos ver que 1, 2, 4 y 8 son potencias de dos, porque sus logaritomos de base 2 son n´meros enteros. Si quisi´ramos encontrar los logaritmos de otras u e potencias de dos, podr´ ıamos modificar el programa de la siguiente manera: x = 1.0 while x < 100.0:

66 print x, ’\t’, math.log(x)/math.log(2.0) x = x * 2.0

Iteraci´n o

Ahora, en lugar de a˜adir algo a x cada vez que atravesamos el bucle, que n devuelve una secuencia aritm´tica, multiplicamos x por algo, devolviendo una e secuencia geom´trica. El resultado es: e 1.0 2.0 4.0 8.0 16.0 32.0 64.0 0.0 1.0 2.0 3.0 4.0 5.0 6.0

Debido a que usamos caracteres de tabulaci´n entre las columnas, la posici´n de o o la segunda columna no depende del n´mero de d´ u ıgitos de la primera columna. Las tablas logar´ ıtimicas quiz´s ya no sean utiles, pero conocer las potencias de a ´ dos no ha dejado de serlo para los cient´ ıficos inform´ticos. a Como actividad, modifique el programa para que muestre las potencias de dos hasta 65536 (es decir, 216 ). Impr´ ımala y memor´ ıcela. El car´cter de barra invertida en ’\t’ indica el principio de una secuencia de a escape. Las secuencias de escape se usan para representar caracteres invisibles como tabulaciones y retornos de carro. La secuencia \n representa un retorno de carro. Una sentencia de escape puede aparecer en cualquier lugar de una cadena; en el ejemplo, la secuencia de escape del tabulador es la unica de la cadena. ´ ¿C´mo cree que puede representar una barra invertida en una cadena? o Como ejercicio, escriba un unica cadena que ´ presente esta salida.

6.4.

Tablas de dos dimensiones

Una tabla de dos dimensiones es una tabla en la que Usted elige una fila y una columna y lee el valor de la intersecci´n. Un buen ejemplo es una tabla de o

6.5 Encapsulado y generalizaci´n o

67

multiplicar. Supongamos que desea imprimir una tabla de multiplicar para los valores del 1 al 6. Una buena manera de comenzar es escribir un bucle sencillo que imprima los m´ltiplos de 2, todos en una l´ u ınea. i = 1 while i <= 6: print 2*i, ’\t’, i = i + 1 print La primera l´ ınea inicializa una variable lllamada i, que actuar´ como contador, a o variable de bucle. Conforme se ejecuta el bucle, el valor de i se incrementa de 1 a 6. Cuando i vale 7, el bucle termina. Cada vez que se atraviesa el bucle, imprimimos el valor 2*i seguido por tres espacios. De nuevo, la coma de la sentencia print suprime el salto de l´ ınea. Despu´s de e completar el bucle, la segunda sentencia print crea una l´ ınea nueva. La salida de este programa es: 2 4 6 8 10 12

Hasta ahora, bien. El siguiente paso es encapsular y generalizar.

6.5.

Encapsulado y generalizaci´n o

Por “encapsulado” generalmente se entiende tomar una pieza de c´digo y envolo verla en una funci´n, permiti´ndole obtener las ventajas de todo aquello para o e lo que valen las funciones. Hemos visto dos ejemplos de encapsulado, cuando escribimos imprimeParidad en la Secci´n 4.5 y esDivisible en la Secci´n 5.4. o o Por “generalizaci´n” entendemos tomar algo espec´ o ıfico, como imprimir los m´ltiu plos de 2, y hacerlo m´s general, como imprimir los m´ltiplos de cualquier entero. a u He aqu´ una funci´n que encapsula el bucle de la secci´n anterior y la generaliza ı o o para imprimir m´ltiplos de n. u def imprimeMultiplos(n): i = 1 while i <= 6: print n*i, ’\t’, i = i + 1 print

68

Iteraci´n o

Para encapsular, todo lo que hubimos de hacer fue a˜adir la primera l´ n ınea, que declara el nombre de la funci´n y la lista de par´metros. Para generalizar, todo o a lo que tuvimos que hacer fue sustituir el valor 2 por el par´metro n. a Si llamamos a esta funci´n con el argumento 2, obtenemos la misma salida que o antes. Con el argumento 3, la salida es: 3 4 6 8 9 12 12 16 15 20 18 24 y con argumento 4, la salida es A estas alturas es probable que haya adivinado c´mo vamos a imprimir una o tabla de multiplicaci´n: llamaremos a imprimeMultiplos repetidamente con o diferentes argumentos. De hecho, podemos a usar otro bucle: i = 1 while i <= 6: imprimeMultiplos(i) i = i + 1 Observe hasta qu´ punto este bucle es similar al que hay en el interior de e imprimeMultiplos. Todo lo que hicimos fue sustituir la sentencia print por una llamada a una funci´n. o La salida de este programa es una tabla de multiplicaci´n: o 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 5 10 15 20 25 30 6 12 18 24 30 36

6.6.

M´s encapsulaci´n a o

Para dar m´s ejemplos de encapsulaci´n, tomaremos el c´digo del final de la a o o Secci´n 6.5 y lo envolveremos en una funci´n: o o def imprimeTablaMult(): i = 1 while i <= 6: imprimeMultiplos(i) i = i + 1 El proceso que mostramos aqu´ es un plan de desarrollo habitual. Se desaı rrolla gradualmente el c´digo a˜adiendo l´ o n ıneas fuera de cualquier funci´n o en o

6.7 Variables locales

69

el int´rprete. Cuando conseguimos que funcionen, se extraen y se envuelven en e una funci´n. o Este plan de desarrollo es especialmente si, al comenzar a escribir, no sabe c´mo dividir el programa en funciones. Este enfoque le permite dise˜arlo sobre o n la marcha.

6.7.

Variables locales

Quiz´ se est´ preguntando c´mo podemos usar la misma variable tanto en a e o imprimeMultiplos como en imprimeTablaMult. ¿No habr´ problemas cuana do una de las funciones cambie los valores de la variable? La respuesta es no, ya que la variable i en imprimeMultiplos y la variable i in imprimeTablaMult no son la misma variable. Las variables creadas dentro de una funci´n son locales. No puede acceder a una o variable local fuera de su funci´n “hu´sped”. Eso significa que es posible tener o e m´ltiples variables con el mismo nombre, siempre que no est´n en la misma u e funci´n. o El diagrama de pila de esta funci´n muestra claramente que las dos variables o llamadas i no son la misma variable. Pueden referirse a diferentes valores, y cambiar uno no afecta al otro.
printMultTable i 1 2 3 1 2

printMultiples n 3 i

El valor de i en imprimeTablaMult va desde 1 hasta 6. En el diagrama, resulta ser 3. El pr´ximo recorrido del bucle ser´ 4. En cada recorrido del bucle, o a imprimeTablaMult llama a imprimeMultiplos con el valor actual de i como argumento. Ese valor se asigna al par´metro n. a Dentro de imprimeMultiplos, el valor de i va desde 1 hasta 6. En el diagrama, resulta ser 2. Los cambios en esta variable no tienen ning´n efecto sobre el valor u de i en imprimeTablaMult. Es habitual y perfectamente legal tener diferentes variables locales con el mismo nombre. En especial, los nombres i, j y k se suelen usar como variables de

M´s generalizaci´n a o Como otro ejemplo de generalizaci´n. obtenemos: 1 2 3 4 5 6 7 2 4 6 8 10 12 14 3 6 9 12 15 18 21 4 8 12 16 20 24 28 5 10 15 20 25 30 35 6 12 18 24 30 36 42 lo que es correcto. excepto por el hecho de que seguramente queremos que la tabla est´ cuadrada. llamaremos tambi´n a este par´metro mayor. con el mismo n´mero de filas que de columnas. para demostrar o e a que diferentes funciones pueden tener par´metros con el mismo nombre (al igual a que las variables locales). Podr´ a˜adir un par´metro a imprimeTablaMult: ıa n a def imprimeTablaMult(mayor): i = 1 while i <= mayor: imprimeMultiplos(i) i = i + 1 Hemos sustituido el valor 6 con el par´metro mayor. y no s´lo la tabla de o n o 6x6.70 Iteraci´n o bucle. ’\t’. mayor): int i = 1 while i <= mayor: print n*i. Si evita usarlas en una funci´n porque las utiliz´ en alg´n otro lugar. imagine que desea un programa que imo prima una tabla de multiplicaci´n de cualquier tama˜o. Aqu´ tenemos el programa completo: ı def imprimeMultiplos(n. ıa S´lo para fastidiar.8. a fin de especificar cu´ntas n a a columnas tendr´ que tener la tabla. a˜adimos otro par´metro a imprimeMultiplos. i = i + 1 print def imprimeTablaMult(mayor): int i = 1 while i <= mayor: . o o u probablemente consiga que el programa sea m´s dif´ de leer. Para hacere u lo. Si ahora se llama a a imprimeTablaMult con el argumento 7. a ıcil 6.

o 6. siga o trace la ejecuci´n de esta nueva versi´n de o o imprimeTablaMult para hacerse una idea de c´mo funciona. Puede que ya se est´ preguntando qu´ cosas son e e exactamente. o Seg´n lo esperado.6. mayor) por imprimeMultiplos(i. i) y obtendr´ a 1 2 3 4 5 6 7 4 6 8 10 12 14 9 12 15 18 21 16 20 24 28 25 30 35 36 42 49 Como actividad. este programa genera una tabla cuadrada de 7x7: u 1 2 3 4 5 6 7 2 4 6 8 10 12 14 3 6 9 12 15 18 21 4 8 12 16 20 24 28 5 10 15 20 25 30 35 6 12 18 24 30 36 42 7 14 21 28 35 42 49 Cuando generaliza correctamente una funci´n. Por ejemplo. porque ab = ba. Para hacerlo. Cambie imprimeMultiplos(i. a menudo se encuentra con que o el programa resultante tiene capacidades que Usted no pensaba. quiz´ observe que la tabla de multiplicaci´n es sim´trica.9. y tuvimos tambi´n que cambiar el o o e lugar donde se llama a la funci´n en imprimeTablaMult. tuvimos que cambiar la primera l´ o n a ınea de la funci´n (el encabezado de la funci´n). He aqu´ algunas de las razones por las que las funciones son utiles: ı ´ . de a o e manera que todas las entradas de la tabla aparecen dos veces. Funciones Hasta el momento hemos mencionado en alguna ocasi´n “todas las cosas para o las que sirven las funciones”. mayor) i = i + 1 71 N´tese que al a˜adir un nuevo par´metro. Puede ahorrar tinta imprimiendo s´lo la mitad de la tabla.9 Funciones imprimeMultiplos(i. s´lo tiene que cambiar o o una l´ ınea de imprimeTablaMult.

depurarlas aisladamente. cursor: Un marcador invisible que sigue el rastro de d´nde se imprimir´ el o a siguiente car´cter. nueva l´ ınea: Un car´cter especial que hace que le cursor se mueva al inicio de a la siguiente l´ ınea.72 Iteraci´n o Al dar un nombre a una secuencia de sentencias. Una vez escritas y depuradas. Glosario asignaci´n m´ ltiple: Hacer m´s de una asignaci´n a la misma variable duo u a o rante la ejecuci´n de un programa. o bucle: Sentencia o grupo de sentencias que se ejecutan repetidamente hasta que se cumple una condici´n de terminaci´n. a encapsular: Dividir un programa largo y complejo en componentes (como las funciones) y aislar los componentes unos de otros (por ejemplo usando variables locales). hace que su programa sea m´s f´cil de leer y depurar. . o o bucle infinito: Bucle cuya condici´n de terminaci´n nunca se cumple. variable de bucle: Variable que se usa para determinar la condici´n de tero minaci´n de un bucle. a secuencia de escape: Car´cter de escape (\) seguido por uno o m´s caracteres a a imprimibles. y luego recomponerlas en un todo. puden reutilizarse.10. 6. o o cuerpo: Las sentencias que hay dentro de un bucle. que se usan para designar un car´cter no imprimible. o iteraci´n: La ejecuci´n repetida de un conjunto de sentencias por medio de o o una llamada recursiva a una funci´n o un bucle. o Las funciones bien dise˜adas son generalmente utiles para m´s de un pron ´ a grama. Las funciones facilitan tanto la recursividad como la iteraci´n. a a Dividir un programa largo en funciones le permite separar partes del programa. o tabulador: Car´cter especial que hace que el cursor se mueva hasta la siguiente a marca de tabulaci´n en la l´ o ınea actual.

6. . La generalizaci´n hace el c´digo m´s vers´til.10 Glosario 73 generalizar: Sustituir algo innecesariamente espec´ ıfico (como es un valor constante) con algo convenientemente general (como es una variable o par´mea tro). y luego encapsularlas y generalizarlas. hemos mostrado un estilo de desarrollo basado en desarrollar c´digo para o hacer cosas simples y espec´ ıficas. a a plan de desarrollo: Proceso para desarrollar un programa. m´s apto para reutilio o a a a zarse y algunas veces incluso m´s f´cil de escribir. En este cap´ ıtulo.

.

Cuando mostramos letra. entre los corchetes: o . float.1. nos encontramos con una sorpresa: a La primera letra de "banana" no es a.Cap´ ıtulo 7 Cadenas 7. los cient´ ıficos de la computaci´n siempre empiezan a o contar desde cero. y la 2-´sima (“dos´sima”) letra es n. La 0-sima letra (“cer´sima”) de "banana" es b. podemos querer tratar un tipo e compuesto como una unica cosa o acceder a sus partes. a >>> fruta = "banana" >>> letra = fruta[1] >>> print letra La expresi´n fruta[1] selecciona el car´cter n´mero 1 de fruta. A no ser que usted sea un programador. e e e Si quiera la cer´sima letra de una cadena. Dependiendo de qu´ estemos haciendo. Los tipos que comprenden piezas menores se llaman tipos de datos compuestos. simplemente pone 0. ´ u ´ El operador corchete selecciona un car´cter suelto de una cadena. La variable o a u letra apunta al resultado. Las cadenas son cuantitativamente diferentes de los otros dos porque est´n hechas de piezas a menores: caracteres. o cualquier o expresi´n de valor 0. La 1-´sima o e (“un´sima”) es a. Esta ambig¨edad es util. Por perversas razones. y string. Un tipo de datos compuesto Hasta el momento hemos visto tres tipos: int.

La raz´n es que no hay una sexta letra en o "banana". de ah´ el nombre. o 7. o ´ fruta[-2] nos da la pen´ltima. podemos usar ´ ındices negativos. Provoca un error en tiempo de ejecuci´n IndexError: a o string index out of range. Puede ser cualquier a ı expresi´n entera.2. que cuentan hacia atr´s a desde el final de la cadena.3.76 >>> letra = fruta[0] >>> print letra b Cadenas A la expresi´n entre corchetes se le llama ´ o ındice. Una e o forma de codificar un recorrido es una sentencia while: indice = 0 while indice < len(fruta): letra = fruta[indice] . las seis letras est´n numeradas a del 0 al 5. Un ´ ındice identifica a un miembro de un conjunto ordenado. Este patr´n de proceso se llama recorrido. Para obtener el ultimo car´cter tenemos que restar 1 de longitud: ´ a longitud = len(fruta) ultima = fruta[longitud-1] De forma alternativa. en este caso el conjunto de caracteres de la cadena. seleccionan cada car´cter por turno. Como empezamos a contar por cero. Longitud La funci´n len devuelve el n´mero de caracteres de una cadena: o u >>> fruta = "banana" >>> len(fruta) 6 Para obtener la ultima letra de una cadena puede sentirse tentado a probar algo ´ como esto: longitud = len(fruta) ultima = fruta[longitud] # ERROR! Eso no funcionar´. 7. La expresi´n fruta[-1] nos da la ultima letra. hacen algo a con ´l y siguen hasta el final. Recorrido y el bucle for Muchos c´lculos incluyen el proceso de una cadena car´cter a car´cter. A mea a a nudo empiezan por el principio. El ´ ındice indica cu´l quiere usted. y as´ u ı.

los nombres de los patitos son Jack. El ultimo car´cter al que se accede es el que tiene el ´ ´ a ındice len(fruta)-1. La condici´n del bucle es indice < len(fruta).7. y Quack. Por ejemplo. que es el ultimo car´cter de la cadena. esto no es del todo correcto. porque “Ouack” y “Quack” no est´n a correctamente escritos. en el libro e de Robert McCloskey Make Way for Ducklings (Dejad paso a los patitos). una por l´ ınea. Nack. la condici´n es falsa y no se ejecuta el cuerpo del o bucle. . ´ a Como ejercicio.3 Recorrido y el bucle for print letra indice = indice + 1 77 Este bucle recorre la cadena y muestra cada letra en una l´ ınea distinta. Pack. Este bucle saca esos nombres en orden: prefijos = "JKLMNOPQ" sufijo = "ack" for letra in prefijos: print letra + sufijo La salida del programa es: Jack Kack Lack Mack Nack Oack Pack Qack Por supuesto. Es tan habitual usar un ´ ındice para recorrer un conjunto de valores que Python facilita una sintaxis alternativa m´s simple: el bucle for: a for car in fruta: print car Cada vez que recorremos el bucle. se asigna a la variable car el siguiente car´cter a de la cadena. u El ejemplo siguiente muestra c´mo usar la concatenaci´n junto a un bucle for o o para generar una serie abeced´rica. Ouack. escriba una funci´n que tome una cadena como aro gumento y entregue las letras en orden inverso. Lack. Kack. de modo que cuando indice es o igual a la longitud de la cadena. “Abeced´rica” es la serie o lista en la que a a cada uno de los elementos aparece en orden alfab´tico. Mack. El bucle contin´a hasta que no quedan caracteres.

Comparaci´n de cadenas o Los operadores de comparaci´n trabajan sobre cadenas.4. Pablo. la porci´n llega al final de la o cadena. Para ver si dos cadenas o son iguales: . Si omite el segundo ´ ındice. modifique el programa para corregir este error. Porciones de cadenas Llamamos porci´n a un segmento de una cadena. As´ ı: >>> fruta = "banana" >>> fruta[:3] ’ban’ >>> fruta[3:] ’ana’ ¿Qu´ cree usted que significa s[:]? e 7.5. incluyendo el primero pero excluyendo el ultimo.78 Como ejercicio. como en el siguiente diagrama: n fruta indice "banana" 0 1 2 3 4 5 6 Si omite el primer ´ ındice (antes de los dos puntos). la porci´n comienza al o principio de la cadena. La selecci´n de una porci´n o o o es similar a la selecci´n de un car´cter: o a >>> s = "Pedro. Cadenas 7. tiene m´s sentido si imagina los o a ´ ındices se˜alando entre los caracteres. y Mar´a" ı >>> print s[0:5] Pedro >>> print s[7:12] Pablo >>> print s[15:20] Mar´a ı El operador [n:m] devuelve la parte de la cadena desde el en´simo car´cter e a hasta el “em´simo”. Este come ´ portamiento contradice a nuestra intuici´n.

este c´digo presenta el siguieno te error en tiempo de ejecuci´n TypeError: object doesn’t support item o assignment. Como resultado de ello: u Tu palabra. lo que significa que no puede cambiar una cadena existente." + palabra + ". va antes de banana." e else: print "S´.6.6 Las cadenas son inmutables if palabra == "banana": print "S´. Todas las may´suculas van antes de la u u min´sculas. mundo" nuevoSaludo = ’M’ + saludo[1:] print nuevoSaludo . Las cadenas son inmutables Es tentador usar el operador [] en el lado izquierdo de una asignaci´n. 7. Zapato. va antes de banana." elif palabra > "banana": print "Tu palabra. va despu´s de banana. no tenemos bananas!" ı 79 Otras operaciones de comparaci´n son utiles para poner palabras en orden alo ´ fab´tico: e if palabra < "banana": print "Tu palabra. con la o intenci´n de cambiar un car´cter en una cadena. no tenemos bananas!" ı Sin embargo. Una forma com´n de abordar este problema es convertir las cadenas a un formau to est´ndar. Por ejemplo: o a saludo = "Hola. Las cadenas son inmutables. deber´ usted ser consciente de que Python no maneja las may´scuıa u las y min´sculas como lo hace la gente. mundo. mundo" saludo[0] = ’M’ print saludo # ERROR! En lugar de presentar la salida Mola." + palabra + ". a u o Un problema mayor es hacer que el programa se d´ cuenta de que los zapatos e no son frutas.7. como pueden ser las min´sculas. antes de realizar la comparaci´n. Lo m´s que puede hacer es crear una nueva cadena que sea una a variaci´n de la original: o saludo = "Hola.

modifique la funci´n encuentra para que acepte o un tercer par´metro. Una funci´n “encuentra” o ¿Qu´ hace la siguiente funci´n? e o def encuentra(cad. el ´ a ındice de la cadena donde deber´ empezar a ıa buscar. toma un car´cter y encuentra a a el ´ ındice donde aparece el car´cter. Si el car´cter no aparece en la cadena. A modo de ejercicio. o 7. Este patr´n de computaci´n se llama a veces un recorrido “eureka” porque en o o cuanto encontramos lo que buscamos. encuentra es lo contrario del operador []. 7. Bucles y conteo El programa que sigue cuenta el n´mero de veces que la letra a aparece en una u cadena: .7. podemos gritar “¡Eureka!” y dejar de buscar. el programa sale del bucle normalmente a y devuelve -1. la funci´n vuelve inmediatamente. Si el car´cter no se encuentra. Este es el primer ejemplo que hemos visto de una sentencia return dentro de un bucle.80 Cadenas Aqu´ la soluci´n es concatenar una nueva primera letra a una porci´n de saludo. c): indice = 0 while indice < len(cad): if cad[indice] == c: return indice indice = indice + 1 return -1 En cierto sentido. escapando o del bucle prematuramente. En lugar de tomar un ´ ındice y extraer el car´cter correspondiente. Si cad[indice] == c.8. ı o o Esta operaci´n no tiene efectos sobre la cadena original. la funci´n a a o devuelve -1.

Para llamarla debemos especificar el nombre o del m´dulo y el nombre de la funci´n por medio de la notaci´n de punto. reescriba esta funci´n para que en luo gar de recorrer la cadena. Como es o ´ habitual. a Como un segundo ejercicio.) Al salir del bucle. Al usar la notaci´n de punto podr´ o ıamos especificar qu´ versi´n de e o find queremos en caso de haberle daddo un nombre en ingl´s a nuestra funci´n. que es un nombre. o cuenta contiene el resultado – el n´mero total de aes. a o puede encontrar subcadenas. 7. "a") >>> print indice 1 Este ejemplo demuestra uno de los beneficios de los m´dulos: ayudan a evitar o las colisiones entre los nombres de las funciones predefinidas y las definidas por el usuario. es lo contario de decrementar. o o o >>> fruta = "banana" >>> indice = string. no s´lo caracteres: o . Para empezar. u Como ejercicio. use la versi´n de tres par´metros de o a encuentra del anterior. El m´dulo “string” o El m´dulo string contiene funciones utiles para manipular cadenas. y sin relaci´n alguna con “excremento”.find es m´s general que nuestra versi´n. (Incrementar es aumentar en uno. tenemos que importar el m´dulo antes de poder usarlo: o >>> import string El m´dulo string incluye una funci´n llamada find que hace lo mismo que la o o funci´n encuentra que escribimos.find(fruta. e o En realidad.9.7. string. y general´ ıcela de forma que acepte la cadena y la letra como par´metros. encapsule este c´digo en una funci´n llamada o o cuentaLetras. La o o variable cuenta se incializa a 0 y luego se incrementa cada vez que se encuentra una a.9 El m´dulo “string” o fruta = "banana" cuenta = 0 for car in fruta: if car == ’a’: cuenta = cuenta + 1 print cuenta 81 Este programa muestra otro patr´n de computaci´n llamado contador.

lowercase contiene todas las letras que el sistema considera como min´sculas. Pruebe lo que sigue y vea qu´ obtiene: u e >>> print string. ´ La cadena string. "na") 2 Cadenas Adem´s. "na".uppercase >>> print string.10. 2) -1 En este ejemplo. De forma similar. 3) 4 O puede tomar dos argumentos adicionales que especifican un intervalo de ´ ındices: >>> string.find("banana". El m´dulo string proporciona o varias constantes que son utiles para estos menesteres. "s".82 >>> string. que determina si un car´cter aparece en una cadena: a def esMinuscula(c): return c in string.find("sus". c) != -1 Alternativamente.lowercase .lowercase >>> print string. acepta un argumento adicional que especifica el ´ a ındice en el que deber´ ıa comenzar: >>> string.lowercase.uppercase contiene todas las u may´sculas.find("banana". si find(lowercase. c) devuelve un valor que no sea -1. Clasificaci´n de caracteres o A menudo viene bien examinar un car´cter y comprobar si es una letra may´scua u la o min´scula. 7. 1. entonces c es una min´scula: u def esMinuscula(c): return find(string. string. podemos aprovecharnos del operador in. o si es un car´cter o un d´ u a ıgito. la b´squeda falla porque la letra s no aparece en el intervalo u de ´ ındices desde 1 hasta 2 (sin incluir 2). Por ejemplo.digits Podemos usar estas constantes y find para clasificar caracteres.

Crean los espacios en blanco entre los caracteres visibles (al menos sobre papel blanco). a porci´n: Una parte de una cadena especificada por un intervalo de ´ o ındices.org. Glosario tipo de datos compuesto: Un tipo de datos en el que los valores est´n hechos a de componentes o elementos que son a su vez valores. ´ ındice: Una variable o valor usado para seleccionar un miembro de un conjunto ordenado. inclu´ ıdos espacio. tiene que ser una min´scula.11. ¿Puede pensar en otras razones aparte de la velocidad a a para preferir una sobre la otra? Otra constante definida en el m´dulo string puede sorprenderle cuando la o imprima: >>> print string. y salto de l´ ınea (\n). Por otra parte. tabulador (\t).whitespace contiene todos los caracteres de espacio en blanco.11 Glosario 83 Como una alternativa m´s. recorrer: Realizar de forma iterativa una operaci´n similar sobre cada uno de o los elementos de un conjunto. est´ disponible en el sitio ı o a o a web de Python. www. Hay otras funciones utiles en el m´dulo string.whitespace Los caracteres de whitespace mueven el cursor sin imprimir nada. podemos usar el operador de comparaci´n. mutable: Un tipo de datos compuesto a cuyos elementos se les puede asignar nuevos valores. pero este libro no pretende ser ´ o un manual de referencia. la Referencia de la Biblioteca de Python s´ lo es. normalmente inicializado a cero e incrementado posteriormente. Junto con un mont´n m´s de documentaci´n. aunque a o esta soluci´n s´lo sea pr´ctica para el alfabeto ingl´s: o o a e def esMinuscula(c): return ’a’ <= c <= ’z’ Si c est´ entre a y z. contador: Una variable usada para contar algo.python.7. a u Como ejercicio. explique qu´ versi´n de esMinuscula cree que es e o m´s r´pida. La constante string. . como puede ser un car´cter de una cadena. 7.

La constante string. .whitespace contiene todos los caracterse de espacio en blanco.84 incrementar: Aumentar el valor de una variable en una unidad. decrementar: Disminuir el valor de una variable en una unidad. Cadenas espacio en blanco: Cualquiera de los caracteres que mueven el cursor sin imprimir caracteres visibles.

8. El segundo es una lista de tres cadenas de texto. 40] ["spam". maravilla de las maravillas. Los elementos de una lista no tienen por qu´ ser del mismo e tipo.Cap´ ıtulo 8 Listas Una lista es un conjunto ordenado de valores. Las listas son similares a las cadenas de texto (strings). la m´s sencilla es encerrar sus a elementos entre corchetes: [10. 20]] Se dice que una lista dentro de otra lista est´ anidada.1. otra lista: ["hola". Valores de una lista Hay varias maneras de crear una nueva lista. 2. Las listas y las cadenas.0. a Las listas que contienen n´meros enteros consecutivos son comunes.5) [1. en el cual cada valor va identificado por un ´ ındice. 30. que son conjuntos ordenados de caracteres. 20. se llaman secuencias. [10. de manera u que Python proporciona una manera sencilla de crearlas: >>> range(1. y otras cosas que se comportan como conjuntos ordenados. "golondrina"] a El primer ejemplo es una lista de cuatro enteros. un n´mero con decimales y un u entero. excepto en que los elementos de una lista pueden ser de cualquier tipo. 5. 4] . La siguiente lista contiene una cadena. 2. Los valores que constituyen una lista son sus elementos. y. "el´stico". 3.

Se la llama lista vac´ y se representa []. 9] Si hay un tercer argumento. 7.86 Listas La funci´n range toma dos argumentos y devuelve una lista que contiene todos o los enteros entre el primero y el segundo. 4. de manera que el “un´simo” elemento de numeros. ’castigar’. Este ejemplo cuenta de 1 a 10 de dos en dos (con pasos de 2). 2) [1. Acceso a los elementos La sintaxis para acceder a los elementos de una lista es la misma que para acceder a los caracteres de una cadena: el operador corchetes []. Cuando o aparece a la izquierda de una asignaci´n. 2. 9] Para terminar. especificar´ el espacio entre dos valores sucesivos. La expresi´n o dentro de los corchetes especifica el ´ ındice. ¡incluyendo el primero pero no el segundo! Hay dos formas alternativas para range. crea una lista que empieza desde 0: >>> range(10) [0. ahora es e 5. numeros. ’defenestrar’] [17. "defenestrar"] numeros = [17. ser´ decepcionante que no pudi´raıa e mos asignar valores de listas a variables o pasar listas como par´metros a funa ciones. Recuerde que los ´ ındices siempre comienzan en cero: print numeros[0] numeros[1] = 5 El operador [] puede aparecer en cualquier parte de una expresi´n. o . 8. Se puede usar como ´ ındice cualquier expresi´n entera. 5. >>> range(1. cambia uno de los elementos de la o lista. Con un solo argumento. 6. vacio [’mejorar’. 1. vocabulario = ["mejorar". 3. 7. a a esto se le llama paso (step). 123] vacio = [] print vocabulario. 3. 123] [] 8. que era 123. "castigar". 10. ıa Con todas estas maneras para crear listas. Por supuesto que podemos. hay una lista especial que no contiene elementos. 5.2.

"peste". Es muy habitual usar una varible de bucle como ´ ındice para una lista: jinetes i = 0 while i print i = i = ["guerra". De esta manera. y ´ u numeros[-3] no existe. 1. "peste". obtendr´ un a error en tiempo de ejecuci´n: o >>> numeros[2] = 5 IndexError: list assignment index out of range Si se da un ´ ındice negativo. si el tama˜o de la lista cambia. "hambre". la variable i se usa como ´ ındice de la lista. Por tanto. a >>> numeros[-1] 5 >>> numeros[-2] 17 >>> numeros[-3] IndexError: list index out of range numeros[-1] es el ultimo elemento de la lista. funcionar´n correctamente con cualquier tama˜o de lista. Esta plantilla de computaci´n se llama e o recorrido de lista. no habr´ que estar haciendo cambios n a en todos los bucles. se cuenta hacia atr´s desde el final de la lista.8. la condici´n falla y acaba el bucle. 2 y 3. "muerte"] < 4: jinetes[i] + 1 Este bucle while cuenta desde 0 hasta 4. Es una buena idea usar o n este valor como l´ ımite superior de un bucle. "muerte"] i = 0 . Cada vez que recorremos el bucle. 8. a n jinetes = ["guerra".0] TypeError: sequence index must be integer 87 Si intenta acceder (leer o modificar) un elemento que no existe. Longitud (tama˜ o) de una lista n La funci´n len toma una lista y devuelve su tama˜o. el cuerpo del bucle s´lo se ejecuta o o cuando i es 0.3 Longitud (tama˜ o) de una lista n >>> numeros[3-2] 5 >>> numeros[1. imprimiendo el elemento i-´simo. "hambre".3. numeros[-2] es el pen´ltimo. en lugar de una constante. Cuando la variable de bucle vale 4.

1. Listas y bucles for El bucle for que vimos en la Secci´n 7.88 while i < len(jinetes): print jinetes[i] i = i + 1 Listas La ultima vez que se ejecuta el cuerpo del bucle. Como “libertinaje” no est´ en la lista.10 con las cadenas. Aunque una lista puede contener otra lista como elemento. ¿qu´ ocurre si env´ un entero e ıa a len? 8. ’hambre’. pero tambi´n funciona con las listas o e y otras secuencias: >>> jinetes = [’guerra’. ’muerte’] >>> ’peste’ in jinetes 1 >>> ’libertinaje’ in jinetes 0 Como “peste” es un miembro de la lista jinetes. la lista anidada cuenta como un elemento sencillo. [1.3 tambi´n funciona con las listas. la condici´n ´ o falla y no se ejecuta el cuerpo. [’Brie’. ’peste’. ya que len(jinetes) no es un ´ ındice legal. escriba un bucle que recorra la lista anterior e imprima la longitud de cada elemento.4. Pertenencia a una lista in es un operador booleano que comprueba la pertenencia a una secuencia. ’Roquefort’. Lo usamos en la Secci´n 7. el operador in devuelve verdadero. i es len(jinetes) .5. a Podemos usar not en combinaci´n con in para comprobar si un elemento no es o miembro de una lista: >>> ’libertinaje’ not in jinetes 1 8. 1. que es ´ el ´ ındice del ultimo elemento. El tama˜o de esta lista es 4: n [’spam!’. in devuelve falso. ’Pol le Veq’]. La o e sintaxis generalizada de un bucle for es: . 2. Cuando i se iguala a len(jinetes). lo que es una cosa buena. 3]] Como ejercicio.

3. En el segundo ejemplo. 3. "manzana".6 Operaciones con listas 89 for VARIABLE in LISTA: CUERPO Esta sentencia es equivalente a: i = 0 while i < len(LISTA): VARIABLE = LISTA[i] CUERPO i = i + 1 El bucle for es m´s conciso porque podemos eliminar la variable de bucle. . 1. 2. el operador * repite una lista un n´mero dado de veces: u >>> [0] * 4 [0. Se puede usar cualquier expresi´n de lista en un bucle for: o for numero in range(20): if numero % 2 == 0: print numero for fruta in ["pl´tano".8. 4. 2. i. El segundo u ejemplo expresa su entusiasmo por diferentes frutas. la lista [1. 3] se repite tres veces. 8. 5. 0. 0. casi se lee igual que en espa˜ol. "membrillo"]: a print "Me gusta comer " + fruta + "s!" El primer ejemplo imprime todos los n´meros pares entre el 0 y el 19. 6] De forma similar. 3. 1. 2. 3] * 3 [1. 3] >>> b = [4. 2. 2. “Para (cada) jinete en (la lista de) a u n jinetes. Operaciones con listas El operador + concatena listas: >>> a = [1. 2. 5. a Aqu´ tenemos el bucle anterior con un bucle for: ı for jinete in jinetes: print jinete M´s a´n. imprime (el nombre del) jinete”.6. 0] >>> [1. 6] >>> c = a + b >>> print c [1. 2. 3] En el primer ejemplo la lista [0] contiene un solo elemento que es repetido cuatro veces.

’c’] >>> print lista . ’d’. ’b’. ’naranja’] Con el operador de porci´n podemos reemplazar varios elementos a la vez: o >>> lista = [’a’. ’f’] >>> lista[1:1] = [’b’. ’manzana’. puede eliminar elementos de una lista asign´ndoles la lista vac´ a a ıa: >>> lista = [’a’. ’y’.8. ’d’. ’y’] >>> print lista [’a’. ’f’] >>> lista[1:3] = [] >>> lista [’a’. "membrillo"] a >>> fruta[0] = "pera" >>> fruta[-1] = "naranja" >>> print fruta [’pera’. ’e’. ’c’] >>> lista[:4] [’a’. ’b’. ’f’] Adem´s. Porciones (slices) Las operaciones de porciones que vimos en la Secci´n 7. ’c’. ’d’. ’b’. ’e’. ’c’. "manzana". lo que significa que podemos cambiar sus elementos. ’d’. ’d’. ’c’.4 tambi´n funcionan en o e sobre las listas: >>> lista = [’a’. ’d’. ’f’] >>> lista[:] [’a’. ’c’. ’b’. ’d’] >>> lista[3:] [’d’. ’f’] Y puede a˜adir elementos a la lista embuti´ndolos en una porci´n vac´ en la n e o ıa posici´n deseada: o >>> lista = [’a’. ’e’.90 Listas 8. Las listas son mutables A diferencia de las cadenas. ’c’. ’d’. ’e’. Podemos modificar uno de sus elementos usando el operador corchetes en el lado izquierdo de una asignaci´n: o >>> fruta = ["pl´tano". ’b’.7. ’x’. las listas son mutables. ’e’. ’e’. ’f’] >>> lista[1:3] [’b’. ’f’] >>> lista[1:3] = [’x’. ’e’. ’f’] 8.

Python nos da una alternativa que resulta m´s a legible. ’b’. ’b’. del maneja ´ ıa ındices negativos y provoca un error en tiempo de ejecuci´n sin el ´ o ındice est´ fuera de l´ a ımites. ’c’. ’tres’] >>> del a[1] >>> a [’uno’. ’d’. Objetos y valores Si ejecutamos estas sentencias de asignaci´n: o a = "banana" b = "banana" Est´ claro que a y b apuntan ambos a cadenas con las letras "banana". ’c’. ’e’. del elimina un elemento de una lista: >>> a = [’uno’.9 Borrado en una lista [’a’. ’tres’] Como podr´ esperar. ’d’. ’f’] >>> lista[4:4] = [’e’] >>> print lista [’a’. a Hay dos posibles estados: . ’b’. ’f’] Como es habitual. ’f’] >>> del lista[1:5] >>> print lista [’a’. las porciones seleccionan todos los elementos hasta. ’c’. Puede usar una porci´n como ´ o ındice para del: >>> lista = [’a’. pero no inclu´ ıdo. ’d’.9.10.8. Pero no a podemos saber si est´n apuntando a la misma cadena. ’f’] 91 8. 8. Borrado en una lista El uso de porciones para borrar elementos de una lista puede ser extra˜o. y n por ello propicio a los errores. ’e’. ’dos’. el segundo ´ ındice.

Alias (poner sobrenombres) Como las variables apuntan a objetos. ambas variables se refieren al mismo objeto: . s´ que importa. a y b. 8.92 a b "banana" "banana" a b Listas "banana" En un caso. si asigna una variable a otra. 2. se refieren a la misma cosa. 3] >>> b = [1. o o Como las cadenas de texto son inmutables. >>> id(a) 135044008 >>> id(b) 135044008 En este caso. Cada objeto tiene un identificador unico. Cuando crea dos listas. 2. lo que significa que Python s´lo cre´ una cadena y ambas variables. ı Curiosamente. que podemos obtener por medio de ´ la funci´n id. 3 ] a y b tienen el mismo valor. 3 ] [ 1. las dos veces obtenemos el mismo identificador. no hay diferencia pr´ctica entre los a dos posibles estados. Imprimiendo los identificadores de a y b podemos saber si apuntan o al mismo objeto. En el segundo caso. Estas “cosas” tienen nombres. las listas se comportan de otra manera.11. pero no se refieren al mismo objeto. Para tipos mutables como las listas. Un objeto es una cosa a la que se puede referir una variable. 2. a y b se refieren a dos cosas diferentes que tienen el mismo valor. obtiene dos objetos: >>> a = [1. 3] >>> id(a) 135045528 >>> id(b) 135041704 De manera que el diagrama de estado ser´ tal como ´ste: ıa e a b [ 1. 2. apuntan a ella. se les denomina objetos.

necesitaremos ser capaces de hacer una copia de la lista en s´ no s´lo de su referencia. a y b. tenemos libertad de hacer cambios en b sin preocuparnos de a: b[0] = 5 print a 2.8. no hay problema con los objetos inmutables. o proceso a veces se denomina clonado. 3] Como ejercicio. 3] >>> b = a En este caso. 2. Los cambios hechos a un alias afectan al otro: >>> b[0] = 5 >>> print a [5. 2. dibuje un diagrama de estado de a y b antes y despues del cambio. Ahora >>> >>> [1. 3] Aunque este comportamiento puede ser util. . Clonar listas Si queremos modificar una lista y mantener una copia del original.12. 2. 2. ´ En general. para evitar la ambig¨edad de la palabra u “copia”.12 Clonar listas >>> a = [1. La forma m´s f´cil de clonar una lista es por medio del operador de porci´n: a a o >>> a = [1. 3] La extracci´n de una porci´n de a crea una nueva lista. 8. podemos decir que se le ha puesto un alias. es m´s seguro evitar los alias cuando trabajemos con objetos mutaa bles. el diagrama de estados ser´ como ´ste: ıa e a b [ 1. Por ello Python se toma la libertad de poner alias a las cadenas cuando ve una oportunidad de economizar. Este ı. la porci´n o o o consta de la lista completa. 3] >>> b = [] >>> b[:] = a[:] >>> print b [1. En este caso. a veces es inesperado o indeseable. 3 ] 93 Como la misma lista tiene dos nombres diferentes. Por supuesto. 2.

Por ejemplo. Por ejemplo. devuelve una referencia a la lista.2. def cola(lista): return lista[1:] Aqu´ vemos c´mo se usa cola: ı o >>> >>> >>> >>> numeros = [1.2. en realidad se pasa una referencia a ella. a Si la funci´n modifica una lista pasada como par´metro.3] borra_cabeza(numeros) print numeros 3] Si una funci´n devuelve una lista. el que hizo la llamada o a ver´ el cambio. El a diagrama de estado es as´ ı: __main__ numbers [ 1. 2.3] >>> cabeza(numeros) 1 El par´metro lista y la variable numeros son alias de un mismo objeto. Listas como par´meteros a Cuando se pasa una lista como argumento.13. excepto el primero. ı >>> numeros = [1.3] resto = cola(numeros) print resto [2. borra cabeza elimina el primer elemento de una lista. 3] .94 Listas 8. 3 ] head list Como el objeto lista est´ compartido por dos marcos. a def borra_cabeza(lista): del lista[0] Aqu´ vemos el uso de borra cabeza: ı >>> >>> >>> [2. la funci´n cabeza toma una lista o como par´metro y devuelve el primer elemento.2. no una copia de la lista. o cola devuelve una lista que contiene todos los elementos de una lista dada. lo dibujamos entre ambos. numeros = [1. a def cabeza(lista): return lista[0] As´ es como se usa.

[7. 3]. 5. as´ que esta expresi´n u ı o saca el tri-´simo elemento de lista y luego extrae el un´simo elemento de ella. podemos proceder en dos pasos: >>> elt = lista[3] >>> elt[0] 10 O podemos combinarlos: >>> lista[3][1] 20 Los operadores corchete se eval´an de izquierda a derecha. no afectar´ a numbers. Para extraer los elementos de la lista anidada. es una lista. La creaci´n de o o o rest. 20]] Si imprimimos lista[3]. la matriz: u puede ser representada como: >>> matriz = [[1. [10. 2. as´ como cualquier cambio posterior en rest. Matrices 1 2 3 4 5 6 7 8 9 Es com´n usar listas anidadas para representar matrices. Listas anidadas Una lista anidada es una lista que aparece como elemento dentro de otra lista. e e 8.14. ı a 8.14 Listas anidadas 95 Como el valor de retorno se cre´ con una porci´n. Podemos elegir una fila entera de la matriz de la forma normal: >>> matriz[1] [4.15. 8. 20]. 6]. En esta lista. [4. Por ejemplo.8. 6] O tomar s´lo un elemento de la matriz usando la forma de doble ´ o ındice: >>> matriz[1][1] 5 . 9]] matriz es una lista con tres elementos.0. 5. 2. 5. el tri-´simo elemento es una lista anidada: e >>> lista = ["hola". obtendremos [10. siendo cada elemento una fila de la matriz.

’ll’) [’La ’.’] Observe que el delimitador no aparece en la lista.. join acepta un delimitador opcional que se inserta entre los elementos.join(string. Toma una lista de cadenas y concatena o los elementos con un espacio entre cada par: >>> lista = [’La’.. ’en’. M´s adelante veremos a una alternativa m´s radical usando un diccionario.. cualquier n´mero de caracteres de espacio en blanco se considera un u l´ ımite de palabra: >>> import string >>> cancion = "La lluvia en Sevilla..join(lista. ’lluvia’.split(cancion) [’La’...join(lista) ’La lluvia en Sevilla. >>> string. La funci´n split divide una cadena en una lista de palabras. Por o defecto. ¿Es la misma para todas las cadenas? ¿Cu´ndo ser´ diferente? a ıa . La funci´n join es la inversa de split. El siguiente ejemplo usa la cadena ll como delimitador: >>> string. Una peque˜a variaci´n u ´ n o consiste en usar una lista de columnas en lugar de flas. ’Sevilla.’ Como split.. a 8. ’lluvia’. no es la unica posibilidad.’] >>> string. ’Sevilla. Cadenas y listas Dos de las funciones m´s utiles del m´dulo string tienen que ver con listas a ´ o de cadenas.’ A modo de ejercicio.96 Listas El primer ´ ındice escoge la fila y el segundo la columna.split(cancion)) y cancion. describa la relaci´n que hay entre o string. ’en’.split(cancion..’] Se puede usar un argumento opcional llamado delimitador para especificar qu´ caracteres se usar´n como l´ e a ımites de palabra. ’_’) ’La_lluvia_en_Sevilla.." >>> string...16. ’uvia en Sevi’.. ’a. Aunque esta manera de representar matrices es com´n. El delimitador por defecto es el espacio.

17 Glosario 97 8. pero no clona el objeto. El operador corchete selecciona elementos de una lista. Glosario lista: Una colecci´n de objetos con nombre. en la que cada objeto es identificado o por un ´ ındice. secuencia: Cualquier tipo de datos que consita en un conjunto ordenado de elementos.17. con cada elemento identificado por un ´ ındice.8. alias: M´ltiples variables que contienen referencias al mismo objeto. elemento: Uno de los valores de una lista (u otra secuencia). recorrido de lista: Acceso secuencial a cada elemento de una lista. u clonar: Crear un objeto nuevo que tiene el mismo valor que un objeto ya existente. . Copiar una referencia a un objeto crea un alias. objeto: Una cosa a la que se puede referir una variable. lista anidada: Una lista que es elemento de otra lista. ´ ındice: Una variable o valor enteros que se usan para indicar un elemento de una lista. delimitador: Un car´cter o cadena utilizado para indicar d´nde debe cortarse a o una cadena.

.

que est´n hechas de caa racteres. ’e’ Aunque no es necesario. debemos incluir una coma final: >>> t1 = (’a’. las cadenas son inmutables y las listas son mutables. ’c’. En Python hay otro tipo llamado tupla que es similar a una lista salvo en que es inmutable. pero los caracteres de una cadena no. ’b’. Sint´cticamente.1. ’b’. ’c’. que est´n hechas de elementos de cualquier tipo. ’e’) Para crear una tupla con un solo elemento.) >>> type(t1) <type ’tuple’> Sin la coma. Python trata (´’) como una cadena entre par´ntesis: a e >>> t2 = (’a’) >>> type(t2) <type ’string’> . una tupla es una lista de valores separados por a comas: >>> tupla = ’a’. En otras palabras.Cap´ ıtulo 9 Tuplas 9. la convenci´n dice que hay que encerrar las tuplas entre o par´ntesis: e >>> tupla = (’a’. ’d’. ha visto dos tipos compuestos: cadenas. Una de las a diferencias que se˜alamos es que los elementos de una lista se pueden modifin car. y listas. ’d’. Mutabilidad y tuplas Hasta ahora.

’b’.100 Tuplas Dejando a un lado las cuestiones de sintaxis. ’c’. es util intercambiar los valores de dos variables. ’b’. las operaciones sobre las tuplas son las mismas que sobre las listas. el lado derecho es una tupla de valores. podemos sustituir una tupla por otra diferente: >>> tupla = (’A’.) + tupla[1:] >>> tupla (’A’. Por ejemplo. Todas las expresiones del lado derecho se eval´an antes de las asignaciones. Pyto hon proporciona una forma de asignaci´n de tuplas que soluciona este proo blema elegantemente: >>> a. Esta caracter´ u ıstica hace de la asignaci´n de tuplas algo muy vers´til. para intercambiar a y b: >>> temp = a >>> a = b >>> b = temp Si tenemos que hacer esto a menudo. ’d’. Asignaci´n de tuplas o De vez en cuando. o a . >>> tupla = (’a’. ’e’) >>> tupla[0] ’a’ Y el operador de porci´n selecciona un intervalo de elementos. o >>> tupla[1:3] (’b’. Cada valor se asigna a su respectiva variable. ’d’. ’c’. Para ha´ cerlo con sentencias de asignaci´n convencionales debemos usar una variable o temporal. ’e’) 9.2. El operador ´ ındice selecciona un elemento de la tupla. b = b. a El lado izquierdo es una tupla de variables. esta aproximaci´n resulta aparatosa. incluso aunque no podamos modificar los elementos de una tupla. ’c’) Pero si intentamos modificar uno de los elementos de la tupla provocaremos un error: >>> tupla[0] = ’A’ TypeError: object doesn’t support item assignment Por supuesto.

o De hecho. existe un peligro al intentar encapsular intercambio. b) En este caso. Por ejemplo. c. podr´ ıamos escribir una funci´n que intercambie dos par´metros: o a def intercambio(x.4. ya que esperamos que un c´lculo nos d´ siempre el mismo a e . x Luego podemos asignar el valor de retorno a una tupla con dos variables: a. Esta funci´n se ejecuta sin generar un mensaje de error. x Si llamamos a esta funci´n as´ o ı: intercambio(a. De forma similar. d = 1. y): return y. 2. cambiar y no tiene efecto sobre b. b. N´ meros aleatorios u La mayor parte de los programas hacen lo mismo cada vez que los ejecutamos. a A modo de ejercicio. el n´mero de variables a la izquierda y el n´mero de valores a la u u derecha deben ser iguales: >>> a. pero no hace lo que o intentamos. Tuplas como valor de retorno Las funciones pueden devolver tuplas como valor de retorno. b = intercambio(a.3. 3 ValueError: unpack tuple of wrong size 9. Normalmente el determinismo es una cosa buena. Cambiar x dentro de intercambio hace que x se refiera a un valor diferente. y): x. y = y.9. por lo que se dice que son deterministas. no hay ninguna ventaja en convertir intercambio en una funci´n. dibuje un diagrama de estados para esta funci´n o de manera que pueda ver por qu´ no trabaja como usted quiere. Este es un ejemplo de error sem´ntico. y es el tentador error que sigue: def intercambio(x. pero no tiene efecto alguno sobre a en main .3 Tuplas como valor de retorno 101 Naturalmente. b) a y x son alias del mismo valor. e # versi´n incorrecta o 9.

listaAleatorios acepta un par´metro entero y devuelve una lista de n´meros aleatorios de la a u longitud dada. pero hay m´s. Lista de n´ meros aleatorios u El primer paso es generar una lista de valores aleatorios. u Como ejercicio adicional. pero servir´n para a a nuestros prop´sitos. Una de ellas es generar n´meros aleatorios y usarlos para determinar el resultado del programa.0 y 1. Python u proporciona una funci´n interna que genera n´meros pseudoaleatorios. multiplique x por maximo. n . sin embargo. incluyendo ambos extremos. a Hacer que un programa sea realmente no determinista resulta no ser tan sencillo. Cada vez que ejecuta el bucle. A la hora de o depurar es una buena idea empezar con algo peque˜o. genere un n´mero aleatorio entre minimo y maximo. pero hay formas de que al menos parezca no determinista. Cada vez que usted llama a random obtiene el siguiente n´mero de una larga serie. ejecute este bucle: u import random for i in range(10): x = random.5. o El m´dulo random contiene una funci´n llamada random que devuelve un n´mero o o u en coma flotante entre 0. El valor de retorno es u una referencia a la lista completa: def listaAleatorios(n): s = [0] * n for i in range(n): s[i] = random. sustituye uno de los elementos con un n´mero aleatorio.0 y un l´ u ımite superior como maximo. 9.random() print x Para generar un n´mero aleatorio entre 0. El ejemplo obvio son los juegos. genere un n´mero aleatorio entero entre u minimo y maximo.0. que o u no son verdaderamente aleatorios en un sentido matem´tico.102 Tuplas resultado. Comienza con una lista de n ceros. Como ejercicio.random() return s Vamos a probar esta funci´n con una lista de ocho elementos. Para ver un ejemplo. Para algunas aplicaciones. queremos que el computador sea impredecible.

u 9.360371157682 0.275119183077 0. a . a u Podemos contrastar esta teor´ escribiendo un programa que divida el intervalo ıa en baldes y contando el n´mero de valores en cada uno.800367163582 103 Se supone que los n´meros generados por random est´n distribuidos uniformeu a mente. queremos recorrer una lista de n´meros y contar el n´mero de u u veces que un valor cae en un intervalo dado. En la Secci´n 7.6. Eso nos suena. Si dividimos el intervalo de valores posibles en “baldes” de igual tama˜o y n contamos el n´mero de veces que un valor cae en cada balde. deber´ u ıamos tener m´s o menos el mismo n´mero en todos. En este caso.810894847068 0.15156642489 0. Esto no cambia el programa. Queremos ver si num est´ entre los valores de minimo y maximo. o a El segundo paso es cambiar la comprobaci´n.759199803101 0.9.8 o escribimos un programa que recorr´ una cadena de texto y contaba el n´mero ıa u de veces que aparec´ una letra determinada. Conteo Un buen enfoque sobre problemas como ´ste es dividir el problema en subproe blemas que encajen en un esquema computacional que hayamos visto antes. a actual.6 Conteo >>> listaAleatorios(8) 0.498048560109 0. No estamos interesados en encono trar letras.328578797631 0. El programa original era: cuenta = 0 for car in fruta: if car == ’a’: cuenta = cuenta + 1 print cuenta El primer paso es sustituir fruta con lista y car con num. s´lo lo hace m´s legible. lo que significa que cada valor es igualmente probable. ıa As´ podemos hacerlo copiando el programa viejo y adapt´ndolo al problema ı.

0.25. reutilice la soluci´n. Empezaremos por solucionar el segundo problema.0 / numBaldes. 1. Si el n´mero de baldes es u numBaldes. la anchura de cada balde es 1.0. i. a def enElBalde(lista. ´ o o Los par´metros son la lista y los valores minimo y maximo.5) alto = enElBalde(a.25) 0. no est´ mal: a bajo = enElBalde(a. maximo): cuenta = 0 for num in lista: if minimo < num < maximo: cuenta = cuenta + 1 return cuenta Copiar y modificar un programa existente nos facilita escribir esta funci´n r´pio a damente y nos ahorra un mont´n de tiempo de depuraci´n. cuenta de 1 a numBaldes-1: . Uno es que tenemos que inventar nuevos nombres de variables para cada resultado. enElBalde(a. enElBalde(a. Este plan de desao o rrollo se llama coincidencia de esquemas. enElBalde se hace un tanto dif´ de u ıcil manejar.7.5) 0. La variable del bucle. 0.0) Hay dos problemas. minimo. 0. 0. Si se encuentra trabajando en un problema que ya solucion´. enElBalde(a. 1) Pero con cuatro baldes ya es aparatoso. El otro es que tenemos que calcular el intervalo de cada balde. 0.0.75.75) 0. 0. Muchos baldes Tal como aumenta el n´mero de baldes. 0. balde1 balde2 balde3 balde4 = = = = enElBalde(a.104 cuenta = 0 for num in lista if minimo < num < maximo: cuenta = cuenta + 1 print cuenta Tuplas El ultimo paso es encapsular este c´digo en una funci´n llamada enElBalde. o o 9.5. Usaremos un bucle para calcular el intervalo de cada balde.5. Con dos baldes.

128.875 0.25 hasta 0. 118. est´n lo bastante cerca como para que podamos pensar que el a generador de n´meros aleatorios funciona. este c´digo genera esta lista de baldes: o [138.9. que no se solapan y que cubren todo el intervalo entre 0.125 hasta 0.75 hasta 0. Dentro del bucle. u .25 0. porque s´lo queremos hacero lo una vez. maximo) print baldes Con una lista de 1000 valores.125 0.375 0. que es lo que esper´bamos u o a Por lo menos.0 y 1. usando la variable de bucle para se˜alarlos uno por uno. "hasta".625 0. multiplicamos la variable de bucle por la anchura de balde.75 0. la salida es: 0.5 hasta 0.625 hasta 0. a o Con numBaldes = 8. El l´ ımite superior est´ a tan s´lo una anchuraBalde.0 / numBaldes for i in range(numBaldes): minimo = i * anchuraBalde maximo = minimo + anchuraBalde baldes[i] = enElBalde(lista. 130. ıa Debemos crear la lista de baldes fuera del bucle. 114. 124. Necesitamos un modo de almacenar ocho enteros.5 0.0 Puede confirmar que todos los bucles tienen la misma anchura.0. 131] Estos n´meros son razonablemente pr´ximos a 125. En estos mon mentos deber´ usted estar pensando “¡Lista!”.0 / numBaldes for i in range(numBaldes): minimo = i * anchuraBalde maximo = minimo + anchuraBalde print minimo. maximo 105 Para calcular el l´ ımite inferior de cada balde. 117.0 hasta 0. Volvamos ahora al primer problema.875 hasta 1.375 hasta 0.7 Muchos baldes anchuraBalde = 1. minimo. podemos llamar repetidamente a enElBalde y actualizar el i-´simo elemento de la lista: e numBaldes = 8 baldes = [0] * numBaldes anchuraBalde = 1.

y lo multiplicamos por la anchuraBalde para hallar el l´ ımite inferior de un balde dado.0 a 1. podemos suponer que deber´ ıamos dividir por anchuraBalde en lugar de multiplicar. escriba una funci´n llamada histograma que tome o como par´metros una lista y un n´mero de baldes y devuelva un a u histograma con el n´mero dado de baldes. u 9. y vea o a si el n´mero de valores en cada balde tiende a equilibrarse. Luego podemos incrementar el contador apropiado.0 y hallar el ´ ındice del balde en el que cae.0 a 1. o u ¿Es posible que este c´lculo genere un ´ a ındice que est´ fuera del intervalo (tanto e negativo como mayor que len(baldes)-1)? Una lista como baldes que contiene conteos del n´mero de valores en cada u intervalo se llama histograma. obtenemos un n´mero del intervalo entre u 0.0 y numBaldes. La suposici´n es correcta. compruebe esta funci´n con listas m´s largas.8.0 por numBaldes. Si multiplicamos un n´mero del intervalo u que va de 0. llega a ser un mont´n de recorridos. Con el aumento del n´mero de u baldes. Cada vez ıa que llama a enElBalde recorre la lista entera. u .0 / numBaldes. Una soluci´n en una sola pasada o Aunque este programa funciona. o Como anchuraBalde = 1. o Ser´ mejor hacer una sola pasada por la lista y calcular para cada valor el ´ ıa ındice del balde en el que cae. no es tan eficiente como podr´ ser.106 Tuplas Como ejercicio. dividir por anchuraBalde es lo mismo que multiplicar por numBaldes. Ahora queremos tomar un valor del intervalo 0. Como ejercicio. Si redondeamos ese n´mero al entero inferior obtendremos u exactamente lo que estamos buscando. un ´ ındice de balde: numBaldes = 8 baldes = [0] * numBaldes for i in lista: indice = int(i * numBaldes) baldes[indice] = baldes[indice] + 1 Usamos la funci´n int para convertir un n´mero en coma flotante en un entero. En la secci´n anterior tomamos un ´ o ındice. i. Como el problema es el inverso del anterior.

Glosario tipo inmutable: Un tipo en el cual los elementos no se puede modificar. determinista: Un programa que hace lo mismo todas las veces que se ejecuta. asignaci´n de tuplas: Una asignaci´n de todos los elementos de una tupla o o usando una unica sentencia de asignaci´n.9. tupla: Un tipo de secuencia que es similar a una lista excepto en que es inmutable. como puede ser la clave de un diccionario. o . coincidencia de esquemas: Un plan de desarrollo de programas que implica la identificaci´n de un esquema computacional conocido y el copiado de o la soluci´n para un problema similar.9 Glosario 107 9. haci´ndola util para intercama e ´ biar valores.9. Las listas y diccionarios son tipos de datos mutables. Las asignaciones de elementos o porciones de tipos inmutables provocan un error. las cadenas y las tuplas no. La asignaci´n de tuplas sucede ´ o o m´s bien en paralelo que secuencialmente. tipo mutable: Un tipo de datos en el cual los elementos pueden ser modificados. Todos los tipos mutables son compuestos. a histograma: Una lista de enteros en la que cada elemento cuenta el n´mero u de veces que ocurre algo. Las tuplas se pueden usar donde quiera que se necesite un tipo inmutable. pseudoaleatorio: Una secuencia de n´meros que parece ser aleatoria pero que u en realidad es el resultado de un c´lculo determinista.

.

’two’: ’dos’} Los elementos de un diccionario aparecen en una lista separada por comas. En este diccionario. En un diccionario. listas y tuplas) usan enteros como ´ ındices. Una forma de crear un diccionario es empezar con el diccionario vac´ y a˜adir ıo n elementos. Podemos presentar el valor n actual del diccionario del modo habitual: >>> print ing\_a\_esp {’one’: ’uno’. las otras asigo naciones a˜aden nuevos elementos al diccionario. El diccionario vac´ se expresa como {}: ıo >>> ing\_a\_esp = {} >>> ing\_a\_esp[’one’] = ’uno’ >>> ing\_a\_esp[’two’] = ’dos’ La primera asignaci´n crea un diccionario llamado ing a esp. Los diccionarios son similares a otros tipos compuestos excepto en que pueden usar como ´ ındice cualquier tipo inmutable. Otra forma de crear un diccionario es dando una lista de pares clave-valor con la misma sintaxis que la salida del ejemplo anterior: . Cada entrada contiene un ´ ındice y un valor separado por dos puntos (:). A modo de ejemplo. Si intenta usar cualquier otro tipo como ´ ındice provocar´ un a error. los ´ ındices se llaman claves.Cap´ ıtulo 10 Diccionarios Los tipos compuestos que ha visto hasta ahora (cadenas. por eso los elementos se llaman pares clave-valor. los n ´ ındices son strings (cadenas). crearemos un diccionario que traduzca palabras inglesas al espa˜ol.

podemos simplemente cambiar el ina ventario asociado con las peras: >>> inventario[’peras’] = 0 >>> print inventario {’naranajas’: 525. ’three’: ’tres’} Si volvemos a imprimir el valor de ing a esp. devuelve el n´mero de pares o e u clave-valor: >>> len(inventario) 4 . usamos las claves para buscar los valores correspondientes: >>> print ing\_a\_esp[’two’] ’dos’ La clave ’two’ nos da el valor ’dos’ aunque aparezca en el tercer par clavevalor. Operaciones sobre diccionarios La sentencia del elimina un par clave-valor de un diccionario. ’peras’: 0. podemos eliminar la entrada del diccionario: >>> del inventario[’peras’] >>> print inventario {’naranjas’: 525. ’naranjas’: 525.1. En lugar de eso. nos llevamos una sorpresa: >>> print ing\_a\_esp {’one’: ’uno’.110 Diccionarios >>> ing\_a\_esp = {’one’: ’uno’. ’manzanas’: 430. el diccionario siguiente contiene los nombres de varias frutas y el n´mero de esas u frutas en el almac´n: e >>> inventario = {’manzanas’: 430.. ’peras’: 217. 10. . Por ejemplo. ’manzanas’: 430. ’two’: ’dos’} ¡Los pares clave-valor no est´n en orden! Afortunadamente. ’peras’: 217} >>> print inventario {’naranjas’: 525. ’three’: ’tres’. ’two’: ’dos’.. ’bananas’: 312} O si esperamos recibir m´s peras pronto. ’bananas’: 312} La funci´n len tambi´n funciona con diccionarios. ’bananas’: 312} Si alguien compra todas las peras. no necesitamos preoa cuparnos por el orden. ’manzanas’: 430. ’bananas’: 312. ya que los elementos de un diccionario nunca se indexan con ´ ındices enteros.

10.2 M´todos del diccionario e

111

10.2.

M´todos del diccionario e

Un m´todo es similar a una funci´n, acepta par´metros y devuelve un valor, e o a pero la sintaxis es diferente. Por ejemplo, el m´todo keys acepta un diccionario e y devuelve una lista con las claves que aparecen, pero en lugar de la sintaxis de la funci´n keys(ing a esp), usamos la sintaxis del m´todo ing a esp.keys(). o e >>> ing\_a\_esp.keys() [’one’, ’three’, ’two’] Esta forma de notaci´n de punto especifica el nombre de la funci´n, keys, y el o o e nombre del objeto al que se va a aplicar la funci´n, ing a esp. Los par´ntesis o indican que este m´todo no admite par´metros. e a La llamda a un m´todo se denomina invocaci´n; en este caso, dir´ e o ıamos que estamos invocando keys sobre el objeto ing a esp. El m´todo values es similar; devuelve una lista de los valores del diccionario: e >>> ing\_a\_esp.values() [’uno’, ’tres’, ’dos’] El m´todo items devuelve ambos, una lista de tuplas con los pares clave-valor e del diccionario: >>> ing\_a\_esp.items() [(’one’,’uno’), (’three’, ’tres’), (’two’, ’dos’)] La sintaxis nos proporciona informaci´n muy util acerca del tipo de datos. Los o ´ corchetes indican que es una lista. Los par´ntesis indican que los elementos de e la lista son tuplas. Si un m´todo acepta un argumento, usa la misma sintaxis que una llamada e a una funci´n. Por ejemplo, el m´todo has key acepta una clave y devuelve o e verdadero (1) si la clave aparece en el diccionario: >>> ing\_a\_esp.has_key(’one’) 1 >>> ing\_a\_esp.has_key(’deux’) 0 Si usted invoca un m´todo sin especificar un objeto, provoca un error. En este e caso, el mensaje de error no es de mucha ayuda: >>> has_key(’one’) NameError: has_key

112

Diccionarios

10.3.

Asignaci´n de alias y copiado o

Debe usted estar atento a los alias a causa de la mutabilidad de los diccionarios. Si dos variables se refieren al mismo objeto los cambios en una afectan a la otra. Si quiere modificar un diccionario y mantener una copia del original, use el m´todo copy. Por ejemplo, opuestos es un diccionario que contiene pares de e opuestos: >>> opuestos = {’arriba’: ’abajo’, ’derecho’: ’torcido’, ... ’verdadero’: ’falso’} >>> alias = opuestos >>> copia = opuestos.copy() alias y opuestos se refieren al mismo objeto; copia hace referencia a una copia nueva del mismo diccionario. Si modificamos alias, opuestos tambi´n resulta e cambiado: >>> alias[’derecho’] = ’sentado’ >>> opuestos[’derecho’] ’sentado’ Si modificamos copia, opuestos no var´ ıa: >>> copia[’derecho’] = ’privilegio’ >>> opuestos[’derecho’] ’sentado’

10.4.

Matrices dispersas

En la Secci´n 8.14 usamos una lista de listas para representar una matriz. Es o una buena opci´n para una matriz en la que la mayor´ de los valores es diferente o ıa de cero, pero piense en una matriz como ´sta: e
0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 0 0

La representaci´n de la lista contiene un mont´n de ceros: o o matriz = [ [0,0,0,1,0], [0,0,0,0,0],

10.5 Pistas [0,2,0,0,0], [0,0,0,0,0], [0,0,0,3,0] ]

113

Una posible alternativa es usar un diccionario. Como claves, podemos usar tuplas ´ que contengan los n´meros de fila y columna. Esta es la representaci´n de la u o misma matriz por medio de un diccionario: matriz = {(0,3): 1, (2, 1): 2, (4, 3): 3} S´lo hay tres pares clave-valor, una para cada elemento de la matriz diferente o de cero. Cada clave es una tupla, y cada valor es un entero. Para acceder a un elemento de la matriz, podemos usar el operador []: matriz[0,3] 1 F´ ıjese en que la sintaxis para la representaci´n por medio del diccionario no es o la misma de la representaci´n por medio de la lista anidada. En lugar de dos o ´ ındices enteros, usamos un ´ ındice que es una tupla de enteros. Hay un porblema. Si apuntamos a un elemento que es cero, se produce un error porque en el diccionario no hay una entrada con esa clave: >>> matriz[1,3] KeyError: (1, 3) El m´todo get soluciona este problema: e >>> matriz.get((0,3), 0) 1 El primer argumento es la clave; el segundo argumento es el valor que debe devolver get en caso de que la clave no est´ en el diccionario: e >>> matriz.get((1,3), 0) 0 get mejora sensiblemente la sem´ntica del acceso a una matriz dispersa. L´stima a a de sintaxis.

10.5.

Pistas

Si estuvo jugando con la funci´n fibonacci de la Secci´n 5.7, es posible que o o haya notado que cuanto m´s grande es el argumento que le da, m´s tiempo le a a

114

Diccionarios

cuesta ejecutarse. M´s a´n, el tiempo de ejecuci´n aumenta muy r´pidamente. a u o a En nuestra m´quina, fibonacci(20) acaba instant´neamente, fibonacci(30) a a tarda m´s o menos un segundo, y fibonacci(40) tarda una eternidad. a Para entender por qu´, observe este gr´fico de llamadas de fibonacci con e a n=4:
fibonacci n 4

fibonacci n 3

fibonacci n 2

fibonacci n 2

fibonacci n 1

fibonacci n 1

fibonacci n 0

fibonacci n 1

fibonacci n 0

Un gr´fico de llamadas muestra un conjunto de cajas de funci´n con l´ a o ıneas que conectan cada caja con las cajas de las funciones a las que llama. En lo alto del gr´fico, fibonacci con n=4 llama a fibonacci con n=3 y n=2. A su vez, a fibonacci con n=3 llama a fibonacci con n=2 y n=1. Y as´ sucesivamente. ı Cuente cu´ntas veces se llama a fibonacci(0) y fibonacci(1). Es una soluci´n a o ineficaz al problema, y empeora mucho tal como crece el argumento. Una buena soluci´n es llevar un registro de los valores que ya se han calculado o almacen´ndolos en un diccionario. A un valor que ya ha sido calculado y almaa cenado para un uso posterior se le llama pista. Aqu´ hay una implementaci´n ı o de fibonacci con pistas: anteriores = {0:1, 1:1} def fibonacci(n): if anteriores.has_key(n): return anteriores[n] else: nuevoValor = fibonacci(n-1) + fibonacci(n-2) anteriores[n] = nuevoValor return nuevoValor El diccionario llamado anteriores mantiene un registro de los valores de Fibonacci que ya conocemos. El programa comienza con s´lo dos pares: 0 corresponde o a 1 y 1 corresponde a 1.

10.6 Enteros largos

115

Siempre que se llama a fibonacci comprueba si el diccionario contiene el resultado ya calculado. Si est´ ah´ la funci´n puede devolver el valor inmediatamente a ı, o sin hacer m´s llamadas recursivas. Si no, tiene que calcular el nuevo valor. El a nuevo valor se a˜ade al diccionario antes de que la funci´n vuelva. n o Con esta versi´n de fibonacci, nuestra m´quina puede calcular fibonacci(40) o a en un abrir y cerrar de ojos. Pero cuando intentamos calcular fibonacci(50), nos encontramos con otro problema: >>> fibonacci(50) OverflowError: integer addition La respuesta, como ver´ en un momento, es 20.365.011.074. El problema es a que este n´mero es demasiado grande para caber en un entero de Python. Se u desborda. Afortunadamente, hay una soluci´n f´cil para este problema. o a

10.6.

Enteros largos

Python proporciona un tipo llamado long int que puede manejar enteros de cualquier tama˜o. Hay dos formas de crear un valor long int. Una es escribir n un entero con una L may´scula al final: u >>> type(1L) <type ’long int’> La otra es usar la funci´n long para convertir un valor en long int. long acepta o cualquier tipo num´rico e incluso cadenas de d´ e ıgitos: >>> long(1) 1L >>> long(3.9) 3L >>> long(’57’) 57L Todas las operaciones matem´ticas funcionan sobre los long ints, as´ que no a ı tenemos que hacer mucho para adaptar fibonacci: >>> previous = {0:1L, 1:1L} >>> fibonacci(50) 20365011074L Simplemente cambiando el contenido inicial de anteriores cambiamos el comportamiento de fibonacci. Los primeros dos n´meros de la secuencia son long u ints, as´ que todos los n´meros subsiguientes lo ser´n tambi´n. ı u a e

116

Diccionarios Como ejercicio, modifique factorial de forma que produzca un long int como resultado.

10.7.

Contar letras

En el cap´ ıtulo 7 escribimos una funci´n que contaba el n´mero de apariciones o u de una letra en una cadena. Una versi´n m´s gen´rica de este problema es crear o a e un histograma de las letras de la cadena, o sea, cu´ntas veces aparece cada letra. a Ese histograma podr´ ser util para comprimir un archivo de texto. Como las ıa ´ diferentes letras aparecen con frecuencias distintas, podemos comprimir un archivo usando c´digos cortos para las letras m´s habituales y c´digos m´s largos o a o a para las que aparecen con menor frecuencia. Los diccionarios facilitan una forma elegante de generar un histograma: >>> cuentaLetras = {} >>> for letra in "Mississippi": ... cuentaLetras[letra] = cuentaLetras.get (letra, 0) + 1 ... >>> cuentaLetras {’M’: 1, ’s’: 4, ’p’: 2, ’i’: 4} >>> Inicialmente, tenemos un diccionario vac´ Para cada letra de la cadena, busıo. camos el recuento actual (posiblemente cero) y lo incrementamos. Al final, el diccionario contiene pares de letras y sus frecuencias. Puede ser m´s atractivo mostrar el histograma en orden alfab´tico. Podemos a e hacerlo con los m´todos items y sort: e >>> itemsLetras = cuentaLetras.items() >>> itemsLetras.sort() >>> print itemsLetras [(’M’, 1), (’i’, 4), (’p’, 2), (’s’, 4)] Ya hab´ visto usted el m´todo items, pero sort es el primer m´todo aplicable ıa e e a listas que hemos visto. Hay varios m´s, como append, extend, y reverse. a Consulte la documentaci´n de Python para ver los detalles. o

10.8.

Glosario

diccionario: Una colecci´n de pares clave-valor que establece una correspono dencia entre claves y valores. Las claves pueden ser de cualquier tipo inmutable, los valores pueden ser de cualquier tipo.

e . tambi´n llamado e “asociaci´n”.10. o m´todo: Un tipo de funci´n al que se llama con una sintaxis diferente y al que e o se invoca “sobre” un objeto. 117 par clave-valor: Uno de los elementos de un diccionario. e pista: Almacenamiento temporal de un valor precalculado para evitar c´lculos a redundantes.8 Glosario clave: Un valor que se usa para buscar una entrada en un diccionario. invocar: Llamar a un m´todo. desbordamiento: Un resultado num´rico que es demasiado grande para ree presentarse en formato num´rico.

.

La apertura de un archivo crea un objeto archivo. Para abrir un archivo.dat’. e u pero tambi´n puede ir saltando de una p´gina a otra. mode ’w’ at fe820> . sabe en a e e qu´ lugar del libro se encuentra. Trabajar con archivos se parece mucho a trabajar con libros.Cap´ ıtulo 11 Archivos y excepciones Cuando un programa se est´ ejecutando. >>> f = open("test. disquete o CD-ROM. Casi siempre lee el libro seg´n su orden natural. suelen estar organizados en directou rios (tambi´n llamados “carpetas”). tiene que cerrarlo. especifique su e nombre e indique si quiere leer o escribir. e a Todo esto sirve tambi´n para los archivos. Para usar un libro. ´ o Leyendo y escribiendo archivos. los datos de la memoria desaparecen. los programas pueden intercambiar informaci´n o entre ellos y generar formatos imprimibles como PDF."w") >>> print f <open file ’test. Para almacenar los datos de forma permanente debe usted ponerlos en un archivo.dat". tiene que abrirlo. Cuando ha terminado. En cualquier caso. En este ejemplo. sus datos est´n en la memoria. Cuando hay un gran n´mero de archivos. o se apaga el computador. Cuando a a un programa termina. Cada archivo se identifica con un nombre e unico. la variable f apunta al nuevo objeto archivo. Normalmente los archivos se guardan en un disco duro. Mientras el libro est´ abierto. o una combinaci´n de nombre de archivo y nombre de directorio. puede escribir en ´l o leer de ´l.

recibimos un mensaje de error: >>> f = open("test. Sin argumentos.read(7) Ya es h Si no quedan suficientes caracteres en el archivo. Si no hay un archivo llamado test. y poner su contenido en una cadena."r") >>> print f.120 Archivos y excepciones La funci´n open toma dos argumentos. read tambi´n puede aceptar un argumento que le indica cu´ntos caracteres leer: e a >>> f = open("test. a Al imprimir el objeto archivo. el archivo que a estamos escribiendo lo reemplazar´.write("Ya es hora") >>> f.dat se crear´. El modo ’w’ (write) significa que lo estamos abriendo para escribir. o Para meter datos en el archivo invocamos al m´todo write sobre el objeto e archivo: >>> f.dat". Si ya hay uno.write("de cerrar el archivo") El cierre del archivo le dice al sistema que hemos terminado de escribir y deja el archivo listo para leer: >>> f."r") Si intentamos abrir un archivo que no existe. read devuelve una cadena vac´ ıa: . lee e el archivo completo: >>> text = f. Esta vez el argumento de modo es ’r’ (read) para lectura: >>> f = open("test.close() Ya podemos abrir el archivo de nuevo.cat"."r") IOError: [Errno 2] No such file or directory: ’test. el modo y la localizaci´n del objeto.read() >>> print text Ya es horade cerrar el archivo No hay un espacio entre “hora” y “de” porque no escribimos un espacio entre las cadenas. vemos el nombre del archivo.cat’ Como era de esperar. el m´todo read lee datos del archivo. El primero es el nombre del archivo y o el segundo es el modo. esta vez para lectura.dat". read devuelve los que haya. Cuando llegamos al final del archivo.

1 Archivos de texto >>> print f.11. lo que sucede cuando texto ´ es una cadena vac´ lo que sucede cuando llegamos al final del archivo. Archivos de texto Un archivo de texto es un archivo que contiene caracteres imprimibles y espacios organizados en l´ ıneas separadas por caracteres de salto de l´ ınea. o En este ejmplo. El primer argumento es el nombre del archivo original. leyendo y escribiendo los caracteres de o cincuenta en cincuenta.read(1000006) orade cerrar el archivo >>> print f. "w") while 1: texto = f1.close() return La sentencia break es nueva.close() El m´todo readline lee todos los caracteres hasta e inclusive el siguiente salto e de l´ ınea: . el segundo es el nombre del archivo nuevo: def copiaArchivo(archViejo. Como Python est´ dise˜ado espec´ a n ıficamente para procesar archivos de texto.dat". el bucle while es infinito porque el valor 1 siempre es verdadero. e Para hacer una demostraci´n.1."w") >>> f. Su ejecuci´n interrumpe el bucle.read() >>> 121 La siguiente funci´n copia un archivo. proporciona m´todos que facilitan la tarea. 11.write("l´nea uno\nl´nea dos\nl´nea tres\n") ı ı ı >>> f.close() f2. archNuevo): f1 = open(archViejo. La unica forma de salir del bucle es ejecutar break.write(texto) f1. "r") f2 = open(archNuevo. el flujo de la o ejecuci´n pasa a la primera sentencia tras el bucle. crearemos un archivo de texto con tres l´ o ıneas de texto separadas por saltos de l´ ınea: >>> f = open("test. ıa.read(50) if texto == "": break f2.

close() return La sentencia continue termina la iteraci´n actual del bucle. la salida est´ en forma de lista. lo que significa que las cadenas a aparecen con comillas y el car´cter de salto de l´ a ınea aparece como la secuencia de escape 012.write(texto) f1. El flujo de ejecuci´n pasa al principio del bucle. "r") f2 = open(archNuevo. filtraArchivo hace una copia de archViejo. archNuevo): f1 = open(archViejo. comprueba la condici´n o o y contin´a en consecuencia.readlines() [’l´nea dos\012’. readline devuelve una cadena vac´ y readlines devuelve ıa una lista vac´ ıa: >>> print f.122 >>> f = open("test.dat". omitiendo las l´ ıneas que comienzan por #: def filtraArchivo(archViejo."r") >>> print f.close() f2. Al final del archivo. u . pero sigue haciendo o bucles. "w") while 1: texto = f1.readline() if texto == "": break if texto[0] == ’#’: continue f2.readline() >>> print f.readline() l´nea uno ı >>> Archivos y excepciones readlines devuelve todas las l´ ıneas que queden como una lista de cadenas: >>> print f. ’l´nea tres\012’] ı ı En este caso.readlines() [] Lo que sigue es un ejemplo de un programa de proceso de l´ ıneas.

’ La secuencia de formato ’%f’ formatea el siguiente elemento de la tupla como un n´mero en coma flotante. S´lo si o o ambas condiciones fallan copiamos texto en el archivo nuevo.2. Pero cuando el primer operando es una cadena. 11.6.11. tenemos que convertirlos antes en cadenas. formateados de acuerdo a la cadena de formato. y el segundo operando es una tupla de expresiones. y ’%s’ formatea el siguiente elemento como una u cadena: >>> "En %d d´as ingresamos %f millones de %s. % es el operador de m´dulo. Escribir variables El argumento de write debe ser una cadena.’d´lares’) o ’En 34 d´as ingresamose 6. Cuando aplica a enteros. as´ que si queremos poner otros ı valores en un archivo.2 Escribir variables 123 As´ si texto es una cadena vac´ el bucle termina. a texto es una almohadilla. la secuencia de formato ’%d’ significa que la primera expresi´n de la tupla deber´ formatearse como un entero. de modo que podemos incrustar un valor en una frase: >>> motos = 52 >>> "En julio vendimos %d motos. Una secuencia de formato puede aparecer en cualquier lugar de la cadena de formato. A modo de ejemplo simple. % es o el operador de formato."\ ı % (34." % motos ’En julio vendimos 52 motos. La forma m´s a f´cil de hacerlo es con la funci´n str: a o >>> x = 52 >>> f. el flujo de ejecuci´n va al principio del bucle.write (str(x)) Una alternativa es usar el operador de formato %. Si el primer car´cter de ı. ıa. El resultado es una cadena que contiene los valores de las expresiones. Aqu´ la letra o ıa ı d quiere decir “decimal”: >>> motos = 52 >>> "%d" % motos ’52’ El resultado es la cadena ’52’.’ ı o .100000 miliones de d´lares. El primer operando es la cadena de formato. que no debe confundirse con el valor entero 52.1.

podemos detallar el a u n´mero de d´ u ıgitos como parte de la secuencia de formato: >>> "%6d" % 62 ’ 62’ >>> "%12f" % 6. el resultado ocupa doce espacios e incluye dos d´ ıgitos tras la coma. los tipos de las expresiones deben coincidir con las secuencias de formato: >>> "%d %d TypeError: >>> "%d" % TypeError: %d" % (1. Si el valor necesita menos d´ a u ıgitos.10’ En este ejemplo. el formato de coma flotante imprime seis decimales. Para tener m´s control sobre el formato de los n´meros. no hay suficientes expresiones. se a˜aden espacios en n blanco delante del n´mero. He aqu´ una funci´n que imprime ı o el contenido del diccionario como un informe formateado: def informe (tarifas) : estudiantes = tarifas.2f" % 6.keys() estudiantes. la expresi´n o es de un tipo incorrecto. Igualmente.100000’ El n´mero tras el signo de porcentaje es el n´mero m´ u u ınimo de espacios que ocupar´ el n´mero.1 ’ 6. El n´mero de expresiones en la tupla tiene que coincidir con el n´mero de u u secuencias de formato de la cadena. se a˜aden los u u n espacios tras el n´mero: u >>> "%-6d" % 62 ’62 ’ Tambi´n podemos especificar el n´mero de decimales para los n´meros en coma e u u flotante: >>> "%12.sort() .124 Archivos y excepciones Por defecto. Si el n´mero de espacios es negativo.2) not enough arguments for format string ’d´lares’ o illegal argument type for built-in operation En el primer ejemplo. un diccionario que contiene los nombres de los estudiantes como clave y las tarifas horarias como valores. Este formato es util para imprimir cantidades de dinero con las comas ´ alineadas. Imagine. por ejemplo. en el segundo.1 ’ 6.

El archivo /usr/share/dict/words contiene una lista de palabras en orden alfab´tico. Python lo busca en el directorio en uso.02f" % (estudiante. Directorios Cuando usted crea un archivo nuevo abri´ndolo y escribiendo. que est´ en el directorio de nivel a a a superior del sistema. Encurtido Para poner valores en un archivo. No puede usar / como parte del nombre de un archivo.23. siempre que los nombres tengan menos de veinti´n caracteres u y las tarifas sean menos de mil millones la hora. tarifas[estudiante]) 125 Para probar la funci´n.11.23 Controlando la anchura de cada valor nos aseguramos de que las columnas van a quedar alineadas. que est´ en usr.3 Directorios for estudiante in estudiantes : print "%-20s %12.4.45 jes´s u 4. que est´ en share. debe convertirlos en cadenas. 11. e Del mismo modo. ’jos´’: 5. est´ reservado como a delimitador entre nombres de archivo y directorios. ’jes´s’: 4."r") >>> print f. el nuevo archie vo va al directorio en uso (aqu´l en el que etuviese al ejecutar el programa). crearemos un peque˜o diccionario e imprimiremos el o n contenido: >>> tarifas = {’mar´a’: 6. e 11. Ya ha visto c´mo hacerlo con str: o . tiene que especificar la ruta del archivo.45. la primera de las cuales es el nombre de una universidad danesa. cuando abre un archivo para leerlo.25} ı e u >>> informe (tarifas) jos´ e 5.readline() Aarhus Este ejemplo abre un archivo llamado words que est´ en un directorio llamado a dict. Si quiere abrir un archivo de cualquier otro sitio. llamado /. que es el nombre del directorio (o carpeta) donde se encuentra ´ste: e >>> f = open("/usr/share/dict/words".3.25 mar´a ı 6.

Excepciones Siempre que ocurre un error en tiempo de ejecuci´n. Para usarlo. f) >>> f.write (str([1.pck".3])) Archivos y excepciones El problema es que cuando vuelve usted a leer el valor.3]. o o Normalmente el programa se para y Pythton presenta un mensaje de error.3.3 >>> type(x) <type ’float’> >>> y = pickle. 2.load(f) >>> y [1."r") >>> x = pickle. En realidad.dump(12.2.close() Ahora podemos abrir el archivo para leer y cargar las estructuras de datos que volcamos ah´ ı: >>> f = open("test. 2. no puede distinguir o d´nde termina un valor y comienza el siguiente: o >>> f. . importe pickle o o y luego abra el archivo de la forma habitual: >>> import pickle >>> f = open("test. completo con su tipo original. 11. llamado as´ porque “conserva” estructuras de datos. use el m´todo dump y luego cierre el e archivo de la forma habitual: >>> pickle."w") Para almacenar una estructura de datos. f) >>> pickle.dump([1.load(f) >>> x 12.3[1. Ha perdido la informaci´n del tipo de dato original. obtiene una cadena.pck". 3] >>> type(y) <type ’list’> Cada vez que invocamos load obtenemos un valor del archivo.5. o ı El m´dulo pickle contiene las ´rdenes necesarias.3)) >>> f.126 >>> f.2.write (str(12.readline() ’12. 3]’ La soluci´n es el encurtido. se crea una excepci´n.

o ıa o pero no queremos que se pare el programa. no queremos que el programa se pare.11. pasa por alto la sentencia except. A veces queremos realizar una operaci´n que podr´ provocar una excepci´n.close() . Podemos manejar la excepci´n o usando las sentencias try y except. Si ocurre cualquier excepci´n. Si el archivo no existe. nombreArch u La sentencia try ejecuta las sentencias del primer bloque. la divisi´n por cero crea una excepci´n: o o >>> print 55/0 ZeroDivisionError: integer division or modulo Un elemento no existente en una lista hace lo mismo: >>> a = [] >>> print a[5] IndexError: list index out of range O el acceso a una clave que no est´ en el diccionario: a >>> b = {} >>> print b[’qu´’] e KeyError: qu´ e 127 En cada caso. Si no se produce ninguna excepci´n. o o ejecuta las sentencias de la rama except y despu´s contin´a. podemos preguntar al usuario por el nombre de un archivo y luego intentar abrirlo. e u Podemos encapsular esta capacidad en una funci´n: existe acepta un nombre o de archivo y devuelve verdadero si el archivo existe y falso si no: def existe(nombreArch): try: f = open(nombreArch) f. queremos manejar la excepci´n. pero e o la hemos omitido en los ejemplos. el mensaje de error tiene dos partes: el tipo de error antes de los dos puntos y detalles sobre el error depu´s de los dos puntos. "r") except: print ’No hay ning´n archivo que se llame’. o nombreArch = raw_input(’Introduce un nombre de archivo: ’) try: f = open (nombreArch.5 Excepciones Por ejemplo. Normalmente e Python tambi´n imprime una traza de d´nde se encontraba el programa. Por ejemplo.

tambi´n llamado carpeta. puede hacer que lance (raise en o ingl´s) una excepci´n. de archivos. o e ruta: Una secuencia de nombres de directorio que especifica la localizaci´n o exacta de un archivo. lanzamos una excepci´n. ErrorN´meroMalo es un nuevo tipo de excepci´n que u o hemos inventado para esta aplicaci´n. escriba una funci´n que use tomaNumero para leer o un n´mero del teclado y que maneje la excepci´n ErrorN´meroMalo. El Manual de Referencia de Python contiene los detalles. . Aqu´ tiene usted un ejemplo que acepta una entrada del e o ı usuario y comprueba si es 17. los acentos est´n a # prohibidos en los nombres # de funciones y variables! un mal n´mero’ u La sentencia raise acepta dos argumentos: el tipo de excepci´n e informaci´n o o espec´ ıfica acerca del error. que contiene una secuencia de caracteres. o Como ejercicio. o Si la funci´n llamada tomaNumero maneja el error. directorio: Una colecci´n. disquete o CD-ROM. el programa puede continuar. Python imprime el mensaje de error y sale: >>> tomaNumero () Elige un n´mero: 17 u ErrorN´meroMalo: 17 es un mal n´mero u u El mensaje de error incluye el tipo de excepci´n y la informaci´n adicional que o o usted proporcion´. Glosario archivo: Una entidad con nombre. u o u 11.128 return 1 except: return 0 Archivos y excepciones Puede usar m´ltiples bloques except para manejar diferentes tipos de excepu ciones. ’17 es u return x # Recuerde. o o def tomaNumero () : x = input (’Elige un n´mero: ’) u if x == 17 : raise ’ErrorN´meroMalo’. o en caso contrario. normalmente almacenada en un disco duro. Suponiendo que 17 no es una entrada v´lida por a cualquier raz´n. Si su programa detecta una condici´n de error. con nombre.6.

o operador de formato: El operador % toma una cadena de formato y una tupla de expresiones y entrega una cadena que incluye las expresiones. El flujo de la ejecuci´n va al principio del bucle. formateadas de acuerdo con la cadena de formato. eval´a o u la condici´n. n o . sentencia break: Una sentencia que provoca que el flujo de ejecuci´n salga de o un bucle. a excepci´n: Un error que ocurre en tiempo de ejecuci´n. y procede en consecuencia.11. o encurtir: Escribir el valor de un dato en un archivo junto con la informaci´n o sobre su tipo de forma que pueda ser reconstituido m´s tarde. sentencia continue: Una sentencia que provoca que termine la iteraci´n aco tual de un bucle. lanzar: Se˜alar una excepci´n usando la sentencia raise. o secuencia de formato: Una secuencia de caracteres que comienza con % e indica c´mo formatear un valor. cadena de formato: Una cadena que contiene caracteres imprimibles y secuencias de formato que indican c´mo formatear valores. o o manejar: Impedir que una excepci´n detenga un programa utilizando las seno tencias try y except.6 Glosario 129 archivo de texto: Un archivo que contiene caracteres imprimibles organizados en l´ ıneas separadas por caracteres de salto de l´ ınea.

.

pero o a tiene sus ventajas que pronto se har´n evidentes. Una forma natural de representar un punto en Python es con dos valores en coma flotante. los puntos suelen escribirse entre par´ntesis con una o a e coma separando las coordenadas. un punto es a dos n´meros (coordenadas) que se tratan colectivamente como un solo objeto. 0) representa el origen.1. u En notaci´n matem´tica. tambi´n e llamado una clase. Tipos compuestos definidos por el usuario Una vez utilizados algunos de los tipos internos de Python. a Una definici´n de clase se parece a esto: o class Punto: pass Las definiciones de clase pueden aparecer en cualquier lugar de un programa. Piense en el concepto de un punto matem´tico. Por ejemplo. Esta aproximaci´n exige un poco m´s de esfuerzo. (0. La cuesti´n es. y (x. entonces. La soluci´n r´pida y burda es utilizar una lista o tupla.Cap´ ıtulo 12 Clases y objetos 12. En dos dimensiones. pero normalmente est´n al principio (tras las sentencias import). c´mo agrupar esos dos valores en un o o objeto compuesto. Las reglas a . estamos listos para crear un tipo definido por el usuario: el Punto. y o a para algunas aplicaciones esa podr´ ser la mejor opci´n. ıa o Una alternativa es que el usuario defina un nuevo tipo compuesto. y) representa el punto x unidades a la derecha e y unidades hacia arriba desde el origen.

132 Clases y objetos sint´cticas de la definici´n de clases son las mismas que para cualesquiera otras a o sentencias compuestas.0 >>> blanco. La creaci´n o de una nueva instancia se llama instanciaci´n.0 .2.0 >>> x = blanco. sin embargo. Atributos Podemos a˜adir nuevos datos a una instancia utilizando la notaci´n de punto: n o >>> blanco. que tambi´n se llama Punto.y 4. Al crear la clase Punto hemos creado un nuevo tipo. estamos seleccionando un dato de una instancia. o 12. s´lo es necesaria porque una sentencia compuesta debe tener algo en su o cuerpo. La sentencia pass no tiene o efectos. Estos ´ ıtemes con nombre se llaman atributos. u Podemos leer el valor de un atributo utilizando la misma sintaxis: >>> print blanco. (ver la Secci´n 4.uppercase. A una funci´n como Punto que crea un objeto nuevo se le llama constructor.0 Esta sintaxis es similar a la sintaxis para seleccionar una variable de un m´duo lo. Para instanciar un objeto Punto o ejecutamos una funci´n que se llama (lo ha adivinado) Punto: o blanco = Punto() A la variable blanco se le asigna una referencia a un nuevo objeto Punto.pi o string. o Esta definici´n crea una nueva clase llamada Punto.y = 4. Cada atributo apunta a un n´mero en coma flotante.x = 3. En este caso.0 La variable blanco apunta a un objeto Punto.x >>> print x 3.4). e Los miembros de este tipo se llaman instancias del tipo u objetos. como math.0 4. que contiene dos atributos. El diagrama de estados que sigue muestra el resultado de esas asignaciones: blanco x y 3.

x) + ’. ’ + str(p. En breve ver´ c´mo cambiarlo. Si llama a imprimePunto(blanco). e Puede usted usar la notaci´n de punto como parte de cualquier expresi´n. 4.y) + ’)’ imprimePunto acepta un punto como argumento y lo muestra en formato est´ndar.x significa. reescriba la funci´n distancia de la Secci´n 5.0. Por a ejemplo: def imprimePunto(p): print ’(’ + str(p. Probablemente no es esta la manera m´s clara de mostrar un a objeto Punto.0. Puede tentarle imprimir el propio valor de blanco: >>> print blanco <__main__.3 Instancias como par´metro a 133 La expresi´n blanco. No hay conflicto entre la variable x y el atributo x.2 de o o forma que acepte dos Puntos como par´metros en lugar de cuatro a n´meros. ’ + str(blanco. As´ o o ı.0). asignamos ese valor a una variable llamada x. Instancias como par´metro a Puede usted pasar una instancia como par´metro de la forma habitual. cree e imprima un objeto Punto y luego use id para imprimir el identificador unico del objeto.12.3.y) + ’)’ distanciaAlCuadrado = blanco.x + blanco. El prop´sito de la notaci´n de punto o o es identificar de forma inequ´ ıvoca a qu´ variable se refiere. En este caso. Traduzca el n´mero ´ u hexadecimal a decimal y aseg´rese de que coinciden.0).0. “ve al objeto al que apunta blanco y toma el o valor de x”. escrito en o ´ hexadecimal.x * blanco.Punto instance at 80f8e70> El resultado indica que blanco es una instancia de la clase Punto que se defini´ en main .y La primera l´ ınea presenta (3. u . u 12. el resultado es (3. la segunda l´ ınea calcula el valor 25. a Como ejercicio.y * blanco. 80f8e70 es el identificador unico de este objeto. 4. las sentencias que siguen son correctas: print ’(’ + str(blanco.x) + ’. a o Como ejercicio.

Por ejemplo.x = 3 p1. las dos variables son alias del mismo objeto: >>> >>> 1 p2 = p1 p1 == p2 Este tipo de igualdad se llama igualdad superficial porque s´lo compara las o referencias. pero no el contenido de los objetos. Si dice “Pepe y yo tenemos la misma madre”.x = 3 p2. Por ejemplo. Si asignamos p1 a p2. lo que quiere decir es que su moto y la de usted son de la misma marca y modelo. “Misma moto” en este contexto ser´ “gleiche ıa Motorrad” y “misma madre” ser´ “selbe Mutter”.y == p2.x == p2. Para comparar los contenidos de los objetos (igualdad profunda) podemos escribir una funci´n llamada mismoPunto: o def mismoPunto(p1. ıa . y entonces se da cuenta de que hay algo m´s de lo que a supon´ ıa. si dos u Puntos son el mismo. quiere decir que su madre y la de usted son la misma persona1 . Por ejemplo: >>> >>> >>> >>> >>> >>> >>> 0 p1 = Punto() p1. Por ejemplo.y) 1 No todas las lenguas tienen el mismo problema. As´ que la idea de “identidad” ı es diferente seg´n el contexto. p2) : return (p1. utilice el operador ==. no son el mismo objeto. u Cuando habla de objetos. el alem´n tiene palabras a diferentes para los diferentes tipos de identidad. pero que son dos motos distintas. hay una ambig¨edad parecida. ¿significa que contienen los mismos datos (coordenadas) o que son de verdad el mismo objeto? Para averiguar si dos referencias se refieren al mismo objeto. si dice “Pepe y yo tenemos la misma moto”.y = 4 p1 == p2 Aunque p1 y p2 contienen las mismas coordenadas.134 Clases y objetos 12.4. Mismidad El significado de la palabra “mismo” parece totalmente claro hasta que uno se para un poco a pensarlo.x) and (p1.y = 4 p2 = Punto() p2.

caja.y = 4 p2 = Punto() p2.y = 0. . Tenemos varias posibilidades: podemos se˜alar el centro del rect´ngulo (dos n a coordenadas) y su tama˜o (anchura y altura).5. n a n De nuevo.anchura = 100.x = 3 p2. definiremos una nueva clase: class Rectangulo: # Prohibidos los acentos fuera de las cadenas! pass Y la instanciaremos: caja = Rectangulo() caja. La pregunta es.12. Un modo conn n vencional es se˜alar la esquina superior izquierda del rect´ngulo y el tama˜o.esquina.altura = 200.5 Rect´ngulos a 135 Si ahora creamos dos objetos diferentes que contienen los mismos datos podremos usar mismoPunto para averiguar si representan el mismo punto: >>> >>> >>> >>> >>> >>> >>> 1 p1 = Punto() p1. o podemos se˜alar dos esquinas opuestas. supongamos que el rect´ngulo est´ orientado vertical u a a horizontalmente. nunca en diagonal. si las dos variables apuntan al mismo objeto mismoPunto devuelve verdadero. Rect´ngulos a Digamos que queremos una clase que represente un rect´ngulo.x = 0.0 caja. a ¿qu´ informaci´n tenemos que proporcionar para definir un rect´ngulo? Para e o a simplificar las cosas.x = 3 p1. 12.esquina.y = 4 mismoPunto(p1. p2) Por supuesto.0 Este c´digo crea un nuevo objeto Rectangulo con dos atributos en coma floo tante.0. ¡Para se˜alar la esquina superior izquierda podemos incrustar un objeto n dentro de otro! caja.esquina = Punto() caja.0. o podemos se˜alar una de las n n esquinas y el tama˜o.

0 return p Para llamar a esta funci´n. encuentraCentro acepta un Rectangulo como argumento y devuelve un Punto que contiene las coordenadas del centro del Rectangulo: def encuentraCentro(caja): p = Punto() p.altura + 100 Podemos encapsular este c´digo en un m´todo y generalizarlo para agrandar el o e rect´ngulo en cualquier cantidad: a . Instancias como valores de retorno Las funciones pueden devolver instancias. Los objetos son mudables Podemos cambiar el estado de un objeto efectuando una asignaci´n sobre uno o de sus atributos.0 p.anchura + 50 caja.altura/2.0 12.136 Clases y objetos El operador punto compone. entonces ve a ese objeto y selecciona el atributo llamado x”.0.7.anchura/2. La expresi´n caja.0 200.0 x y 0.x = caja.esquina.0 0. 100.6.y = caja. podemos cambiar los valores de anchura y altura: o caja. pase caja como argumento y asigne el resultado a o una variable: >>> centro = encuentraCentro(caja) >>> imprimePunto(centro) (50.y + caja.altura = caja.0) 12.x significa “ve al obo jeto al que se refiere caja y selecciona el atributo llamado esquina. Por ejemplo. para cambiar el tama˜o de un rect´ngulo sin n a cambiar su posici´n.esquina. La figura muestra el estado de este objeto: caja anchura altura esquina 100.x + caja.anchura = caja.esquina. Por ejemplo.

altura + daltura 137 Las variables danchura y daltura indican cu´nto debe agrandarse el rect´ngulo a a en cada direcci´n. podemos crear un nuevo Rectangulo llamado bob y pas´rselo a a agrandaRect: >>> >>> >>> >>> >>> >>> >>> bob = Rectangulo() bob.0 bob.x = 0.8. Copiar un objeto es.y = 4 p2 = copy. Es dif´ estar al tanto de todas las variables a las que puede apuntar un objeto ıcil dado.esquina = Punto() bob.8 Copiado def agrandaRect(caja.altura = 200.anchura = 100. Por ejemplo. bob. agrandaRect(bob.0. Copiado El uso de alias puede hacer que un programa sea dif´ de leer.x = 3 p1. porque los ıcil cambios hechos en un lugar pueden tener efectos inesperados en otro lugar. Tiene que a cambiar la posici´n del rect´ngulo a˜adiendo dx a la coordenada x o a n de esquina y a˜adiendo dy a la coordenada y de esquina. n 12. Invocar este m´todo tiene el efecto de modificar el Rectangulo o e que se pasa como argumento.anchura + danchura caja.esquina.0 bob.0. a a Cualquier cambio que haga a caja afectar´ tambi´n a bob. El o m´dulo copy contiene una funci´n llamada copy que puede duplicar cualquier o o objeto: >>> >>> >>> >>> >>> >>> import copy p1 = Punto() p1. escriba una funci´n llamada mueveRect que o tome un Rectangulo y dos par´metros llamados dx y dy.esquina. una alternativa a la creaci´n de un alias. daltura) : caja.y = 0.anchura = caja. a e A modo de ejercicio.altura = caja. muchas veces. 50. 100) Mientras agrandaRect se est´ ejecutando.copy(p1) p1 == p2 . el par´metro caja es un alias de bob. danchura.12.

anchura = nuevaCaja.anchura + danchura nuevaCaja.deepcopy(b1) Ahora b1 y b2 son objetos totalmente independientes.0 0.0 200. cree un nuevo Rectangulo que tiene la misma localizaci´n que el viejo pero nuevas dimensiones: o def agrandaRect(caja. p2) 1 Clases y objetos Una vez que hemos importado el m´dulo copy. p1 y p2 no son el mismo punto. el diagrama de estados resultante se ve as´ ı: b1 anchura altura esquina 100.0 x y 0. copy es suficiente.0 anchura altura esquina b2 Es casi seguro que esto no es lo que queremos. que contiene una referencia a un Punto. de la forma habitual y entonces hacemos una copia. Esto se llama copiado superficial. Para copiar un objeto simple como un Punto.altura + daltura return nuevaCaja .0 100. b1. ´ Si creamos una caja. copy no lo hace del todo bien. b2. Para algo como un Rectangulo.138 0 >>> mismoPunto(p1. el m´dulo copy contiene un m´todo llamado deepcopy que o e copia no s´lo el objeto sino tambi´n cualesquiera objetos incrustados.deepcopy(caja) nuevaCaja. pero contienen los mismos datos. podemos usar el m´todo copy o e para hacer un nuevo Punto. de modo que tanto el Rectangulo viejo como el nuevo apuntan a un unico Punto.altura = nuevaCaja. la invocaci´n de o agrandaRect sobre uno de los Rectangulos no afectar´ al otro. Copia la referencia al objeto Punto. No le o e sorprender´ saber que esta operaci´n se llama copia profunda (deep copy). ¡pero la invoıa caci´n de mueveRect sobre cualquiera afectaria a ambos! Este comportamiento o es confuso y propicia los errores. que no contiene objetos incrustados. daltura) : import copy nuevaCaja = copy. usando copy. Afortunadamente. danchura. a o >>> b2 = copy. En este caso.0 200. Podemos usar deepcopy para reescribir agrandaRect de modo que en lugar de modificar un Rectangulo existente.

constructor: Un m´todo usado para crear nuevos objetos. y as´ sucesivamente.9. igualdad profunda: Igualdad de valores. Glosario clase: Un tipo compuesto definido por el usuario. instanciar: Crear una instancia de una clase. incluyendo cualquier referencia a objetos incrustados. copia profunda: Copiar el contenido de un objeto as´ como cualesquiera obı jetos incrustados. e atributo: Uno de los elementos de datos con nombre que constituyen una instancia. y los incrustados en estos. copia superficial: Copiar el contenido de un objeto. implementada por la funci´n copy del m´dulo o o copy. Tambi´n se puede pensar e en una clase como una plantilla para los objetos que son instancias de la misma.9 Glosario Como ejercicio.12. o o . o dos referencias que apuntan al mismo objeto. impleı mentada por la funci´n deepcopy del m´dulo copy. igualdad superficial: Igualdad de referencias. instancia: Un objeto que pertenece a una clase. o dos referencias que apuntan a objetos que tienen el mismo valor. 139 12. objeto: Un tipo de dato compuesto que suele usarse para representar una cosa o concepto del mundo real. resscriba mueveRect de modo que cree y devuelva un nuevo Rectangulo en lugar de modificar el viejo.

.

escriba una funci´n imprimeHora que acepo te un objeto Hora como argumento y lo imprima en el formato horas:minutos:segundos. definiremos una clase llamada Hora que registra la hora del d´ La definici´n de la clase es como ıa.horas = 11 hora. o sigue: class Hora: pass Podemos crear un nuevo objeto Hora y asignar atributos para contener las horas. Hora Como otro ejemplo de un tipo definido por el usuario. . minutos y segundos: hora = Hora() hora.minutos = 59 hora.Cap´ ıtulo 13 Clases y funciones 13.segundos = 30 El diagrama de estado del objeto Hora es as´ ı: time hour minute second 11 59 30 A modo de ejercicio.1.

Aqu´ tiene un ejemplo de c´mo usar esta funci´n. escribiremos dos versiones de una funci´n llamada o o sumaHora que calcule la suma de dos Horas.142 Clases y funciones Como un segundo ejercicio. y horaPan. escriba una funci´n booleana despues o que tome dos objetos Hora.horas = 3 horaPan.horas + t2. Crearemos dos objetos Hora: ı o o horaActual. t1 y t2.minutos = t1. A esto se le llama funci´n pura porque no modifica o ninguno de los objetos que se le pasan y no tiene efectos laterales.minutos suma.segundos = 0 >>> horaHecho = sumaHora(horaActual. como mostrar un valor o tomar una entrada del usuario.2. Luego usaremos sumaHora para averiguar cu´ndo estar´ hecho el pan. 13.minutos = 35 horaPan.minutos + t2. Mostrar´n dos tipos de funciones: a funciones puras y modificadores.segundos return suma La funci´n crea un nuevo objeto Hora.segundos = t1. que contiene la hora actual. que contiene la cantidad de tiempo que necesita un panadero para hacer pan.2 antes de probar esto: o >>> >>> >>> >>> >>> >>> >>> >>> horaActual = Hora() horaActual. t2): suma = Hora() suma.segundos = 30 horaPan = Hora() horaPan. horaPan) >>> imprimeHora(horaHecho) . Si a´n no ha terminado de escribir a a u imprimeHora. inicializa sus atributos y devuelve una o referencia al nuevo objeto. eche un vistazo a la Secci´n 14.horas suma.horas = 9 horaActual.segundos + t2. como argumentos y devuelva verdadero (1) si t1 sigue cronol´gicamente a t2 y falso (0) en caso o contrario. ´ Este es un esbozo de sumaHora: def sumaHora(t1. Funciones puras En las pr´ximas secciones.horas = t1.minutos = 14 horaActual.

Un esbozo r´pido de la funci´n ıa a o podr´ ser ´ste: ıa e .60 suma.3 Modificadores 143 La salida de este programa es 12:49:30. o a o a 13.horas suma. as´ que cualquier cambio que la funci´n haga ser´ visible ı o a para el llamante. Por otra parte.horas + t2.minutos .minutos = t1.segundos if suma. se n u escribir´ de forma natural como un modificador.minutos suma. t2): suma = Hora() suma.60 suma. Cuando ocurre eso. ¿Puede imaginar uno? El problema es que esta funci´n no trata los casos en los que el n´mero de o u segundos o minutos suma m´s que sesenta. ı incremento.segundos . lo que es correcto.horas + 1 return suma Aunque esta funci´n es correcta.segundos = suma. hay casos en los que el resultado no es correcto.minutos = suma. M´s adelante sugeriremos o a una aproximaci´n alternativa que nos dar´ un c´digo m´s corto. que a˜ade un n´mero dado de segundos a un objeto Hora.minutos + 1 if suma.minutos = suma.13. Normalmente.segundos + t2. Modificadores Hay veces en las que es util que una funci´n modifique uno o m´s de los objetos ´ o a que recibe como par´metros. He aqu´ una versi´n corregida de la funci´n: ı o o def sumaHora(t1. Las funciones que trabajan as´ se llaman modificadores.minutos + t2.horas = suma. debemos “llevar” a los segundos sobrantes a la columna de los minutos o los minutos extras a la columna de las horas.minutos >= 60: suma. el llamante conserva una referencia a a los objetos que pasa. empieza a ser grande.horas = t1.segundos >= 60: suma.3.segundos = t1.

y escriba una funci´n que llame a ambas versiones. debemos seguir haci´ndolo hasta que segundos sea menor que sesenta. o 13.minutos + 1 if hora.segundos = hora.minutos >= 60: hora.minutos .minutos = hora.minutos + 1 while hora.minutos = hora. Como un segundo ejercicio. pero no es la soluci´n m´s eficiente. Una soluci´n es e o sustituir las sentencias if por sentencias while: def incremento(hora.60 hora. Hay ciertas evidencias de que los programas que usan funciones puras son m´s r´pidos de desarrollar y menos propensos a los errores que a a .horas + 1 Ahora esta funci´n es correcta.segundos = hora. no es suficiente con acarrear una vez.segundos + segundos if hora.segundos .segundos = hora. En realidad.minutos .60 hora. reescriba esta funci´n de modo que no contenga tano tos bucles. o o a Como ejercicio.60 hora.horas + 1 Clases y funciones La primera l´ ınea realiza la operaci´n b´sica.horas = hroa. algunos lenguajes de programaci´n s´lo permiten o o funciones puras. segundos): hora. ¿Es correcta esta funci´n? ¿Qu´ ocurre si el par´metro segundos es mucho o e a mayor que sesenta? En tal caso. ¿Qu´ es mejor? e Todo lo que se pueda hacer con modificadores puede hacerse tambi´n con fune ciones puras.segundos >= 60: hora.segundos >= 60: hora.segundos = hora.144 def incremento(hora.segundos + segundos while hora. reescriba incremento como una funci´n o pura.minutos = hora.60 hora.horas = hroa.4. las restantes tratan con los casos o a especiales que vimos antes.minutos = hora.minutos >= 60: hora. segundos): hora.segundos .

Desarrollo de prototipos frente a planificaci´n o En este cap´ ıtulo mostramos una aproximaci´n al desarrollo de programas a la o que llamamos desarrollo de prototipos.5. a Aunque este enfoque puede ser efecitvo. el componente minuto es la “columna de las sesententas” y el componente hora es la “columna de las tresmilseiscentenas”. y en algunos casos los programas funcionales son menos eficientes. y poco fiable.horas * 60 + t. escribimos un esbozo basto (o prototipo) que realizaba el c´lculo b´sico y luego lo probamos sobre a a unos cuantos casos.minutos segundos = minutos * 60 + t. ıcil o Una alternativa es el desarrollo planificado. Sin embargo. puede conducirnos a c´digo que es o innecesariamente complicado. recomendamos que escriba funciones puras siempre que sea razonable hacerlo as´ y recurra a los modificadores s´lo si hay una ventaja convincente. La siguiente funci´n convierte un objeto Hora en e o un entero: def convierteASegundos(t): minutos = t.segundos return segundos Ahora. el enfoque es que un objeto Hora es en realidad ¡un n´mero de tres d´ u ıgitos en base 60! El componente segundo es la “columna de unidades”. a veces los modificadores son utiles. s´lo necesitamos una forma de convertir un entero en un objeto Hora: o def haceHora(segundos): hora = Hora() hora. en el que una comprensi´n del o problema en profundidad puede hacer la programaci´n mucho m´s f´cil. corrigiendo los fallos tal como los encontr´bamos. En este o a a caso. ı o Este enfoque podr´ llamarse estilo funcional de programaci´n. en realidad est´bamos haciendo a una suma en base 60. ya que trata con muchos casos especiales.horas = segundos/3600 . ıa o 13. que es por lo que deb´ ıamos acarrear de una columna a la siguiente.5 Desarrollo de prototipos frente a planificaci´n o 145 los programas que usan modificadores. Podemos convertir un o objeto Hora en un simple n´mero y sacar provecho del hecho de que la m´quina u a sabe la aritm´tica necesaria. En cada caso. Esta observaci´n sugiere otro enfoque para el problema. porque es dif´ saber si encontr´ todos los errores. Cuando escribimos sumaHora e incremento.13. ´ En general.

.segundos = segundos return hora Clases y funciones Puede que tenga usted que pensar un poco para convencerse de que esta t´cnie ca para convertir de una base a otra es correcta. a a 13. o a nuestra intuici´n para tratar con las horas es mejor. Con el uso de las funciones de conversi´n ıa o ser´ m´s f´cil y con mayor probabilidad.7. Algoritmos Cuando escribe una soluci´n general para una clase de problemas. Por ejemplo. ha escrito un algoritmo. a a a Ir´nicamente. puede usar estas funciones para reescribir sumaHora: def sumaHora(t1. correcto. o Pero si tenemos la comprensi´n para tratar las horas como n´meros en base 60.minutos * 60 hora. 13.hora. La conversi´n de base es m´s abstracta. m´s f´cil de leer y a a a depurar y m´s fiable. que las funciones a las que llama son correctas).146 segundos = segundos . Generalizaci´n o De alg´n modo.horas * 3600 hora. t2): segundos = convierteASegundos(t1) + convierteASegundos(t2) return haceHora(segundos) Esta versi´n es mucho m´s corta que la original.hora. y o u hacer la inversi´n de escribir las funciones de conversi´n (convierteASegundos o o y haceHora).6. reescriba incremento de la misma forma. a veces hacer un poblema m´s complejo (o m´s general) lo hace o a a m´s f´cil (porque hay menos casos especiales y menos oportunidades de error). Suponiendo que est´ usted a convencido. Como ejercicio. como es habitual. y es mucho m´s f´cil de deo a a a mostrar que es correcta (suponiendo. La aproximaci´n ingenua o ser´ implementar la resta con acarreo. en contraste o con una soluci´n espec´ o ıfica a un problema concreto. convertir de base 60 a base 10 y de vuelta es m´s dif´ que u a ıcil simplemente manejarse con las horas. imagine e a a n a restar dos Horas para hallar el intervalo entre ellas.minutos = segundos/60 segundos = segundos . a Tambi´n es m´s f´cil a˜adir funcionalidades m´s tarde. obtenemos un programa que es m´s corto.

as´ que probaremos un par de enfoques. ¡Eso es o u un algoritmo! De forma similar. La mayor´ de las funciones puras son rentables. Pero si usted era “harag´n” probablemente hizo trampa aprendiendo algunos a trucos. ıa desarrollo de prototipos: Una forma de desarrollar programas empezando con un prototipo y prob´ndolo y mejor´ndolo gradualmente. son las m´s dif´ a ıciles de expresar algor´ ıtmicamente. para encontrar el producto de n por 9. memoriz´ 100 soluciones espec´ o ıficas. de forma bastante similar. probablemente memoriz´ la tabla de multiplicar. a ıa modificador: Una funci´n que modifica uno o m´s de los objetos que recibe o a como par´metros. puede escribir n − 1 como el primer d´ ıgito y 10 − n como el segundo d´ ıgito. Entender el lenguaje natural es un buen ejemplo. al menos no en la forma o de un algoritmo. sin dificultad ni pensamiento consciente.8 Glosario 147 Mencionamos esta palabra antes pero no la definimos con precisi´n. En nuestra opini´n. La mayor´ de los modificadores no entregan resultado. 13. el proceso de dise˜ar algoritmos es interesante. Una de las caracter´ o ısticas de los algoritmos es que no requieren inteligencia para llevarse a cabo.13. a a . Glosario funci´n pura: Una funci´n que no modifica ninguno de los objetos que recibe o o como par´metros. Algunas de las cosas que la gente hace naturalmente. Por ejemplo. Cuando usted aprendi´ a mulo tiplicar n´meros de una cifra. pero hasta el momento nadie ha sido capaz de explicar c´mo lo hacemos. Por otra parte. Todos lo hacemos. no exigen inteligencia. Este truco es una soluci´n general para multiplicar cualquier n´mero de una cifra por 9. u o En efecto. un desaf´ inten ıo lectual y una parte primordial de lo que llamamos programar. Ese tipo de conocimiento no es algor´ ıtmico. Son procesos mec´nicos en los que cada paso sigue al anterior de acuerdo a un conjunto simple a de reglas. piense en algo que no es un algoritmo. No es f´cil o a de definir.8. las t´cnicas que aprendi´ para la suma y la resta con acae o rreo y la divisi´n larga son todas algoritmos. ı Primero. a ıa estilo funcional de programaci´n: Un estilo de programaci´n en el que la o o mayor´ de las funciones son puras. es un poco vergonzoso que los humanos pasen tanto tiempo o en la escuela aprendiendo a ejecutar algoritmos que.

algoritmo: Un conjunto de instrucciones para solucionar una clase de problemas por medio de un proceso mec´nico sin intervenci´n de inteligencia. a o .148 Clases y funciones desarrollo planificado: Una forma de desarrollar programas que implica una comprensi´n de alto nivel del problema y m´s planificaci´n que desarrollo o a o incremental o desarrollo de prototipos.

no nos hemos aprovechado de las caracter´ ısticas que Python nos ofrece para dar soporte a la programaci´n orientada a objetos. Hablando estrico tamente. y la mayor parte de la computaci´n se expresa en t´rminos de o e operaciones sobre objetos. De forma similar. a Hasta ahora. . una sintaxis alternativa para cosas que ya hemos hecho. ponden con el tipo de cosas que la gente hace con las horas. En su mayor´ proporcionan ıa. la clase Hora definida en el Cap´ ıtulo 13 se corresponde con la forma en la que la gente registra la hora del d´ y las funciones que definimos se corresıa. estas caracter´ ısticas no son necesarias. Cada definici´n de un objeto se corresponde con un objeto o concepto del o mundo real.Cap´ ıtulo 14 Clases y m´todos e 14. No es f´cil definir la programaci´n orientada a objetos. las clases Punto y Rectangulo se corresponden con los conceptos matem´ticos a de un punto y un rect´ngulo.1. pero ya hemos visto a o algunas de sus caracter´ ısticas: Los programas se hacen a base de definiciones de objetos y definiciones de funciones. Caracter´ ısticas de la orientaci´n a objetos o Python es un lenguaje de programaci´n orientado a objetos. pero en muchos casos. lo que signio fica que porporciona caracter´ ısticas que apoyan la programaci´n orientada o a objetos. u Por ejemplo. y las funciones que operan en ese objeto se corresponden con las formas en que interact´an los objetos del mundo real.

minutos = 14 horaActual. Esta transformaci´n es puramente mec´nica. o e e como keys y values. Observando bien.150 Clases y m´todos e la alternativa es m´s concisa y expresa con m´s precisi´n a la estructura del a a o programa. o e La sintaxis para invocar un m´todo es diferente de la de una llamada a e una funci´n. con dos diferencias: e Los m´todos se definen dentro de una definici´n de clase para explicitar e o la relaci´n entre la clase y el m´todo.segundos = 30 impriemHora(horaActual) .minutos) + ":" + str(hora. a Los m´todos son como las funciones. a Esta observaci´n es la que motiva los m´todos. o En las pr´ximas secciones tomaremos las funciones de los cap´ o ıtulos anteriores y las transformaremos en m´todos. que deber´ ser parecida a esto: ıa class Hora: pass def imprimeHora(hora): print str(hora. pas´bamos un objeto Hora como par´metro: o a a >>> >>> >>> >>> >>> horaActual = Hora() horaActual. en el programa Hora no hay una conexi´n obvia entre la definici´n o o de la clase y las definiciones de las funciones que siguen. definimos una clase llamada Hora y escribimos una fuci´n o llamada imprimeHora.segundos) Para llamar a esta funci´n. Por ejemplo. se hace patente que todas esas funciones toman al menos un objeto Hora como par´metro. 14.horas = 9 horaActual.horas) + ":" + str(hora. e o a puede hacerla simplemente siguiendo una secuencia de pasos. Cada m´todo est´ asoe a ciado con una clase y est´ pensado para invocarse sobre instancias de esa clase. Ya hemos visto varios m´todos. que se invocan sobre diccionarios.2. Si se acostumbra a convertir de una forma a la otra ser´ capaz de elegir la mejor forma de hacer a lo que quiere. imprimeHora En el Cap´ ıtulo 13.

F´ o o o ıjese en c´mo cambia el sangrado. Para ahoo e rrar espacio. pero usted deber´ e ıa mantenerlos en su versi´n: o class Hora: #aqu´ van las definiciones anteriores de m´todos. En los ejemplos que hemos visto hasta ahora. as´ que e a ı en este caso horaActual se asigna al par´metro hora. pero no es obvio que sea a util. imprimeHora(horaActual).horas) + ":" + str(hora. a Por convenio.segundos) Ahora podemos invocar imprimeHora usando la notaci´n de punto.imprimeHora() Como es habitual.3) en un m´todo. e El objeto sobre el que se invoca el m´todo se asigna al primer par´metro. Dice algo como “¡Oye imprimeHora! Aqu´ hay o ı un objeto para que lo imprimas”..minutos) + ":" + str(hora.3 Otro ejemplo 151 Para convertir imprimeHora en un m´todo. sugiere o que la funci´n es el agente activo. a a a a o 14. o class Hora: def imprimeHora(hora): print str(hora. La raz´n de a e o esto es un tanto rebuscada. o >>> horaActual. a ´ La sintaxis para la llamada a una funci´n. Otro ejemplo Vamos a convertir incremento (de la Secci´n 13.imprimeHora() dice “¡Oye horaActual! ¡Impr´ o ımete!” Este cambio de perspectiva puede ser m´s elegante. puede no serlo. y hace m´s f´cil mantener y reutilizar c´digo.14. ı e . Una ino vocaci´n como horaActual. el primer par´metro de un m´todo se llama self. el objeto sobre el que se invoca el m´todo aparece delante e del punto y el nombre del m´todo aparece tras el punto.. dejaremos a un lado los m´todos ya definidos. los objetos son los agentes activos. pero se basa en una met´fora util.3. todo lo que necesitamos hacer es e mover la definici´n de la funci´n al interior de la definici´n de la clase. Pero a veces ´ transferir la responsabilidad de las funciones a los objetos hace posible escribir funciones m´s vers´tiles. En programaci´n orientada a objetos.

horas + 1 La transformaci´n es puramente mec´nica.4.horas: return 0 if self.minutos >= 60: self.minutos = self.60 self.segundos = self.minutos + 1 while self.horas < hora2.horas = self. ı e def despues(self.5) o en un m´todo de la clase Hora. El segundo par´metro.60 self. e horaActual.segundos .minutos > hora2. hora2): if self. no s´lo sobre uno.. el otro se queda como est´: a class Hora: #aqu´ van las definiciones anteriores de m´todos. segundos): self.horas > hora2. a Ahora podemos invocar incremento como un m´todo. e 14. Un ejemplo m´s complicado a La funci´n despues es ligeramente m´s complicada porque opera sobre dos o a objetos Hora.minutos: return 1 .segundos >= 60: self.minutos .incremento(500) De nuevo.. convierta convertirASegundos (de la Secci´n 13. el objeto sobre el que invocamos el m´todo se asigna al primer par´mee a tro. hemos llevado la definici´n del m´too a o e do al interior de la definici´n de la clase y hemos cambiado el nombre del primer o par´metro. self.horas: return 1 if self. a Como ejercicio.segundos = segundos + self.152 Clases y m´todos e def incremento(self. segundos toma el valor de 500.minutos = self.segundos while self. S´lo podemos convertir uno de los par´metros o o a en self.

comienzo=0): indice = comienzo while indice < len(cad): if str[indice] == c: return indice indice = indice + 1 return -1 . c.5. podemos modernizar nuestra propia versi´n de encuentra o para que haga lo mismo que string.find.minutos < hora2.5 Argumentos opcionales if self. u Por ejemplo." a e Casi puede leer la invocaci´n como una mezcla de ingl´s y espa˜ol: “Si la horao e n hecho es depu´s de la hora-actual. string. Esta es la versi´n original de la Secci´n 7.segundos > hora2. c): indice = 0 while indice < len(cad): if str[indice] == c: return indice indice = indice + 1 return -1 Esta es la versi´n aumentada y mejorada: o def encuentra(cad.. Por ejemplo..despues(horaActual): print "El pan estar´ hecho despu´s de empezar.14. Es posible escribir funciones definidas por el usuario con listas de argumentos opcionales. tres o cuatro argumentos. Argumentos opcionales Hemos visto funciones internas que toman un n´mero variable de argumentos. entonces.segundos: return 1 return 0 153 Invocamos este m´todo sobre un objeto y pasamos el otro como argumento: e if horaHecho.minutos: return 0 if self.find puede tomar dos.7: o o def encuentra(cad.” e 14.

as´ que no puede averiguar su longiu ı tud. cad a´n no existe. 2) 2 >>> encuentra("arriba". Cuando se define u o encuentra.horas = horas self. comienzo. 30) >>> horaActual. o Cuidado: Este ejercicio tiene truco. El valor por omisi´n de fin deo ber´ ser len(cad). "r") 1 Si le damos un tercer par´metro. pero eso no funciona. anula el predefinido: a >>> encuentra("arriba". "r".imprimeHora() >>> 9:14:30 . seguidos de e init y dos guiones bajos m´s).segundos = segundos No hay conflicto entre el atributo self. segundos=0): self. 14.horas y el par´metro horas. El nombre de este m´todo es init (dos guiones bajos. Si invocamos encuentra s´lo con dos argumentos. minutos=0. que especifique n a d´nde dejar de buscar. no al llamarla.154 Clases y m´todos e El tercer par´metro. a˜ada un cuarto par´metro. horas=0. la notaci´n a o de punto especifica a qu´ variable nos referimos. Los valores por omisi´n ıa o se eval´an al definir la funci´n. Un m´todo de inicializaci´n para la clase Hora a e o es as´ ı: class Hora: def __init__(self. 0. los argumentos que damos se pasan a init: >>> horaActual = Hora(9. fin. es opcional porque se proporciona un valor por a omisi´n. 3) -1 Como ejercicio. "r". e Cuando invocamos el constructor Hora.6. utilizamos el valor o o por omisi´n y comenzamos por el principio de la cadena: o >>> encuentra("arriba". 14.minutos = minutos self. El m´todo de inicializaci´n e o El m´todo de inicializaci´n es un m´todo especial que se invoca al crear un e o e objeto.

y = y def __str__(self): return ’(’ + str(self.imprimeHora() >>> 9:0:30 14.7 Revisi´n de los Puntos o Como los par´metros son opcionales.imprimeHora() >>> 9:0:0 O los dos primeros par´metros: a >>> horaActual = Hora (9. Si una clase ofrece un m´todo llamado str .14. ’ + str(self. str . o a El siguiente m´todo.1 con un estilo m´s orientado o a a objetos: class Punto: def __init__(self. 14) >>> horaActual. podemos omitirlos: a >>> horaActual = Hora() >>> horaActual. o .imprimeHora() >>> 9:14:0 155 Finalmente. y=0): self. podemos dar un subconjunto de los par´metros nombr´ndolos exa a plicitamente: >>> horaActual = Hora(segundos = 30. se impone e al comportamiento por defecto de la funci´n interna str de Python. Revisi´n de los Puntos o Vamos a reescribir la clase Punto de la Secci´n 12.7.imprimeHora() >>> 0:0:0 O dar s´lo el primer par´metro: o a >>> horaActual = Hora (9) >>> horaActual. devuelve una representaci´n en forma de cadena e o de un objeto Punto.x = x self. x=0.x) + ’. el valor por omisi´n de cada par´metro es 0. horas = 9) >>> horaActual.y) + ’)’ El m´todo de inicializaci´n toma los valores de x e y como par´metros opcioe o a nales.

4) >>> str(p) ’(3. Python invocar´ a a add : >>> p1 = Punto(3.x. 4)’ Clases y m´todos e Imprimir un objeto Punto invoca impl´ ıcitamente a str sobre el objeto.156 >>> p = Punto(3. a Por ejemplo. Sobrecarga de operadores Algunos lenguajes hacen posible cambiar la definici´n de los operadores internos o cuando se aplican a tipos definidos por el usuario.8.y + otro. Es especialmente util cuando definimos nuevos ´ tipos matem´ticos. 11) . el primer par´metro es el objeto sobre el que se invoca el a m´todo. que facilita el instanciar objetos. ı e ı def __add__(self. para suplantar al operador de suma + necesitamos proporcionar un m´todo llamado add : e class Punto: # aqu´ van los m´todos que ya hab´amos definido. cuando apliquemos el operador + a objetos Punto. El segundo par´metro se llama convenientemente otro para distinguirlo e a del mismo (self). y str . creamos y devolvemos un nuevo Punto que contiene la suma de las coordenadas x y la suma de las coordenadas y.. Para sumar dos Puntos. otro): return Punto(self. o 14. casi siempre empezamos escribiendo init . e as´ que definir str tambi´n cambia el comportamiento de print: ı >>> p = Punto(3. self. 4) >>> print p (3.y) Como es habitual. 4) Cuando escribimos una nueva clase. Esta caracter´ ıstica se llama sobrecarga de operadores.. 7) >>> p3 = p1 + p2 >>> print p3 (8.x + otro. 4) >>> p2 = Punto(5. Ahora. que casi siempre es util ´ para la depuraci´n.

o e Si el operando a la izquierda de * es un Punto. a˜ada un m´todo sub (self. e Hay varias formas de sobrecargar el comportamiento del operador multiplicaci´n: definiendo un m´todo llamado mul .8 Sobrecarga de operadores 157 La expresi´n p1 + p2 equivale a p1.x + self. Este ejemplo muestra algunas de las difucultades de la programaci´n orientada a objetos.y) El resultado es un nuevo Punto cuyas coordenadas son m´ltiplos de las coordeu nadas originales. Calcula el producto e interno de dos puntos. Dentro de a mul . 7) >>> print p1 * p2 43 >>> print 2 * p2 (10. 4) >>> p2 = Punto(5. pero es obviamente m´s eleo a gante. ıcil e o a . o rmul . Python invoca a mul con 2 como el segundo par´metro. otro): return Punto(otro * self. lo que realiza una multiplicaci´n o escalar: def __rmul__(self.y Si el operando a la izquierda de * es un tipo primitivo y el operando de la derecha es un Punto. otro): return self. otro * self. Python invoca a mul .y * otro. pero no lo consigue porque un entero no tiene atributos: >>> print p2 * 2 AttributeError: ’int’ object has no attribute ’x’ Desgraciadamente. Si otro es un tipo que no se puede multiplicar por un n´mero u a en coma flotante. entonces rmul causar´ un error. el programa intenta acceder a la coordenada x de otro. Python invca a rmul . otro) que sobren e cargue el operador resta y pru´belo. definido seg´n las reglas del ´lgebra lineal: u a def __mul__(self. add (p2).14. o ambos.x * otro. A veces es o dif´ averiguar simplemente qu´ c´digo se est´ ejecutando. Este ejemplo muestra ambos tipos de multiplicaci´n: o >>> p1 = Punto(3. lo que presupone que el otro operando es tambi´n un Punto.x. el mensaje de error es un poco opaco. Como ejercicio. 14) ¿Qu´ ocurre si intentamos evaluar p2 * 2? Como el primer par´metro es un e a Punto.

15) >>> print multisuma (p1. Pero hay ciertas operaciones que querr´ aplicar a muchos tipos. la operaci´n multisuma (com´n en ´lgebra lineal) toma tres o u a par´metros. p1. z): return x * y + z Este m´todo trabajar´ con cualquier valor de x e y que se pueda multiplicar y e a con cualquier valor de z que se pueda sumar al producto. 1) 44 En el primer caso. 7) >>> print multisuma (2. Polimorfismo La mayor´ de los m´todos que hemos escrito funcionan s´lo para un tipo esıa e o pec´ ıfico.9. 14. Si muchos tipos admiten el mismo e conjunto de operaciones. Cuando usted crea un nuevo objeto. ı a e e Una funci´n como ´sta que puede tomar par´metros con diferentes tipos se o e a llama polim´rfica. que imprime a e dos veces una lista. el Punto se multiplica por un escalar y luego se suma a otro Punto. y. observe el m´todo delDerechoYDelReves. puede escribir funciones que trabajen sobre cualquiera de esos tipos. o Como un ejemplo m´s. 1) 7 O con Puntos: >>> p1 = Punto(3. Podemos escria birla en Python as´ ı: def multisuma (x.158 Clases y m´todos e Para ver un ejemplo m´s completo de sobrecarga de operadores. Podemos invocarlo con valores num´ricos: e >>> multisuma (3. vaya al Ap´ndia e ce B. En el segundo caso. 4) >>> p2 = Punto(5. Por ejemplo. como las operaa ciones aritm´ticas de las secciones anteriores. el producto interior produce un valor num´rico. escribe m´todos que operan sobre e ese tipo. p2) (11. e as´ que el tercer par´metro tambi´n debe ser un valor num´rico. hacia adelante y hacia atr´s: a . p2. 2. multiplica los dos primeros y luego suma el tercero.

4][4. 2. cuando usted descubre que una funci´n que hab´ escrito se puede aplicar a un tipo para el que nunca la o ıa hab´ planeado. 4) >>> delDerechoYDelReves(p) (3. Lo sorprendente es que pudi´ramos usarla con un Punto. self.9 Polimorfismo def delDerechoYDelReves(derecho): import copy reves = copy. 3. a He aqu´ un ejemplo que aplica delDerechoYDelReves a una lista: ı >>> miLista = [1. ıa .14.x Ahora podemos pasar Puntos a delDerechoYDelReves: >>> p = Punto(3.y = self. reverse y print.y. 3) El mejor tipo de polimorfismo es el que no se busca. 3. 2. pretend´ ıamos aplicar esta funci´n a listas. la funci´n se puede aplicar al tipo. 1] Por supuesto.copy(derecho) reves. 3. 2.x .reverse() print str(derecho) + str(reves) 159 Como el m´todo reverse es un modificador. e par´metro. hacemos una copia de la lista e antes de darle la vuelta. As´ este m´todo no modifica la lista que recibe como ı. e Para determinar si una funci´n se puede aplicar a un nuevo tipo. o Las operaciones del m´todo incluyen copy. 4] >>> delDerechoYDelReves(miLista) [1. as´ que no es sorpreno ı dente que funcione. as´ que todo lo que necesitamos es un m´todo reverse en la clase ı e Punto: def reverse(self): self. self. aplicamos la o regla fundamental del polimorfismo: Si todas las operaciones realizadas dentro de la funci´n se o pueden aplicar al tipo. e copy trabaja sobre cualquier objeto. y ya hemos escrito un m´todo str para e los Puntos. 4)(4.

e m´todo: Una funci´n definida dentro de una definici´n de clase y que se invoca e o o sobre instancias de esa clase. e multiplicaci´n escalar: Una operaci´n definida en ´lgebra lineal que multio o a plica cada una de las coordenadas de un Punto por un valor num´rico. o la funci´n se puede aplicar a ese tipo. imponer: Reemplazar una opci´n por omisi´n.) de modo que trabajen con tipos definidos por el usuario. producto interno: Una operaci´n definida en ´lgebra lineal que multiplica o a dos Puntos y entrega un valor num´rico. Glosario lenguaje orientado a objetos: Un lenguaje que ofrece caracter´ ısticas. *. Si todas las o o a operaciones realizadas dentro de una funci´n se pueden aplicar a un tipo. -. programaci´n orientada a objetos: Un estilo de programaci´n en el que los o o datos y las operaciones que los manipulan est´n organizadas en clases y a m´todos. o .160 Clases y m´todos e 14. etc. m´todo de inicializaci´n: Un m´todo especial que se invoca autom´ticamene o e a te al crear un nuevo objeto y que inicializa los atributos del objeto. >. sobrecarga de operadores: Ampliar los operadores internos (+. e polim´rfica: Una funci´n que puede operar sobra m´s de un tipo. Los ejemplos incluyen el reemo o plazo de un par´metro por omisi´n con un argumento particular y el reema o plazo de un m´todo por omisi´n proporcionando un nuevo m´todo con el e o e mismo nombre.10. como clases definidas por el usuario y herencia. que facilitan la programaci´n o orientada a objetos. <.

Hay cincuenta y dos naipes en una baraja inglesa. Composici´n o Hasta ahora. exploraremos algunos ejemplos de estas combinaciones. 10.1. Sota.2. Tambi´n puede crear objetos que e contengan listas (en forma de atributos). Objetos Carta Si no est´ usted familiarizado con los naipes de juego comunes. 9. Corazones. Dependiendo del tipo de juego que se juegue. 6. el valor del As puede ser mayor al Rey o inferior al 2. Los valores son As. e o Otro ejemplo es la estructura anidada de las sentencias. 5. 2. y as´ indefinidamente. Uno de los primeros o ejemplos fue el uso de la llamada a un m´todo como parte de una expresi´n. cada uno de los cuales pertenece a un palo y tiene un valor. Diamantes. 15. puede ser un a buen momento para que consiga un mazo. objetos que contengan objetos. 8. 7.Cap´ ıtulo 15 Conjuntos de objetos 15. 4. si no este cap´ ıtulo puede que no tenga mucho sentido. puede crear listas que contengan listas. . y sabiendo acerca de listas y objetos. y Tr´boles (en el orden e descendente seg´n el bridge). dentro de otra sentencia if. hay cuatro palos diferentes y trece valores. se puede escribir una sentencia if dentro de un bucle while. no le deber´ o ıa sorprender que pueda crear listas de objetos. u Reina. y Rey. Una vez visto este patr´n. y usaremos objetos Carta como ejemplo. ı En este cap´ ıtulo y el siguiente. 3. y as´ suceı sivamente. ya ha visto varios ejemplos de composici´n. Los palos son Picas.

pero nunca aparecen expl´ ıcitamente en el c´digo fuente. Una posibilidad es usar cadenas de caracteres que contengan palabras como "Picas" para los palos y "Reina" para los valores. 0. Lo que no es tan obvio es el tipo que se debe ıa dar a los atributos.162 Conjuntos de objetos Si queremos definir un nuevo objeto para representar un naipe. Por ejemplo: u Picas Corazones Diamantes Tr´boles e → → → → 3 2 1 0 Esta correspondencia tiene una caracter´ ıstica obvia: los palos corresponden a n´meros enteros en orden. 3) El primer argumento. cada uno de los u o valores num´ricos se asocia con el entero correspondiente. acerca de cifrar o traducir a un c´digo secreto. proporcionaremos un m´todo de inicializaci´n que toma e o un par´metro opcional para cada atributo.valor = valor Como acostumbramos. Con u el t´rmino “codificar” no queremos significar lo que algunas personas pueden e pensar. valor=0): self. La definici´n de o o clase para el tipo Carta se parecer´ a: a class Carta: def __init__(self. palo=0. representa el palo de Tr´boles. Lo que un programador o entiende por “codificar” es “definir una correspondencia entre una secuencia de n´meros y los elementos que se desea representar”. usaremos la instrucci´n: e o tresDeTreboles = Carta(0.palo = palo self. Son parte del dise˜o del prograo n ma. o sea que podemos comparar los palos al comparar u los n´meros. a Para crear un objeto que representa el 3 de Tr´boles. La asociaci´n de los valores es bastante obvia. y para las figuras: e Sota Reina Rey → → → 11 12 13 Estamos usando una notaci´n matem´tica para estas asociaciones por una o a raz´n: no son parte del programa Python. e . es obvio qu´ atrie butos deber´ tener: valor y palo. Una alternativa es usar n´meros enteros para codificar los valores y palos. Un problema de esta implementaci´n es que no ser´ f´cil comparar naipes para ver cu´l tiene o a a a mayor valor o palo.

"8". y selecciona la cadena apropiada”.15. "9". podemos usar listaDePalos y listaDeValores para asociar los valores num´ricos de palo y valor con cadenas de caracteres. "As". e "Picas"] listaDeValores = ["nada". que nunca se usar´. la expresi´n self. "10".3. No es obligatorio que desperdiciemos este primer elemento. podemos crear e imprimir naipes: e >>> carta1 = Carta(1. La ventaja de esto es que podemos usar cualquier objeto Carta para acceder a los atributos de clase: . "Diamantes". "6".listaDePalos[self. y as´ sucesivamente. Una manera natural de hacer esto es con listas de cadenas de caracteres.palo]) Un atributo de clase se define fuera de cualquier m´todo. e Dentro de str .listaDeValores[self. "2". "Reina". y puede accederse e desde cualquiera de los m´todos de la clase. El motivo del ‘‘nada" en el primer elemento de listaDeValores es para relleno del elemento de posici´n cero en la lista. "Sota". el 3 como 3. pero es menos confuso si el 2 se codifica como 2.palo] significa “usa el atribuo to palo del objeto self como un ´ ındice dentro del atributo de clase denominado listaDePalos. Por e ejemplo. ı Con los m´todos que tenemos hasta ahora. Los unicos valores o a ´ l´ ıcitos para el valor van de 1 a 13. "7". 11) >>> print carta1 Sota de Diamantes Los atributos de clase como listaDePalos son compartidos por todos los objetos de tipo Carta.listaDePalos[self.3 Atributos de clase y el m´todo e str 163 15. "3". Podr´ ıamos haber comenzado en 0 como es usual. "4". Asignaremos estas listas dentro de atributos de clase al principio de la definici´n de clase: o class Carta: listaDePalos = ["Tr´boles".valor] + " de " + self. "Corazones". "5". "Rey"] # se omite el m´todo init e def __str__(self): return (self. vamos a establecer una correspondencia entre los c´digos enteros y o las palabras. Atributos de clase y el m´todo e str Para poder imprimir los objetos Carta de una manera f´cil de leer para las a personas.

los a n´meros enteros y los n´meros en coma flotante tienen un orden completo. self y otro. y retorna 1 si el primer o a objeto es el mayor. e El conjunto de los naipes tiene un orden parcial.164 >>> carta2 = Carta(1. usted sabe que el 3 de Tr´boles es mayor que el 2 de Tr´boles y el 3 de Diamantes es e e mayor que el 3 de Tr´boles. que no existe ninguna manera significativa de decir que un elemento es mayor a otro. Por ejemplo. podemos sustituir el comportamiento de los operadores internos si proporcionamos un m´todo llamado cmp . podr´ ıa ıamos hacer lo siguiente: >>> carta1. . Por ejemplo. Para los tipos definidos por el usuario. si decidimos que “Sota de Diamantes” en realidad deber´ llamarse “Sota de Ballenas Bailarinas”. Comparaci´n de naipes o Para los tipos primitivos. Alguu u nos conjuntos no tienen orden. lo que explica por qu´ no se pueden comparar peras con manzanas. Algunos tipos est´n completamente ordenados. Por ejemplo. las frutas no tienen orden. afectaremos a cada instancia de la clase. Por ejemplo.listaDePalos[1] = "Ballenas Bailarinas" >>> print carta1 Sota de Ballenas Bailarinas El problema es que todos los Diamantes se transformar´n en Ballenas Bailarinas: a >>> print carta2 3 de Ballenas Bailarinas En general no es una buena idea modificar los atributos de clase. cmp toma dos par´metros. 15. lo que significa que algunas veces se pueden comparar los naipes. y 0 si ambos son iguales. existen operadores condicionales (< .) que comparan valores y determinan cuando uno es mayor. y otras veces no. lo que significa que se pueden a comparar dos elementos cualesquiera y decir cu´l es el mayor. etc. ==. Uno tiene mayor valor.listaDePalos[1] Diamantes Conjuntos de objetos La desventaja es que si modificamos un atributo de clase. >. ¿cu´l es mejor?.4. o sea. 3) >>> print carta2 3 de Diamantes >>> print carta2. Pero. pero el otro tiene mayor palo. -1 si el segundo objeto es el mayor. o igual a otro. ¿el 3 de Tr´boles o el 2 de e a e Diamantes?. menor. Por e convenci´n.

El bucle a a exterior enumera los palos desde 0 hasta 3. El m´todo de o o e inicializaci´n crea el atributo cartas y genera el conjunto est´ndar de cincuenta o a y dos naipes.cartas. otro): # controlar el palo if self. luego con todos los Diamantes.valor > otro.palo: return -1 # si son del mismo palo.palo: return 1 if self.palo < otro.5 Mazos de naipes 165 A los fines de hacer que los naipes sean comparables.valor < otro. e y as´ sucesivamente. la selecci´n es arbitraria. valor)) La forma m´s f´cil de poblar el mazo es mediante un bucle anidado.5.valor: return -1 # los valores son iguales. modifique cmp mayor valor que los Reyes. Como algo o hay que elegir. podemos escribir o cmp : def __cmp__(self. y el interior . diremos que el palo es m´s importante. Por supuesto. se debe decidir qu´ es m´s e a importante: valor o palo. controlar el valor if self.15. 14): self. es un empate return 0 En este ordenamiento. class Mazo: def __init__(self): self.palo > otro. Para no mentir. El bucle interior enumera los valores desde 1 hasta 13.cartas = [] for palo in range(4): for valor in range(1. Mazos de naipes Ahora que ya tenemos los objetos para representar las Cartas.append(Carta(palo. as´ que cada objeto Mazo contendr´ una lista de a ı a naipes como atributo. de tal manera que los Ases tengan 15. Como ejercicio. A continuaci´n se muestra una definici´n para la clase Mazo. el pr´ximo paso o l´gico es definir una clase para representar un Mazo.valor: return 1 if self. Como el bucle exterior itera cuatro veces. porque un mazo nuevo a viene ordenado con todos los Tr´boles primero. un mazo o est´ compuesto de naipes. ı Con esa decisi´n tomada. los Ases son menores que los doses.

en lugar de recorrer self. la cantidad total de veces que se ejecuta el cuerpo interior es cincuenta y dos (trece por cuatro). cuando definimos un nuevo tipo de objeto queremos un m´todo e que imprima el contenido del objeto. acomoda los naipes en una cascada.cartas[i]) + "\n" return s Este ejemplo demuestra varias caracter´ ısticas. e En lugar de escribir un m´todo muestraMazo.6. Segundo. La expresi´n *i prooprciona a o una cantidad de espacios igual al valor actual de i. La ventaja de str est´ en que es m´s flexible. por supuesto. Impresi´n del mazo de naipes o Como es usual.. En a a lugar de imprimir directamente el contenido del objeto.. str genera una representaci´n en forma de cadena de caracteres que las otras partes del programa o pueden manipular antes de imprimir o almacenar para un uso posterior. e 15. ... def muestraMazo(self): for carta in self. Para imprimir un Mazo.cartas y asignar cada naipe a una variable. Se presenta ahora una versi´n de str que retorna una representaci´n como o o cadena de caracteres de un Mazo. podr´ e ıamos escribir un m´todo e str para la clase Mazo.166 Conjuntos de objetos itera trece veces. Para darle un toque especial. utilizamos el operador de multiplicaci´n de cadenas de caracteres para o sangrar cada naipe un espacio m´s que el anterior. los puntos suspensivos (.cartas)): s = s + " "*i + str(self. de tal manera que cada naipe est´ sangrado un espacio a m´s que el precedente. recorremos la lista e imprimimos cada Carta: class Mazo: .cartas: print carta Desde ahora en adelante.. def __str__(self): s = "" for i in range(len(self.. y agrega dicho naipe a la lista de cartas. a class Mazo: . El m´todo append funciona sobre listas pero no sobre tuplas. usamos i como variable de bucle e ´ ındice de la lista de naipes. Primero. Cada iteraci´n crea una nueva instancia de o Carta con el palo y valor actual.) indicar´n que hemos a omitido los otros m´todos en la clase.

cualquier naipe tiene la misma probaa bilidad de aparecer en cualquier posici´n del mazo. en lugar de usar la instrucci´n print para imprimir los naipes. y cualquier lugar en el mazo o tiene la misma probabilidad de contener cualquier naipe. utilizao mos la funci´n str. s es una cadena de caracteres vac´ En cada pasada a trav´s del bucle. Eso o ta funci´n toma dos enteros como argumentos a y b. Cuando el bucle termina. Inicialmente. la cual se ve como a continuaci´n o se presenta: >>> mazo = Mazo() >>> print mazo As de Tr´boles e 2 de Tr´boles e 3 de Tr´boles e 4 de Tr´boles e 5 de Tr´boles e 6 de Tr´boles e 7 de Tr´boles e 8 de Tr´boles e 9 de Tr´boles e 10 de Tr´boles e Sota de Tr´boles e Reina de Tr´boles e Rey de Tr´boles e As of Diamantes Y as´ sucesivamente. e Finalmente. 15.15. se genera una ıa. El pasar un objeto como argumento a str es equivalente a o invocar el m´todo str sobre dicho objeto. Barajar el mazo Si un mazo est´ perfectamente barajado. utilizaremos la funci´n randrange del m´dulo random.7 Barajar el mazo 167 Tercero. s contiene la representaci´n completa o en formato de cadena de caracteres del Mazo. A´n cuando los resultados aparecen en 52 renglones.7. e nueva cadena de caracteres que se concatena con el viejo valor de s para obtener el nuevo valor. se ı u trata de s´lo una unica larga cadena de caracteres que contiene los saltos de o ´ l´ ınea. Para mezclar el mazo. y elige un n´mero entero en o u . usamos la variable s como acumulador.

Por ejemplo. self. como se describe en la Secci´n 9..cartas[i].cartas)) Una manera sencilla de mezclar el mazo es recorrer los naipes e intercambiar cada una con otra elegida al azar. self.cartas[i] En lugar de presuponer que hay cincuenta y dos naipes en el mazo. self.cartas[j]. seleccionamos un naipe al azar entre aquellos que no han sido intercambiados a´n. Eliminaci´n y reparto de los naipes o Otro m´todo que podr´ ser util para la clase Mazo es eliminaCarta.cartas[j]..cartas[i].2: o self. self. reescriba esta l´ ınea de c´digo sin usar una asignao ci´n de secuencias. y falso (0) si no estaba: .randrange(i. Luego intercambiamos el naipe actual (i) con el u naipe seleccionado (j). Para cada naipe del mazo.168 Conjuntos de objetos forma aleatoria en el rango a <= x <b. el orden de los naipes no ser´ completamente al azar: a class Mazo: . podemos usar la longitud de la lista como el segundo argumento y de esa manera tendremos garantizado un ´ ındice legal dentro de la lista. esta expresi´n selecciona el ´ o ındice de un naipe al azar dentro del mazo: random. nCartas) self.cartas[j] = self. Para intercambiar los naipes usaremos la asignaci´n de o tuplas. De hecho. Es posible que el naipe se intercambie consigo mismo.cartas[j] =\ self. len(self. pero no es un problema.8. lo elimina.cartas[i] Como ejercicio. Como el l´ ımite superior es estrictamente menor a b. que toma e ıa ´ un naipe como par´metro. def mezclar(self): import random nCartas = len(self.cartas) for i in range(nCartas): j = random. si eliminamos esa posibilidad. y retorna verdadero (1) si el naipe estaba a en el mazo. o 15.randrange(0. obtenemos la longitud real de la lista y la almacenamos en nCartas.

9 Glosario class Mazo: . el m´todo eliminaCarta tambi´n verifica igualdad en profundidad.. el a cual debe ser una lista o tupla.9.. queremos eliminar y devolver el naipe que ocupa la posici´n superior en el mazo..cartas) == 0) 15. Si el primer operando es un objeto. Como el cmp en la clase Carta verifica la igualdad en profundidad. Otra operaci´n m´s que es muy probable necesitemos es la funci´n booleana o a o estaVacio..cartas. carta): if carta in self.. atributo de clase: Una variable que se define dentro de la definici´n de una o clase pero fuera de cualquiera de sus m´todos. Los atributos de clase son e accesibles desde cualquier m´todo de la clase y est´n compartidos por e a todas las instancias de la misma. def eliminaCarta(self.cartas: self.. . as´ que en efecto estamos ´ ı repartiendo desde el extremo inferior del mazo.pop() En realidad. def estaVacio(self): return (len(self. la cual devuelve verdadero si el mazo no contiene ning´n naipe: u class Deck: . Python usa el m´todo cmp del objeto para determinar la igualdad entre los elementos de e la lista.15. e e Para repartir los naipes. Glosario codificar: Representar un conjunto de valores uilizando otro conjunto de valores. entre los cuales se construye una correspondencia. El m´todo pop de las listas proporciona una manera o e conveniente de realizar esto: class Mazo: . def darCarta(self): return self.cartas. pop elimina el ultimo naipe en la lista.remove(carta) return 1 else: return 0 169 El operador in retorna verdadero si el primer operando est´ en el segundo.

170 Conjuntos de objetos acumulador: Una variable que se usa en un bucle para acumular una serie de valores. a . por ejemplo concaten´ndolos dentro de una cadena de caracteres a o adicion´ndolos a una suma.

La herencia es la capacidad de definir una nueva clase que es una versi´n modificada de otra ya existente. Herencia La caracter´ ıstica de un lenguaje que m´s se asocia con la programaci´n orientada a o a objetos es la herencia. Ciertos programas que ser´ compliıan cados sin herencia pueden escribirse de manera simple y concisa gracias a ella. Adem´s. El c´digo relevante puede estar diseminado por varios m´dulos. se puea den lograr de forma igualmente (incluso m´s) elegante sin ella. a . o La principal ventaja de esta caracter´ ıstica es que se pueden agregar nuevos m´toe dos a una clase sin modificar la clase existente. Cuando se llama a un m´todo. pues se puede a o o adaptar el comportamiento de la clase padre sin tener que modificarla. En algunos casos. a veces no est´ claro d´nde debe uno encontrar e a o su definici´n. la estructura de la herencia refleja la propia estructura del problema. Se denomina “herencia” porque la nueva clase hereda todos los m´todos de la clase existente. muchas de las cosas que se hacen mediante el uso de la herencia. Si la estructura a general del problema no nos gu´ hacia la herencia. o tambi´n “subclase”. dicho estilo de programaci´n ıa o puede hacer m´s mal que bien. e La herencia es una caracter´ ıstica poderosa. a la clase existente a veces se la denomina clase padre. la herencia puede facilitar la reutilizaci´n del c´digo. La nueva e clase puede denominarse clase hija. la herencia pude hacer que los porgramas sean dif´ ıciles de leer. o o o Adem´s. a a Por otro lado. Si extendemos e esta mat´fora.Cap´ ıtulo 16 Herencia 16. lo que hace que el programa sea m´s f´cil de comprender.1.

En bridge necesitaremos calcular el puntaje para la mano para as´ poder ı hacer la subasta. El nombre es un par´metro a opcional con un valor por omisi´n de cadena vac´ cartas es la lista de cartas o ıa. inicializada como lista vac´ ıa. Esta situaci´n sugiere el uso de la herencia. En la definici´n de clase. Por ejemplo. Si Mano es una subclase de Mazo. que son nombre y cartas. el nombre de la clase padre aparece entre par´ntesis: o e class Mano(Mazo): pass Esta sentencia indica que la nueva clase Mano hereda de la clase existente Mazo. es necesario agregar y quitar cartas del mazo. podemos querer realizar ciertas operaciones sobre una mano que e no tienen sentido sobre un mazo. y ambos requieren de operaciones tales como agregar y eliminar una carta. nombre=""): self.2. Seg´n el juego al que se u est´ jugando. o entonces tendr´ todos los m´todos de Mazo y le podremos agregar otros m´todos a e e nuevos. La cadena de caracteres nombre identifica a esta mano.cartas = [] self. La eliminaci´n de cartas ya ha sido resuelta. Ambos est´n compuestos de un a conjunto de naipes. necesitamos representar una mano de cartas. necesitaremos la capacidad de mezclar tanto un a mazo como una mano de cartas.) y compararla con otra. Pero deberemos escribir agregaCarta: . El constructor de Mano inicializa los atributos para la mano.172 Herencia En este cap´ ıtulo demostraremos el uso de la herencia como parte de un programa que juega a las cartas a la “Mona”. Una de nuestras metas ser´ que el c´digo a o que escribamos se pueda reutilizar para implementar otros juegos de naipes. Una mano es diferente de un mazo en ciertos aspectos. class Mano(Mazo): def __init__(self. probablemente mediante el nombre del jugador que la sostiene. en el p´ker queremos clasificar o una mano (straight (consecutiva). 16. etc. de la mano.nombre = nombre Casi para cualquier juego de naipes. por supuesto. Una mano de cartas Para casi cualquier juego de naipes. pues Mano hereda eliminaCarta o de Mazo. Una mano es similar a un mazo. flush (de un solo palo). Adem´s.

el m´todo reparte e todas las cartas y se detiene: class Mazo : . repartir toma dos par´metros. nCartas=999): nManos = len(manos) for i in range(nCartas): if self. o que agreguemos una carta a cada mano. es m´s natural ponerlo en el Mazo. A cada paso a trav´s del e bucle. Cuando i es igual a la cantidad de manos en la lista. Si no hay suficientes cartas en el mazo. se elimina una carta del mazo mediante el m´todo de lista pop.. pues los diferentes juegos tienen distintos requerimentos.. ´ El operador m´dulo ( %) permite que podamos repartir las cartas de una en una o (una carta cada vez para cada mano).16. . def repartir(self. los puntos suspensivos indican que hemos omitido los otrs m´todos. el valor por omisi´n es un n´mero a o u muy grande. Puede que necesitemos repartir todo el mazo de una vez. e 16.carta) : self. una lista (o tupla) de manos y la cantidad total a de naipes a repartir. El reparto de los naipes Ahora que ya tenemos la clase Mano.3. la expresi´n i % nManos salta hacia el comienzo de la lista (el ´ o ındice es 0).estaVacio(): break # fin si se acaban las cartas carta = self.. nCartas es opcional.darCarta() # da la carta superior mano = manos[i % nManos] # a qui´n le toca? e mano.3 El reparto de los naipes class Mano(Mazo): . queremos repartir las cartas del Mazo en manos. lo cual es lo mismo que decir que se repartir´n todos los naipes del a mazo. manos. e El m´todo de lista append agrega la nueva carta al final de la lista de cartas. La variable de bucle i va desde 0 hasta nCartas-1.append(carta) 173 De nuevo.. a repartir debe ser bastante general. def agregaCarta(self. que quita e y devuelve el ultimo elemento de la lista.cartas. No es claramente obvio si este m´todo debe ir en la clase Mano o en la e clase Mazo. pero como opera sobre un mazo unico y (posiblemente) sobre varias ´ manos.agregaCarta(carta) # agrega la carta a la mano El segundo par´metro.

Puede parecer extra˜o que enviemos a self. Aunque es conveniente usar la herencia de los m´todos existentes.mezclar() >>> mano = Mano("hugo") >>> mazo. el programa agrega la palabra contiene y la representaci´n o como cadena de caracteres del Mazo. que se obtiene llamando al m´todo str e de la clase Mazo sobre la instancia self. podemos proporcionar a la clase Mano un m´todo str que reemplace al de e la clase Mazo: class Mano(Mazo) . podemos sacar partido de la existencia de los m´todos muestraMazo y str que se heredan de Mazo. Mostremos la mano Para mostrar el contenido de una mano.nombre if self.174 Herencia 16.repartir([mano]. hasta que nos damos cuenta e de que una Mano es un tipo de Mazo. a ıa.estaVacio(): s = s + " est´ vac´a\n" a ı else: s = s + " contiene\n" return s + Mazo. def __str__(self): s = "La mano de " + self. existe infore maci´n adicional en una Mano que desear´ o ıamos mostrar al imprimirla. 5) >>> print mano La mano de hugo contiene 2 de Picas 3 de Picas 4 de Picas As de Corazones 9 de Tr´boles e No es una gran mano. Por ejemplo: e >>> mazo = Mazo() >>> mazo. n como argumento de un m´todo de la clase Mazo. Los objetos Mano pueden hacer cualquier . a ı En caso contrario.. Si la mano est´ vac´ el programa agrega las palabras est´ vac´a y devuelve s..4.__str__(self) Al principio s es una cadena de caracteres que identifica a la mano. Para ello. que se refiere a la Mano actual. pero tiene lo necesario como para disponer de una escalera de color.

de manera que e la Reina de Picas no tiene con qui´n emparejarse. Como ejemplo. e La Sota de Corazones se empareja con la Sota de Diamantes porque ambos son rojos. Si la carta elegida concuerda con una de la mano del u jugador.mezclar() Esta es la primera vez que vemos que un m´todo de inicializaci´n realiza una e o actividad computacional significativa. Para iniciar el juego. Uno se saca las cartas de encima emparej´ndolas por valor y color. Luego del reparto. o La meta de La Mona es desembarazarse de las cartas que uno tiene en la mano. a cada jugador toma una carta (sin mirarla) del vecino m´s cercano de la izquierda a que a´n tiene cartas. Si no. m´s all´ de la inicializaci´n de atributos. 16. La clase JuegoDeCartas La clase JuegoDeCartas asume la responsabilidad sobre algunas obligaciones b´sicas comunes a todos los juegos. de una en una. el jugador que tiene la Mona realiza ciertos esfuerzos para . Las cincuenta y una cartas e restantes se reparten entre los jugadores. se elimina la Reina de Tr´boles del mazo. Llega el momento en el que se realizan todas las concordancias posibles. se pierden algunos de los matices del juego real.5. se elimina dicho par.mazo. siempre es legal usar una instancia de una subclase en el lugar de una instancia de una clase padre. Desafortunadamente. la computadora juega todas las o a manos.16. En una partida real. Cuando no se pueden realizar m´s concordancias. la carta se agrega a la mano del jugador.mazo = Mazo() self.5 La clase JuegoDeCartas 175 cosa que pueda hacer un objeto Mazo. el juego comienza. tales como la creaci´n del mazo y la mezcla a o de los naipes: class JuegoDeCartas: def __init__(self): self. e En general. a el 4 de Tr´boles se empareja con el 4 de Picas porque ambos palos son negros. escribiremos una simulaci´n para La Mona. a a o Para implementar juegos espec´ ıficos. Por ejemplo. con lo que queda s´lo la Reina de Picas en la mano del perdedor. y por ello es legal que pasemos una Mano a un m´todo de Mazo. todos los jugadores emparejan y descartan tantas cartas como sea posible. o En nuestra simulaci´n inform´tica del juego. debemos heredar de JuegoDeCartas y agregar las caracter´ ısticas del nuevo juego. Por turnos.

de tal manera que podamos recorrer la copia mientras vamos quitando cartas de la lista original. 16. 13) . La carta que concuerda tiene el mismo valor y el otro palo del mismo color.cartas se modifica en el bucle. Si la carta que e concuerda est´ en la mano.nombre. ambas se eliminan. a que hereda de Mano y nos proporciona un m´todo adicional denominado e eliminaCoincidencias: class ManoDeLaMona(Mano): def eliminaCoincidencias(self): cant = 0 cartasOriginales = self.cartas: self. carta.6. por ejemplo mostr´ndola prominentemente o al contrario.176 Herencia que su vecino la tome.cartas[:] for carta in cartasOriginales: empareja = Carta(3 .carta. a El siguiente ejemplo demuestra el uso de eliminaCoincidencias: >>> juego = JuegoDeCartas() >>> mano = ManoDeLaMona("hugo") >>> juego. Definiremos una nueva clase ManoDeLaMona.carta.valor) if empareja in self.carta. ¡Python puede quedar realmente confundido si se recorre una lista que est´ cambiando! a Para cada carta de la mano.palo. La clase ManoDeLaMona Una mano para jugar a La Mona requiere ciertas capacidades que est´n m´s a a all´ de las que posee una Mano. o incluso puede fallar al tratar de errar en su intento de mostrarla prominentemente. averiguamos cu´l es la carta que concordar´ con a a ella y la buscamos.cartas.repartir([mano]. Como self. La expresi´n 3 . La computadora simplemente toma una carta al azar de su vecino. a errando al intentar mostrarla abiertamente. Verifique o por su cuenta que las operaciones opuestas tambi´n funcionan.palo transforma un Tr´bol (palo 0) o e en una Pica (palo 3) y un Diamante (palo 1) en un Coraz´n (palo 2).remove(carta) self.mazo. no vamos a querer usarla para controlar el recorrido.empareja) cant = cant + 1 return cant Comenzamos por hacer una copia de la lista de las cartas.cartas.remove(empareja) print "Mano %s: %s con %s" % (self.

mazo. a Como el m´todo init se hereda de JuegoDeCartas. 16. el nuevo objeto e JuegoDeLaMona contiene un mazo recientemtente mezclado: class JuegoDeLaMona(JuegoDeCartas): def jugar(self.manos = [] for nombre in nombres : self.append(ManoDeLaMona(nombre)) .7 La clase JuegoDeLaMona >>> print mano La mano de hugo contiene As de Picas 2 de Diamantes 7 de Picas 8 de Tr´boles e 6 de Corazones 8 de Picas 7 de Tr´boles e Raina de Tr´boles e 7 de Diamantes 5 de Tr´boles e Sota de Diamantes 10 de Diamantes 10 de Corazones >>> mano.eliminaCoincidencias() Mano hugo: 7 de Picas con 7 de Tr´boles e Mano hugo: 8 de Picas con 8 de Tr´boles e Mano hugo: 10 de Diamantes con 10 de Corazones Debe usted notar que no existe un m´todo e Lo heredamos de Mano.eliminaCarta(Carta(0.12)) # construimos una mano para cada jugador self.manos. JuegoDeLaMona o ı es una subclase de JuegoDeCartas con un m´todo nuevo denominado jugar que e toma una lista de jugadores como par´metro.16. init 177 para la clase ManoDeLaMona. nombres): # quitamos la Reina de Tr´boles e self.7. La clase JuegoDeLaMona Ahora podemos poner nuestra atenci´n en el juego en s´ mismo.

el operador de m´dulo lo hace volver a cero. o La variable turno recuerda el turno de cu´l jugador se est´ jugando. lo que es lo mismo que decir que s´lo queda una carta y el juego ha terminado. el cual recorre self.mazo.muestraManos() # se juega hasta que se han descartado las 50 cartas turno = 0 cantManos = len(self." self.Coincidencias eliminadas.. cuando alcanza el valor cantManos.Se han repartido las cartas. o . eliminaTodasLasCoincidencias recorre la lista de manos y llama a eliminaCoincidencias para cada una de ellas: class JuegoDeLaMona(JuegoDeCartas): .eliminaTodasLasCoincidencias() print "----." o self." self.repartir(self.eliminaCoincidencias() return cant Como ejercicio.manos y muestra cada mano. def eliminaTodasLasCoincidencias(self): cant = 0 for mano in self. Cuando la cantidad total de coincidencias alcanza a las veinticinco significa que se han eliminado cincuenta cartas de las manos.jugarUnTurno(turno) turno = (turno + 1) % cantManos print "----.muestraManos() Herencia # eliminamos las coincidencias iniciales emparejadas = self.manos: cant = cant + mano. Comienza a a en cero y se incrementa en uno cada vez. cant es un acumulador que va sumando la cantidad de concordancias en cada mano y devuelve el total.manos) print "----.manos) while emparejadas < 25: emparejadas = emparejadas + self. escriba muestraManos.178 # repartimos los naipes self.muestraManos() Algunos de los pasos que componen el juego se han colocado en m´todos see parados. el juego comienza.El juego termin´..

cantManos): vecino = (i + proximo) % cantManos if not self. y controlar si hay concordancias. tomar una carta de las que posee. devolver´ None y eso causar´ un error en alguna ıa ıa otra parte del programa.manos[i]..eliminaCoincidencias() self.manos) for proximo in range(1. un turno consiste en encontrar el primer jugador a la izquierda que a´n u tiene cartas. u class JuegoDeLaMona(JuegoDeCartas): . e a e El valor de retorno es la cantidad de concordancias que se han realizado durante ese turno: class JuegoDeLaMona(JuegoDeCartas): . Si no.7 La clase JuegoDeLaMona 179 El m´todo jugarUnTurno toma un par´metro que indica de qui´n es el turno.estaVacio(): return vecino Si por cualquier motivo encuentraVecino llegara a dar la vuelta completa al c´ ırculo sin encontrar cartas... i): cantManos = len(self.manos[i].agregaCarta(cartaElegida) print "Mano".manos[vecino].nombre. def jugarUnTurno(self. Afortunadamante podemos probar que eso no va a suceder nunca (siempre y cuando se detecte correctamente el final del juego).manos[i]. self. as´ que no hace a ıa.manos[i].. i): if self.encuentraVecino(i) cartaElegida = self.manos[vecino]. en la cual solamente se reparten las quince cartas m´s altas (desde los dieces hacia arriba) a tres a .16. cartaElegida o cant = self. o ı nada y devuelve 0.mezclar() return cant Si la mano de un jugador est´ vac´ el jugador sali´ del juego. de tal manera que la selecci´n o del siguiente jugador sea al azar. Ese puede escribirlo usted mismo.darCarta() self. ´ Hemos omitido el m´todo muestraManos. El m´todo encuentraVecino comienza con el jugador que est´ inmediatamante e a a la izquierda y contin´a alrededor del c´ u ırculo hasta que encuentra un jugador que a´n tiene cartas. Antes de volver se mezclan las cartas de la mano.estaVacio(): return 0 vecino = self. "eligi´". e La siguiente salida proviene de una forma reducida del juego.manos[i]. def encuentraVecino(self.

Con este mazo m´s peque˜o."Jeff".Se han repartido las cartas.Se eliminaron las coincidencias. Mano Allen contiene Rey de Corazones Sota de Tr´boles e Reina de Picas Rey de Picas 10 de Diamantes Mano Jeff contiene Reina de Corazones Sota de Picas Sota de Corazones Rey de Diamantes Reina de Diamantes Mano Chris contiene Sota de Diamantes Rey de Tr´boles e 10 de Picas 10 de Corazones 10 de Tr´boles e Mano Jeff: Reina de Corazones con Reina de Diamantes Mano Chris: 10 de Picas con 10 de Tr´boles e ----. Mano Allen contiene Rey de Corazones Sota de Tr´boles e Reina de Picas Rey de Picas 10 de Diamantes Mano Jeff contiene Sota de Picas Sota de Corazones Rey de Diamantes . el juego comienza.JuegoDeLaMona() >>> juego. >>> import cartas >>> juego = cartas.180 Herencia jugadores."Chris"]) ----. el juego termina tras siete coincidencias.jugar(["Allen". a n en lugar de veinticinco.

ı o 16.El juego termin´. a ı As´ que Jeff es quien perdi´.8 Glosario Mano Sota Rey 10 Chris contiene de Diamantes de Tr´boles e de Corazones 181 Mano Allen: eligi´ Rey de Diamantes o Mano Allen: Rey de Corazones con Rey de Diamantes Mano Jeff: eligi´ 10 de Corazones o Mano Chris: eligi´ Sota de Tr´boles o e Mano Allen: eligi´ Sota de Corazones o Mano Jeff: eligi´ Sota de Diamantes o Mano Chris: eligi´ Reina de Picas o Mano Allen: eligi´ Sota de Diamantes o Mano Allen: Sota de Corazones con Sota de Diamantes Mano Jeff: eligi´ Rey de Tr´boles o e Mano Chris: eligi´ Rey de Picas o Mano Allen: eligi´ 10 de Corazones o Mano Allen: 10 de Diamantes con 10 de Corazones Mano Jeff: eligi´ Reina de Picas o Mano Chris: eligi´ Sota de Picas o Mano Chris: Sota de Tr´boles con Sota de Picas e Mano Jeff: eligi´ Rey de Picas o Mano Jeff: Rey de Tr´boles con Rey de Picas e ----.16. a ı La mano de Jeff contiene Reina de Picas La mano de Chris est´ vac´a.8. Glosario herencia: La capacidad de definir una nueva clase que es una versi´n modifio cada de una clase previamente definida. . clase padre: Aquella clase de la cual la clase hija hereda. o La mano de Allen est´ vac´a.

182 Herencia clase hija: Una nueva clase creada heredando de una clase existente. tambi´n e se la llama “subclase”. .

La clase Nodo Como es habitual cuando se escribe una clase.2. para poder comprobar el mecanismo b´sico de crear o a y mostrar el nuevo tipo: . Adem´s. comenzaremos con los m´todos e de inicializaci´n y str . Las estructuras recursivas de datos nos llevan a m´todos recursivos. cada nodo contiene una unidad o a de datos llamada carga Podemos considerar una lista enlazada como una estructura de datos recursiva porque tiene una definici´n recursiva.8). o bien ıa. la lista enlazada. a los que llamamos referencias incrustadas (v´ase la Secci´n 12. Referencias incrustadas Hemos visto ejemplos de atributos que hacen referencia a otros objetos. saca partido de esta caracter´ u ıstica. donde cada nodo contiene una referencia al pr´ximo nodo de la lista.1. Las listas enlazadas se componen de nodos. un nodo que contiene un objeto de carga y una referencia a una lista enlazada.Cap´ ıtulo 17 Listas enlazadas 17. o Una lista enlazada puede ser: la lista vac´ representada por None. e 17. Una estrutura e o de datos com´n.

Por defecto.carga = carga self. pero a´n no tenemos una lista porque los nodos o u todav´ no est´n enlazados. se ponen a None. que indica que es el final de la lista.siguiente = nodo3 La referencia del tercer nodo ser´ None. siguiente=None): self. podemos crear un Nodo e o imprimirlo: >>> nodo = Nodo("prueba") >>> print nodo prueba Para hacerlo m´s interesante.siguiente = nodo2 >>> nodo2. debemos hacer que el primer nodo haga referencia al segundo. podemos guardar cualquier valor o en una lista.184 class Nodo: def __init__(self. los par´metros para el m´todo de inicializaci´n son opcionaa e o les. Como o e ´ se puede pasar cualquier valor a la funci´n str. necesitaremos una lista que contenga m´s de un a a nodo: >>> nodo1 = Nodo(1) >>> nodo2 = Nodo(2) >>> nodo3 = Nodo(3) Este c´digo crea tres nodos.carga) Listas enlazadas Como es habitual. Para comprobar la implementaci´n en este punto. El diagrama de estados tiene el siguiente aspecto: ıa a node1 node2 node3 cargo next 1 None cargo next 2 None cargo next 3 None Para enlazar los nodos.siguiente = siguiente def __str__(self): return str(self. La representaci´n alfanum´rica de un nodo es unicamente la de la carga. carga=None. la carga y el enlace. a Ahora el diagrama de estados tendr´ el siguiente aspecto: a . siguiente. y que ´ste haga referencia al tercero: e >>> nodo1.

pasamos una referencia al primer nodo: e >>> imprimeLista(nodo1) 1 2 3 Dentro de imprimeLista tenemos una referencia al primer nodo de la lista. Este diagrama muestra el valor de lista y los valores que va tomando nodo: . Listas como colecciones Las listas son utiles porque aportan un modo de ensamblar m´ltiples objetos u dentro de una unica entidad. Para pasar la lista como par´metro. def imprimeLista(nodo): while nodo: print nodo. Empezando con la cabeza de la lista. pero no hay una variable que haga referencia a los otros nodos. nodo = nodo.3 Listas como colecciones node1 node2 node3 185 cargo next 1 cargo next 2 cargo next 3 None Ahora ya sabe c´mo crear nodos y enlazarlos en listas.siguiente print Para llamar a este m´todo. e 17. Por ejemplo. Para recorrer una lista enlazada es habitual usar la variable de un bucle como nodo para hacer referencia sucesivamente a cada uno de los nodos.17. el primer ´ o nodo de la lista sirve como referencia a la lista completa. s´lo tenemos que hacer referencia al primer a o nodo. la funci´n imprimeLista toma como argumento un nodo o simple. imprime cada nodo hasta que llega al final. En el ejemplo. Tendremos que usar el valor de siguiente de cada nodo para acceder al siguiente nodo. a veces llamada colecci´n.3. Lo que podr´ estar o ıa menos claro es por qu´.

Pero si suponemos que la llamada recursiva e funciona —el acto de fe— entonces podemos estar convencidos de que este algoritmo funciona. 2. 3. un caso b´sico natural es la lista vac´ representada por None: a ıa. Imprimir la cola hacia atr´s. la llamada recursiva. . El siguiente ejemplo es un algoritmo recursivo para imprimir una lista hacia atr´s: a 1. 3]. Todo lo que necesitamos es un caso b´sico y una forma de demostrar que para a cualquier lista podemos obtener el caso b´sico. Separar la lista en dos partes: el primer nodo (llamado cabeza) y el resto (llamado cola). como [1. Listas y recursividad Es natural expresar muchas operaciones con listas por medio de m´todos ree cursivos. el paso 2.186 node1 node2 node3 Listas enlazadas cargo y 1 cargo y 2 cargo y 3 None node Por convenio. Como ejercicio. modifique imprimeLista para que genere una salida con este formato. Dada la definici´n recursiva de a o una lista. las listas suelen imprimirse entre corchetes con comas entre los elementos. supone que tenemos una manera de imprimir una lista del rev´s. a Imprimir la cabeza. 2. def imprimeAlReves(lista): if lista == None: return cabeza = lista cola = lista. 17.4. Por supuesto.siguiente imprimeAlReves(cola) print cabeza.

5 Listas infinitas 187 La primera l´ ınea maneja el caso inicial no haciendo nada.5. ıcil Sin embargo. Si llaa mamos a imprimeAlReves. esta figura muestra una lista con dos e nodos. La coma que hay al final de la ultima l´ ´ ınea evita que Python salte de l´ ınea despu´s de imprimir un nodo. Las dos siguientes l´ ıneas dividen la lista en cabeza y cola. o . a ¿siempre alcanzaremos el caso b´sico? De hecho. Las dos ultimas l´ ´ ıneas imprimen la lista. La raz´n es que queremos usar None para e o representar la lista vac´ y no es legal llamar un m´todo sobre None. entrar´ en un bucle infinito. la respuesta es no. lo har´ de forma infinitamente recursiva. Por ejemplo. Por ejemplo. ¿Podemos demostrar que imprimeAlReves siempre acabar´? En otras palabras. Esta limiıa e taci´n resulta algo inc´moda a la hora de escribir c´digo para manipular listas o o o con un estilo orientado a objetos puro. Es posible que se pregunte por qu´ imprimeLista e imprimeAlReves son fune ciones y no m´todos de la clase Nodo. uno de los cuales apunta a s´ mismo: ı list cargo next 1 cargo next 2 Si llamamos a imprimeLista sobre esta lista. a e 17.17. en ocasiones resultan utiles. incluido ´l mismo. Algunas a listas har´n que el m´todo no funcione. Listas infinitas No hay nada que impida a un nodo hacer referencia a un nodo anterior de la lista. e Llamamos este m´todo tal como antes invocamos a imprimeLista: e >>> imprimeAlReves(nodo1) 3 2 1 El resultado es una lista invertida. podr´ ´ ıamos representar un n´mero como una lista de d´ u ıgitos y usar una lista infinita para representar una fracci´n repetida. Eeste tipo a de comportamiento da lugar a que sea muy dif´ trabajar con listas infinitas.

a En general no podemos decir con s´lo mirar un programa qu´ papel desemo e pe˜ar´ un variable.188 Listas enlazadas A pesar de todo. es un problema que no podamos probar que imprimeLista e imprimeAlReves puedan terminar correctamente. ¿para qu´ hemos creado un nueva variable? e La raz´n es que las dos variables desempe˜an papeles diferentes. e a Este tipo de afirmaciones se conocen como condiciones previas. Esta ambig¨edad puede ser util. Mirando esas dos llamadas. Lo mejor que podemos hacer es afirmar que “si la lista no contiene bucles. que lo har´ mas ıa conciso. pero posiblemente menos claro: def imprimeAlReves(lista) : if lista == None : return imprimeAlReves(lista.6. Asi que. pero tambi´n puede difin a u ´ e cultar la lectura del programa. estos m´todos podr´n terminar”. Pensamos en o n la cabeza como una referencia al primer nodo de la lista. A menudo usaremos nombres para las variables como nodo y lista para explicar c´mo queremos usar una variable y a veces o creamos variables adicionales para eliminar ambig¨edades. hemos de recordar que imprimeAlReves trata sus argumentos como una colecci´n y print los trata como a un s´lo objeto. Teorema fundamental de la ambig¨ edad u Una parte de imprimeAlReves podr´ habernos sorprendido: ıa cabeza = lista cola = lista. Estos “papeles” no forman parte del programa. la cabeza y la cola tienen el mismo tipo y e o el mismo valor.siguiente) print lista. u Podr´ ıamos haber escrito imprimeAlReves sin cabeza ni cola. sino que est´n en la mente del programador. . Imponen una restricci´n sobre uno de los par´metros y describen el comportamiento del o a m´todo si la restricci´n se satisface.siguiente Despu´s de la primera asignaci´n. o o El teorema fundamental de la ambig¨ edad indica que la ambig¨edad que u u es inherente a una referencia a un nodo: Una variable que hace apunta a nodo puede tratar a este nodo como un objeto o como el primero de una lista de nodos. e o a a 17. Veremos m´s ejemplos m´s adelante.

7.siguiente = segundo. quitan o reordenan los nodos.17. Obviamente. .7 Modificar listas 189 17. a o As´ es como usamos este m´todo: ı e >>> 1 2 >>> >>> 2 >>> 1 3 imprimeLista(nodo1) 3 eliminado = elimnaSegundo(nodo1) imprimeLista(eliminado) imprimeLista(nodo1) El diagrama de estado nos muestra el efecto de la operaci´n: o first second cargo next 1 cargo next 2 cargo next 3 None ¿Qu´ ocurrir´ si llam´ramos a este m´todo y pas´ramos una lista de un unico e ıa a e a ´ elemento (un singleton)? ¿Qu´ suceder´ si pas´ramos una lista vac´ como e ıa a ıa argumento? ¿Hay una condici´n previa para este m´todo? Si es as´ ser´ algo o e ı.siguiente # hacer que el primer noda apunte al tercero primero. Modificar listas Hay dos formas de modificar una lista enlazada. escribamos un m´todo que quite el segundo nodo de la lista y e devuelva una referencia al nodo quitado: def eliminaSegundo(lista): if lista == None: return primero = lista segundo = lista. estamos usando variables temporales para hacer m´s legible el c´digo. n Como ejemplo. ıa razonable establecer un m´todo para manejar una violaci´n de la condici´n e o o previa.siguiente = None return segundo De nuevo.siguiente # separar el segundo nodo del resto de la lista segundo. podemos cambiar la carga de uno de los nodos. pero las operaciones m´s interesantes son las que a a˜aden.

Envoltorios y ayudantes A menudo es util dividir una operaci´n de listas en dos m´todos. o e En primer lugar crearemos un nueva clase llamada ListaEnlazada. 1] podemos usar el m´todo imprimeAlReves para imprimir 3.cabeza = None Una ventaja de la clase ListaEnlazada es que suministra un marco natural para poner funciones-envoltorio como imprimeAlRevesBonito. 2. ıa Cuando usamos este m´todo en alg´n otro lugar del programa. imprimeAlRevesBonito act´a como un envoltorio. if lista != None : cabeza = lista cola = lista. que podemos convertir en un m´todo de la clase ListaEnlazada: e . En cierto modo. 17. vemos que es buena idea comprobar m´todos como ´ste para ver si e e funcionan con casos especiales como una lista vac´ o un singleton.190 Listas enlazadas 17. Llam´moslo e e imprimeAlRevesBonito: def imprimeAlRevesBonito(lista) : print "[".longitud = 0 self. pero necesitaremos e un m´todo aparte para imprimir los corchetes y el primer nodo. La clase ListaEnlazada Existen ciertos problemas delicados con la forma en que se implementaron las listas. 2.siguiente imprimeAlReves(cola) print cabeza. propondremos primero una implementaci´n alternativa y explicaremos luego los problemas que ´sta resuelve. y u utiliza a imprimeAlReves como su ayudante. Por ejemplo. print "]". Los objetos ListaEnlazada sirven de asas para la manipulaci´n de las o listas de los objetos de tipo Nodo: class ListaEnlazada : def __init__(self) : self. y ´ste llama a imprimeAlReves en nuestro e lugar. Sus atributos son un entero que contiene la longitud de la lista y una referencia al primer nodo.9. llamamos direce u tamente a imprimeAlRevesBonito. Inviertiendo el orden de causa y efecto.8. De nuevo. ´ o e para imprimir una lista invertida en el formato convencional [3.

. toma un elemento de la carga como argumento y lo coloca en el principio de la lista: class ListaEnlazada: . Por ejemplo. y otro en la clase ListaEnlazada (el envoltorio).carga.longitud = self.cabeza self. agregaPrimero es un m´todo e para ListaEnlazada..cabeza = nodo self. Otro requisito es que el valor de el valor . Por ejemplo. def imprimeAlReves(self): if self.cabeza != None: self.imprimeAlReves() print self.10 Invariantes class ListaEnlazada: . est´ llamando al ayudante.10. renombramos imprimeAlRevesBonito. as´ que podr´ a e ı ıamos exigir que las listas no contengan bucles.siguiente cola. def agregaPrimero(self.. carga): nodo = Nodo(carga) nodo. def imprimeAlReves(self): print "["..imprimeAlReves. provocar´ que nuestros m´todos se cuelguen. Cuando el envoltorio llama a self. if self. class Nodo: .cabeza es un objeto de tipo Nodo. Invariantes Algunas listas est´n “bien construidas”. 191 Para complicar un poco m´s las cosas.cabeza. si una lista cona tiene un bucle.cabeza.siguiente = self.17..longitud + 1 Como suele ser usual. Por ejemplo..imprimeAlReves() print "]". ¿qu´ ocurrir´ si la lista est´ unicialmente vac´ e ıa a ıa? 17. Otra ventaja de la clase ListaEnlazada es que facilita la forma de a˜adir o quin tar el primer elemento de una lista.siguiente != None: cola = self. otras no. ya que a self. deber´ ıamos comprobar ´ste c´digo para ver si maneja e o casos especiales. a Ahora hay dos m´todos llamados imprimeAlReves: uno en la clase Nodo (el e ayudante).

o Una cosa que a veces confunde respecto a los invariantes es que en ocasiones son violados.11. 17. comprobar la integridad de las estructuras de o datos y la detecci´n de errores. singleton: Lista enlazada con un solo nodo. de hecho. Glosario referencia incrustada: Es una referencia almacenada en un atributo de un objeto. normalmente implementado como un objeto que contiene una referencia a otro objeto del mismo tipo. A este tipo de requisitos los llamaremos invariantes porque. condici´n previa: Afirmaci´n que debe ser cierta para que un m´todo funcioo o e ne correctamente. Se acepta este tipo de violaci´n. idealmente deber´ cumplirse en todos los objetos en todo momento. Especificar invariantes ıan para objetos es una pr´ctica util de la programaci´n porque hace m´s f´cil dea ´ o a a mostrar la idoneidad del c´digo. se exige que todo m´todo que viole un invariante debe restablecerlo. lista enlazada: Estructura de datos que implementa una colecci´n por medio o de una secuencia de nodos enlazados. se viola el invariante. Normalmente. carga: Datos contenidos en un nodo. e Si hay alg´n tramo significativo de c´digo en el que el invariante se ve violado. a menudo es imposible modificar un objeto sin violar un o invariante durante al menos un corto espacio de tiempo. de modo que no se realicen operaciones que dependan del invariante. enlace: Referencia incrustada usada para enlazar un objeto con otro. u o es importante que los comentarios lo dejen claro. teorema fundamental de la ambig¨ edad: Una referencia a un nodo de una u lista puede tratarse como un objeto individual o como el primero de una lista de nodos. Por ejemplo. despu´s de a˜adir el nodo e n paro antes de incrementar la longitud. .192 Listas enlazadas de longitud en el objeto de tipo ListaEnlazada deber´ ser igual al n´mero ıa u verdadero de nodos de la lista. nodo: Elemento de una lista. en medio de agregaPrimero.

e o invariante: Afirmaci´n que deber´ ser cierta para un objeto en todo momento o ıa (excepto tal vez cuando se est´ modificando el objeto). a .11 Glosario 193 envoltorio: M´todo que act´a como mediador entre un m´todo invocador y e u e m´todo ayudante. ayudante: M´todo al que no se invoca directamente por un m´todo llamante e e sino por otro m´todo para formar parte de una operaci´n.17. haciendo a menudo su invocaci´n m´s f´cil o menos e o a a proclive a errores.

.

1. en el sentido que se ha especificado su implementaci´n completamente.Cap´ ıtulo 18 Pilas 18. se implementan a menudo en bibliotecas est´ndares de manera que se puedan escribir a una vez y usarlas luego muchos programadores. la clase o Carta representa un naipe por medio de dos enteros. Tipos abstractos de datos Los tipos de datos vistos hasta ahora han sido todos concretos. Como suelen existir muchas maneras de implementar un TAD. Los TADs mas conocidos. existen muchas implementaciones ´ alternativas. u . especifica un conjunto de operaciones (o m´todos) y la sem´ntica de las operaciones (lo que hacen). Un tipo abstracto de datos. Esto es lo hace lo abstracto. o ¿Para qu´ sirve? e Simplifica la tarea de especificar un algoritmo si se pueden indicar las operaciones necesarias sin preocuparse de c´mo se ejecutar´n dichas opeo a raciones. esa no es la unica manera de representar una carta. Por ejemplo. puede ser util desarrollar un algoritmo que se pueda usar con cualquiera de las im´ plementaciones posibles. como el TAD Pila de este cap´ ıtulo. Como dijimos. Las operaciones ejecutadas con TADs proporcionan un lenguaje de alto nivel com´n para desarrollar y hablar sobre algoritmos. pero no especifica e a la implementaci´n de las operaciones. o TAD.

a u o lo que significa que es una estructura de datos que contiene elementos m´ltiples. C´mo implementar pilas con listas de Pyto hon Las operaciones sobre listas que posee Python son parecidas a las operaciones que definen a una pila. el c´digo cliente. La interfaz para una pila consta de estas e operaciones1 : init : Inicializar una pila nueva y vac´ ıa. 18. Una pila es una colecci´n. A veces a una pila se la llama una estructura “´ltimo en entrar primero en salir” u (“last in. y el c´digo que implementa el TAD. pero ıa se pueden desarrollar programas para convertir el TAD Pila a las operaciones predefinidas. push: A˜adir un elemento a la pila. el c´digo o o o proveedor. a a He aqu´ una implementaci´n de el TAD Pila que utiliza una lista Python: ı o 1 Mantenemos los nombres ingleses porque son est´ndar en otros TADs en Python y otros a lenguajes. la pila. porque el elemento a˜adido en ultimo e n ´ lugar es el primero que extraemos. o LIFO. A este programa se lo llama implementaci´n del TAD Pila.2. Un TAD se definido por medio de las operaciones que se pueden ejecutar sobre ´l. n pop: Extraer un elemento de la pila. lo que se llama un interfaz. 18. En general. El elemento devuelto siempre es el ultimo ´ que se a˜adi´. n o isEmpty: Probar si la pila est´ vac´ a ıa. first out” en ingl´s).3. u Otras colecciones que se han visto son los diccionarios y las listas. La interfaz no es exactamente la que deber´ de ser. una o implementaci´n es un conjunto de m´todos que satisfacen los prerrequisitos o e sint´cticos y sem´nticos de la interfaz. . El TAD Pila En este cap´ ıtulo se presentar´ un TAD com´n.196 Pilas Cuando hablamos de TADs a menudo se hace la distinci´n entre el c´digo que o o usa el TAD.

elementos. Para quitar un elemento de la pila.4.pop() def isEmpty(self) : return (self.elementos = [] def push(self. e o ıa Para meter un elemento nuevo en la pila. lo significa que se puede a˜adir e n cualquier tipo de elementos a ella.push("+") Se pueden utilizar isEmpty y pop para quitar e imprimir todos los elementos en la pila: 2 del mismo nombre . a ıa) elementos con la lista vac´ ıa. El ejemplo mete en la pila dos enteros y una cadena: >>> >>> >>> >>> s = Stack() s.4 Uso de push y pop class Pila : def __init__(self) : self. se llama enchapado.elementos == []) 197 Un objeto Pila contiene un atributo llamado elementos que es una lista de elementos en la pila. Los cient´ ıficos inform´ticos utilizan esta a met´fora para describir una parte de un programa que esconde los detalles de a una implementaci´n y que provee una interfaz mas simple o mas est´ndar. pop utiliza el m´todo de lista hom´nimo2 para e o quitar y devolver el ultimo elemento de la lista. para probar si la pila esta vac´ isEmpty (est´ vac´ compara ıa. Una implementaci´n como esta. o a 18.append(elemento) def pop(self) : return self. en la cual los m´todos consisten de llamadas a o e m´todos existentes. En la vida real. El m´todo de inicializaci´n pone una lista vac´ en elementos.18. Uso de push y pop Una pila es una estructura gen´rica de datos. un enchapado es una e capa fina de madera de alta calidad que se utiliza en la fabricaci´n de muebles o para ocultar madera de baja calidad.push(54) s. elemento) : self.elementos. push lo apila en elementos.push(45) s. ´ Finalmente.

¡se ha utilizado una pila para imprimir los elementos en orden inverso! Reconocemos que no es el formato est´ndar de a impresi´n de listas. o Este ejemplo demuestra una de las ventajas de el formato postfijo—no hay necesidad de usar par´ntesis para controlar el orden de operaciones. eval´e los operadores y operandos uno o u por uno. Cuando llegue al final de la expresi´n habr´ un operando en la pila. pero fue muy f´cil usar una pila para lograrlo. as´ 1 e ı: 2 +. A este formato se le llama infijo.isEmpty() : print s.5. utilice pop con dos operandos de la pila. utilice push para colocarlo en la pila. La diferencia es que imprimeAlReves utiliza la pila de tiempo de ejecuci´n para mantenerse al o tanto de los nodos mientras recorre la lista y luego los imprime cuando regresa de la recursi´n. La raz´n por la que el formato postfijo es util es que existe una forma natural o ´ de evaluar una expresi´n en formato postfijo utilizando una pila: o Desde el principio de la expresi´n. Con postfijo. escriba una expresi´n en formato postfijo que sea o equivalente a 1 + 2 * 3. e ejecute la operaci´n sobre ellos. Para practicar. aplique este algoritmo a la expresi´n 1 2 + 3 *.4. o a Compare estas l´ ıneas con la implementaci´n de imprimeAlReves que vimos o en la Secci´n 17. . el operador va despu´s de los operandos. se tendr´ que escribir (1 + 2) * 3). de esta manera: 1+2. • Si el t´rmino es un operando. Existe un paralelo natural entre la versi´n recurrente de o o imprimeAlReves y el algoritmo de pila que acabamos de ver. Usar una pila para evaluar postfijo Las expresiones matem´ticas en la mayor´ de lenguajes de programaci´n se a ıa o escriben con el operador entre los dos operandos. Algunas calculadoras utilizan un formato alternativo llamado postfijo. Pilas La salida es + 45 54. o 18. y coloque el resultado en la pila con o push. pero utiliza un objeto Pila o en vez de la pila de tiempo de ejecuci´n. Para obtener e el mismo resultado con el formato infijo. El algoritmo de pila hace lo mismo. ıa Para practicar. e • Si el t´rmino es un operador. Ese o a operando es el resultado.pop().198 while not s. En otras palabras.

[A-z] es el conjunto de todas las letras y [0-9] es el conjunto de todas las cifras. ’+’.split("La hora ha llegado". Python posee un m´todo llamado split (partir) en el m´dulo string (cadena) e o y en el m´dulo re (expresiones regulares). "123+456*/") [’123’. Quiz´s se acuerde de esas palabras del Cap´ a ıtulo 1. Evaluar un postfijo Para evaluar una expresi´n en formato postfijo usaremos el analizador sint´ctico o a de la secci´n anterior y el algoritmo de la secci´n previa a ´sa. La lista resultante incluye los operandos 123 y 456 y los operadores * y /. el delimitador viene antes de la cadena. n ıa o . Este proceso es un ejemplo del an´lisis sint´ctico. ’456’. La funci´n string.split. en ocasiones tambi´n como “s´ e ımbolo” pero la expresi´n inglesa est´ tan introducida en el vocabulario inform´tico que s´lo o a a o a˜adir´ confusi´n. Tambi´n incluye dos cadenas vac´ que se insertan despu´s de los operandos.split tiene m´s potente. y los resultados—la piezas individuales de la cadena—son a a tokens3 .6. y [^0-9] es el conjunto de todo lo que no es un n´mero. lo cual es exactamente u lo que queremos utilizar para partir expresiones en el formato postfijo: >>> import re >>> re. ’’] F´ ıjese que el orden de los argumentos es diferente del de string. ’/’. e ıas e 18.split parte una o o cadena y la convierte en una lista utilizando un s´lo car´cter como delimitador. Por ejemplo. y se parte la cadena en cada a espacio.7. El operador ^ niega un conjunto. y nos permite utilizar una expresi´n o a o regular en vez de un delimitador. ’*’. ’hora’.6 An´lisis sint´ctico a a 199 18. La funci´n re. el delimitador es el car´cter espacio. An´lisis sint´ctico a a Para implementar el algoritmo anterior. necesitamos ser capaces de recorrer una cadena y separarla en operandos y operadores. Para no complicar o o e 3 Podr´ ıamos traducir “token” como “cospel” o “pieza”." ") [’La’.split("([^0-9])". ’ha’. ’’. o a Por ejemplo: >>> import string >>> string. Una expresi´n regular es una manera de espeo cificar un conjunto de cadenas.18. ’llegado’] En este caso.

o .pop() * pila.push(producto) else: pila. Por supuesto. a e Comprobemos con una evaluaci´n de la forma postfijo (56+47)*2): o >>> print evalPostfijo ("56 47 + 2 *") 206 Esto es suficiente.8.split("([^0-9])". Clientes y proveedores Uno de los objetivos fundamentales de un TAD es el de separar los intereses del proveedor.pop() pila. quien escribe el c´digo de programa que implementa el TAD. ciones siguientes controlan los operadores. que todo lo dem´s es un operando. quien utiliza el TAD. por ahora. El proveedor s´lo se preocupa de la o implementaci´n y de si es correcta o no—de acuerdo a las especificaciones del o TAD—y no de c´mo se va a utilizar.pop() La primera condici´n se encarga de espacios y cadenas vac´ Las dos condio ıas.pop() + pila.200 Pilas las cosas. o y los del cliente. expr) pila = Pila() for token in listaTokens: if token == ’’ or token == ’ ’: continue if token == ’+’: suma = pila. pero eso se har´ despu´s. 18. comenzaremos con un evaluador que solo implementa los operadores + y *: def evalPostfijo(expr): import re listaTokens = re.push(int(token)) return pila. ser´ mejor verificar si la entrada tiene a ıa errores y mostrar un mensaje con el error.push(suma) elif token == ’*’: producto = pila. Asumimos.pop() pila.

como la puntuaci´n a o en un lenguaje natural. como las palabras de un lenguaje natural. cuando usted implemente un TAD. En ese case. e analizar sint´cticamente: Examinar una cadena de caracteres o tokens y a analizar su estructura gram´tical. . infijo: Un m´todo de escribir expresiones matem´ticas con los operadores entre e a los operandos. el cliente supone que la implementaci´n del TAD es correcta y o no se preocupa de los detalles.9. uno se puede dar el lujo de pensar exclusivamente como un cliente. Glosario tipo abstracto de datos (TAD): Un tipo de datos (a menudo una colecci´n o de objetos) que se define por un conjunto de operaciones pero que se puede implementar de varias maneras. o proveedor: Un programa (o la persona que lo escribi´) que implementa un o TAD. a a cliente: Un programa (o la persona que lo escribi´) que utiliza un TAD. Cuando se usa uno de los tipos predefinidos de Python. Tiene que fijarse bien en del papel que est´ tomando en todo o a momento.18. lo cual puede causar confusi´n. implementaci´n: El c´digo de programa que satisface los prerrequisitos o o sint´cticos y sem´nticos de un interfaz. Por supuesto. a delimitador: Un car´cter utilizado para separar tokens. pero mejora la interfaz vista por el cliente o la hace mas est´ndar. uno toma ambos papeles. 18. enchapado: La definici´n de clase que implementa un TAD con definiciones o de m´todos que son las invocaciones de otros m´todos. El enchapado no ejecuta nada de gran valor. postfijo: Un m´todo de escribir expresiones matem´ticas con los operadores e a despu´s de los operandos. a estructura de datos gen´rica: Un tipo de estructura de datos que puede e contener datos de cualquier tipo. a token: Un conjunto de caracteres que se tratan como una unidad y son analizados sint´cticamente.9 Glosario 201 A la inversa. a veces con transe e formaciones simples. tambi´n debe desarrollar c´die o go de cliente para probarlo. interfaz: El conjunto de operaciones que definen un TAD.

.

e a La t´ctica de encolamiento m´s simple se llama FIFO. Sin embargo. una cola es una fila de clientes esperando un servicio de alg´n tipo. 19. La regla que determina qui´n va primero se llama t´ctica de encolamiento. sin importar a el orden de llegada. cu´n importante es el cliente. en la que a cada cliente se le asigna una prioridad y el cliente con la prioridad m´s alta pasa primero.1. En los supermercados. El TAD Cola y el TAD Cola Priorizada tienen el mismo conjunto de operaciones. El TAD Cola El TAD Cola se define a trav´s de las siguientes operaciones: e init : Inicializa una cola nueva vac´ ıa. y una cola priorizada (como su propio nombre indica) usa una t´ctica de a encolamiento priorizado. hay excepciones. no todas las t´cticas a a de prioridad son “justas”. La diferencia est´ en la sem´ntica de las operaciones: una cola usa la t´ctica a a a FIFO. La t´ctica de encolamiento m´s a a general es el encolamiento priorizado.Cap´ ıtulo 19 Colas Este cap´ ıtulo presenta dos TADs: la Cola y la Cola Priorizada. a veces se saca de la cola a los clientes cuyos vuelos van a salir pronto. Decimos que es la t´ctica m´s general porque la prioridad a a se puede basar en cualquier cosa: a qu´ hora sale el vuelo. cu´ntos productos e a lleva el cliente. . En la vida real. Por supuesto. En la u mayor´ de los casos. un cliente educado puede dejar que alguien que lleva pocos productos pase antes. a a “el primero que entra es el primero que sale”. pero la justicia siempre es subjetiva. de “first-in-first-out”. el primer cliente de la fila es el primero al que se va a ıa servir. En los aeropuertos.

cabeza while ultimo.cabeza.cabeza == None: # si la lista est´ vac´a el nuevo nodo va el primero a ı self. El m´todo inserta es nuevo y un poco m´s e a . n Colas quita: Elimina y devuelve un elemento de la cola. He aqu´ la a ı definici´n de la clase: o class Cola: def __init__(self): self.2.siguiente self.1 return carga Los m´todos estaVacia y quita son id´nticos a los m´todos estaVacia y e e e quitaPrimero de ListaEnlazada. El elemento devuelto es el primero que se a˜adi´. 19.204 inserta: A˜ade un elemento a la cola.longitud = 0 self.siguiente: ultimo = ultimo.siguiente # a~adir el nuevo nodo n ultimo.siguiente = nodo self.cabeza = None def estaVacia(self): return (self. n o estaVacia: Comprueba si la cola est´ vac´ a ıa.longitud = self. carga): nodo = Nodo(carga) nodo.carga self. Cola Enlazada La primera implementaci´n del TAD Cola al que vamos a echar un vistazo se o llama cola enlazada porque est´ hecha de ojetos Nodo enlazados.longitud .cabeza.longitud = self.longitud == 0) def inserta(self.longitud + 1 def quita(self): carga = self.cabeza = nodo else: # encuentra el ´ltimo nodo de la lista u ultimo = self.cabeza = self.siguiente = None if self.

´ Este recorrido cuesta un tiempo proporcional a la longitud de la lista. Ah´ no hay bucles ni llamadas a funciones. o El rendimiento de inserta es muy diferente. ´ En un objeto Cola correctamente construido hay dos invariantes. Rendimiento t´ ıpico Normalmente cuando invocamos un m´todo. simplemente hacemos que cabeza se refiera al nuevo nodo. y c´mo var´ el tiempo de ejecuci´n al e a o ıa o aumentar el n´mero de elementos de la colecci´n? u o Primero mire quita. recorremos la lista hasta el ultimo nodo y lo fijamos al final. 19. es muy pobre. el m´todo podr´ ı o e ıa ser ligeramente m´s r´pido cuando la lista est´ vac´ porque se salta el cuerpo a a a ıa de la condici´n. tenemos que recorrer la lista para encontrar el ultimo elemento. En realidad. y el ultimo nodo deber´ ıa u ´ ıa tener siguiente igual a None. El valor de longitud deber´ ser el n´mero de nodos en la cola.3 Rendimiento t´ ıpico complicado. Si la cola est´ vac´ a ıa. Como el tiempo de ejecuci´n es funci´n lineal de la longitud. Cr´ase que este m´todo cumple con ambas invae e riantes. Pero hay un “detalle” que podr´ interesarnos: el rendimieno ıa to t´ ıpico del m´todo. dando a entenı der que el tiempo de ejecuci´n de este m´todo es siempre el mismo. Una forma de hacerlo es modificar la clase Cola de modo que mantenga una referencia tanto al primero como al ultimo ´ nodo. como se muestra en la figura: . En caso contrario. ¿Cu´nto tarda. Un m´todo o e e as´ se llama operaci´n de tiempo constante. Cola Enlazada Mejorada Nos gustar´ una implementaci´n del TAD Cola capaz de realizar todas las ıa o operaciones en tiempo constante. En el caso general.19.3. Comparado con el tiempo constante. ´ Podemos reconocer el ultimo nodo porque su atributo siguiente es None. este m´todo se llama de o o e tiempo lineal. 19. no nos importan los detalles de su e implementaci´n. pero esa diferencia no es significativa. 205 Queremos insertar nuevos elementos al final de la lista.4.

siguiente = None if self.cabeza = self.ultimo = nodo self.longitud == 0: # si la lista est´ vac´a.longitud + 1 Como ultimo sigue el rastro del ultimo nodo. carga): nodo = Nodo(carga) nodo. este m´todo funciona en tiempo constante.longitud == 0) Hasta ahora.siguiente = nodo self.ultimo # a~adir el nuevo nodo n ultimo.cabeza = None self. e Debemos pagar un precio por esa velocidad.. A causa ´ de esto. el unico cambio es el atributo ultimo.ultimo = nodo else: # encontrar el ´ltimo nodo u ultimo = self.. no necesitamos buscarlo. Se usa en los m´todos ´ e inserta y quita: class ColaMejorada: .longitud = 0 self. el nuevo nodo es cabeza y ´ltimo a ı u self. Tenemos que a˜adir un caso especial n a quita para apuntar ultimo a None cuando quitamos el ultimo nodo: ´ class ColaMejorada: .longitud = self.ultimo = None def estaVacia(self): return (self. def inserta(self.206 head length 3 last Colas cargo next 1 cargo next 2 cargo next 3 La implementaci´n de ColaMejorada es as´ o ı: class ColaMejorada: def __init__(self): self.

podemos elegirlos en orden alfab´tico. De nuevo.5 Cola priorizada . y es m´s o a a dif´ demostrar que es correcta. e pero si son puntuaciones de golf.cabeza. pero diferente sem´ntica. a estaVacia: Comprueba si la cola est´ vac´ a ıa. Cola priorizada El TAD Cola Priorizada tiene el mismo interfaz que el TAD Cola.. Lo que son las prioridades y c´mo se comparan con las otras no se a o especifica en la implementaci´n de la Cola Priorizada.5. def quita(self): carga = self.longitud . ıa inserta: A˜ade un nuevo elemento a la cola. Siempre que podamos comparar los elementos de la cola. si los elementos de la cola tienen nombres. 19.longitud == 0: self.longitud = self. La ventaja es que hemos alcanzado la meta: ıcil tanto inserta como quita son operaciones de tiempo constante. El elemento devuelto es el de prioridad m´s alta. La diferencia sem´ntica es que el elemento eliminado de la cola no es necesaa riamente el primero que se a˜adi´. iremos de menor a mayor. Si son puntuaciones de bolos.cabeza. Esta implementaci´n de Cola Priorizada tiene como atributo una lista de Python o que contiene los elementos de la cola. es el elemento con la prioridad n o m´s alta. . el interfaz es: a init : Inicializa una cola vac´ nueva. Depende de los elementos o de la cola. Compare el rendimiento de esta implementaci´n o con la de la ColaMejorada para varias longitudes de cola. n quita: Elimina y devuelve un elemento de la cola.19. podemos ir de mayor a menor.cabeza = self.. Como ejercicio. Por ejemplo. En su lugar. podremos encontrar y quitar el elemento con mayor prioridad.ultimo = None return carga 207 Esta implementaci´n es m´s complicada que la de la Lista Enlazada. escriba una implementaci´n del TAD Cola usando o una lista de Python.siguiente self.carga self.1 if self.

inserta(11) c. e inserta son todos calcados de las e o operaciones sobre listas..elementos)): if self. Si el e o nuevo elemento es mayor.elementos.elementos[maxi] self. maxi es el ´ o ındice del elemento mayor. Este elemento se elimina de la lista y se devuelve.elementos[maxi:maxi+1] = [] return elemento Al principio de cada iteraci´n.inserta(12) c.len(self. Vamos a probar la implementaci´n: o >>> >>> >>> >>> >>> >>> 14 13 12 11 c = ColaPriorizada() c. maxi contiene el ´ o ındice del elemento m´s grande a (prioridad m´s alta) que hemos visto hasta el momento.append(elemento) Colas El m´todo de inicializaci´n. el valor de maxi se fija a i. estaVacia.elementos == [] def inserta(self..quita() # ver cu´l se quita a . elemento): self. def quita(self): maxi = 0 for i in range(1. Cuando la sentencia for completa su ejecuci´n.estaVacia(): print c. Cada vez que se coma pleta el bucle. el programa compara el i´simo elemento con el campe´n.inserta(14) c.elementos[maxi]: maxi = i elemento = self.elementos[i] > self.elementos = [] def estaVacia(self): return self. El unico m´todo interesante es quita: ´ e class ColaPriorizada: .208 class ColaPriorizada: def __init__(self): self.inserta(13) while not c.

puntos: return 1 if self..nombre = nombre self. se eliminan en orden num´rico u e o alfab´tico. a >>> 61) 72) 69) .6 La clase Golfista 209 Si la cola contiene n´meros o cadenas simples..puntos: return -1 return 0 # menos es m´s a Ya estamos listos para probar la cola priorizada con la clase Golfista: >>> tiger = Golfista("Tiger Woods". -1 si self es “menor que” otro.puntos) str usa el operador de formato para poner los nombres y las puntuaciones en bonitas columnas. class Golfista: . la Cola Priorizada funcionar´. puntos): self. Si la cola contiene un tipo de objeto. cmp devuelve 1 si self es a “mayor que” otro. y 0 si son iguales. A >>> ola = Golfista("J.puntos < otro. e Cuando quita usa el operador > para comparar elementos. def __cmp__(self. invoca al cmp de uno de los elementos y le pasa el otro como par´metro. debe proporcionar un m´todo cmp . nombre.puntos = puntos def __str__(self): return "%-16s: %d" % (self. otro): if self.19.M. Como es habitual. >>> cabr = Golfista("´ngel Cabrera". La clase Golfista Como ejemplo de un objeto con una definici´n inusual de prioridad. vamos a o implementar una clase llamada Golfista que mantiene los nombres y puntuaciones de golfistas. de mayor a menor.nombre. self. Siempre que el m´todo a e cmp trabaje adecuadamete.puntos > otro.6. Python puede encontrar el entero o la cadena e mayor porque puede compararlos usando los operadores de comparaci´n intero nos. Como siempre. Olaz´bal". empezamos por definir init y str : class Golfista: def __init__(self. a 19. A continuaci´n definimos una versi´n de cmp en la que la puntuaci´n m´s o o o a baja tiene la prioridad m´s alta.

o 19. t´ctica de encolamiento: Las reglas que determinan qu´ miembro de la cola a e ser´ el pr´ximo en eliminarse. n tiempo lineal: Una operaci´n cuyo tiempo de ejecuci´n es funci´n lineal del o o o tama˜o de la estructrua de datos.inserta(tiger) >>> cp. Deber´ usted mantener la lista ıa ordenada de modo que la eliminaci´n sea una operaci´n de tiempo o o constante. First Out”. cola enlazada: Una implementacion de una cola utilizando una lista enlazada.inserta(ola) >>> while not cp. cola priorizada: Una t´ctica de encolamiento en la que cada miembro tiene a una prioridad determinada por factores externos. n .quita() Tiger Woods : 61 J.210 >>> cp = ColaPriorizada() >>> cp. Glosario cola: Un conjunto ordenado de objetos esperando un servicio de alg´n tipo. a o FIFO: “First In. El miembro con mayor prioridad es el primero en eliminarse. u Cola: Un TAD que ejecuta las operaciones que uno podr´ realizar sobre una ıa cola.M.inserta(cabr) >>> cp. tiempo constante: Una operaci´n cuyo tiempo de ejecuci´n no depende del o o tama˜o de la estructura de datos. escriba una implementaci´n del TAD Cola Prioo rizada usando una lista enlazada. una t´ctica de encolamiento en la que el primer a miembro en llegar es el primero en salir.7. Compare el rendimiento de esta implementaci´n con la o implementaci´n con la lista de Python. Olaz´bal : 69 a ´ngel Cabrera : 72 A Colas Como ejercicio.estaVacia(): print cp. Cola Priorizada: Un TAD que define las operaciones que se pueden realizar sobre una cola priorizada.

Para empeorar las cosas. Puede parecer extra˜o que n dibujemos la figura con la ra´ arriba y las hojas abajo. pero eso no es lo m´s ız a raro. La parte superior del ´rbol (el nodo al que apunta tree) se llama ra´ Siguiendo a ız. Un diagrama de estado de un ´rbol es as´ a e a ı: tree cargo left 1 right cargo left 2 right cargo left 3 right None None None None Para evitar apelotonar las cosas en la figura. los cient´ ıficos inform´ticos a˜aden a la mezcla otra a n met´fofa: el ´rbol geneal´gico. Nombramos a estas referencias como sub´rboles izquierdo y derecho. en el que cada nodo contiene una referencia u a a a otros dos nodos (posiblemente nula). los nodos de los a ´rboles tambi´n contienen una carga. Como los nodos de las listas. los ´rboles est´n hechos de nodos. los otros nodos se llaman ramas y los nodos de los a a extremos con referencias nulas se llaman hojas.Cap´ ıtulo 20 ´ Arboles Al igual que las listas enlazadas. El nodo superior se llama a veces padre y los a a o . Un tipo a a com´n de ´rbol es un ´rbol binario. solemos omitir los Nones. con la met´fora del ´rbol.

carga. Crear ´rboles a El proceso de montar un ´rbol es similar al proceso de montar una lista enlazada. los ´rboles son estructuras de datos recursivas a porque se definen recursivamente. todos los nodos que ız) e est´n a la misma distancia de la ra´ forman un nivel del ´rbol. a ız a Probablemente no sean necesarias las met´foras arb´reas para hablar de ´rboles. a 20.carga = carga self.1. o Para imprimir un nodo.212 ´ Arboles nodos a los que se refiere son sus hijos. o class Arbol: def __init__(self. Los nodos con el mismo padre se llaman hermanos. el valor por a omisi´n es None. Tambi´n. izquierda=None. a Cada invocaci´n del constructor crea un solo nodo. e a Ya hemos mencionado izquierda y derecha. a o a pero ah´ est´n. pero los par´metros izquierda y derecha a deben ser ´rboles. pero tambi´n est´n “arriba” (hacia e a el padre/ra´ y “abajo” (hacia los hijos/hojas). simplemente imprimimos la carga.carga) La carga puede ser de cualquier tipo. o a ıo.derecha = derecha def __str__(self): return str(self. Una forma de construir un ´rbol es del fondo hacia arriba.izquierda = izquierda self. un nodo que contiene una referencia a un objeto y dos referencias a ´rboles. Tanto izquierda como derecha son opcionales. tenemos un vocabulario geom´trico para hablar sobre los ´rboles. Para terminar. derecha=None): self. ı a Igual que las listas enlazadas. Un ´rbol es: a el ´rbol vac´ representado por None. Asigne primero los a nodos hijos: izquierda = Arbol(2) derecha = Arbol(3) .

ı paso recursivo hace dos llamadas recursivas para hallar la suma de los ´rboles a hijos. esta a funci´n nos devuelve su suma: o def total(arbol): if arbol == None: return 0 return total(arbol. el resultado es el ´rbol del principio del cap´ a ıtulo.derecha) +\ arbol. Por ejemplo. la expresi´n infija 1 + 2 * 3 es ambigua a no ser que o sepamos que la multiplicaci´n se realiza antes que la suma.2. as´ que la suma es 0.3. Cuando terminan las llamadas recursivas. derecha).2 Recorrer ´rboles a Luego cree el nodo padre y vinc´lelo a los hijos: u arbol = Arbol(1.carga El caso base es el ´rbol vac´ que no tiene carga. izquierda. a o Al contrario que otras notaciones. puede representar el c´lculo de forma no a ambigua. Arbol(2). El a ıo. sumamos la carga del padre y devolvemos el total.20. o ´ Este ´rbol de expresi´n representa el mismo c´lculo: a o a . 213 Podemos escribir este c´digo m´s concisamente anidando las invocaciones al o a constructor: >>> arbol = Arbol(1. ´ Arboles de expresi´n o Un ´rbol es un forma natural de representar la estructura de una expresi´n.izquierda) + total(arbol. su primera pregunta deber´ ser: “¿C´mo la recorro?” La forma m´s natural de recorrer un ´rbol ıa o a a es recursivamente. Recorrer ´rboles a Siempre que usted vea una nueva estructura de datos. 20. si el ´rbol contiene enteros como carga. 20. Arbol(3)) En cualquier caso. Por ejemplo.

lo que significa que tienen exactamente dos operandos. optimizar y traducir programas. Los ´rboles de expresi´n tienen muchos usos. no hay duda del orden de las operaciones.214 tree ´ Arboles cargo left + right cargo left 1 right cargo left right * cargo left 3 right cargo left 2 right Los nodos de un ´rbol de expresi´n pueden ser operandos como 1 y 2 u operadoa o res como + y *. Arbol(’*’.carga. Arbol(3))) Mirando la figura. porque el contenido de a la ra´ aparece antes del contenido de los hijos. Recorrido de un ´rbol a Podemos recorrer un ´rbol de expresi´n e imprimir el contenido as´ a o ı: def imprimeArbol(arbol): if arbol == None: return print arbol. 20. ız. a e a Esta forma de recorrer un ´rbol se llama orden prefijo.derecha) En otras palabras. La salida del ejemplo anterior ız es: .) As´ podemos construir este ´rbol: ı a >>> arbol = Arbol(’+’. Arbol(2). Arbol(1).izquierda) imprimeArbol(arbol.4. la multiplicaci´n o se realiza antes para calcular el segundo operando de la suma. (Todos estos operadores son binarios. El ejemplo de este cap´ a o ıtulo usa ´ ´rboles para traducir expresiones a postfijo. imprimeArbol(arbol. prefijo e infijo. Arboles similares se a usan dentro de los compiladores para analizar. para imprimir un ´rbol imprima primero el contenido de la a ra´ luego el sub´rbol izquierdo entero y despu´s el sub´rbol derecho entero. los nodos operadores contienen referencias a sus operandos. Los operandos son nodos hojas.

luego la ra´ y despu´s el ´rbol derecho: ız e a def imprimeArbolInfijo(arbol): if arbol == None: return imprimeArbolInfijo(arbol. si imprime primero los sub´rboles o o a y luego la ra´ tendr´: ız. Puede sospechar que si recorre el ´rbol en un orden diferente obtendr´ la exprea a si´n en una notaci´n diferente. modifique imprimeArbolInfijo de modo que ponga entre par´ntesis cada operador con sus operandos. a def imprimeArbolPostfijo(arbol): if arbol == None: return imprimeArbolPostfijo(arbol. es otra notaci´n o llamada prefija.derecha) El resultado es 1 + 2 * 3. Como ejercicio.derecha) print arbol. Finalmente. Arbol(1). Arbol(3))) >>> imprimeArbol(arbol) + 1 * 2 3 Este formato es diferente tanto del postfijo como del infijo.izquierda) print arbol. debemos usar par´ntesis para o o e preservar el orden de las operacioens. el ´rbol de expresi´n y los tres ren a o corridos nos dan una forma general de traducr expresiones de un formato a otro. con unas peque˜as mejoras. Por ejemplo. o o Para ser justos debemos se˜alar que hemos omitido una importante complin caci´n. Arbol(’*’.carga. podemos generar una representaci´n gr´fica de un ´rbol: a o a a . o No obstante. 1 2 3 * +. imprimeArbolInfijo(arbol.izquierda) imprimeArbolPostfijo(arbol. De modo que una exploraci´n de orden o infijo no es suficiente para generar una expresi´n infija. al escribir una expresi´n infija. ¿La salida es e correcta y sin ambig¨edades? ¿Se necesitan siempre los par´ntesis? u e Si hacemos un recorrido en orden infijo y tomamos nota de en qu´ nivel del e ´rbol estamos. en la que los operadores aparecen delante de sus operandos.4 Recorrido de un ´rbol a 215 >>> arbol = Arbol(’+’. A veces. usted imprime el ´rbol a a izquierdo. est´ en notaci´n posfija! Este orden de recorrido se a o llama orden postfijo.carga.20. Arbol(2). ¡El resultado. que es la expresi´n en notaci´n infija. para recorrer un ´rbol en orden infijo.

nivel+1) ´ Arboles El par´metro nivel lleva la cuenta de d´nde estamos en el ´rbol. u par´ntesis y los operadores + y *.216 def imprimeArbolSangrado(arbol. Por ejemplo. Sangramos cada elemento con dos espacios por nivel. Construir un ´rbol de expresi´n a o En esta secci´n analizamos expresiones infijas y formamos los correspondientes o ´rboles de expresi´n. a o a o incialmente es 0. Cada vez que hacemos una llamada recursiva. la expresi´n (3+7)*9 nos da el siguiente a o o ´rbol: a * + 3 7 9 F´ ıjese en que hemos simplificando el diagrama omitiendo los nombres de los atributos. a o 20.carga) imprimeArbolSangrado(arbol. Suponemos que la cadena de entrada ya ha e sido tokenizada y almacenada en una lista de Python. La lista de tokens de (3+7)*9 es: . nivel=0): if arbol == None: return imprimeArbolSangrado(arbol. pasamos nivel+1 porque el nivel del hijo es siempre uno mayor que el del padre. El resultado del ´rbol de ejemplo es: a >>> imprimeArbolSangrado(arbol) 3 * 2 + 1 Si mira la salida de lado.5. nivel+1) print ’ ’*nivel + str(arbol. ver´ una versi´n simplificada de la figura original. Por omisi´n. El analizador que vamos a escribir maneja expresiones que incluyen n´meros.derecha.izquierda.

devuelve None. Si el siguiente token o de listaToken es un n´mero. Compara el token esperado con el primer token de la lista: si coinciden. 9. ’+’. obtieneNumero. o La primera funci´n que vamos a escribir es tomaToken. 7. que construye un e ´rbol de expresi´n para productos. maneja operandos. Asignamos una lista de n´meros a listaToken. los cambios hechos aqu´ son ı visibles para cualquier otra variable que apunte al mismo objeto. obtieneNumero lo elimina y devuelve un nodo u hoja que contiene el n´mero. escriba una funci´n que tome una cadena cono teniendo una expresi´n y devuelva una lista de tokens. elimina el token de la lista y devuelve verdadero.20. .5 Construir un ´rbol de expresi´n a o [’(’. ’*’. como 3 * 7. ’fin’] 217 El token fin es util para evitar que el analizador lea m´s all´ del final de la ´ a a lista. en caso contrario. Un producto simple tiene dos n´meros como a o u operandos. imprimimos el resultado u e imprimimos lo que quede de la lista de tokens: >>> listaToken = [9. A modo de ejercicio. None) Antes de seguir. None. ’)’. ’fin’] El siguiente m´todo que necesitamos es obtieneProducto. 11. u def obtieneNumero(listaToken): x = listaToken[0] if type(x) != type(0): return None del listaToken[0] return Arbol (x. en caso contrario. La siguiente funci´n. que toma como par´meo a tros una lista de tokens y el token que esperamos. 3. debemos probar obtieneNumero aisladamente. esperado): if listaToken[0] == esperado: del listaToken[0] return 1 else: return 0 Como listaToken apunta a un objeto mutable. ’fin’] >>> x = obtieneNumero(listaToken) >>> imprimeArbolPostfijo(x) 9 >>> print listaToken [11. devuelve falso: def tomaToken(listaToken. extraemos el primero.

b. obtenemos el a segundo n´mero y construimos un ´rbol de expresi´n con a. Si el siguiente car´cter es *.218 ´ Arboles Aqu´ tenemos una versi´n de obtieneProducto que maneja productos simples. 11. ’*’. como 3 * 5 * 13. ’fin’] >>> arbol = obtieneProducto(listaToken) >>> imprimeArbolPostfijo(arbol) 9 El segundo ejemplo implica que entendemos un operando suelto como un tipo de producto. 3 * (5 * o 13). Veamos dos ejemplos: >>> listaToken = [9. ’fin’] >>> arbol = obtieneProducto(listaToken) >>> imprimeArbolPostfijo(arbol) 9 11 * >>> listaToken = [9. ’*’): b = obtieneNumero(listaToken) return Arbol (’*’. ı o def obtieneProducto(listaToken): a = obtieneNumero(listaToken) if tomaToken(listaToken. a. Esta definici´n de “producto” es contraria a la intuici´n. e Tratamos esta expresi´n como un producto de productos. ’+’. u a o Si el siguiente car´cter es cualquier otra cosa. b) else: return a Suponiendo que obtieneNumero se ejecuta con ´xito y devuelve un ´rbol simple. pero resulta o o ser util. y el operador. e a asignamos el primer operando a a. El ´rbol resultante es: a * 3 5 * 13 Con un peque˜o cambio en obtieneProducto podemos manejar productos arn bitrariamente largos: . simplemente devolvemos el nodo a hoja con a. 11. ´ Ahora tenemos que v´rnoslas con productos compuestos. es decir.

Pero si no encuentra un +. tiene una bonita propiedad: podeo mos representar cualquier expresi´n (sin par´ntesis) como una suma de produco e tos. def obtieneSuma(listaToken): a = obtieneProducto(listaToken) if tomaToken(listaToken. simplemente construye un producto. 7. ’*’. 7. ’*’. u tipo de definici´n recursiva deber´ empezar a resultar familiar.20. ız. b) else: return a Vamos a probarla con 9 * 11 + 5 * 7: >>> listaToken = [9. a. 5 . a obtieneSuma intenta construir un ´rbol con un producto en la izquierda y una a suma en la derecha. ’*’. 3.5 Construir un ´rbol de expresi´n a o def obtieneProducto(listaToken): a = obtieneNumero(listaToken) if tomaToken(listaToken. ’*’. ’*’): b = obtieneProducto(listaToken) return Arbol (’*’. ’*’. Esta propiedad es la base de nuestro algoritmo de an´lisis. o ıa Comprobemos la nueva versi´n con un producto compuesto: o >>> >>> >>> 2 3 listaToken = [2. Si quiere seguir adelante con esta definici´n. b) else: return a 219 # cambiamos esta l´nea ı En otras palabras. 11. una suma puede ser un ´rbol con o a + en la ra´ un producto en la izquierda y una suma en la derecha. Este ız. a. ’fin’] >>> arbol = obtieneSuma(listaToken) >>> imprimeArbolPostfijo(arbol) 9 11 * 5 7 * + . usamos una definin ci´n poco intuitiva de “suma”. un producto puede ser bien un operando aislado o un ´rbol a con * en su ra´ un n´mero en la derecha y un producto en la izquierda. ’+’. De nuevo. Para nosotros. O tambi´n. 5. ’+’): b = obtieneSuma(listaToken) return Arbol (’+’. ’fin’] arbol = obtieneProducto(listaToken) imprimeArbolPostfijo(arbol) 5 7 * * * Ahora a˜adiremos la capacidad de analizar sumas. e una suma puede ser simplemente un producto.

’(’. ’)’): raise ’ExpresionErronea’.220 ´ Arboles Ya casi hemos acabado. cuando alcanzamos el final de una subexpresi´n. 5.6. ’falta un par´ntesis’ e return x . ’(’): x = obtieneSuma(listaToken) # obtiene la subexpresi´n o tomaToken(listaToken. 11. Manejar errores En todo momento hemos supuesto que las expresiones estaban bien formadas. e def obtieneNumero(listaToken): if tomaToken(listaToken. deber´ a ıamos ocuparnos de ´l. puede o u haber tambi´n una suma entera entre par´ntesis. o En la versi´n final del programa. ser´ bueno dar a obtieneNumero un nombre o ıa m´s descriptivo de su nueva funci´n. ’)’) # quita el cierre de par´ntesis e return x else: x = listaToken[0] if type(x) != type(0): return None listaToken[0:1] = [] return Arbol (x. None. ’(’): x = obtieneSuma(listaToken) if not tomaToken(listaToken. suponemos que o el car´cter siguiente es un par´ntesis cerrado. ’)’. Si hay un error y el siguiente a e car´cter es cualquier otra cosa. a o 20. la suma ocurre antes de la o e multiplicaci´n. ’fin’] >>> arbol = obtieneSuma(listaToken) >>> imprimeArbolPostfijo(arbol) 9 11 5 + 7 * * El analizador manej´ correctamente los par´ntesis. pero todav´ tenemos que manejar los par´ntesis. Por ejemplo. ’*’. None) Vamos a probar este c´digo con 9 * (11 + 5) * 7: o >>> listaToken = [9. 7. ’*’. ’+’. S´lo necesitamos modificar e e o obtieneNumero para manejar subexpresiones: def obtieneNumero(listaToken): if tomaToken(listaToken. ıa e En culaquier lugar de una expresi´n donde puede haber un n´mero.

7 El ´rbol de animales a else: # omitido el resto de la funci´n o 221 La sentencia raise crea una excepci´n. o o o o alguna de las otras funciones de la pila de llamadas. a Como ejercicio. el o programa podr´ continuar. llamado ExpresionErronea. Python imprimir´ un mensaje de a a error y saldr´. En caso contrario. maneja la expresi´n.7. Aqu´ tenemos un ejemplo de ejecuci´n: ı o Est´s pensando en un animal? s a Es un p´jaro? n a C´mo se llama el animal? perro o Qu´ pregunta distinguir´a a un perro de un p´jaro? Puede volar e ı a Si el animal fuera un perro. en este caso creamos un nuevo tipo de exo cepci´n. o 20. Si la funci´n que llam´ a obtieneNumero. El ´rbol de animales a En esta secci´n desarrollaremos un peque˜o programa que usa un ´rbol para o n a representar una base de conocimientos. cu´l ser´a la respuesta? n a ı Est´s pensando en un animal? s a Puede volar? n Ladra? s Es un perro? s Soy el m´s grande! a .20. El programa interact´a con el usuario para crear un ´rbol de preguntas y nomu a bres de animales. n Pruebe su c´digo con expresiones formadas incorrectamente. cu´l ser´a la respuesta? n a ı Est´s pensando en un animal? s a Puede volar? n Es un perro? n C´mo se llama el animal? gato o Qu´ pregunta distinguir´a a un gato de un perro? Ladra e ı Si el animal fuera un gato. encuentre otros lugares de estas funciones donde puedan ocurrir errores y a˜ada las sentencias raise adecuadas.

tomaCarga() + "? " if si(indicador): arbol = arbol. pide al usuario el nombre del nuevo animal y una pregunta que distinga al intento fallido del nuevo animal.tomaIzquierda() != None: indicador = arbol.tomaIzquierda() # intentar adivinar .tomaDerecha() else: arbol = arbol. intenta adivinar. En ese momento. se mueve al hijo de la izquierda o de la derecha y sigue hasta que llega a un nodo hoja. el programa empieza en lo alto del ´rbol y hace la a primera pregunta. ´ Este es el c´digo: o def animal(): # empezar con un nodo suelto raiz = Arbol("p´jaro") a # bucle hasta que el usuario salga while 1: print if not si("Est´s pensando en un animal? "): break a # recorrer el ´rbol a arbol = raiz while arbol. Dependiendo de la respuesta. Entonces a˜ade un nodo al ´rbol n a con la nueva pregunta y el nuevo animal.222 Est´s pensando en un animal? n a Este es el ´rbol que construye este di´logo: a a ´ Arboles Can it fly? n Does it bark? n cat y dog y bird Al principio de cada ronda. Si falla.

piense en varias formas en las que podr´ guardar el ıa arbol de conocimiento en un archivo.ponCarga(pregunta) indicador = "Si el animal fuera un %s. la pregunta sustituye a la carga y los n a dos hijos son el animal nuevo y la carga original. imprime un indicador y acepta una entrada del o usuario. Si la respuesta comienza con s o S. a a . cu´l ser´a la\ a ı respuesta? " if si(indicador % animal): arbol.ponDerecha(Arbol(animal)) else: arbol. lo que significa que seguir´ hasta que se o a ejecute la sentencia break cuando el usuario ya no piense en ning´n animal. u El bucle while interno recorre el ´rbol de arriba a abajo. la funci´n devuelve verdadero: o def si(preg): from string import lower resp = lower(raw_input(preg)) return (resp[0] == ’s’) La condici´n del bucle externo es 1. ¡olvida todo lo que usted le hab´ ıa ense˜ado con tanto cuidado! n Como ejercicio.adivina)) # a~adir informaci´n nueva al ´rbol n o a arbol. al salir.ponIzquierda(Arbol(adivina)) arbol.7 El ´rbol de animales a adivina = arbol.ponDerecha(Arbol(adivina)) La funci´n si es un auxiliar.20. Cuando se a˜ade un nuevo nodo al ´rbol. Implemente la que piense que ´ es m´s f´cil. guiado por las resa puestas del usuario.tomaCarga() indicador = "Es un " + adivina + "? " if si(indicador): print "Soy el m´s grande!" a continue 223 # obtener informaci´n nueva o indicador = "C´mo se llama el animal? " o animal = raw_input(indicador) indicador = "Qu´ pregunta distinguir´a a un %s de un %s? " e ı pregunta = raw_input(indicador % (animal. Una carencia del programa es que.ponIzquierda(Arbol(animal)) arbol.

hermanos: Nodos que tienen un padre com´n. sin padre. orden infijo: Una forma de recorrer un ´rbol. hijo: Uno de los nodos a los que apunta un nodo. notaci´n prefija: Una forma de escribir una expresi´n matem´tica en la que o o a los operadores aparecen antes que sus operandos. visitando cada nodo antes que a a sus hijos. orden postfijo: Una forma de recorrer un ´rbol. a a luego la ra´ y luego el sub´rbol derecho. ız: a hoja: Un nodo del extremo inferior de un ´rbol. a padre: El nodo que apunta a un nodo dado. a . o orden prefijo: Una forma de recorrer un ´rbol. subexpresi´n: Una expresi´n entre par´ntesis que act´a como un operando o o e u simple dentro de otra expresi´n mayor. o dos nodos a a dependientes. visitando los hijos de cada a nodo antes del propio nodo. Glosario ´rbol binario: Un ´rbol en el que cada nodo apunta a cero. uno. u nivel: El conjunto de nodos equidistante de la ra´ ız. operador binario: Un operador que toma dos operandos.8. sin hijos. ız. ra´ El nodo superior de un ´rbol.224 ´ Arboles 20. visitando el sub´rbol izquierdo.

Ejemplo: o o e una recursi´n infinita termina por provocar un error en tiempo de ejecuo ci´n del “maximum recursion depth exceeded” (superada la profundidad o m´xima de recursi´n). e a o A.Ap´ndice A e Depuraci´n o En un programa pueden suceder varios tipos de error. La mayor´ de los o ıa mensajes de error en tiempo de ejecuci´n incluyen informaci´n acerca de o o d´nde sucedi´ el error y qu´ funciones se estaban ejecutando. muchas veces los mensajes de error no son . Ejemplo: omitir los dos puntos al final de una sentencia def nos da el mensaje SyntaxError: invalid syntax. o e Aunque las secciones que siguen est´n organizadas por tipos de error. Errores de sintaxis Los errores de sintaxis suelen ser f´ciles de arreglar una vez que averigua a lo que son. algunas a t´cnicas son aplicables en m´s de una situaci´n. El sistema de tiempo de ejecuci´n presenta los errores en tiempo de ejeo cuci´n si algo va mal mientras se ejecuta el programa. Desgraciadamente. Ejemplo: una expresi´n puede e o no evaluarse en el orden esperado. dando un resultado inesperado. y resulta util distinguirlos ´ para localizarlos r´pidamente: a Python presenta errores de sintaxis mientras traduce el c´digo fuente en o c´digo binario. El primer paso de la depuraci´n es averiguar con qu´ tipo de error se enfrenta. algo redundante. Normalmente indican que hay algo err´neo en la sintaxis o o del programa.1. a o Los errores sem´nticos son problemas con un programa que compila y se a ejecuta pero no hace lo que se espera de ´l.

Estar´ en la ultima l´ a ´ ınea que a˜adi´. ıan Aseg´rese de que todas las cadenas del c´digo tienen su par de comillas u o de apertura y cierre. { o [—hace que Python continue con la l´ e ınea siguiente como parte de la sentencia actual. a ıa 4. ninguno de los cuales es muy informativo. siga con la secci´n que sigue. o puede tratar la siguiente parte del programa como una cadena hasta que llegue a la siguiente cadena. Puede usted sangrar tanto con espacios como con tabuladores. while. Al mismo tiempo. el mensaje le dice en qu´ lugar del programa sucedi´ el error. Una o u cadena sin terminar puede provocar un error invalid token al final de su programa.. 3. Si tiene cadenas que ocupan varias l´ ıneas con triples comillas (o triples ap´strofos). A veces el error est´ antes de la localizaci´n del mensaje de a a o error. pero es mejor no mezclarlos. Compruebe el cl´sico = donde deber´ haber un == en los condicionales. podr´ serlo. e o En realidad. Por otra parte. le dice d´nde not´ el problema Python.226 Depuraci´n o muy utiles. n o Si est´ usted copiando c´digo de un libro. recuerde o a que el libro podr´ estar equivocado. y def. Aseg´rese de que no utiliza una palabra clave de Python como nombre de u variable. podr´ ıa no presentar ning´n mensaje de error! u Un par´ntesis sin cerrar—(. Compruebe que tiene los dos puntos al final de la cabecera de todas las sentencias compuestas. 2. ıa He aqu´ algunas formas de evitar los errores de sintaxis m´s habituales: ı a 1. que no es necesariamente o o donde est´ el error. 7. if. ¡En el segundo caso.. Los mensajes m´s comunes son SyntaxError: invalid syntax y ´ a SyntaxError: invalid token. Todos los niveles deber´ estar anidados por la misma cantidad. Compruebe cada car´cter. comience comparando con atenci´n a o o su c´digo con el del libro. o . Compruebe que el sangrado es consistente. deber´ tener casi localizado el a ıa error. Si nada funciona. muchas veces en la l´ ınea anterior. Si est´ haciendo el programa incrementalmente. 5. las for. 6. as´ que si ve algo que parezca un error de ıa ı sintaxis. aseg´rese de que ha terminado la cadena correctamente. Generalmente aparecer´ un a error casi inmediatamente en la l´ ınea siguiente.

Si el compilador dice que hay un error pero usted no lo ve. Si un programa se para y parece no hacer nada. puede enfrentarse a ello empezando de nuevo con un programa nuevo como “Hola.1.2. . Mi programa se cuelga. decimos que “se ha colgado”. Compruebe su entorno de o programaci´n para asegurarse de que el programa que est´ editando es el que o a est´ intentando ejecutar Python. Si no est´ seguro. A. Esto puede ser o intencionado cuando s´lo planea importar el m´dulo para suministrar clases y o o funciones.2 Errores en tiempo de ejecuci´n o 227 A. o Si hay un bucle en particular que le resulta sospechoso de provocar el problema. Ahora ejecute (o importe) de nuevo. no importa lo que haga. No consigo ejecutar mi programa. Errores en tiempo de ejecuci´n o Una vez que su programa es sint´cticamente correcto. y asegurarse de que puede hacer que funcione un programa conocido. pruebe a poner un error de a a sintaxis obvio y deliberado al principio del programa. a Si esto ocurre. mundo”. Si el compilador no encuentra el nuevo error probalemente hay algo equivocado en el modo en que est´ configurado su entorno. o ejecute una desde el indicador interactivo.1.2.1. Luego a˜ada gradualmente los trozos del programa nuevo n al que funciona. aseg´rese de que est´ llamando a una funci´n que inicie u a o la ejecuci´n.2. Sin no es intencionado. ¿Qu´ podr´ ir mal? e ıa A. A menudo significa que se ha quedado atrapado en un bucle infinito o en una recursi´n infinita. Mi programa no hace nada de nada. Python pude importarlo a y al menos comenzar a ejecutarlo. a˜ada una sentencia print justo antes del bucle que diga “enn trando al bucle” y otra inmediatamente despu´s que diga “saliendo del e bucle”. podr´ ser porque ıa usted y el compilador no miran el mismo c´digo. o a A.2.A. Vea tambi´n la secci´n o e o “Flujo de Ejecuci´n” m´s adelante. Este problema es muy com´n cuando su archivo consta de funciones y clases u pero en realidad no invoca nada para que empiece la ejecuci´n.

o e a o comience por asegurarse de que hay un caso b´sico. Si no ve este error pero sospecha que hay un problema con un m´todo o e funci´n recursivos tambi´n puede utilizar las t´cnicas de la secci´n “Reo e e o cursi´n Infinita”. (x > 0 and y < 0) o Ahora. Vaya a la secci´n “Bucle Infinito” m´s adelante. Si sospecha que una funci´n o un m´todo est´ causando una recursi´n infinita. y "condici´n: ". comience a probar otros bucles y otros m´todos y funciones recursivos. ver´ tres l´ a ıneas de salida en cada vuelta del bucle. cuando ejecute el programa. Si el bucle ´ o ıa sigue ejecut´ndose. Vaya a la secci´n “Flujo de Ejecuci´n” m´s adelante. o o Por ejamplo: while x > 0 and y < 0 : # hacer algo con x # hacer algo con y print print print "x: ". e Si eso no funciona. Si ocurre eso. y podr´ averiguar por qu´ no a a a e se actualizan correctamente.228 Depuraci´n o Ejecute el programa. a˜ada una sentencia print que imprima los valores de las variables de n la condici´n al final del bucle junto con el valor de la condici´n. Recursi´n Infinita o Una recursi´n infinita casi siempre har´ que el programa se ejecute un rato y o a luego provoque un error de Maximum recursion depth exceeded. o Si no funciona ninguno de estos pasos. vaya a la secci´n “Recursi´n Infinita” m´s adeo o a lante. tiene usted un bucle infinito. En otras palabras. o a Una recursi´n infinita casi siempre har´ que el programa corra un rato o a y luego presente un error de “RuntimeError: Maximum recursion depth exceeded”. x "y: ". o o a Bucle Infinito Si cree que tiene un bucle infinito y piensa que sabe qu´ bucle provoca el proe blema. podr´ ver los valores de x e y. es posible que no comprenda el flujo de ejecuci´n de o su programa. Si obtiene el primer mensaje pero el segundo no. En la ultima vuelta el valor de la condici´n deber´ ser false. deber´ a ıa .

o TypeError: Hay varias causas posibles: Est´ intentando usar un varlor de forma inadecuada. o u u o Cuando ahora ejecute el programa.2. No puede hacer referencia a ellas desde fuera de la funci´n en la que se definen. imprimir´ una traza de cada funci´n a mea o dida que las vaya invocando. . La traza inversa identifica la funci´n que se est´ ejecutando ahora y la funci´n o a o que invoc´ a ´sta. traza la ruta de las llamadas a las funciones que le llevaron a donde se encuentra. a a e Flujo de Ejecuci´n o Si no est´ seguro de qu´ curso sigue el flujo de ejecuci´n en su programa. Si los par´metros no se o e ı a a a acercan al caso b´sico. necesita revisar el algoritmo y encontrar ese caso b´sico. a˜ada a e o n sentencias print al principio de cada funci´n con un mensaje como “entrando o en la funci´n turur´”. En o e o o e ı otras palabras. A. Python imprime un mensaje que incluye el o nombre de la excepci´n. y as´ sucesivamente. ver´ unas pocas l´ a ıneas cada vez que se invoque la funci´n o m´todo y all´ ver´ los par´metros. la l´ o ınea del programa donde sucedi´ el problema y una o traza inversa. Estos son algunos de los errores en tiempo de o ejecuci´n m´s comunes: o a NameError: Est´ intentando usar una variable que no existe en el entorno a actual. Ejemplo: usar a como ´ ındice para una cadena. a Si hay un caso b´sico pero el programa no parece llegar hasta ´l.2 Errores en tiempo de ejecuci´n o 229 haber una condici´n que haga que la funci´n devuelva un valor sin hacer otra o o llamada recursiva. Tambi´n incluye los n´meros de las l´ e u ıneas de sus archivos donde suceden todas esas llamadas. o Si algo va mal durante la ejecuci´n. lista o tupla algo que no es un entero. a o e Cuando ahora ejecute el programa.3.A. Cuando ejecuto el programa recibo una excepci´n. donde turur´ es el nombre de la funci´n. a˜ada una a e n sentencia print que imprima los par´metros al principio de la funci´n o m´todo. El primer paso es examinar el lugar del programa donde sucede el error y ver si puede adivinar lo que sucedi´. eso le dar´ alguna idea de por qu´ no lo hace. Recuerde que las variables locales son locales. y luego la funci´n que invoc´ a ´sa. Si no.

Uno de los problemas de usar sentencias print para la depuraci´n es que pueo de terminar enterrado en informaci´n. Por ejemplo. Si sospecha de una funci´n a o grande. si est´ ordea a nando un vector.230 Depuraci´n o Hay una discrepancia entre los elementos de una cadena de formato y los elementos pasados para la conversi´n. Puse tantas sentencias print que me ahoga la salida. Por ejemplo. Si el programa acepta entradas del n usuario. Hay dos formas de atajar el problema: o simplificar la salida o simplificar el programa. a˜ada una sentencia print que muestre el valor del ´ n ındice y la longitud del vector. Luego f´ a ıjese en la invocaci´n del m´todo. o combinarlas. si sospecha que el problema est´ en una parte del programa con un anidamiento muy profundo. cadena o tupla a es mayor que su longitud menos uno. Esto puede ocurrir tanto si o el n´mero de elementos no coincide como si se solicita una conversi´n u o no v´lida.4. Primero. a Para simplificar el programa puede hacer varias cosas. aseg´rese de que est´ invocando el m´todo sobre o e u a e un objeto del tipo adecuado y d´ndole correctamente el resto de ara gumentos. IndexError: El ´ ındice que est´ usando para acceder a una lista.2. reducir la escala del problema en el que est´ trabajando el programa. ¿Es correcto el tama˜o del vector? ¿Tiene el ´ n ındice un valor correcto? A. limpie el programa. puede elimiar o comentar (convertir en comentarios) las sentencias print que no sean de ayuda. a Est´ pasando un n´mero err´neo de argumentos a una funci´n o a u o o m´todo. o dar a la salida un formato que la haga m´s comprensible. trate de trocearla en funciones menores y pru´belas separadamente. dele la entrada m´s simple que provoque el problema. a AttributeError: Est´ intentando acceder a un atributo o m´todo que no exisa e te. a Segundo. ordene un vector peque˜o. f´ e e ıjese en la definici´n de los m´todos y o e compruebe que el primer par´metro es self. e . Elimine el c´digo muerto y reorganice el programa o para hacerlo tan legible como sea posible. pruebe a a reescribir esa parte con una estructura m´s simple. Para simplificar la salida. KeyError: Est´ tratando de acceder a un elemento de un diccionario con una a clave que no est´ en el diccionario. Con los m´todos. Justo antes de donde aparece el error.

pero s´ lo hace.3. porque el compilador y el sistema de ejecuci´n no proporcionan informaci´n sobre lo o o que va mal. a De forma parecida. S´lo usted sabe lo que se supone que debe hacer el programa.3. a El primer paso es hacer una concexi´n entre el texto del programa y el comporo tamiento que est´ usted viendo. . Lea la documentaci´n e o o de las funciones que invoca. A. y s´lo o o usted sabe que no lo est´ haciendo. Mi programa no funciona. le dar´ una pista. a Si se encuentra con que un programa funciona en una situaci´n pero no en otra. y con alıa gunos programas depuradores podr´ hacerlo. Deber´ hacerse estas preguntas: ıa ¿Hay algo que se supone que deber´ hacer el programa pero que no parece ıa suceder? Busque la secci´n del c´digo que realiza esa funci´n y aseg´rese o o o u de que se ejecuta cuando deber´ ıa. Una de las dificultades que nos encontramos para a ello es la alta velocidad de los computadores. Pru´belas escribiendo casos de prueba simples e y comprobando el resultado. ¿Hay una secci´n de c´digo que causa un efecto que no esperaba? aseg´rese o o u de que entiende el c´digo en cuesti´n. la reescritura de una porci´n de c´digo puede ayudarle a o o encontrar errores sutiles. los errores sem´nticos son los m´s dif´ a a ıciles de corregir. Necesita una hip´tesis sobre lo que realmente a o est´ haciendo el programa.3 Errores sem´nticos a 231 El proceso de encontrar el caso m´ ınimo de prueba le llevar´ a menudo al error. ¿Ocurre algo que no deber´ Busque el programa que realiza esa funci´n ıa? o y vea si se ejecuta cuando no debe. poner y quitar puntos de interrupci´n y “hacer o caminar” el programa hasta donde se produce el error. ı a A.1. Si hace un cambio que a usted le parece que no afecta al programa. o eso le dar´ una pista sobre lo que ocurre.A. Errores sem´nticos a En cierto modo. especialmente si incluye invocaciones o o de funciones o m´todos de otros m´dulos de Python. A menudo desear´ ralentizar el progrma a una velocidad humana. Pero el tiempo que lleva colocar a unas sentencias print en los lugares adecuadoes suele ser menor que el que lleva configurar el depurador.

a La mejor manera de corregir su modelo mental es dividiendo el programa en sus componentes (normalmente las funciones y m´todos) y probando cada compoe nente de forma independiente.agregaCarta (self.manos[\ self. deber´ ir haciendo y probando componentes tal como desarrolla ıa el programa. si est´ traduciendo o a la expresi´n 2π a Python. podr´ escribir: o x ıa y = x / 2 * math. podr´ solucionar el problema.encuentraVecino(i)]. Por ejamplo: self.manos[i]. pero pueden ser a o dif´ ıciles de depurar. Una vez que encuentre la discrepancia entre su modelo y la realidad. Suele ser una buena idea dividir una expesi´n compleja en o una serie de asignaciones de variables temporales.3. Si escribe un programa que no hace lo que espera de ´l.manos[vecino]. y es m´s f´cil de depurar porque puede comprobar o a a los tipos de las variables intermedias y mostrar sus valores.darCarta() self.pi. Est´ bien escribir expresi´n complejas mientras sean legibles. u ı o Una buena forma de depurar expresiones es a˜adir par´ntesis para hacer expl´ n e ıcito el orden de evaluaci´n: o . Tengo una expresi´n grande y peliaguda y no hace o lo que espero. sino en su modelo mental.encuentraVecino (i) cartaElegida = self. porque la multiplicaci´n y la divisi´n tienen la misma preceo o dencia y se eval´an de izquierd a derecha.232 Depuraci´n o Para programar necesitar´ tener un modelo mental de c´mo funcionan los proa o gramas. Por ejemplo. s´lo habr´ una peque˜a cantidad de o a n c´digo nuevo del que no sabe si est´ correcto.manos[i]. Otro problema que puede suceder con las expresiones grandes es que el orden de evaluaci´n puede no ser el que usted esperaba. Eso no es correcto.2. muchas veces e el problema no estar´ en el programa.darCarta()) Puede reescribirse como: vecino = self. As´ que esa expresi´n calcula xπ/2. Si encuentra un problema. a Por supuesto. o a A.agregaCarta (cartaElegida) La versi´n expl´ o ıcita es m´s f´cil de leer porque los nombres de variable nos facilia a tan documentaci´n adicional.

3 Errores sem´nticos a y = x / (2 * math. De nuevo. Algunos de los mejores lugares para encontrar errores son los trenes.3. Si tiene una sentencia return con una expresi´n compleja no tendr´ la oporo a tunidad de imprimir el valor de retorno antes de volver. Estoy atascado de verdad y necesito ayuda. intente alejarse del computador durante unos minutos. piense en el programa.3. El proe o e grama no s´lo ser´ correcto (en el sentido de hacer lo que usted prentend´ o a ıa). a e Cuando est´ calmado. o a Programar dando palos de ciego (el empe˜o de programar escribiendo n todos los programas posibles y eligiendo el que hace lo correcto).4.manos[i]. . o Creencias supersticiosas (“el computador me odia”) y pensamiento m´gico a (“el programa s´lo funciona cuando me pongo la gorra hacia atr´s”). utilice par´ntesis. sino que adem´s ser´ m´s legible para otras personas que no hayan memorizado a a a las reglas de precedencia.manos[i]. Si se encuentra afectado por alguno de estos s´ ıntomas. las duchas y la cma. lev´ntese y d´ un paseo. puede usar una variable temporal.3. 233 Siempre que no est´ seguro del orden de evaluaci´n. Muchas veces encontramos errores cuando estamos lejos del computador y divagamos. en lugar de: return self.A. A. Por ejemplo.eliminaCoincidencias() podr´ excribir: ıa cant = self. A. ¿Qu´ es lo que hace? ¿Cu´les e e a pueden ser las causas de tal comportamiento? ¿Cu´ndo fue la ultima vez que a ´ ten´ un programa que funcinaba y qu´ fue lo siguiente que hizo? ıa e A veces lleva tiempo encontrar un error. Los computadores emiten unas ondas que afectan al cerebro provocando estos efectos: Frustraci´n y/o furia. Primero.pi). Tengo una funci´n o m´todo que no devuelve lo o e que esperaba. justo antes de quedarse dormido.eliminaCoincidencias() return cant Ahora ya tiene la oportunidad de mostrar el valor de cant antes de regresar.

el objetivo no es s´lo hacer que el programa funciones.5. A veces trabaja durante tanto tiempo en un programa que no puede ver el error. Deber´ tener sentencias ıa print en los lugares adecuados (y lo que dicen deber´ ser comprensible). a Recuerde.234 Depuraci´n o A. ser´ capaz de encontrar el error antes. No. o cu´l es el nuevo caso de prueba o o a que no cumple? ¿Qu´ ha intentado hasta ahora y qu´ ha averiguado? e e Cuando encuentre el error. ıa ıa trabajando con la entrada m´ ınima que provoca el error. ¿cu´l es y qu´ parte del programa se˜ala? a e n ¿Qu´ fue lo ultimo que hizo antes de que apareciera el error? ¿Cu´les son e ´ a las ultimas l´ ´ ıneas de c´digo que escribi´. Antes de llamar a andie. La siguiente vez que vea algo ıa a a parecido. ıa Cuando llame a alguien para que le ayude. aseg´rese de que ha agotado las t´cnicas explicadas u e aqu´ Su programa deber´ ser tan simple como sea posible. Incluso los mejores programadores se atascan de vez en cuando. Sucede. de verdad necesito ayuda. El objetivo es o aprender c´mo hacer funcionar al programa. Lo que necesita es un par de ojos nuevos. y usted deber´ estar ı. Deıa ber´ entender el problema lo bastante bien como para describirlo sucintamente. o .3. aseg´rese de darles la informaci´n u o que necesitan: Si hay un mensaje de error. t´mese un momento para pensar acerca de lo que o podr´ haber hecho para encontrarlo m´s r´pido.

o u Al n´mero superior se se le llama numerador y al inferior se se le llama denou minador. tambi´n conocidas como n´meros racionales. denominador=1): self. Comenzamos definiendo la clase Fraccion con un m´todo de inicializaci´n que e o nos surta de un numerador y un demonimador enteros: class Fraccion: def __init__(self.Ap´ndice B e Crear un nuevo tipo de datos Los lenguajes de programaci´n orientados a objetos permiten a los programadoo res crear nuevos tipos de datos que se comporten de manera muy parecida a los tipos de datos nativos. Las fracciones. Una Fraccion con un s´lo par´metro representa un o a n´mero entero. u o El siguente paso es escribir un m´todo str para que imprima las frace ciones de forma que tenga sentido. enteros largos y flotantes. son valores que e u pueden expresrse como la proporci´n entre dos n´meros enteros. tal como 5/6. construimos la fracci´n n/1. La forma natural de hacerlo es “numerador/denominador”: .denominador = denominador El denominador es opcional.numerador = numerador self. Si el numerador es n. e enteros. numerador. Exploraremos esta posibilidad construyendo una clase Fraccion que funcione de manera muy similar a los tipos num´ricos nativos.

Para ello.236 Crear un nuevo tipo de datos class Fraccion: .. Entonces creamos e un objeto fracci´n y lo imprimimos. otro): return Fraccion(self. B. def __mul__(self. multiplicaıa ci´n y divisi´n a las fracciones. mortadela o La fracci´n es 5/6 o Como siempre..1.6) >>> print "La fracci´n es".4) 15/24 Funciona. pero ¡podemos hacerlo mejor! Podemos ampliar el m´todo para mae nejar la multiplicaci´n por un entero.denominador*otro. o class Fraccion: . def __str__(self): return "%d/%d" % (self. . podemos sobrecargar los operadores o o matem´ticos para los objetos de clase Fraccion.py y lo importamos desde el int´rprete de Python. Usamos la funci´n type para ver si otro o o es un entero y convertirlo en una fracci´n en tal caso..numerador.. a Comenzaremos con la multiplicaci´n porque es la m´s f´cil de implementar. self. self.numerador*otro. Multiplicaci´n de fracciones o Nos gustar´ poder aplicar las operaciones normales de suma.. mul es el nombre que Python utiliza para el m´todo que sobrecarga al operador *: e class Fraccion: .. creamos una nueva fracci´n cuyo numerador o es el producto de los numeradores de los operandos y cuyo denominador es el producto de los denominadores de los operandos.denominador) Para probar lo que tenemos hasta ahora.6) * Fraccion(3.numerador. o a a Para multiplicar dos fraciones. o >>> from Fraccion import fraccion >>> mortadela = Fraccion(5. resta.denominador) Podemos probar este m´todo calculando el producto de dos fracciones: e >>> print Fraccion(5. lo ponemos en un fichero llamado Fraccion. la funci´n print invoca impl´ o ıcitamente al m´todo e str .

B.2 Suma de fracciones def __mul__(self, otro): if type(otro) == type(5): otro = Fraccion(otro) return Fraccion(self.numerador * otro.numerador, self.denominador * otro.denominador)

237

Ahora funciona la multiplicaci´n para fracciones y enteros, pero s´lo si la fraco o ci´n es el operando de la izquierda. o >>> print Fraccion(5,6) * 4 20/6 >>> print 4 * Fraccion(5,6) TypeError: __mul__ nor __rmul__ defined for these operands Para evaluar un operador binario como la multiplicaci´n, Python comprueba o primero el operando de la izquierda para ver si proporciona un m´todo mul e que soporte el tipo del segundo operando. En este caso, el operador nativo de multiplicaci´n del entero no soporta fracciones. o Despu´s, Python comprueba el segundo operando para ver si provee un m´todo e e rmul que soporte el tipo del primer operando. En este caso, no hemos provisto el m´todo rmul , por lo que falla. e Por otra parte, hay una forma sencilla de obtener class Fraccion: ... __rmul__ = __mul__ Esta asignaci´n hace que el m´todo rmul sea el mismo que mul . Si ahora o e evaluamos 4 * Fraccion(5,6), Python llamar´ al m´todo rmul del objeto a e Fraccion y le pasar´ 4 como par´metro: a a >>> print 4 * Fraccion(5,6) 20/6 Dado que rmul es lo mismo que tro entero, ya est´ hecho. a mul , y mul puede manejar un par´mea rmul :

B.2.

Suma de fracciones

La suma es m´s complicada que la multiplicaci´n, pero a´n es llevadera. La a o u suma de a/b y c/d es la fracci´n (a*d+c*b)/b*d. o Usando como modelo el c´digo de la multiplicaci´n, podemos escribir o o radd : add y

238

Crear un nuevo tipo de datos

class Fraccion: ... def __add__(self, otro): if type(otro) == type(5): otro = Fraccion(otro) return Fraccion(self.numerador * otro.denominador + self.denominador * otro.numerador, self.denominador * otro.denominador) __radd__ = __add__ Podemos probar estos m´todos con Fracciones y enteros. e >>> print Fraccion(5,6) + Fraccion(5,6) 60/36 >>> print Fraccion(5,6) + 3 23/6 >>> print 2 + Fraccion(5,6) 17/6 Los dos primeros ejemplos llaman a add ; el ultimo llama a ´ radd .

B.3.

Algoritmo de Euclides

En el ejemplo anterior, computamos la suma de 5/6 + 5/6 y obtuvimos 60/36. Es correcto, pero no es la mejor forma de representar la respuesta. Para reducir la fracci´n a su expresi´n m´s simple, hemos de dividir el numerador y el o o a denominador por el m´ximo com´ n divisor (MCD) de ambos, que es 12. a u El resultado ser´ 5/3. ıa En general, siempre que creamos un nuevo objeto Fraccion, deber´ ıamos reducirlo dividiendo el numerador y el denominador por el MCD de ambos. Si la fracci´n ya est´ reducida, el MCD es 1. o a Euclides de Alejandr´ (aprox. 325–265 a. C.) prensent´ un algoritmo para enıa o contrar el MCD de dos n´meros entermos m y n: u Si n divide a m sin resto, entonces n es el MCD. De lo contrario, el MCD es el MCD de n y el resto de dividir m entre n. Esta definici´n recursiva puede expresarse concisamente como una funci´n: o o def mcd (m, n): if m % n == 0:

B.4 Comparar fracciones return n else: return mcd(n, m%n)

239

En la primera l´ ınea del cuerpo, usamos el operador de m´dulo para comprobar la o divisibilidad. En la ultima l´ ´ ınea, lo usamos para calcular el resto de la divisi´n. o Dado que todas las operaciones que hemos escrito creaban un nuevo objeto Fraccion para devolver el resultado, podemos reducir todos los resultados modificando el m´todo de inicializaci´n. e o class Fraccion: def __init__(self, numerador, denominador=1): m = mcd (numerador, denominador) self.numerador = numerador / m self.denominador = denominador / m Ahora siempre que creemos una Fraccion quedar´ reducida a su forma can´nia o ca: >>> Fraccion(100,-36) -25/9 Una caracter´ ıstica estupenda de mcd es que si la fracci´n es negativa, el signo o menos siempre se trasladar´ al numerador. a

B.4.

Comparar fracciones

Supongamos que tenemos dos objetos Fraccion, a y b, y evaluamos a == b. La implemetaci´n por defecto de == comprueba la igualdad superficial, por lo que o s´lo devuelve true si a y b son el mismo objeto. o Queremos m´s bien devolver verdadero si a y b tienen el mismo valor —eso es, a igualdad en profundidad. Hemos de ense˜ar a las fracciones c´mo compararse entre s´ Como vimos en la n o ı. Secci´n 15.4, podemos sobrecargar todos los operadores de comparaci´n de una o o vez proporcionando un m´todo cmp . e Por convenio, el m´todo cmp devuelve un n´mero negativo si self es menor e u que otro, zero si son lo mismo, y un n´mero positivo si self es mayor que otro. u La forma m´s simple de comparar dos fracciones es la multipicaci´n cruzada. a o Si a/b > c/d, entonces ad > bc. Con esto en mente, aqu´ est´ el c´digo para ı a o cmp :

240

Crear un nuevo tipo de datos

class Fraccion: ... def __cmp__(self, otro): dif = (self.numerador * otro.denominador otro.numerador * self.denominador) return dif Si self es mayor que otro, entonces dif ser´ positivo. Si otro is mayor, entonces a dif ser´ ngativo. Si son iguales, dif es cero. a

B.5.

Forzando la m´quina a

Por supuesto, a´n no hemos terminado. Todav´ hemos de implementar la resta u ıa sobrecargando sub y la divisi´n sobrecargando div . o Una manera de manejar estas operaciones es implementar la negaci´n sobreo o cargando neg y la inversi´n sobrecargando invert . Entonces podemos restar negando el segundo operando y sumando, y podemos dividir invirtiendo el segundo operando y multiplicando. Luego, hemos de suministrar los m´todos rsub y rdiv . Desgraciadamene te, no podemos usar el mismo truco que usamos para la suma y la multiplicaci´n, o porque la resta y la divisi´n no son conmutativas. No podemos igualar rsub o y rdiv a sub y div . En estas operaciones, el orden de los operandos tiene importancia. Para manejar la negaci´n unitaria, que es el uso del signo menos con un unico o ´ operando, sobrecargamos el m´todo neg . e Podemos computar potencias sobrecargando pow , pero la implementaci´n o tiene truco. Si el exponente no es un n´mero entero podr´ no ser posible u ıa representar el resultado como una Fraccion. Por ejemplo, Fraccion(2) ** Fraccion(1,2) es la raiz cuadrada de 2, que es un n´mero irracional (no se u puede representar como una fracci´n). Por lo tanto, no es f´cil escribir la vero a si´n m´s general de pow . o a Existe otra extensi´n a la clase Fraccion que cabr´ considerar. Hasta ahora, o ıa hemos asumido que el numerador y el denominador son enteros. Podr´ ıamos considerar la posibilidad de pertimirles que sean enteros largos. Como ejercicio, termine la implementaci´n de la clase Fraccion de o forma que pueda manejar resta, divisi´n, exponenciaci´n y enteros o o largos como numerador y denominador.

B.6 Glosario

241

B.6.

Glosario

m´ximo com´ n divisor (MCD): El mayor entero positivo que divide al nua u merador y al denominador de una fracci´n sin que quede un resto. o reducir: Cambiar la fracci´n a su forma equivalente con un MCD igual a 1. o negaci´n unitaria: Operaci´n que computa el elemento sim´trico aditivo, noro o e malmente denotada con un signo menos delante. Se denomina “unitaria” en contraste con la operaci´n binaria menos, que es la resta. o

y .1.x * otro.x. otro * self. self. otro): return Punto(self.x) + ’.x . otro): return Punto(otro * self.x. ’ + str(self. y=0): self.y + otro.y = y def __str__(self): return ’(’ + str(self. x=0.Ap´ndice C e Listados Completos de Python C. otro): return Punto(self.y) def reverse(self): .y * otro.x. Clase Punto class Punto: def __init__(self.otro.x + self.y) def __mul__(self.x + otro.otro. otro): return self.y) def __sub__(self.y def __rmul__(self. self.y) + ’)’ def __add__(self.x = x self.

horas * 60 + self. horas=0.hora. segs): segs = segs + self.horas = self.segundos = segundos def __str__(self): return str(self. self.horas + segs/3600 segs = segs % 3600 self.2. Clase Hora class Hora: def __init__(self.x.segundos) def convierteASegundos(self): minutos = self.244 self. minutos=0.hora.horas = horas self.horas * 3600 hora.y = self.horas) + ":" + str(self.minutos = self.reverse() print str(derecho) + str(reves) Listados Completos de Python C. self.minutos * 60 + self.minutos * 60 .segundos return segundos def incrementa(self.minutos) \ + ":" + str(self.minutos + segs/60 segs = segs % 60 self.horas = segs/3600 segs = segs .x def delDerechoYDelReves(derecho): from copy import copy reves = copy(derecho) reves. segundos=0): self.minutos = minutos self.segundos = segs def haceHora(segs): hora = Hora() hora.minutos segundos = self.segundos self.minutos = segs/60 segs = segs .y.

14): self. "Diamantes". valor)) def muestraMazo(self): for carta in self. otro): # controlar el palo if self.segundos = segs return hora 245 C. "Reina".3 Cartas. "Corazones".palo = palo self. "3". "10".palo]) def __cmp__(self.listaDePalos[self. valor=0): self. "2". es un empate return 0 class Mazo: def __init__(self): self. palo=0. "5". "Sota". mazos y juegos hora.palo: return -1 # si son del mismo palo. "7".valor: return 1 if self.valor < otro. Cartas. "8".valor > otro. "4".append(Carta(palo. "6". "9".valor: return -1 # los valores son iguales.cartas = [] for palo in range(4): for valor in range(1.palo < otro.cartas: print carta .listaDeValores[self.valor] + " de " +\ self. e "Picas"] listaDeValores = ["nada". "As".3. "Rey"] def __init__(self.palo: return 1 if self.palo > otro. mazos y juegos import random class Carta: listaDePalos = ["Tr´boles". controlar el valor if self.cartas.valor = valor def __str__(self): return (self.C.

cartas[j].nombre = nombre def agregaCarta(self.remove(carta) return 1 else: return 0 def darCarta(self): return self.cartas.pop() def estaVacio(self): return (len(self. manos.cartas.estaVacio(): break # fin si se acaban las cartas carta = self.cartas[j] =\ self.cartas = [] self.carta) : self.246 Listados Completos de Python def __str__(self): s = "" for i in range(len(self.cartas[i]) + "\n" return s def mezclar(self): import random nCartas = len(self. nCartas) self. nCartas=999): nManos = len(manos) for i in range(nCartas): if self.darCarta() # da la carta superior mano = manos[i % nManos] # a qui´n le toca? e mano.cartas[i] def eliminaCarta(self.randrange(i. nombre=""): self.cartas.cartas[i].cartas: self. carta): if carta in self.cartas)): s = s + " "*i + str(self.cartas) for i in range(nCartas): j = random.cartas) == 0) def repartir(self. self. self.agregaCarta(carta) # agrega la carta a la mano class Mano(Mazo): def __init__(self.append(carta) .

mezclar() class ManoDeLaMona(Mano): def eliminaCoincidencias(self): cant = 0 cartasOriginales = self.manos = [] for nombre in nombres : self.__str__(self) class JuegoDeCartas: def __init__(self): self.C.mazo. nombres): # quitamos la Reina de Tr´boles e self.cartas.remove(carta) self.cartas[:] for carta in cartasOriginales: empareja = Carta(3 .nombre." self.palo.carta.mazo.3 Cartas.estaVacio(): s = s + " est´ vac´a\n" a ı else: s = s + " contiene\n" return s + Mazo.mazo = Mazo() self.nombre if self.manos.manos) print "----.valor) if empareja in self.muestraManos() .repartir(self. mazos y juegos 247 def __str__(self): s = "La mano de " + self.eliminaCarta(Carta(0.remove(empareja) print "Mano %s: %s con %s" % (self.append(ManoDeLaMona(nombre)) # repartimos los naipes self.Se han repartido las cartas.cartas: self.empareja) cant = cant + 1 return cant class JuegoDeLaMona(JuegoDeCartas): def jugar(self.cartas.mazo.12)) # construimos una mano para cada jugador self. carta.carta.

manos : print mano .manos[vecino]." self. i): if self.El juego termin´.mezclar() return cant def encuentraVecino(self.muestraManos() def eliminaTodasLasCoincidencias(self): cant = 0 for mano in self.darCarta() self.estaVacio(): return 0 vecino = self.manos[i].manos[i]. cartaElegida o cant = self." o self.Coincidencias eliminadas.248 Listados Completos de Python # eliminamos las coincidencias iniciales emparejadas = self.agregaCarta(cartaElegida) print "Mano".manos[i].manos) for proximo in range(1.eliminaTodasLasCoincidencias() print "----.manos[vecino]. i): cantManos = len(self.manos: cant = cant + mano.encuentraVecino(i) cartaElegida = self. self.manos[i].eliminaCoincidencias() return cant def jugarUnTurno(self.manos[i].eliminaCoincidencias() self.cantManos): vecino = (i + proximo) % cantManos if not self.estaVacio(): return vecino def muestraManos(self) : for mano in self. "eligi´".muestraManos() # se juega hasta que se han descartado las 50 cartas turno = 0 cantManos = len(self.nombre. el juego comienza.jugarUnTurno(turno) turno = (turno + 1) % cantManos print "----.manos) while emparejadas < 25: emparejadas = emparejadas + self.

carga = carga self.4 Lists Enlazadas 249 C.carga) .siguiente imprimeAlReves(cola) print cabeza.siguiente = segundo. Lists Enlazadas def imprimeLista(nodo): while nodo: print nodo.siguiente primero. if lista != None : cabeza = lista cola = lista. def eliminaSegundo(lista): if lista == None: return primero = lista segundo = lista. print "]".siguiente print def imprimeAlReves(lista): if lista == None: return cabeza = lista cola = lista.siguiente = siguiente def __str__(self): return str(self. carga=None.siguiente segundo. siguiente=None): self.siguiente imprimeAlReves(cola) print cabeza. nodo = nodo.C.4.siguiente = None return segundo class Nodo: def __init__(self. def imprimeAlRevesBonito(lista) : print "[".

imprimeAlReves() print "]".longitud = 0 self.cabeza != None: self. def agregaPrimero(self.5.siguiente cola.elementos == []) def evalPostfijo(expr): .cabeza self.elementos.carga.cabeza = nodo self.pop() def isEmpty(self) : return (self. class ListaEnlazada : def __init__(self) : self. con listas de Python class Pila : def __init__(self) : self.250 Listados Completos de Python def imprimeAlReves(self): if self.elementos.siguiente = self. carga): nodo = Nodo(carga) nodo.siguiente != None: cola = self.cabeza. Clase Pila # implem.longitud + 1 C.imprimeAlReves() print self. elemento) : self.cabeza = None def imprimeAlReves(self): print "[".append(elemento) def pop(self) : return self. if self.longitud = self.elementos = [] def push(self.

push(producto) else: pila.pop() pila.cabeza = nodo else : # Encuentra el ´ltimo nodo de la lista u ultimo = self.longitud + 1 .6. Colas y colas priorizadas class Cola : def __init__(self) : self.pop() pila.split("([^0-9])".pop() 251 C. carga) : nodo = Nodo(carga) nodo.cabeza while ultimo.push(int(token)) return pila.longitud = 0 self.push(suma) elif token == ’*’: producto = pila.siguiente = None if self.cabeza == None : # Si la lista est´ vac´a nuestro nuevo nodo es el primero a ı self.pop() + pila.cabeza = None def vacia(self) : return (self. expr) pila = Pila() for token in listaTokens: if token == ’’ or token == ’ ’: continue if token == ’+’: suma = pila.siguiente # A~ada el nuevo nodo n ultimo.siguiente : ultimo = ultimo.C.6 Colas y colas priorizadas import re listaTokens = re.siguiente = nodo self.longitud == 0) def inserta(self.longitud = self.pop() * pila.

longitud = self.ultimo # A~ade nuestro nodo nuevo n ultimo.cabeza = self.siguiente self.siguiente = nodo self.longitud = self.longitud = self.carga self.ultimo = None def vacia(self) : return (self.longitud .cabeza.carga self.longitud == 0 : self.next self.longitud + 1 def quita(self) : carga = self.252 Listados Completos de Python def quita(self) : carga = self.longitud == 0 : # Si la lista est´ vac´a nuestro nuevo nodo es el primero a ı self. carga) : nodo = Nodo(carga) nodo.ultimo = nodo self.cabeza = None self.cabeza = self.1 if self.longitud = 0 self.ultimo = None return carga class ColaPriorizada : def __init__(self) : self.cabeza.longitud == 0) def inserta(self.cabeza = self.longitud .cabeza.elementos = [] def vacia(self) : .ultimo = nodo else : # Encuentra el ultimo nodo de la lista ultimo = self.1 return carga class ColaMejorada : def __init__(self) : self.cabeza.siguiente = None if self.

carga = carga self.7.elementos[i] > self.puntos : return -1 return 0 253 # menos es m´s a C. puntos) : self. carga.izquierda = izquierda self.puntos) def __cmp__(self. nombre.´ C.nombre.elementos == [] def inserta(self.append(elemento) def quita(self) : maxi = 0 for i in range(1.len(self.puntos = puntos def __str__(self) : return "%-15s: %d" % (self.carga) def tomaCarga(self): return self.nombre = nombre self.elementos[maxi:maxi+1] = [] return elemento class Golfista : def __init__(self.carga def tomaIzquierda(self): return self. izquierda=None.izquierda .puntos > otro.puntos < otro. otro) : if self.elementos. self.elementos[maxi] : maxi = i elemento = self.puntos : return 1 if self. derecha=None) : self. ´ Arboles class Arbol : def __init__(self.elementos[maxi] self. elemento) : self.7 Arboles return self.elementos)) : if self.derecha = derecha def __str__(self) : return str(self.

derecha) def imprimeArbolSangrado(arbol. def imprimeArbolInfijo(arbol): if arbol == None: return imprimeArbolInfijo(arbol.derecha) + arbol.izquierda) + total(arbol. carga): self.derecha = derecha def total(arbol) : if arbol == None : return 0 return total(arbol. nivel=0): if arbol == None: return imprimeArbolSangrado(arbol.derecha def ajustaCarga(self.carga) imprimeArbolSangrado(arbol.izquierda) imprimeArbol(arbol.izquierda.izquierda) print arbol.carga = carga def ajustaIzquierda (self.carga def imprimeArbol(arbol): if arbol == None: return print arbol. izquierda): self. esperado): if listaToken[0] == esperado: listaToken[0:1] = [] # quita el token return 1 else: .left = izquierda def ajustaDerecha(self. imprimeArbolInfijo(arbol.254 Listados Completos de Python def tomaDerecha(self): return self.derecha) def imprimeArbolPosfijo(arbol): if arbol == None: return imprimeArbolPosfijo(arbol.izquierda) imprimeArbolPosfijo(arbol.carga. nivel+1) print ’ ’*nivel + str(arbol.8. nivel+1) C.derecha) print arbol. derecha): self.carga. imprimeArbol(arbol.carga. ´ Arboles de expresi´n o def tomaToken(listaToken.derecha.

9. a. ’)’) # se come el cierre de par´ntesis e return x else : x = listaToken[0] if type(x) != type(0) : return None listaToken[0:1] = [] # quita el token return Arbol(x. b) else : return a 255 def obtieneNumero(listaToken): if tomaToken(listaToken.9 Adivina el animal return 0 def obtieneProducto(listaToken) : a = obtieneNumero(listaToken) if tomaToken(listaToken. ’*’) : b = obtieneProducto(listaToken) return Arbol(’*’. ’+’) : b = obtieneSuma(listaToken) return Arbol(’+’. Adivina el animal def animal(): # empezar con un nodo suelto raiz = Arbol("p´jaro") a # bucle hasta que el usuario salga while 1: print if not si("Est´s pensando en un animal? "): break a # recorrer el ´rbol a . ’(’) : x = obtieneSuma(listaToken) # obtiene subexpresi´n o tomaToken(listaToken. b) else : return a def obtieneSuma(listaToken) : a = obtieneProducto(listaToken) if tomaToken(listaToken. None.C. None) # devuelve una hoja sin el n´mero u C. a.

ponDerecha(Arbol(animal)) else: arbol.ponIzquierda(Arbol(animal)) arbol. numerador. Fraction class class Fraccion: def __init__(self.tomaCarga() + "? " if si(indicador): arbol = arbol.ponCarga(pregunta) indicador = "Si el animal fuera un %s.ponDerecha(Arbol(adivina)) def si(preg): from string import lower resp = lower(raw_input(preg)) return (resp[0:1] == ’s’) C. cu´l ser´a la respuesta? " a ı if si(indicador % animal): arbol.tomaIzquierda() != None: indicador = arbol. denominador) .tomaIzquierda() # intentar adivinar adivina = arbol.tomaDerecha() else: arbol = arbol. denominador=1): m = mcd (numerador.ponIzquierda(Arbol(adivina)) arbol.adivina)) # a~adir informaci´n nueva al ´rbol n o a arbol.10.256 Listados Completos de Python arbol = raiz while arbol.tomaCarga() indicador = "Es un " + adivina + "? " if si(indicador): print "^<Soy el m´s grande!" A a continue # obtener informaci´n nueva o indicador = "C´mo se llama el animal? " o animal = raw_input(indicador) indicador = "Qu´ pregunta distinguir´a a un %s de un %s? " e ı pregunta = raw_input(indicador % (animal.

numerador.denominador) __radd__ = __add__ def __cmp__(self.m%n) 257 .numerador * self.denominador * otro. self.denominador) def mcd(m.denominador * otro.denominador + self.denominador * otro.numerador.numerador * otro.numerador = numerador / m self.10 Fraction class self.numerador * otro.denominador otro.n): "devuelve el m´ximo com´n denominador de dos enteros" a u if m % n == 0: return n else: return mcd(n.__str__() def __str__(self): return "%d/%d" % (self.numerador.denominador) __rmul__ = __mul__ def __add__(self. self.denominador) return dif def __repr__(self): return self. otro): if type(otro) == type(5): otro = Fraccion(otro) return Fraccion(self.numerador * otro. self.denominador = denominador / m def __mul__(self.C. otro): if type(otro) == type(5): otro = Fraccion(otro) dif = (self. otro): if type(otro) == type(5): otro = Fraccion(otro) return Fraccion(self.

.

Las ventanas y los controles con wxPython tienen una apariencia m´s nativa que Tkinter y son un poco m´s sencillos de programar. . Tkinter est´ incluido a en la distribuci´n de Python. o ı? ampliando sus conocimientos de Python spec´ ıficamente y de inform´tica en a general. basado en los lenguajes interpretados Tcl y Tk de Jon Ousterhout. o Otra plataforma popular es wxPython. un paquete de C++ que implementa ventanas utilizando la interfaces nativas las plataformas Windows y Unix (incluido Linux). Este estilo de programaci´n requiere de algo de o o tiempo para acostumbrarse. a El primer paquete que ha tenido Python para esto es Tkinter. ¿hacia d´nde ir desde aqu´ Hay muchas direcciones en las que seguir. por lo que pueden no haber mostrado las capacidades m´s excitantes de Python. graphic user o a interface en ingl´s) permite que su programa utilice un entorno de ventanas e para interactuar con el usuario y mostrar gr´ficos. A continuaci´n a o exponemos una muestra de las extensiones de Python y sugerencias sobre sus usos. y a veces le forzar´ a replantearse toda la a estructura del programa. que es esencialmente un enchapado sobre wxWindows. a a Cualquier tipo de programaci´n de GUIs le llevar´ a programaci´n basada o a o en eventos. Los ejemplos en este libro han sido deliberadamente simples.Ap´ndice D e Lecturas recomendadas Y ahora. donde es el usuario y no el programador quien determina el flujo de la ejecuci´n. La programaci´n de GUIs (interfaces gr´ficas de usuario.

La programaci´n multi-procesos (multi-hilos) le permite ejecutar varios o procesos (hilos) de ejecuci´n dentro de un unico programa. documentaci´n. a e .. y las relaciones entre los a datos le permiten acceder a ellos de varias maneras. un conjuto de estudios de casos en Python de Chris Meyers.python. Encontrar´ ayuda. con 300 p´ginas de trucos y t´cnicas. Getting down with .com/obp contiene no s´lo o este libro en l´ ınea sino tambi´n otros libros similares para Java y C++ e de Allen Downey. El proyecto Open Book Project www..ibiblio.1. Las bases de datos son un poco como super ficheros en donde los datos est´n almacenados en esquemas predefinidos.. y The Linux Cookbook de Michael Stultz. Por ejemplo.260 Lecturas recomendadas La programaci´n web integra Python en la Internet. un conjunto de tutoriales de varios temas sobre inform´tica. a a Kuphaldt. escritos y editados por estudiantes de institulo. Python a for Fun. Python tiene varios m´dulos para permitir a los usuarios conectarse a varios motores de bases o de datos. entonces u tiene una idea de lo que los hilos pueden hacer. y ıa m´dulos que le permiten enviar y recibir correos electr´nicos. u a o enlaces a otros libros y listas de correo de SIGs (Special Interest Group) a las que se puede unir. Libros y sitios web sobre Python Aqu´ tiene las recomendaciones de los autores sobre recursos para Python en la ı web: La p´gina de inicio de Python en www.org es el lugar para empezar a su b´squeda de material sobre Python. a D. tanto Open Source como comerciales. Adem´s est´ Lessons in Electric Circuits de Tony R. Tales extensiones forman la base de la mayor´ de m´dulos en la librer´ de Python. Python tamo o bi´n es ampliamente utilizado en el lado del servidor de la programaci´n e o web para manejar los datos de entrada de los formularios. puede o construir programas de cliente web que abran y lean una p´gina remota a (casi) tan f´cilmente como si fuera un fichero en disco. SWIG (Simplified Wrapper and Interface Generator) es una herramienta para hacer este proceso mucho m´s sencillo. Tambi´n hay m´dua e o los de Python que le permiten acceder a ficheros remotamente v´ ftp. Cuando la velocidad es m´s importante se pueden escribir extensiones a para Python en un lenguaje compilado como C o C++. ıa o ıa El mecanismo de enlazar funciones y datos es un poco complejo. Si ha tenido la o ´ experiencia de usar un navegador web para desplazarse por una p´gina web a mientras el navegador contin´a cargando el resto de la misma.

La primera parte del libro cubre las caracter´ a ısticas b´sicas del a lenguaje Python. Los ejemplos est´n o a principalmente en C++ y Java. ıa a e a Python Pocket Reference de Mark Lutz realmente cabe en el bolsillo. construye una peque˜a aplicaci´n con o n o wxPython. Libros recomendados sobre inform´tica en a general Las siguientes sugerencias sobre lecturas adicionales incluyen muchos de los libros favoritos de los autores.000 resultados. sino tambi´n depurao e ci´n.D. uno de los primeros (y m´s e a largos) libros de Python y no est´ dirigido al programador principiante. Tambi´n est´ muy bien indexado. Python Essential Reference de David M. e incluso utiliza Python para escribir scripts para aplicaciones tales como Word y Excel. m´s de 750 a p´ginas. La segunda parte proporciona una introducci´n paso o a paso a temas m´s avanzados incluyendo muchos de los mencionados a anteriormente.2 Libros recomendados sobre inform´tica en general a 261 Finalmente si acude a Google y busca con la cadena “python -snake monty” obtendr´ cerca de 750. n pero contiene informaci´n sobre el lenguaje en s´ mismo y los m´dulos de o ı o la librer´ est´ndar. D. a n a Python Programming on Win32 de Mark Hammond y Andy Robinson es un libro que “debe tener” cualquiera que que utilice seriamente Python para desarrollar aplicaciones para Windows. Mark Lutz ´ o a tambi´n es autor de Programming Python.2. sin nada de Python. Aunque no es tan extensivo como Python Essential Reference es una referencia util para los m´dulos y funciones m´s comunmente usadas. a Su siguiente libro Learning Python es m´s peque˜o y m´s accesible. Estos tratan sobre buenas pr´cticas de prograa maci´n e inform´tica en general. Beazley es un libro peque˜o. . o a The Practice of Programming de Kernighan y Pike cubre no s´lo el dise˜o o n y dodificaci´n de algoritmos y estructuras de datos. testeo y mejora de rendimiento de los programas. a Y aqu´ algunos libros que contienen m´s material sobre el lenguaje Python: ı a Core Python Programming de Wesley Chun es un libro largo. Entre otras cosas cubre la integraci´n de Python y COM.

o Programming Pearls de Jon Bentley es un libro cl´sico. Todos los temas son cortos y entretenidos. Bach de Douglas Hofstadter. y programaci´n correcta con o hilos y su sincronizaci´n.262 Lecturas recomendadas The Elements of Java Style editado por Al Vermeulen es otro libro peque˜o n que discute algunos de los puntos m´s sutiles de la buena programaci´n. Introduce el lenguaje StarLogo. Consiste en esa tudios de caso que aparecieron originalmente en la columna del autor en Communications of the ACM. usando aserciones para encontrar los errores o probando precondiciones y postcondiciones. o e a Uno de los temas de Hofstadter concierne a los “lazos extra˜os” donde los n patrones se desenvuelven y ascienden hasta que se encuentran a s´ mismos ı de nuevo. o The New Turing Omnibus de A. La mayor´ de los programas en el libro fueron desarrollados por estudiantes ıa de colegio e instituto. Simplemente. desde TACs (tomograf´ computerizadas) hasta a ıas algoritmos gen´ticos. algunos con soluciones y otros con pistas. Escher. si encuentra o magia en la recursi´n tambi´n la encontrar´ en este libro superventas.K Dewdney proporciona una introducci´n amigable a 66 temas de inform´tica desde computaci´n en parelelo o a o hasta virus inform´ticos. Es una disputa de Hofstadter que tales “lazos extra˜os” son n ´ una parte esencial de lo que separa lo animado de lo no animado. El libro tambi´n cubre la o e programaci´n por contrato. Tortugas. Hay muchos proa a blemas para resolver. o . las ilustraciones de Escher u y el teorema de incompletitud de G¨del. La ejecuci´n del programa demuestra o comportamientos complejos agregados. Un libro e anterior de Dewdney Aventuras Inform´ticas es una colecci´n de su coa o lumna Juegos de ordenador en Invertigaci´n y Ciencia. Ambos libros son o ricas fuentes de ideas para proyectos. a por lo que los ejemplos est´n en lenguajes m´s antiguos. Los estudios tratan sobre toma y daca en programaci´n y por qu´ suele ser mala idea desarrollar con la primera idea o e de un programa. El demuestra tales patrones en la m´sica de Bach. a o tales como el buen uso de las convenciones de nombres. Este libro fue muy popular y le sigui´ un segundo volumen. Termitas y Atascos de Tr´fico de Mitchel Resnick trata sobre a el poder de la descentralizaci´n y de como pueden obtenerse comportao mientos complejos a partir de las actividades simples de una multitud de agentes coordinados. que permite al usuario escribir programas para agentes. El libro es un poco m´s antiguo que los anteriores (1986). comentarios e indentaci´n (un poco irrelevante en Python). a G¨del. que suelen ser intuitivos. Programas similares pueden escribirse en Python usando gr´ficos e hilos.

Preamble The purpose of this License is to make a manual. or other written document “free” in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it. This License is a kind of “copyleft. Inc. March 2000 Copyright c 2000 Free Software Foundation.1. but changing it is not allowed. MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document. with or without modifying it. either commercially or noncommercially.Ap´ndice E e GNU Free Documentation License Version 1. Boston. this License preserves for the author and publisher a way to get credit for their work. Secondarily. which is a copyleft license designed for free software.” which means that derivative works of the document must themselves be free in the same sense. We have designed this License in order to use it for manuals for free software. Suite 330. because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. while not being considered responsible for modifications made by others. But this . textbook. It complements the GNU General Public License. 59 Temple Place.

(For example. commercial. Applicability and Definitions This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. regardless of subject matter or whether it is published as a printed book. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. or political position regarding them. Any member of the public is a licensee. ethical. or with modifications and/or translated into another language. and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. refers to any such manual or work. it can be used for any textual work. The “Cover Texts” are certain short passages of text that are listed. a Secondary Section may not explain any mathematics. E. as being those of Invariant Sections. A “Transparent” copy of the Document means a machine-readable copy. in the notice that says that the Document is released under this License.” . represented in a format whose specification is available to the general public. A copy that is not “Transparent” is called “Opaque.1. The “Invariant Sections” are certain Secondary Sections whose titles are designated.) The relationship could be a matter of historical connection with the subject or with related matters.” A “Modified Version” of the Document means any work containing the Document or a portion of it. or of legal. as FrontCover Texts or Back-Cover Texts. We recommend this License principally for works whose purpose is instruction or reference. The “Document.264 GNU Free Documentation License License is not limited to software manuals. philosophical. either copied verbatim. if the Document is in part a textbook of mathematics. and is addressed as “you. whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor. A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. in the notice that says that the Document is released under this License.” below.

SGML or XML using a publicly available DTD. you must enclose the copies in covers that carry.3. Copying with changes limited to the covers. proprietary formats that can be read and edited only by proprietary word processors.E. and that you add no other conditions whatsoever to those of this License. The “Title Page” means.2. legibly. under the same conditions stated above. and the machine-generated HTML produced by some word processors for output purposes only. for a printed book. However. and you may publicly display copies. You may add other material on the covers in addition. “Title Page” means the text near the most prominent appearance of the work’s title. You may also lend copies. preceding the beginning of the body of the text. you may accept compensation in exchange for copies. Opaque formats include PostScript. can be treated as verbatim copying in other respects. plus such following pages as are needed to hold. Both covers must also clearly and legibly identify you as the publisher of these copies. the material this License requires to appear in the title page. L TEX input format. the copyright notices. The front cover must present the full title with all words of the title equally prominent and visible. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. Texinfo input format. Copying in Quantity If you publish printed copies of the Document numbering more than 100. E. and Back-Cover Texts on the back cover. PDF. as long as they preserve the title of the Document and satisfy these conditions. all these Cover Texts: Front-Cover Texts on the front cover. For works in formats which do not have any title page as such. .2 Verbatim Copying 265 Examples of suitable formats for Transparent copies include plain ASCII witA hout markup. Verbatim Copying You may copy and distribute the Document in any medium. the title page itself. provided that this License. and standard-conforming simple HTML designed for human modification. and the Document’s license notice requires Cover Texts. E. either commercially or noncommercially. and the license notice saying this License applies to the Document are reproduced in all copies. SGML or XML for which the DTD and/or processing tools are not generally available. clearly and legibly. If you distribute a large enough number of copies you must also follow the conditions in Section 3.

but not required. provided that you release the Modified Version under precisely this License. If you use the latter option. you must take reasonably prudent steps. if it has less than five). Modifications You may copy and distribute a Modified Version of the Document under the conditions of Sections 2 and 3 above. to give them a chance to provide you with an updated version of the Document. It is requested. In addition. which the general network-using public has access to download anonymously at no charge using public-standard network protocols. E. and from those of previous versions (which should. that you contact the authors of the Document well before redistributing any large number of copies. with the Modified Version filling the role of the Document. one or more persons or entities responsible for authorship of the modifications in the Modified Version. if any) a title distinct from that of the Document. you should put the first ones listed (as many as fit reasonably) on the actual cover. If you publish or distribute Opaque copies of the Document numbering more than 100. you must either include a machine-readable Transparent copy along with each Opaque copy. thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. if there were any. to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. Preserve all the copyright notices of the Document. You may use the same title as a previous version if the original publisher of that version gives permission. or state in or with each Opaque copy a publicly accessible computer-network location containing a complete Transparent copy of the Document. as the publisher. be listed in the History section of the Document). .4. you must do these things in the Modified Version: Use in the Title Page (and on the covers. State on the Title page the name of the publisher of the Modified Version.266 GNU Free Documentation License If the required texts for either cover are too voluminous to fit legibly. as authors. and continue the rest onto adjacent pages. List on the Title Page. together with at least five of the principal authors of the Document (all of its principal authors. free of added material. when you begin distribution of Opaque copies in quantity.

immediately after the copyright notices. and likewise the network locations given in the Document for previous versions it was based on. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice. a license notice giving the public permission to use the Modified Version under the terms of this License. then add an item describing the Modified Version as stated in the previous sentence. Include. Delete any section entitled “Endorsements. Preserve the network location. In any section entitled “Acknowledgements” or “Dedications. You may omit a network location for a work that was published at least four years before the Document itself. and add to it an item stating at least the title. given in the Document for public access to a Transparent copy of the Document.” Such a section may not be included in the Modified Version. Preserve the section entitled “History. and publisher of the Modified Version as given on the Title Page. and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. or if the original publisher of the version it refers to gives permission. If there is no section entitled “History” in the Document. in the form shown in the Addendum below. .” preserve the section’s title.4 Modifications 267 Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. authors. Preserve all the Invariant Sections of the Document. Do not retitle any existing section as “Endorsements” or to conflict in title with any Invariant Section. Include an unaltered copy of this License.E. and publisher of the Document as given on its Title Page. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document. Section numbers or the equivalent are not considered part of the section titles. year. create one stating the title. if any. These may be placed in the “History” section. you may at your option designate some or all of these sections as invariant.” and its title. new authors. year. unaltered in their text and in their titles.

” You must delete all sections entitled “Endorsements. Only one passage of Front-Cover Text and one of BackCover Text may be added by (or through arrangements made by) any one entity. add their titles to the list of Invariant Sections in the Modified Version’s license notice. or else a unique number. provided that you include in the combination all of the Invariant Sections of all of the original documents. If there are multiple Invariant Sections with the same name but different contents.” and any sections entitled “Dedications. unmodified.268 GNU Free Documentation License To do this. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.” . but you may replace the old one. previously added by you or by arrangement made by the same entity you are acting on behalf of. These titles must be distinct from any other section titles. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. and multiple identical Invariant Sections may be replaced with a single copy. the name of the original author or publisher of that section if known. in parentheses.5. The combined work need only contain one copy of this License. E. statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. and list them all as Invariant Sections of your combined work in its license notice. you may not add another. likewise combine any sections entitled “Acknowledgements. You may add a section entitled “Endorsements. make the title of each such section unique by adding at the end of it. Combining Documents You may combine the Document with other documents released under this License. to the end of the list of Cover Texts in the Modified Version. forming one section entitled “History”. and a passage of up to 25 words as a Back-Cover Text. you must combine any sections entitled “History” in the various original documents. under the terms defined in Section 4 above for modified versions. on explicit permission from the previous publisher that added the old one. If the Document already includes a cover text for the same cover. In the combination. You may add a passage of up to five words as a Front-Cover Text.” provided it contains nothing but endorsements of your Modified Version by various parties—for example.

in or on a volume of a storage or distribution medium. You may extract a single document from such a collection.8. and follow this License in all other respects regarding verbatim copying of that document. the Document’s Cover Texts may be placed on covers that surround only the Document within the aggregate. provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. Collections of Documents You may make a collection consisting of the Document and other documents released under this License. if they are not themselves derivative works of the Document.7. and replace the individual copies of this License in the various documents with a single copy that is included in the collection.6. and distribute it individually under this License.E. . then if the Document is less than one quarter of the entire aggregate. on account of their being thus compiled. In case of a disagreement between the translation and the original English version of this License. so you may distribute translations of the Document under the terms of Section 4. You may include a translation of this License provided that you also include the original English version of this License. E.6 Collections of Documents 269 E. provided no compilation copyright is claimed for the compilation. does not as a whole count as a Modified Version of the Document. Otherwise they must appear on covers around the whole aggregate. If the Cover Text requirement of Section 3 is applicable to these copies of the Document. provided you insert a copy of this License into the extracted document. Aggregation with Independent Works A compilation of the Document or its derivatives with other separate and independent documents or works. Such a compilation is called an “aggregate.” and this License does not apply to the other self-contained works thus compiled with the Document. the original English version will prevail. Translation Translation is considered a kind of modification. E. Replacing Invariant Sections with translations requires special permission from their copyright holders. but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections.

However.1 or any later version published by the Free Software Foundation. If the Document specifies that a particular numbered version of this License .10. but may differ in detail to address new problems or concerns. you may choose any version ever published (not as a draft) by the Free Software Foundation.270 GNU Free Documentation License E. with the Invariant Sections being LIST THEIR TITLES. or distribute the Document is void.gnu. Such new versions will be similar in spirit to the present version. Addendum: How to Use This License for Your Documents To use this License in a document you have written. or rights.applies to it.” . Permission is granted to copy. distribute and/or modify this document under the terms of the GNU Free Documentation License. Termination You may not copy.org/copyleft/. E. and with the Back-Cover Texts being LIST.or any later version. See http:///www. modify. revised versions of the GNU Free Documentation License from time to time. and will automatically terminate your rights under this License. sublicense. Each version of the License is given a distinguishing version number. Any other attempt to copy. you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. with the Front-Cover Texts being LIST. If the Document does not specify a version number of this License. include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright c YEAR YOUR NAME.9. Future Revisions of This License The Free Software Foundation may publish new. Version 1. E. parties who have received copies. sublicense. or distribute the Document except as expressly provided for under this License. from you under this License will not have their licenses terminated so long as such parties remain in full compliance. modify. A copy of the license is included in the section entitled “GNU Free Documentation License.11.

such as the GNU General Public License. we recommend releasing these examples in parallel under your choice of free software license.11 Addendum: How to Use This License for Your Documents 271 If you have no Invariant Sections. If you have no Front-Cover Texts. to permit their use in free software. write “with no Invariant Sections” instead of saying which ones are invariant. If your document contains nontrivial examples of program code. likewise for Back-Cover Texts.E. write “no Front-Cover Texts” instead of “Front-Cover Texts being LIST”. .

.

´ Indice alfab´tico e ´rbol. 112 o asignaci´n de tuplas. 77 a acceso. 216 analizar sint´cticamente. 201 a andamiaje. 228 recorrido. 165 condici´n. 83 . 28 asignaci´n. 10. 230 barajar. 86 acto de fe. 119 argumento. 178 aleatorio. 170 atributo de clase. 37 o bloque. 33 argumentos. 73. 146. 216 a o ´ ındice. 7. 214 vac´ 212 ıo. 187 for. 100 asignaci´n de alias. 12. 52 borrado lista. 20. 92. 213. 107 atributo. 167 algoritmo. 45 booleana expresi´n. 76 Make Way for Ducklings. 134 u teorema fundamental. 148 alias. 37. 77 Referencia de la Biblioteca de Python. 109. 170 atributos. 211 a expresi´n. 228 o cuerpo. 139 clase. 168 tuplas. 167 base de conocimiento. 7. 10 a a analizar. ´rbol binario. 21. 63. 100. 73 en una lista. 91 bucle. 36 o booleanas funciones. 48. 163. 63. 45 archivo. 168 o asignaci´n m´ltiple. 213. 76 infinito. 63. 128 archivos. 221 bifurcaci´n condicional. 167. 163. 33 abeced´rico. 224 a ´rbol de expresi´n. 132 AttributeError. 61 o tupla. 211. 97 ambig¨edad. 128 texto. 97. 216 o recorrido. 229 negativo. 213. 170. 84. 107. 76. 55. 61. 73 o u asignmaci´n o tupla. 73 anidado. 186 acumulador. 76 . 188 an´lisis sint´ctico. 121 archivo de texto. 121. 91 borrado en una lista. 199. 59 anidamiento.

196. 204 o implementaci´n mejorada. 204. 116 o comprobaci´n de errores. 2. 162 contador. 171. 45 cifrar. 239 o comparaci´n de cadenas. 175. 10 o c´digo fuente. 203. 20. 172. 11. 210 cola mejorada. 131. 155 clase abstracta. 62 bucle for. 57 o concatenaci´n. 112 ´ Indice alfab´tico e clonar. 20 concatenation. 48. 76 porci´n. 228 o condici´n previa. 75 a carga. 20. 164 comparaci´n o cadenas. 63 o condici´n. 162 clase. 170 coerci´n. 211 Carta. 183 padre. 209 JuegoDeLaMona. 22 o coercion. 227. 45. 19 comparable. 128 cadena inmutable. 93. 38 constructor. 114 o car´cter. 210 clase hija. 51. 161 caso base. 165 o compresi´n. 84 conteo. 161 Golfista. 162. 18. 97 codificar. 109. 59 o cadena. 80 o concatenar. 80. 114 caja de funci´n. 182 clase Punto. 210 c´digo de objeto. 183. 38 condiciones encadenadas. 10 composici´n. 20 comentarios. 82 o clave. 117 cliente. 182 clase padre. 176 Nodo. 115 coerci´n de tipos. 192. 73 while. 185. 203. 196 o columna. 79 caja. 12 inmutable. 96 coma flotante. 33 o tipo. 76. 18 condici´n. 201 clonado. 171. 131. 78 fracci´n. 175 Pila. 192 o condiciones encadenadas. 139. 43. 123. 210 implementaci´n con Lista. 78 o compilador. 228 buffer circular. 78 o cadena de formato. 196 Punto.274 variable de. 155 clasificaci´n o car´cter. 24. 207 colecci´n. 88 bucle infinito. 77. 103 . 190 ManoDeLaMona. 210 TAD. 177 ListaEnlazada. 10 o c´digo ejecutable. 205 o cola enlazada. 139 Carta. 188. 161. 205 cola priorizada. 203 o implementaci´n enlazada. 107 cola. 131 comentario. 172. 82 a clasificaci´n de caracteres. 10 o c´digo muerto. 23 coincidencia de esquemas. 79 longitud. 225 compilar.

73 generalizaci´n. 219 o delimitador. 53 recursiva. 125. 5. 97 eliminaci´n de naipes. 37 o elemento. 168 o encapsulaci´n. 109. 162 cuelgue. 87. 199. 10 escalera de color. 10. 195. 22 o documentaci´n. 136. 192 o Doyle. 67 o desarrollo de prototipos. 107 diagrama de estado. 4 o desarrollo incremental. 225 o sem´ntico. 10. 5 o error (bug). 192 error de sintaxis. 148 desbordamiento. 137 corresponder. 139 copiado. 84 definici´n o circular. 148 desarrollo incremental de programas. 124. 225 o error en tiempo de ejecuci´n. 225. 49. 5. 67 encapsular. 145 desarrollo incremental. 110 directorio. 128 enlace. 5. 235 depuraci´n. 229 error sem´ntico. 22 o copia profunda. 76. 96. 124. 201 denominador. 100. 37. 43. 101. 115 enteros largos. 117. 63 cursor. o 43. 148 planificado. 225. 225 o en tiempo de ejecuci´n. 20 diagrama de pila. 219 definici´n circular. 45 bucle. 225 error en tiempo de compilaci´n. 139 copia superficial. 53 o definici´n de funci´n. 115 determinista. 115. 111. 10 a error(bug). 59. 33 diagramas de pila. Arthur Conan. 13. 6 275 ejecuci´n o flujo. 192 enteros divisi´n. 110 diccionarios. 16. 227 cuerpo. 115 envoltorio. 30. 128 dise˜o orientado a objetos. 125. 67 desarrollo de programas. 10. 33 o conversi´n de tipos. 230 m´todos. 203 encurtido. 231 a sintaxis. 225 o depuraci´n (debugging). 225 en tiempo de compilaci´n. 97. 125. 111 e operaciones sobre. 229 ejecuci´n condicional. 231 a error sint´ctico. 22 o largos. 148 desarrollo de progamas encapsulado. 73 enchapado. 197 encolamiento priorizado. 73 decrementar. 25. 33 o o definici´n recursiva. 200 o encapsulado. 42 diccionario. 85. 174 . 5 tiempo de ejecuci´n. 171 n divisi´n de enteros. 20. 109 m´todos.´ Indice alfab´tico e conversi´n de tipo. 79. 120. 225. 226 desarrollo planificado. 113. 4 error de sintaxis. 111 e operaciones. 112.

101 funciones booleanas. 192 Euclides. 33. 126. 114 a guardi´n. 14 o herencia. 20. 134. 106. e 197 estructura recursiva de datos. 192. o 144. 59 a gui´n. Sherlock. 237 frangoso. 150 o booleana. 25 o factorial. 146 o generalizar. 57 o funci´n pura. 161 estructura de datos gen´rica. 236 o suma. 28 a recursivas. 84 estilo funcional de programaci´n. 229 o formal lenguaje. 174 objeto mazo. 5. 21 par´metros. 73 espacio en blanco. 171. 71 o funci´n join. 96 o funci´n. 44. 230 indicador. 28 composici´n. 52 funciones matem´ticas. 212 estructura de datos recursiva. 67 o generalizaci´n. 45 o expresi´n regular. 54 funci´n booleana. 148 o funciones argumentos. 150 incrementar. 235 o comparaci´n. 84 IndexError. 96 o funci´n split. 12 flujo de ejecuci´n. 45 . 33. 225. 182 histograma. 183. 183. 196. 148 estructura anidada. 210 fila. 169 o ´ Indice alfab´tico e funci´n de Fibonacci. 25. 134 igualdad profunda. 141. 199 o Fibonacci function. 73 Golfista. 169 definici´n. 107. 239 o multiplicaci´n. 196.276 escape secuencia de. 23 a generalizaci´n. 10 o gui´n bajo. 57 o funci´n gamma. 139 implementaci´n o Cola. 139 igualdad superficial. 54. 42 tuplas como valor de retorno. 134. 96 float. 56 FIFO. 136. 10. 53 funci´n. 6 identidad. 116 Holmes. 128. 16. 27. 36. 203. 115 fracci´n. 212 estructura gen´rica de datos. 238 excepci´n. 198 o booleana. 134 igualdad. 197 e recursiva. 232 expresi´n booleana. 51 o llamadas. 229 o expresi´n. 113 o funci´n factorial. 160 impresi´n o mano de cartas. 133. 203 imponer. 24. 142. 166 imprimir objeto. 45 grande y peliaguda. 6 forzado de tipo de datos. 209 gr´fico de llamadas.

183. 132. 192 invocar. 2 bajo nivel. 63 infio. 4 o int. 88 porciones. 2. 111 e irracional. 191 bucle. 36 lanzar una excepci´n. 150 instanciaci´n. 221 KeyError. 191. 2. 2. 1 o lenguaje completo. 221 juego de los animales. 97. 6. 94 a operaciones con. 183. 185 lista anidada. 136. 128 o lenguaje. 99 instancia. 86 enlazada. 185 a de objetos. 192 lista infinita. 192 impresi´n. 12 Intel. 53 lenguaje de alto nivel. 189 mutable. 139 instrucci´n. 201 infinito bucle. 2 completo. 126. 95. 132 o instanciar. 10. 6 lista. 139 objeto. 10 lenguaje natural. 187 bucle for. 88 como par´metro. 87 . 6. 112 lista enlazada. 1 o lenguaje de programaci´n orientado o a objetos. 149. 87. 134 alto nivel. 90 recorrer recursivamente. 85. 10 invariante. 150. 7 llamada a funci´n. 97. 210 interpretar. 5 Linux. 134 lenguaje seguro. 196. 190 listas anidadas. 165 elemento. 93 como par´metros. 160 277 lenguaje formal. 53 programaci´n. 29 logaritmo. 85. 185 o imprimir hacia atr´s. 61. 230 l´gico o operador. 187 longitud. 64 longitud. 73 o juego animales. 10 lenguaje de programaci´n. 21 local variable. 64 intercambio. 168 interfaz. 90 pertenencia. 164 instancia de un objeto. 33 o llamadas a funciones. 240 iteraci´n. 117 invocar m´todos. 132.´ Indice alfab´tico e infijo. 62. 133. 95 clonado. 183 anidada. 186 recorrido. 186 a infinita. 164 instancia de objeto. 213 inmutable. 87 modificar. 198. 10 lenguaje de bajo nivel. 95 literalidad. 89 listas anidadas. 69 locales variables. 112 bien construida. 187 ListaEnlazada.

111 e m´dulo. None. 190 e m´todos de desarrollo e incremental. 189 multiplicaci´n o fracci´n. 79. 89 operaciones con listas. 211. 183. 59 notaci´n de punto. 166 e m´todo ayudante. 154 o nueva l´ ınea. 116. 210 a operaciones con listas. 128 o manejo de errores. 141. 97. 136 objeto invariante. 101 n´mero aleatorio. 165 obst´culo al rendiminto. 23. 238. 111 o lista. 211 a nodo hermano. 84. 134 modelo mental. 23 matriz. 156. 137 operador. 83 m´dulo copy. 99 lista. 224 nodo ra´ 211. 111. 116 e m´todo envoltorio. 211. 191 objeto mudable. 190 inicializaci´n. 112 mazo. 225 mismidad. 81 o copy. 154. 232 modelo mental. 150. 16. 95 dispersa. 42 o matem´ticas a funciones. 137 o m´dulo string. 148 modificador. 224 Nodo clase. 89 operaciones sobre cadenas.278 lowercase. 131. 111. 241 a u m´todo. 235 objeto. 17 operador. 82 m´ximo com´n divisor. 224 ız. 151. 236 o multiplicaci´n escalar. 160 e ayudante. 6 negaci´n. 73 o manejar errores. 139 mudable. 160. 20 . 81. 166 e m´todos sobre diccionarios. 224 nodo hoja. 211. 91. 49 m´todos de lista. 211. 154. 33. 224 nodo hijo. 166 m´todo append. 229 natural lenguaje. 48. 190 envoltorio. 211. 73 numerador. 220 marco. 77 mensajes de error. 241 o nivel. 117. 224 nodo padre. 83 o m´ltiple u asignaci´n. 220 manejar una excepci´n. 232 ´ Indice alfab´tico e modifcador. 35 string. 165 o invocaci´n. 192 e m´todo de inicializaci´n. e o 165 m´todo de lista. 165 McCloskey. 90 n´mero u aleatorio. 42 marco de funci´n. 126. Robert. 101 u NameError. 192. 240 o negaci´n unitaria. 224 nodo. 160 o mutable. 136 objetos lista de. 143 modificar listas. 183 nodo de un ´rbol. 190.

80 o Pentium. 36 o operador m´dulo. 196. 169 operador l´gico. 117 par´metros. 10 portable. 196 pista. 214. 230 operador in. 88. polim´rfica. 185. 224 condicional. 94. 161 papel variable. 84. 213 recorrido. 2 postfijo. 215. 214 o infinita. 16. 9. 164 orden completo.´ Indice alfab´tico e binario. 75 formato. 160 programa. 135 a recuento. 186. 90 portabilidad. 14 palo. 209. 123. 73 poes´ 8 ıa. 230 in. 64 279 Pila. 238 o push. 197 porci´n. 236 operador binario. 169 m´dulo. 80 o patr´n computacional. 213. 164 operador corchete. 37 patr´n. 224 orden prefijo. 80. 224 orden parcial. 94 pass sentencia. 197 racional. 20 palabras reservadas. 76. 109. 228 . 113. 28 a par´metro. 232 prefijo. 164 corchete. 80 rect´ngulo. 84 o porciones. 235 rama. 173 o sobrecarga. 214 lista. 171 prosa. 20 orden. 87 recorrido de lista. 128. 224 palabra reservada. 219 producto interior. 214. 33. 209 producto. 156. 10 desarrollo de. 176. 160 o polimorfismo. 20. 213. 213 precedencia. 8 proveedor. o 149. 215. 156. 88. 224 print sentencia. 123. 117 plan de desarrollo. 224 operador condicional. 75 operador de formato. 13. 97 recorrido eureka. 88. 214. 213. 116 recursi´n. 188 par clave-valor. 209. 78. 167 randrange. 38. 236 a operador unitario. 240 operadores para listas. 10 prioridad. 167 recorrer. 45. 164 orden de evaluaci´n. 158 pop. 133 a lista. 196 pila. 201 pseudoaleatorio. 45 random. 173 o operador matem´tico. 164 orden postfijo. 89 operando. 214. 201. 35. 107 pseudoc´digo. 17 orden infijo. 73 programaci´n orientada a objetos. 128. 198. 208. 232 o orden de las operaciones.

57 redimiento. 7 referencia. 230 return. 238. 121. 61 o break. 171. 55 caso base. 203. 205 reducir.280 recursi´n infinita. 73 TAD. 64 dos dimensiones. 228 o recursividad. 10. 5 sem´ntica. 5. 97 secuencia aritm´tica. 12. 45 sentencia continue. 183. 37 sentencia print. 9. 17. 122. 57 recursividad infinita. 85 singleton. 175. 128 condicional. 160. 219 fracci´n. 237 o sustituir. 203 temporal variable. 211 referencia incrustada. 209 sobrecarga de operadores. 53. 45 sentencia condicional. 66 tabulador. 182 subexpresi´n. 43. 43. 5 sentencia. 241 redundancia. 183 incrustada. 236 operador. 233 sentencia try. 164 t´ctica de encolamiento. 126 print. 42. 210 a tablas. 10 o subclase. 89 runtime error. 220 o suma. 40. 37 compuestas. 203 Cola Priorizada. 66 e seguro lenguaje. 92 reglas de precedencia. 37 sentencias compuestas. 190. 230 sentencia return. 192 sintaxis. 156. 73 secuencia geom´trica. 183. 203. 37 cuerpo. 126. 209 soluci´n de problemas. 122. 125 secuencia. 201 Cola. 189. 48 teorema fundamental de la ambig¨edad. 195. 59 temporales variables. 40. 128 except. 66. 20 asignaci´n. 203 cola. 66 e secuencia de escape. 233 try. 76 ruta. 45. 227. 196 TAD Cola. 45. 5. 37 cabecera. 45 continue. 37 bloque de sentencias. 10. 128 sentencia pass. 37 sequencia. 207 Pila. 192 referencia empotrada. 40. 200. 226 sobrecarga. 43 infinita. 10 a error. 126 sentencias bloque. 173 repetici´n o lista. 20 reparto de naipes. 128 ´ Indice alfab´tico e sentencia except. 160. 126 while. u 188 . 128 sentencia compuesta. 62 sentencia break. 121. 192 referencias alias. 164.

29 variables temporales. 142 tipo inmutable. 235 diccionario. 232 variables locales. 210 tipo. 12. 131. 69 variables locales. 131 tipo de funci´n o modifcador. 62 whitespace. 188 temporal. 10 uppercase. 137 281 valor. 229 try. 109 tipo de datos compuesto. 107 tipos coerci´n. 101 valores de retorno tuplas. 205. 43. 33.´ Indice alfab´tico e teorema fundamental de la ambig¨edad. 20. 82 uso de alias. 101 Turing. 99 tuplas. 12 tipo abstracto de datos |verTAD. 210 tiempo lineal. 199. 82 . 192 u tesis de Turing. 136 valores tuplas. 59. 205. 216 traceback. 91. 127 traza inversa. 131 tipo de datos definido por el usuario. 59. 73. 12 float. 12 int. 12. 99. 229 unidad. 20 bucle. 107 tipo mutable. 75. 143 pura. 11. 22 o comprobaci´n. 53 tiempo constante. 53 TypeError. 11 variable. Alan. 22 o tipos de datos enteros largos. 131 definido por el usuario. 201. 173. 173 papeles. 101 value. 33 variable temporal. 21. 20 cadena. 31 traza. 75. 84 tipo de datos compuesto. 99 token. 232 variable de bucle. 115 inmutables. 161 valor de retorno. 128 tupla. 48 while sentencia. 47. 57 o conversi´n. 195 tipo compuesto de datos. 107 tuplas. 185 variable local.

Sign up to vote on this title
UsefulNot useful