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

el lenguaje de ense˜anza n era Pascal tanto en nuestro curso de primer a˜o como en el AP. C´mo y por qu´ vine a usar Python o e En 1999. tambi´n es extremadamente dif´ de aprender y ense˜ar. n Dos a˜os m´s tarde. o directo sobre el curriculum de inform´tica en el Insituto de Yorktown en Ara lington. el examen de Advanced Placement (AP) de Ciencias de la Computaci´n del Claustro Escolar se realiz´ por primera vez en C++. 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. y como consecuencia perd´ muchos estudiantes sin ıa . 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. donde doy clase. Creemos que este libro es un testamento a los beneficios y futuras posibilidades de este tipo de colaboraci´n. Virgina. cuyo marco han establecido Richard Stallman y la o Free Software Foundation. Sus tres autores. 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. Aunque es un lenguaje de programaci´n a o muy poderoso. un profesor universitario. me convenc´ de que C++ era una mala elecci´n para iniciar n a ı o a los estudiantes en la inform´tica. un profesor de instituto y un programador profesional.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. Hasta ese momento. todav´ tienen que conocerse ıa cara a cara. 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. Como en muchos o o institutos en todo el pa´ la decisi´n de cambiar de lenguaje tuvo un impacto ıs.

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

dirigi´ndoe les m´s all´ de donde yo pod´ llevarles. 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. Como pod´ hacer cambios instant´neos cuando alguien encontraba ıa a un error ortogr´fico o un pasaje dif´ a ıcil.ibiblio. o n en Eugene. La perspectiva de impartir el curso llev´ a Chris haso ta el libro. a a Para la segunda mitad del libro. o o Recib´ un correo electr´nico de Chris Meyers expresando su inter´s en el liı o e bro. o n o . 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. 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. n el proceso.ix partir de ´l me hizo posible hacerlo. 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. Hacia el final del o e a˜o escolar hab´ creado un proyecto complementario en nuesto sitio web en n ıa http://www.org/obp llamado Python for Fun y estaba trabajando con algunos de mis estudiantes aventajados como profesor magistral. 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. 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. ı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 ı. 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. 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. Oregon.

P´rrafos enteros desapareciendo de la versi´n Python del texto porque la a o sintaxis clara de Python los hace innecesarios. Algunos de a ellos est´n sin duda un poco nerviosos. En C++ una variable es un nombre para un lugar que contiene una cosa. tras haber o´ que programar compua ıdo tadores es algo dif´ de aprender. y arriesgarme a lo mismo. La versi´n C++ siempre me ha obligado a ıcil o elegir entre dos opciones insatisfactorias: explicar las sentencias #include. void main(). Hay trece p´rrafos de explicaci´n de “¡Hola. present´ndoles de esta forma o a el entorno de programaci´n. o decirles “No te preocupes de todo eso ahora. {. que en la versi´n C++ del libro es as´ o ı: #include <iostream. y nada m´s. mundo”. Encontr´ que esto mismo suced´ por todo el e ıa libro. La programaci´n con Python tiene exactamente lo o o que necesito para hacer estas cosas. sino las o minucias de la sintaxis de C++. as´ que muchos de los estua ı diantes que ven este ejemplo est´n mirando su primer programa. mundo" << endl. hablaremos de ello m´s tarde”.x Prefacio El primer ejemplo del texto ilustra esta cuesti´n. Mundo" Aunque es un ejemplo trivial. } en la versi´n Python se convierte en: o print "Hola. El curso de Inform´tica I en Yorktown no tiene prerrequisitos. Es el tradicional programa o “hola. 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.h> void main() { cout << "Hola. est´ ligada al hardware de la m´quina. 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. En la a o o versi´n Python s´lo hay dos. 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. destacan las ventajas de Python. El concepto poderoso y fundamental de a a . y } y arriesgarme a confundir o intimidar a algunos estudiantes desde el principio. 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. 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. mundo!” en la versi´n C++. Uno de o los mejores ejemplos de ello es la manera en la cual Python maneja las variables. As´ la idea de una variable ı. De este modo crea la habilidad de poner pedag´gicamente “antes lo primero”.

o o a Python viene al rescate con una sintaxis a la que no le falta belleza. o El uso de Python ha mejorado la eficacia de nuestro programa de inform´tica a para todos los estudiantes. y simplemente digo a mis o o estudiantes: “cuando definas una funci´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. 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. podemos incrementar la calidad de los materiales . con mejor comprensi´n. 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. 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. a Este a˜o tuve muchas menos dificultades ense˜ando lo que son las variables que n n en el anterior. o par´metro por a a referencia y valor de por medio. Ha emn pezando a surgir una comunidad de usuarios. En Python una variable es un nombre que se˜ala una cosa. Octetos y direcciones no ayudan a la a a comprensi´n. simplemente di o e o (escribe) su nombre”. La definici´n de una funci´n empieza con la palabra clave def. cuando llames a una funci´n. Mis estudiantes siempre han o tenido una gran dificultad comprendiendo las funciones. 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. seguido del nombre o de la funci´n que est´s definiendo. o e n ne Avanzo m´s r´pido con mejores resultados. empieza con def. 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++. por lo que ahora soy capaz de ense˜ar funciones n en la mitad de tiempo que antes. y pas´ menos tiempo ayud´ndoles con los problemas derivados e a de su uso. y muchas personas han contribuido al proyecto mandando materiales a trav´s del sitio web complementario e http://www. No hay tipo de retorno. Trabajando juntos.thinkpython. 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. tipos de par´metros. Los par´metros van con las definiciones. 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). Con la publicaci´n de este libro en forma impresa. y la distinci´n asociada entre un par´metro y un argumento.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.com. Jeffrey Elkner Escuela Secundaria Yortown Arlington. Por favor. Virginia .

aparecer´ en la siguiente versi´n de la lista de colaboradores (a no ser que pida a o quedar omitido). esperamos que se tome un minuto para ponerse en contacto con nosotros. Si se encontrara con una. ¡Gracias! Lloyd Hugh Allen envi´ una correcci´n de la Secci´n 8. ponerla a nuestra disposici´n. Si cambiamos algo a partir de su sugerencia. este libro es libre ıa como la libre expresi´n. Siguiendo el esp´ n ıritu del software libre.1. pero no necesariamente gratis como la pizza gratis. o o o Yvon Boulianne envi´ una correcci´n de un error sem´ntico en el Cap´ o o a ıtulo 5. . a Pos imposible que parezca tras tantas correcciones. o o o A Jonah Cohen escribi´ los scripts en Perl para convertir la fuente L TEX del o libro en hermoso HTML. todav´ puede haber ıa errores en el libro.4. La direcci´n de correo es o feedback@thinkpython. pero hacemos lo que podemos para mantenerla actualizada.Lista de Colaboradores Parafraseando la filosof´ de la Free Software Foundation. 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. o Se hizo realidad a causa de una colaboraci´n que no habr´ sido posible sin o ıa la GNU Free Documentation License.com. esta listo no est´ completa. 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. por supuesto. decidimos expresar nuestra gratitud en la forma de una lista de colaboradores. Desgraciadamente. As´ que queremos agradecer a la Free ı Software Foundation por desarrollar esta licencia y. Fred Bremmer comunic´ una correcci´n de la Secci´n 2.

10. e inici´ una discusi´n sobre aspectos o o t´cnicos de los int´rpretes. James Kaylin es un estudiante que us´ el texto. Envi´ numerosas correco o ciones. o Man-Yong Lee envi´ una correcci´n del c´digo de ejemplo de la Secci´n o o o o 2.9 y 3. Tambi´n encontr´ errores en e o la funci´n incrementa del Cap´ o ıtulo 13. 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 ı. John Ouzts corrigi´ la definici´n de “valor de retorno”del Cap´ o o ıtulo 3. ıa Chris McAloon envi´ varias correciones de las Secciones 3. y tambi´n amables palabras de ´nimo. o o o Courtney Gleason y Katherine Smith escribieron horsebet. Moelter ha sido un colaborador durante mucho tiempo y ha enviado numerosas correcciones y sugerencias.4. e e Benoit Girard envi´ una correcci´n de un divertido error de la Secci´n 5.py. e a . David Mayo se˜al´ que la palabra “unconscientemente”en el Cap´ n o ıtulo 1 deb´ cambiarse por “subconscientemente”. 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. o David Pool envi´ un error tipogr´fico en el glosario del Cap´ o a ıtulo 1. 2 y 3.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. o Eddie Lam ha enviado numerosas correcciones de los Cap´ ıtulos 1.6. Su proo o grama puede encontrarse en el sitio web. 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. 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.10. que se us´ como un caso de estudio en una versi´n temprana del libro. ıa del texto.

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

y pill´ un par de errores o a o graves en el Cap´ ıtulo 5. o David Hutchins pill´ un error tipogr´fico en el Pr´logo.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. Smith encontr´ varios errores tipogr´ficos y nos est´ ayuo a a dando a preparar la actualizaci´n del libro para Python 2. o a .2. Austria. Julie Peters encontr´ un error tipogr´fico en el Prefacio. a Christopher P. Kalin Harvey sugiri´ una clarificaci´n al Cap´ o o ıtulo 7 y detect´ varios errores o tipogr´ficos. Est´ tran a bajando en una traducci´n del libro al alem´n. o a o Gregor Lingl ense˜a Python en un instituto de Viena.

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

. . . o Condiciones encadenadas .3. . . . . . . . . . . . . . . . . . . . . . o Par´metros y argumentos . . . . . . . . . .12. . . . . . . . . . . . . . 3. Condicionales y recursividad 4. . 4. . . 3. . . . . . . .1. . . . . . . . .8. . . . . . . . . . . . . . . . . . 3. . 3. . . . . .xviii ´ Indice general El orden de las operaciones . . . . . . . . . . . . . . . . .9. . . El operador m´dulo . . . . . . . . .13. . .8. . . . . . o Ejecuci´n alternativa . . . . . .4. . 4. . . . . . . . . . . . . . . 2. . . . . . Flujo de ejecuci´n . . . . . . . . . . . . . . . . . . . 4. . . . .11. . . . 2. . . . 2. . .6. . . . . . o Funciones matem´ticas . . . . . . . . . . . o Ejecuci´n condicional . Conversi´n de tipos . . . . . 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. . . . . . .4. . . . Funciones 3. . . . . . . . . . . . . . . . . a Composici´n . . . . . . . . .3. . . . . . . 4. . . . . . . 3. o Coerci´n de tipos . . . . . . . . a 3. . Llamadas a funciones . . . . .7. . 4. 3. . . . . . . . . Operadores l´gicos . . . . . . . . . 3. . n Las definiciones y el uso . . . . . . . .11. . . . . .10. . . . .2. Funciones con resultado . . . . . . . . . . . . . . . . . . . . . . . . . .9. . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . 2. . . .5. . . . . . . . . .7. . . . . . . . . . . . 3. . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . .1. . . . . . . . Glosario . . . . . . . . . . . . . . . . . . 3. . Diagramas de pila . . 3. . . . . . . . . . Composici´n . . o Expresiones booleanas . . 3. . . . . . . . . . . . . . . . . . . .10. . . . . . . 4. . . Los comentarios . . . . . Las operaciones sobre cadenas . . . . . . . . . . . . . . . . . . . . . . a 3. . . Las variables y los par´metros son locales . . . . . . . . . . . . . . . .6. . . . . . . . o A˜adir funciones nuevas . . . . . . . . . . . . . . . . . . Glosario . . . . . . . . . . . . . . . . . . .

. . . . . .9. . . . . 6. . . . . . . . . . . . . . . . . . Condiciones anidadas . . . . . . . 5. . . . . . . . . . . . . . . . . . . . a o Funciones . . . . . . . . . . . . . . . . Glosario . . . .6. 5. . . . . . 4. . . . . . . . . . 5. . 6. . . . . . . . . . . . . . . . . . . .11. . . . . . . . . . . . . . . . . .2. .9. . . . . . . 4. . . . . 5.1. . . . . . . . . . . . . . . 6. . . . . . . . . . . . . . . . . . Funciones productivas 5. . . . .3.7. . 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. . . . . . . 6. . . . . . . . . . La sentencia return . . . . o Glosario . . . . . . . . . . . . . . . . . . . . 5. . . . .9. .7. . .1. 5. . . . . . . . . . 5. . . . . .4. . . . . . . . . . . . . . .2. . . . 6. 6. . . . . . . . . . . . 4.5. . . . . . . . . .6. . . . . . . . . . . . . . . . . . . . . . Recursividad infinita . . . . . . . . . . . . . . . . . . 4. . . . . . . . . . . . .13. . . . . . . . . . . . . . . . . . . . . . . . . Un ejemplo m´s . . . . .10. . . . . . . . . . . . . . . . . . . . . . . . . . . a Acto de fe . . . . . . . . . . . . . . . . . . 6. . . . . . . . . . . . . . . . . . . . . . . . a Comprobaci´n de tipos . .8. . . . . . . . . . . . o M´s encapsulaci´n . . . Encapsulado y generalizaci´n . . . . . . . .8.5. . . . . . 4. . . o u La sentencia while . . . . . . . . . . . . . . M´s generalizaci´n . Valores de retorno . . . . . . . . . . . . . . . . Tablas . Asignaci´n m´ltiple . . . . . . . . . . . . . Recursividad . . . . . .4. . Tablas de dos dimensiones . . . . . . . Composici´n . . . . . . . . . M´s recursividad . . . . . . . . . Entrada por teclado . . . . . . . . . . . . . . .3. . . . . . . . . . . .7.12. . . . . . . . Iteraci´n o 6. 5. Glosario . . 6. . . . a o Variables locales . . . . .´ Indice general 4. . . . . . . . . . . . 5.10. . . . . . . . . . . . . . . 6. . . . . . . . . . . . . . . . . . . 6. . . . Diagramas de pila para funciones recursivas . o Funciones booleanas . . . . . . . Desarrollo de programas . . .8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

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

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

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

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

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

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

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

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

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

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

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

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

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).2") <type ’string’> Son cadenas. Este no es un entero legal en Python. Python interpreta 1. >>> type("17") <type ’string’> >>> type("3. Una variable es un nombre que hace referencia a un valor.000 1 0 0 En fin. La primera de ellas asigna el valor "Que onda?" a una variable nueva. La sentencia de asignaci´n crea nuevas variables y les asigna un valor: o >>> mensaje = "Que onda?" >>> n = 17 >>> pi = 3.2"? Parecen n´meros.000. 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.000. Cuando escriba un entero largo.2) <type ’float’> ¿Qu´ ocurre con los valores como "17" y "3.14159 Este ejemplo muestra tres asignaciones. >>> type(3. 1 2. de nombre mensaje.000 como una lista de tres n´meros que debe imprimir. podr´ estar tentado de usar comas entre grupos ıa ´ de tres d´ ıgitos. como en 1. pero est´n e u a entre comillas como las cadenas.000. pero es una expresi´n legal: o >>> print 1.2. como se u e n apunt´ en una nota anterior o 1 El .12 Variables. no era eso lo que quer´ ıamos. Variables Una de las caracter´ ısticas m´s potentes de los lenguajes de programaci´n es a o la capacidad de manipular variables.000. As´ que recuerde no insertar comas en u ı sus enteros.

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

El lenguaje usa las palabras reservadas para definir sus reglas y estructura. o e Hemos visto dos tipos de sentencias: print y la asignaci´n. y no pueden usarse como nombres de variables.14 Variables. Pero ¿qu´ tiene de malo class? a o e Resulta que class es una de las palabras reservadas de Python. Sentencias Una sentencia es una instrucci´n que puede ejecutar el int´rprete de Python. recuerde u o que la distinci´n es importante: Bruno y bruno son dos variables diferentes. o u Normalmente un gui´n contiene una secuencia de sentencias. 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. o El gui´n bajo ( ) tambi´n es legal y se utiliza a menudo para separar nombres o e con m´ltiples palabras. u Si intenta darle a una variable un nombre ilegal. Las sentencias de asignaci´n no entregan ning´n resultado. El resultado de una sentencia print es un valor. el signo del d´lar. Si el int´rprete se queja de alguno e de sus nombres de variable. compruebe si est´ en esta e a lista. los resultados aparecen de uno en uno tal como se van ejecutando las sentencias. por convenci´n no lo hacemos. Si hay m´s de una o a sentencia. 2. y usted no sabe por qu´. mas$ es ilegal porque contiene un car´cter ilegal. Si lo hace. Python la ejecuta y muestra el resultado. expresiones y sentencias aceptable usar may´sculas. como mi nombre o precio del cafe colombiano. o Cuando usted escribe una sentencia en la l´ ınea de comandos. obtendr´ un error de sintaxis. .4. 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.

eso significa que ıa incluye las comillas. y tambi´n una variable. evaluar una expresi´n no es del todo lo mismo que o imprimir un valor. una expresi´n sin m´s es una sentencia v´lida. Evaluar expresiones Una expresi´n es una combinaci´n de valroes. variables y operadores. e o ı >>> 17 17 >>> x 2 Para complicar las cosas. En un gui´n. En el caso de las cadenas. >>> mensaje = "Que onda?" >>> mensaje "Que onda?" >>> print mensaje Que onda? Cuando Python muestra el valor de una expresi´n. se considera una expresi´n por s´ mismo. 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.5 Evaluar expresiones Por ejemplo. o 15 2.5. la sentencia de asignaci´n no produce ninguna salida. 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. pero no hace nada.2. o o a a El gui´n o . Pero la sentencia print imprime el valor de la expresi´n. el gui´n o print 1 x = 2 print x prsenta la salida 1 2 De nuevo.

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

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

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

pero ya veremos otros ejemplos donde la composici´n hace posible expresar c´lculos complejos con o a limpieza y brevedad. Por tanto es ilegal lo siguiente: minute+1 o = hour. qu´ hace el programa. la parte izquierda de una sentencia de asignaci´n tiene que ser un o nombre de variable.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. El mensaje est´ destinado al programador. ´ ATENCION: Hay l´ ımites al lugar donde pueden usarse ciertas expresiones. el comentario aparece en una l´ ınea propia.11. En este caso avisa al lector sobre el ıan o sorprendente comportamiento de la divisi´n de enteros.2. 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. 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 2.10. o por qu´ lo hace. se vuelven n a m´s complicados de leer. ıcil o e Por ello es una buena idea a˜adir notas a su programa que expliquen. no una exrpresi´n. Los comentarios Conforme los programas van creciendo de tama˜o y complic´ndose. 2. Por ejemplo. Los lenguajes formales son densos y con frecuencia es a dif´ observar un trozo de c´digo y averiguar lo que hace. 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. o . en un n lenguaje natural. o a futuros programaa dores que podr´ tener que usar el c´digo.

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

o El valor o variable. y muestra el tipo de un valor o de una variable. 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. ha de estar encerrado o entre par´ntesis. llamado el argumento de la funci´n. El id de una variable es el id del valor al que hace referencia. 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. Es habitual decir que una funci´n “toma” un argumento y e o “devuelve” un resultado. En lugar de imprimir el valor de retorno.1.Cap´ ıtulo 3 Funciones 3. El resultado se llama valor de retorno. . que es un valor unico relacionado con d´nde se almacena ´ o en la memoria del computador. u ´ >>> id(3) 134882108 >>> yanira = 3 >>> id(yanira) 134882108 Cada valor tiene un id. podemos asign´rselo a una variable.

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

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

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

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

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

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

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

Dafne. aqu´ en imprimeDoble llamamos a todo el mundo o ı paso. as´ que puede usar e ı cualquier tipo de expresi´n como argumento de imprimeDoble.pi)) -1. Las variables y los par´metros son locales a Cuando crea una variable dentro de una funci´n. y no puede usarla fuera de ella. la funci´n o o >>> def catDoble(parte1. No importa c´mo se llamaba el valor en su lugar original (el a o lugar desde donde se invoc´).. 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.. el argumento es una cadena. s´lo existe dentro de dicha o o funci´n. en la segunda o es un entero.14159 En la primera llamada a la funci´n. parte2): . 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. >>> .. imprimeDoble(cat) .10. se eval´a la expresi´n antes de ejecutar la funci´n.14159) 3.cos(math.14159 3. 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). 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.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. cat = parte1 + parte2 . y en la tercera es un n´mero de coma flotante. 3..0 Como de costumbre.3..0 -1.. es mitad laurel mitad ninfa. Por ejemplo. o o Asimismo podemos usar una variable como argumento: >>> latoya = ’Dafne.

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

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

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

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. 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. variable local: variable definida dentro de una funci´n. presentadas cuando sucede un error en tiempo de ejecuci´n.3. o o diagrama de pila: Representaci´n gr´fica de una pila de funciones. traza inversa: (traceback en ingl´s) Una lista de las funciones en curso de e ejecuci´n. o o notaci´n de punto o traza inversa .

.

Por ejemplo. . Por ejemplo. De forma similar. 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 % 100 devuelve los dos ultimos d´ ´ ıgitos. el operador de m´dulo es el signo de tanto por ciento ( %). En Python. El operador m´dulo o El operador m´dulo funciona con enteros (y expresiones enteras). ı. El operador de m´dulo resulta ser soprendentemente util. 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.Cap´ ıtulo 4 Condicionales y recursividad 4. entonces x es u divisible entre y. y devuelve o el resto de dividir el primer operando entre el segundo.1. puede o ´ comprobar si un n´mero es divisible entre otro: si x % y es cero. x % 10 devuelve el d´ u ıgito m´s a la derecha de x (en a base 10).

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

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

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

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

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

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

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

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

e Puede proporcionarle un indicador a raw input como argumento: >>> nombre = raw_input ("C´mo te llamas? ") o C´mo te llamas? H´ctor. Python proporciona funciones internas que obtienen entradas desde el teclado. si el usuario escribe algo que no sea un a d´ ıgito. Por desgracia. 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. utilice la funci´n input. ¡Cuando sucede el error. 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. Cuando llamamos a esta funci´n. "Cu´l es la velocidad de una golondrina sin carga?\n" a >>> velocidad = input (indicador) Si el usuario teclea una cadena de n´meros. se convertir´ en un entero y se u a asignar´ a velocidad. Este mensaje se llama indicador (prompt en ingl´s). 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.. Por ejemplo: o >>> indicador = \ . el proa o grama se detiene y espera a que el usuario escriba algo.44 Condicionales y recursividad Esta traza inversa es un poco mayor que la que vimos en el cap´ ıtulo anterior. Cuando el usuario pulsa la tecla Return o Enter. u e 4. Simplemente hacen lo mismo siempre. La m´s sencilla se llama raw input..12. h´roe de los Troyanos! e e Si espera que la entrada sea un entero. escriba una funci´n con recursividad infinita y o ejec´tela en el int´rprete de Python. hay 100 marcos recurre en la pila! Como actividad. . 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. h´roe de los Troyanos! o e e >>> print nombre H´ctor.

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

.

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

s´lo se a o o ejecutar´ una de ellas. Desarrollo de programas Llegados a este punto. 5. En cuanto se ejecuta una de ellas. a A veces es util disponer de varias sentencias de retorno. tendr´ que poder mirar a funciones Python completas ıa y adivinar qu´ hacen. escriba una funci´n comparar que devuelva 1 si x o >y .48 def area(radio): return math. 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. 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. recibe el nombre de c´digo muerto.pi * radio**2 Funciones productivas Por otra parte. En este caso. el valor de retorno es un valor especial llamado None: >>> print valorAbsoluto(0) None Como actividad. Tambi´n. o o En una funci´n productiva es una buena idea asegurarse de que cualquier posible o recorrido del programa alcanza una sentencia return. 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.2. habr´ escrito algue e a nas funcioncillas. 0 si x == y . si ha hecho los ejercicios. la funci´n termina sin a o ejecutar ninguna de las sentencias siguientes. 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 . las variables temporales como temporal suelen hacer m´s a f´cil el depurado. y -1 si x <y .

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

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

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

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

o Como actividad. o ıa si ha buscado la definici´n de la funci´n matem´tica factorial. Una definici´n recursiva es semejante a una definici´n circular. completado por primera vez o por Alan Turing. M´s recursividad a Hasta ahora. 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. Si estudia un curso de Teor´ de la Computaci´n. 53 5. z) que deo vuelva 1 en caso de que y <= x <= z y que devuelva 0 en cualquier otro caso. pero o o eso es todo). y) == 1: Pero la comparaci´n extra es innecesaria. se quedar´ confuso. Probar tal afirmaci´n es un ejercicio nada trivial. y. Para darle una idea de lo que puede hacer con las herramientas que ha aprendido hasta ahora. el rat´n.5. o o en el sentido de que la definici´n contiene una referencia a lo que se define. uno de los primeros cient´ ıficos inform´ticos (algunos argumena tar´n que era un matem´tico. 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. etc. Por otra parte. se la conoce como la a tesis de Turing. con esto queremos decir que cualquier cosa que pueda o computarse se puede expresar en este lenguaje.5 M´s recursividad a if esDivisible(x. habr´ visto algo o o a a sejemante a lo siguiente: .5. necesitar´ algunas ıa ´rdenes para controlar dispositivos como el teclado. los discos. En correspondencia. tendr´ oporıa o a tunidad de ver la prueba. usted ha aprendido solamente un peque˜o subconjunto de Python. 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. y): print "x es divisible entre y" else: print "x no es divisible entre y" Puede parecer tentador escribir algo como: if esDivisible(x. pero muchos de los cient´ a a ıficos inform´ticos pionea ros comenzaron como matem´ticos). escriba una funci´n estaEntre(x.

Si llamamos a factorial con el valor 3: o Puesto que 3 no es 0.9. que es una vez 0!.. n. es n multiplicado por el factorial de n − 1. 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. As´ pues. 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. . y que el factorial de cualquier o otro valor. tomamos la segunda rama y calculamos el factorial de n-1. tomamos la segunda rama y calculamos el factorial de n-1. todo lo que hemos de hacer es devolver 1: def factorial(n): if n == 0: return 1 En otro caso.54 Funciones productivas 0! = 1 n! = n · (n − 1)! Esta definici´n establece que el factoral de 0 es 1.. Puesto que 0 es 0.. ı a . El primer paso es decidir cu´les son los a par´metros para esta funci´n. Puesto que 1 no es 0.. que es 2 veces 1!. y he aqu´ la parte interesante. normalmente podr´ escribir o a un programa de Python para evaluarlo. Junt´ndolos todos.. que es 6. 3! es 3 veces 2!. Si puede escribir una definici´n recursiva de algo. Puesto que 2 no es 0. 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 igual a 3 veces 2 veces 1 vez 1.

y se devuelve el resultado. pero puede o volverse r´pidamente una tarea laber´ a ınitca. 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. La alternativa es lo que llamamos el “acto de fe”. damos por sentado que la funci´n trabaja correctamente y devuelve o o el valor apropiado. El valor de retorno (1) se multiplica por n. Cuando llegamos a una funci´n. 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. se convierte en el valor de retorno de la llamada a la funci´n que comenz´ todo el proceso. en lugar de seguir el flujo de o ejecuci´n. En cada marco. y el resultado 6. usted ya practica dicho salto de fe cuando usa funciones internas. 5. 55 El valor de retorno (2) se multiplica por n. que es 2. que es 3.6 Acto de fe El valor de retorno (1) se multiplica por n.5. Cuando llama a math. que es 1. que es el producto de n por recursivo. y se devuelve el resultado. el valor de retorno es el valor de resultado.6. no examina la implementaci´n de o . Acto de fe Seguir el flujo de ejecuci´n es una de las maneras de leer programas. De hecho.exp.cos o a math.

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

5 como argumento? e >>> factorial (1. En la siguiente vez su valor es -0. As´ pues. a 5.5) RuntimeError: Maximum recursion depth exceeded Tiene todo el aspecto de una recursi´n infinita.5. Pero. Comprobaci´n de tipos o ¿Qu´ sucede si llamamos a factorial y le damos 1." a o return -1 elif n < 0: print "El factorial est´ definido s´lo para enteros\ a o positivos. La primera opci´n se llama funci´n gamma. a a n a Tenemos dos opciones. ı.8. peque˜os de n." return -1 elif n == 0: return 1 else: return n * factorial(n-1) . le puede dar un dolor de cabeza.5. a o o y est´ m´s all´ del objetivo de este libro. 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). el valor de n es 0. Podemos intentar generalizar la funci´n factorial para o que trabaje con n´meros de coma flotante.5. tomemos la segunda. Pero si confiamos en el acto de n fe. Ya que estamos en ello.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. si da por supuesto que las dos llamadas recursivas funcionan correctamente. pero nunca ser´ 0. ¿c´mo ha podido ocurrir? o o Hay una condici´n de salida o caso base: cuando n == 0. 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. entonces estar´ claro que obtiene el resultado correcto al sumarlas juntas. El problema es que el o valor de n yerra el caso base. En la primera llamada recursiva. A partir de ah´ se vuelve m´s y m´s peque˜o.

58 Funciones productivas Ahora tenemos tres condiciones de salida o casos base. -1. -1 >>> factorial ("paco") El factorial esta definido solo para enteros. o variable temporal: Variable utilizada para almacenar un valor intermedio en un c´lculo complejo. entonces sabemos que n es un entero positivo y podemos probar que la recursi´n termina. En ambos casos. o o valor de retorno: El valor obtenido como resultado de una llamada a una funci´n.9. 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. -1 Si pasamos ambas comprobaciones. se u muestra un mensaje de error y se devuelve un valor especial. a meo a nudo debido a que aparece tras una sentencia de return. o Este programa muestra un patr´n que se llama a veces guardi´n. a c´digo muerto: Parte de un programa que no podr´ ejecutarse nunca. o o 5. Glosario funci´n productiva: Funci´n que devuelve un valor de retorno. -1 >>> factorial (-2) El factorial esta definido solo para enteros positivos. protegiendo al c´digo que sigue de u o los valores que pudieran causar errores. o . 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. Los guardianes hacen posible demostrar la correcci´n del c´digo. andamiaje: El c´digo que se usa durante el desarrollo del programa pero que o no es parte de la versi´n final. Las primeras o a dos condicionales act´an como guardianes.5) El factorial esta definido solo para enteros. El segundo evita los enteros negativos. El primero filtra los n´meros no enteros.

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

.

Pero no lo es. Puesto o que Python usa el s´ ımbolo = para la asignaci´n. 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. es tentador interpretar una o sentencia como a = b como sentencia de igualdad.1. . ya que la primera vez que imprimimos bruno su valor es 5. es especialmente importante u distinguir entre una sentencia de asignaci´n y una sentencia de igualdad.Cap´ ıtulo 6 Iteraci´n o 6. bruno print bruno print = 5 bruno. y la segunda vez su valor es 7. por eso ambos valores aparecen en la misma l´ ınea. La coma al final de la primera sentencia print impide que se imprima una nueva l´ ınea en ese punto. 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. 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. = 7 bruno La salida del programa es 5 7.

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

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

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

a˜adimos otro par´metro a imprimeMultiplos. imagine que desea un programa que imo prima una tabla de multiplicaci´n de cualquier tama˜o. o o u probablemente consiga que el programa sea m´s dif´ de leer. a ıcil 6. 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. M´s generalizaci´n a o Como otro ejemplo de generalizaci´n. i = i + 1 print def imprimeTablaMult(mayor): int i = 1 while i <= mayor: . Si ahora se llama a a imprimeTablaMult con el argumento 7. Para hacere u lo. Si evita usarlas en una funci´n porque las utiliz´ en alg´n otro lugar. llamaremos tambi´n a este par´metro mayor. excepto por el hecho de que seguramente queremos que la tabla est´ cuadrada. para demostrar o e a que diferentes funciones pueden tener par´metros con el mismo nombre (al igual a que las variables locales). mayor): int i = 1 while i <= mayor: print n*i. con el mismo n´mero de filas que de columnas. y no s´lo la tabla de o n o 6x6. ıa S´lo para fastidiar.70 Iteraci´n o bucle.8. 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. ’\t’. Aqu´ tenemos el programa completo: ı def imprimeMultiplos(n. a fin de especificar cu´ntas n a a columnas tendr´ que tener la tabla.

6. o Seg´n lo esperado. Puede ahorrar tinta imprimiendo s´lo la mitad de la tabla. s´lo tiene que cambiar o o una l´ ınea de imprimeTablaMult. y tuvimos tambi´n que cambiar el o o e lugar donde se llama a la funci´n en imprimeTablaMult. Puede que ya se est´ preguntando qu´ cosas son e e exactamente. Funciones Hasta el momento hemos mencionado en alguna ocasi´n “todas las cosas para o las que sirven las funciones”.9 Funciones imprimeMultiplos(i. Cambie imprimeMultiplos(i. siga o trace la ejecuci´n de esta nueva versi´n de o o imprimeTablaMult para hacerse una idea de c´mo funciona. Por ejemplo. 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. porque ab = ba. quiz´ observe que la tabla de multiplicaci´n es sim´trica. He aqu´ algunas de las razones por las que las funciones son utiles: ı ´ . tuvimos que cambiar la primera l´ o n a ınea de la funci´n (el encabezado de la funci´n). o 6. 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. mayor) i = i + 1 71 N´tese que al a˜adir un nuevo par´metro. de a o e manera que todas las entradas de la tabla aparecen dos veces.9. a menudo se encuentra con que o el programa resultante tiene capacidades que Usted no pensaba. Para hacerlo. mayor) por imprimeMultiplos(i.

o o bucle infinito: Bucle cuya condici´n de terminaci´n nunca se cumple.10. variable de bucle: Variable que se usa para determinar la condici´n de tero minaci´n de un bucle. puden reutilizarse. 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. 6. a secuencia de escape: Car´cter de escape (\) seguido por uno o m´s caracteres a a imprimibles. que se usan para designar un car´cter no imprimible.72 Iteraci´n o Al dar un nombre a una secuencia de sentencias. 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 o cuerpo: Las sentencias que hay dentro de un bucle. o bucle: Sentencia o grupo de sentencias que se ejecutan repetidamente hasta que se cumple una condici´n de terminaci´n. Una vez escritas y depuradas. Las funciones facilitan tanto la recursividad como la iteraci´n. 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. depurarlas aisladamente. 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). . o Las funciones bien dise˜adas son generalmente utiles para m´s de un pron ´ a grama. hace que su programa sea m´s f´cil de leer y depurar. a a Dividir un programa largo en funciones le permite separar partes del programa. y luego recomponerlas en un todo. 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. a a plan de desarrollo: Proceso para desarrollar un programa. En este cap´ ıtulo. La generalizaci´n hace el c´digo m´s vers´til. y luego encapsularlas y generalizarlas. . m´s apto para reutilio o a a a zarse y algunas veces incluso m´s f´cil de escribir.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). hemos mostrado un estilo de desarrollo basado en desarrollar c´digo para o hacer cosas simples y espec´ ıficas.

.

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

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

u El ejemplo siguiente muestra c´mo usar la concatenaci´n junto a un bucle for o o para generar una serie abeced´rica. escriba una funci´n que tome una cadena como aro gumento y entregue las letras en orden inverso. y Quack. Kack. Lack. . que es el ultimo car´cter de la cadena. Por ejemplo. se asigna a la variable car el siguiente car´cter a de la cadena. Ouack. 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. en el libro e de Robert McCloskey Make Way for Ducklings (Dejad paso a los patitos). El bucle contin´a hasta que no quedan caracteres. porque “Ouack” y “Quack” no est´n a correctamente escritos.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. esto no es del todo correcto. de modo que cuando indice es o igual a la longitud de la cadena. 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. Nack. Mack. la condici´n es falsa y no se ejecuta el cuerpo del o bucle. “Abeced´rica” es la serie o lista en la que a a cada uno de los elementos aparece en orden alfab´tico. 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. ´ a Como ejercicio. los nombres de los patitos son Jack. Pack. una por l´ ınea.

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.78 Como ejercicio.4. Este come ´ portamiento contradice a nuestra intuici´n. 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 llega al final de la o cadena. As´ ı: >>> fruta = "banana" >>> fruta[:3] ’ban’ >>> fruta[3:] ’ana’ ¿Qu´ cree usted que significa s[:]? e 7. Para ver si dos cadenas o son iguales: . incluyendo el primero pero excluyendo el ultimo. Pablo.5. Si omite el segundo ´ ındice. 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”. modifique el programa para corregir este error. Porciones de cadenas Llamamos porci´n a un segmento de una cadena. Comparaci´n de cadenas o Los operadores de comparaci´n trabajan sobre cadenas.

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

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

a o puede encontrar subcadenas. reescriba esta funci´n para que en luo gar de recorrer la cadena. 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. encapsule este c´digo en una funci´n llamada o o cuentaLetras. e o En realidad.9. es lo contario de decrementar.) Al salir del bucle. string. u Como ejercicio. use la versi´n de tres par´metros de o a encuentra del anterior. y general´ ıcela de forma que acepte la cadena y la letra como par´metros. a Como un segundo ejercicio. (Incrementar es aumentar en uno. "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. que es un nombre. El m´dulo “string” o El m´dulo string contiene funciones utiles para manipular cadenas. o cuenta contiene el resultado – el n´mero total de aes.find es m´s general que nuestra versi´n. y sin relaci´n alguna con “excremento”. no s´lo caracteres: o . Para empezar. o o o >>> fruta = "banana" >>> indice = string. Como es o ´ habitual. 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.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. 7. 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. La o o variable cuenta se incializa a 0 y luego se incrementa cada vez que se encuentra una a.7.

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

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

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

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

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

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

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

2. 3. i. 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".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. la lista [1. 3] >>> b = [4. 3. 4. 2. 2. "manzana". 6] De forma similar. . 3. 5. El segundo u ejemplo expresa su entusiasmo por diferentes frutas. 2. 0. Operaciones con listas El operador + concatena listas: >>> a = [1. el operador * repite una lista un n´mero dado de veces: u >>> [0] * 4 [0. 0. "membrillo"]: a print "Me gusta comer " + fruta + "s!" El primer ejemplo imprime todos los n´meros pares entre el 0 y el 19. 0] >>> [1. En el segundo ejemplo. 5. 1. “Para (cada) jinete en (la lista de) a u n jinetes. 2. 2. 3] * 3 [1. imprime (el nombre del) jinete”.8. casi se lee igual que en espa˜ol. a Aqu´ tenemos el bucle anterior con un bucle for: ı for jinete in jinetes: print jinete M´s a´n. 6] >>> c = a + b >>> print c [1.6. 8. 2. 3] En el primer ejemplo la lista [0] contiene un solo elemento que es repetido cuatro veces. 3] se repite tres veces.

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

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

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

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

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

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

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

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

.

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

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

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

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

a actual.800367163582 103 Se supone que los n´meros generados por random est´n distribuidos uniformeu a mente. 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. En la Secci´n 7. 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.810894847068 0.6 Conteo >>> listaAleatorios(8) 0.328578797631 0.360371157682 0.275119183077 0. ıa As´ podemos hacerlo copiando el programa viejo y adapt´ndolo al problema ı. No estamos interesados en encono trar letras. 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. o a El segundo paso es cambiar la comprobaci´n.15156642489 0.759199803101 0.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. u 9.6. lo que significa que cada valor es igualmente probable. a .9.498048560109 0. Esto no cambia el programa. deber´ u ıamos tener m´s o menos el mismo n´mero en todos. s´lo lo hace m´s legible. Eso nos suena. Queremos ver si num est´ entre los valores de minimo y maximo. En este caso. queremos recorrer una lista de n´meros y contar el n´mero de u u veces que un valor cae en un intervalo dado. 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.

5) 0. Empezaremos por solucionar el segundo problema. 0. la anchura de cada balde es 1. cuenta de 1 a numBaldes-1: .25) 0. a def enElBalde(lista. Si se encuentra trabajando en un problema que ya solucion´. 0. 1.5. enElBalde(a.75. minimo. Usaremos un bucle para calcular el intervalo de cada balde. 0. enElBalde(a. enElBalde se hace un tanto dif´ de u ıcil manejar.75) 0. Este plan de desao o rrollo se llama coincidencia de esquemas. La variable del bucle. Si el n´mero de baldes es u numBaldes.0) Hay dos problemas.5. 0.25. 0. 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.7. 0. enElBalde(a. Muchos baldes Tal como aumenta el n´mero de baldes. o o 9. 1) Pero con cuatro baldes ya es aparatoso.5) alto = enElBalde(a. 0. Uno es que tenemos que inventar nuevos nombres de variables para cada resultado. Con dos baldes.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.0. i.0 / numBaldes. ´ o o Los par´metros son la lista y los valores minimo y maximo. balde1 balde2 balde3 balde4 = = = = enElBalde(a. El otro es que tenemos que calcular el intervalo de cada balde.0. reutilice la soluci´n. no est´ mal: a bajo = enElBalde(a.

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

Si multiplicamos un n´mero del intervalo u que va de 0. Con el aumento del n´mero de u baldes.0 a 1. Como el problema es el inverso del anterior. i. y vea o a si el n´mero de valores en cada balde tiende a equilibrarse.8.0 por numBaldes. u 9.0 y hallar el ´ ındice del balde en el que cae. obtenemos un n´mero del intervalo entre u 0. y lo multiplicamos por la anchuraBalde para hallar el l´ ımite inferior de un balde dado. podemos suponer que deber´ ıamos dividir por anchuraBalde en lugar de multiplicar. Una soluci´n en una sola pasada o Aunque este programa funciona. Cada vez ıa que llama a enElBalde recorre la lista entera. u . llega a ser un mont´n de recorridos.0 / numBaldes. 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.0 a 1. En la secci´n anterior tomamos un ´ o ındice. compruebe esta funci´n con listas m´s largas. 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. Como ejercicio. no es tan eficiente como podr´ ser. La suposici´n es correcta. Si redondeamos ese n´mero al entero inferior obtendremos u exactamente lo que estamos buscando.0 y numBaldes. o Ser´ mejor hacer una sola pasada por la lista y calcular para cada valor el ´ ıa ındice del balde en el que cae. Luego podemos incrementar el contador apropiado. 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.106 Tuplas Como ejercicio. Ahora queremos tomar un valor del intervalo 0. o Como anchuraBalde = 1. dividir por anchuraBalde es lo mismo que multiplicar por numBaldes.

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

.

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

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

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.

tambi´n llamado e “asociaci´n”. 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.10. e pista: Almacenamiento temporal de un valor precalculado para evitar c´lculos a redundantes. invocar: Llamar a un m´todo. 117 par clave-valor: Uno de los elementos de un diccionario. e .8 Glosario clave: Un valor que se usa para buscar una entrada en un diccionario. desbordamiento: Un resultado num´rico que es demasiado grande para ree presentarse en formato num´rico.

.

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

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

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

write(texto) f1. readline devuelve una cadena vac´ y readlines devuelve ıa una lista vac´ ıa: >>> print f. Al final del archivo. filtraArchivo hace una copia de archViejo.readlines() [’l´nea dos\012’. la salida est´ en forma de lista. ’l´nea tres\012’] ı ı En este caso.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. El flujo de ejecuci´n pasa al principio del bucle. omitiendo las l´ ıneas que comienzan por #: def filtraArchivo(archViejo. "r") f2 = open(archNuevo. "w") while 1: texto = f1. u .dat". comprueba la condici´n o o y contin´a en consecuencia.close() return La sentencia continue termina la iteraci´n actual del bucle."r") >>> print f. pero sigue haciendo o bucles.122 >>> f = open("test. 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.readlines() [] Lo que sigue es un ejemplo de un programa de proceso de l´ ıneas.close() f2. archNuevo): f1 = open(archViejo.

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

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

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

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

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.11. Si no se produce ninguna excepci´n. Podemos manejar la excepci´n o usando las sentencias try y except. A veces queremos realizar una operaci´n que podr´ provocar una excepci´n.close() . o ıa o pero no queremos que se pare el programa. "r") except: print ’No hay ning´n archivo que se llame’.5 Excepciones Por ejemplo. 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. no queremos que el programa se pare. o nombreArch = raw_input(’Introduce un nombre de archivo: ’) try: f = open (nombreArch. 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. nombreArch u La sentencia try ejecuta las sentencias del primer bloque. pasa por alto la sentencia except. Si el archivo no existe. pero e o la hemos omitido en los ejemplos. o o ejecuta las sentencias de la rama except y despu´s contin´a. Normalmente e Python tambi´n imprime una traza de d´nde se encontraba el programa. Por ejemplo. queremos manejar la excepci´n. podemos preguntar al usuario por el nombre de un archivo y luego intentar abrirlo. Si ocurre cualquier excepci´n.

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

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

.

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

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

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

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

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

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

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

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

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

.

Hora Como otro ejemplo de un tipo definido por el usuario. .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.minutos = 59 hora. escriba una funci´n imprimeHora que acepo te un objeto Hora como argumento y lo imprima en el formato horas:minutos:segundos. o sigue: class Hora: pass Podemos crear un nuevo objeto Hora y asignar atributos para contener las horas.horas = 11 hora. minutos y segundos: hora = Hora() hora. definiremos una clase llamada Hora que registra la hora del d´ La definici´n de la clase es como ıa.1.

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

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

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

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

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

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

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.

1. estas caracter´ ısticas no son necesarias. En su mayor´ proporcionan ıa. De forma similar. una sintaxis alternativa para cosas que ya hemos hecho. 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. y las funciones que operan en ese objeto se corresponden con las formas en que interact´an los objetos del mundo real. lo que signio fica que porporciona caracter´ ısticas que apoyan la programaci´n orientada o a objetos. las clases Punto y Rectangulo se corresponden con los conceptos matem´ticos a de un punto y un rect´ngulo. y la mayor parte de la computaci´n se expresa en t´rminos de o e operaciones sobre objetos. 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. No es f´cil definir la programaci´n orientada a objetos. . u Por ejemplo. Cada definici´n de un objeto se corresponde con un objeto o concepto del o mundo real. 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. pero en muchos casos. Caracter´ ısticas de la orientaci´n a objetos o Python es un lenguaje de programaci´n orientado a objetos. a Hasta ahora. ponden con el tipo de cosas que la gente hace con las horas.Cap´ ıtulo 14 Clases y m´todos e 14.

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

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

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

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

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

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

El segundo par´metro se llama convenientemente otro para distinguirlo e a del mismo (self). casi siempre empezamos escribiendo init . y str . 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. 4)’ Clases y m´todos e Imprimir un objeto Punto invoca impl´ ıcitamente a str sobre el objeto.156 >>> p = Punto(3. otro): return Punto(self. el primer par´metro es el objeto sobre el que se invoca el a m´todo. 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. que facilita el instanciar objetos. Ahora.y) Como es habitual. 11) ..x + otro. cuando apliquemos el operador + a objetos Punto. que casi siempre es util ´ para la depuraci´n.x. a Por ejemplo. o 14. self. Esta caracter´ ıstica se llama sobrecarga de operadores. Python invocar´ a a add : >>> p1 = Punto(3. creamos y devolvemos un nuevo Punto que contiene la suma de las coordenadas x y la suma de las coordenadas y. 7) >>> p3 = p1 + p2 >>> print p3 (8. 4) >>> print p (3. e as´ que definir str tambi´n cambia el comportamiento de print: ı >>> p = Punto(3.8. Es especialmente util cuando definimos nuevos ´ tipos matem´ticos.. 4) >>> p2 = Punto(5. 4) Cuando escribimos una nueva clase. Para sumar dos Puntos. 4) >>> str(p) ’(3.y + otro. ı e ı def __add__(self.

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

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

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

*. 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. que facilitan la programaci´n o orientada a objetos. 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. e polim´rfica: Una funci´n que puede operar sobra m´s de un tipo. como clases definidas por el usuario y herencia. etc. 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. 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. o la funci´n se puede aplicar a ese tipo. imponer: Reemplazar una opci´n por omisi´n. 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. -. >.) de modo que trabajen con tipos definidos por el usuario. sobrecarga de operadores: Ampliar los operadores internos (+. producto interno: Una operaci´n definida en ´lgebra lineal que multiplica o a dos Puntos y entrega un valor num´rico.160 Clases y m´todos e 14. <. o . 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.

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

Una alternativa es usar n´meros enteros para codificar los valores y palos. 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. es obvio qu´ atrie butos deber´ tener: valor y palo. usaremos la instrucci´n: e o tresDeTreboles = Carta(0. Una posibilidad es usar cadenas de caracteres que contengan palabras como "Picas" para los palos y "Reina" para los valores. Son parte del dise˜o del prograo n ma. o sea que podemos comparar los palos al comparar u los n´meros. e . La asociaci´n de los valores es bastante obvia. a Para crear un objeto que representa el 3 de Tr´boles. representa el palo de Tr´boles. 3) El primer argumento.valor = valor Como acostumbramos. 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. 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. valor=0): self. La definici´n de o o clase para el tipo Carta se parecer´ a: a class Carta: def __init__(self. 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. Lo que no es tan obvio es el tipo que se debe ıa dar a los atributos. 0. pero nunca aparecen expl´ ıcitamente en el c´digo fuente.palo = palo self. Con u el t´rmino “codificar” no queremos significar lo que algunas personas pueden e pensar.162 Conjuntos de objetos Si queremos definir un nuevo objeto para representar un naipe. palo=0. proporcionaremos un m´todo de inicializaci´n que toma e o un par´metro opcional para cada atributo. 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”.

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

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

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

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

s es una cadena de caracteres vac´ En cada pasada a trav´s del bucle. y cualquier lugar en el mazo o tiene la misma probabilidad de contener cualquier naipe.7 Barajar el mazo 167 Tercero. Barajar el mazo Si un mazo est´ perfectamente barajado. utilizao mos la funci´n str. 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. A´n cuando los resultados aparecen en 52 renglones. e Finalmente. se ı u trata de s´lo una unica larga cadena de caracteres que contiene los saltos de o ´ l´ ınea. e nueva cadena de caracteres que se concatena con el viejo valor de s para obtener el nuevo valor. en lugar de usar la instrucci´n print para imprimir los naipes. 15. Eso o ta funci´n toma dos enteros como argumentos a y b. El pasar un objeto como argumento a str es equivalente a o invocar el m´todo str sobre dicho objeto. usamos la variable s como acumulador.15. utilizaremos la funci´n randrange del m´dulo random. s contiene la representaci´n completa o en formato de cadena de caracteres del Mazo.7. Inicialmente. cualquier naipe tiene la misma probaa bilidad de aparecer en cualquier posici´n del mazo. se genera una ıa. Cuando el bucle termina. Para mezclar el mazo. y elige un n´mero entero en o u .

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

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

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

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

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

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

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

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

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

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.16. init 177 para la clase ManoDeLaMona.7. a Como el m´todo init se hereda de JuegoDeCartas.append(ManoDeLaMona(nombre)) .eliminaCarta(Carta(0.12)) # construimos una mano para cada jugador self. nombres): # quitamos la Reina de Tr´boles e self.manos = [] for nombre in nombres : self.mazo. JuegoDeLaMona o ı es una subclase de JuegoDeCartas con un m´todo nuevo denominado jugar que e toma una lista de jugadores como par´metro.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. La clase JuegoDeLaMona Ahora podemos poner nuestra atenci´n en el juego en s´ mismo. el nuevo objeto e JuegoDeLaMona contiene un mazo recientemtente mezclado: class JuegoDeLaMona(JuegoDeCartas): def jugar(self. 16.manos.

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

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

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 ----.jugar(["Allen". 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 .Se eliminaron las coincidencias.JuegoDeLaMona() >>> juego.180 Herencia jugadores. >>> import cartas >>> juego = cartas. el juego termina tras siete coincidencias. a n en lugar de veinticinco. el juego comienza.Se han repartido las cartas."Jeff". Con este mazo m´s peque˜o."Chris"]) ----.

. ı o 16.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 ----. Glosario herencia: La capacidad de definir una nueva clase que es una versi´n modifio cada de una clase previamente definida.El juego termin´. a ı La mano de Jeff contiene Reina de Picas La mano de Chris est´ vac´a.8.16. o La mano de Allen est´ vac´a. clase padre: Aquella clase de la cual la clase hija hereda. a ı As´ que Jeff es quien perdi´.

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

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

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

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

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

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

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

podemos cambiar la carga de uno de los nodos.7 Modificar listas 189 17.7.siguiente = None return segundo De nuevo.siguiente # separar el segundo nodo del resto de la lista segundo. .siguiente # hacer que el primer noda apunte al tercero primero. n Como ejemplo. pero las operaciones m´s interesantes son las que a a˜aden. ıa razonable establecer un m´todo para manejar una violaci´n de la condici´n e o o previa.17.siguiente = segundo. Modificar listas Hay dos formas de modificar una lista enlazada. estamos usando variables temporales para hacer m´s legible el c´digo. quitan o reordenan los nodos. Obviamente. 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 ı. 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.

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

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

carga: Datos contenidos en un nodo. A este tipo de requisitos los llamaremos invariantes porque. singleton: Lista enlazada con un solo nodo. idealmente deber´ cumplirse en todos los objetos en todo momento. . o Una cosa que a veces confunde respecto a los invariantes es que en ocasiones son violados. e Si hay alg´n tramo significativo de c´digo en el que el invariante se ve violado. comprobar la integridad de las estructuras de o datos y la detecci´n de errores. Se acepta este tipo de violaci´n. nodo: Elemento de una lista. condici´n previa: Afirmaci´n que debe ser cierta para que un m´todo funcioo o e ne correctamente. Normalmente.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. Por ejemplo. lista enlazada: Estructura de datos que implementa una colecci´n por medio o de una secuencia de nodos enlazados. 17. se exige que todo m´todo que viole un invariante debe restablecerlo. 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 viola el invariante. enlace: Referencia incrustada usada para enlazar un objeto con otro. 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 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. 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. de hecho. u o es importante que los comentarios lo dejen claro. despu´s de a˜adir el nodo e n paro antes de incrementar la longitud. en medio de agregaPrimero.11.

17.11 Glosario 193 envoltorio: M´todo que act´a como mediador entre un m´todo invocador y e u e m´todo ayudante. 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). haciendo a menudo su invocaci´n m´s f´cil o menos e o a a proclive a errores. 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. a .

.

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

el c´digo cliente. 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. . porque el elemento a˜adido en ultimo e n ´ lugar es el primero que extraemos. El TAD Pila En este cap´ ıtulo se presentar´ un TAD com´n.2. first out” en ingl´s). una o implementaci´n es un conjunto de m´todos que satisfacen los prerrequisitos o e sint´cticos y sem´nticos de la interfaz. Un TAD se definido por medio de las operaciones que se pueden ejecutar sobre ´l. El elemento devuelto siempre es el ultimo ´ que se a˜adi´. La interfaz para una pila consta de estas e operaciones1 : init : Inicializar una pila nueva y vac´ ıa. la pila. 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. 18. u Otras colecciones que se han visto son los diccionarios y las listas. lo que se llama un interfaz. Una pila es una colecci´n. n o isEmpty: Probar si la pila est´ vac´ a ıa. o LIFO.3. En general. 18. push: A˜adir un elemento a la pila. 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. a u o lo que significa que es una estructura de datos que contiene elementos m´ltiples. A este programa se lo llama implementaci´n del TAD Pila. el c´digo o o o proveedor. n pop: Extraer un elemento de la pila. La interfaz no es exactamente la que deber´ de ser.196 Pilas Cuando hablamos de TADs a menudo se hace la distinci´n entre el c´digo que o o usa el TAD.

elementos = [] def push(self.elementos. para probar si la pila esta vac´ isEmpty (est´ vac´ compara ıa. ´ Finalmente.4 Uso de push y pop class Pila : def __init__(self) : self. El m´todo de inicializaci´n pone una lista vac´ en elementos. e o ıa Para meter un elemento nuevo en la pila. Uso de push y pop Una pila es una estructura gen´rica de datos. Una implementaci´n como esta. elemento) : self.push(45) s.elementos. 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.18. en la cual los m´todos consisten de llamadas a o e m´todos existentes. pop utiliza el m´todo de lista hom´nimo2 para e o quitar y devolver el ultimo elemento de la lista. push lo apila en elementos. se llama enchapado.push(54) s. El ejemplo mete en la pila dos enteros y una cadena: >>> >>> >>> >>> s = Stack() s.push("+") Se pueden utilizar isEmpty y pop para quitar e imprimir todos los elementos en la pila: 2 del mismo nombre . Para quitar un elemento de la pila.append(elemento) def pop(self) : return self. o a 18. 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. lo significa que se puede a˜adir e n cualquier tipo de elementos a ella. En la vida real.4.elementos == []) 197 Un objeto Pila contiene un atributo llamado elementos que es una lista de elementos en la pila.pop() def isEmpty(self) : return (self. a ıa) elementos con la lista vac´ ıa.

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. e • Si el t´rmino es un operador. • Si el t´rmino es un operando. el operador va despu´s de los operandos.5. El algoritmo de pila hace lo mismo. utilice pop con dos operandos de la pila. Para obtener e el mismo resultado con el formato infijo. ıa Para practicar. o 18. e ejecute la operaci´n sobre ellos. y coloque el resultado en la pila con o push. 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. aplique este algoritmo a la expresi´n 1 2 + 3 *. eval´e los operadores y operandos uno o u por uno. o a Compare estas l´ ıneas con la implementaci´n de imprimeAlReves que vimos o en la Secci´n 17. 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. Ese o a operando es el resultado. A este formato se le llama infijo.198 while not s.4. de esta manera: 1+2. Para practicar. Pilas La salida es + 45 54. En otras palabras. pero fue muy f´cil usar una pila para lograrlo. Con postfijo.isEmpty() : print s.pop(). Cuando llegue al final de la expresi´n habr´ un operando en la pila. ¡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. se tendr´ que escribir (1 + 2) * 3). pero utiliza un objeto Pila o en vez de la pila de tiempo de ejecuci´n. escriba una expresi´n en formato postfijo que sea o equivalente a 1 + 2 * 3. 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. Existe un paralelo natural entre la versi´n recurrente de o o imprimeAlReves y el algoritmo de pila que acabamos de ver. as´ 1 e ı: 2 +. Algunas calculadoras utilizan un formato alternativo llamado postfijo. .

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

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

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

.

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

cabeza == None: # si la lista est´ vac´a el nuevo nodo va el primero a ı 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. carga): nodo = Nodo(carga) nodo.longitud == 0) def inserta(self. n o estaVacia: Comprueba si la cola est´ vac´ a ıa. 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. El m´todo inserta es nuevo y un poco m´s e a .cabeza.cabeza = nodo else: # encuentra el ´ltimo nodo de la lista u ultimo = self.siguiente # a~adir el nuevo nodo n ultimo.cabeza while ultimo.longitud = 0 self.2.longitud = self. n Colas quita: Elimina y devuelve un elemento de la cola.carga self.siguiente = nodo self.longitud + 1 def quita(self): carga = self.siguiente = None if self. El elemento devuelto es el primero que se a˜adi´. 19.204 inserta: A˜ade un elemento a la cola.cabeza.siguiente: ultimo = ultimo.siguiente self. He aqu´ la a ı definici´n de la clase: o class Cola: def __init__(self): self.longitud .cabeza = self.cabeza = None def estaVacia(self): return (self.longitud = self.

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

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

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

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

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

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

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. La parte superior del ´rbol (el nodo al que apunta tree) se llama ra´ Siguiendo a ız. solemos omitir los Nones. 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. Para empeorar las cosas. los nodos de los a ´rboles tambi´n contienen una carga. en el que cada nodo contiene una referencia u a a a otros dos nodos (posiblemente nula).Cap´ ıtulo 20 ´ Arboles Al igual que las listas enlazadas. los ´rboles est´n hechos de nodos. El nodo superior se llama a veces padre y los a a o . los otros nodos se llaman ramas y los nodos de los a a extremos con referencias nulas se llaman hojas. los cient´ ıficos inform´ticos a˜aden a la mezcla otra a n met´fofa: el ´rbol geneal´gico. con la met´fora del ´rbol. Un tipo a a com´n de ´rbol es un ´rbol binario. Como los nodos de las listas. Nombramos a estas referencias como sub´rboles izquierdo y derecho.

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

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

4. ız. lo que significa que tienen exactamente dos operandos. Arbol(’*’.carga. (Todos estos operadores son binarios. porque el contenido de a la ra´ aparece antes del contenido de los hijos. Arbol(2). Arbol(3))) Mirando la figura. Arboles similares se a usan dentro de los compiladores para analizar. El ejemplo de este cap´ a o ıtulo usa ´ ´rboles para traducir expresiones a postfijo. no hay duda del orden de las operaciones. 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.) As´ podemos construir este ´rbol: ı a >>> arbol = Arbol(’+’. 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. Los ´rboles de expresi´n tienen muchos usos. los nodos operadores contienen referencias a sus operandos. 20. prefijo e infijo.derecha) En otras palabras. optimizar y traducir programas.izquierda) imprimeArbol(arbol. Los operandos son nodos hojas. a e a Esta forma de recorrer un ´rbol se llama orden prefijo. Arbol(1). la multiplicaci´n o se realiza antes para calcular el segundo operando de la suma.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 *. imprimeArbol(arbol. La salida del ejemplo anterior ız es: .

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

carga) imprimeArbolSangrado(arbol. a o a o incialmente es 0.izquierda. 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 20. nivel+1) ´ Arboles El par´metro nivel lleva la cuenta de d´nde estamos en el ´rbol. La lista de tokens de (3+7)*9 es: . Por ejemplo.5. ver´ una versi´n simplificada de la figura original. Sangramos cada elemento con dos espacios por nivel. nivel=0): if arbol == None: return imprimeArbolSangrado(arbol.derecha. Cada vez que hacemos una llamada recursiva. El analizador que vamos a escribir maneja expresiones que incluyen n´meros. u par´ntesis y los operadores + y *. 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. Por omisi´n. Suponemos que la cadena de entrada ya ha e sido tokenizada y almacenada en una lista de Python. 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.216 def imprimeArbolSangrado(arbol. nivel+1) print ’ ’*nivel + str(arbol.

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

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

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

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

maneja la expresi´n. 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. En caso contrario. 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 .7 El ´rbol de animales a else: # omitido el resto de la funci´n o 221 La sentencia raise crea una excepci´n. Si la funci´n que llam´ a obtieneNumero. en este caso creamos un nuevo tipo de exo cepci´n. n Pruebe su c´digo con expresiones formadas incorrectamente. a Como ejercicio. llamado ExpresionErronea. o 20. Python imprimir´ un mensaje de a a error y saldr´.20. el o programa podr´ continuar. 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. o o o o alguna de las otras funciones de la pila de llamadas. encuentre otros lugares de estas funciones donde puedan ocurrir errores y a˜ada las sentencias raise adecuadas. El programa interact´a con el usuario para crear un ´rbol de preguntas y nomu a bres de animales. 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.7.

el programa empieza en lo alto del ´rbol y hace la a primera pregunta.tomaCarga() + "? " if si(indicador): arbol = arbol.tomaIzquierda() # intentar adivinar . En ese momento. Entonces a˜ade un nodo al ´rbol n a con la nueva pregunta y el nuevo animal. intenta adivinar.tomaIzquierda() != None: indicador = arbol.tomaDerecha() else: arbol = arbol. Dependiendo de la respuesta. pide al usuario el nombre del nuevo animal y una pregunta que distinga al intento fallido del 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. se mueve al hijo de la izquierda o de la derecha y sigue hasta que llega a un nodo hoja. Si falla. ´ 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.

imprime un indicador y acepta una entrada del o usuario. Si la respuesta comienza con s o S.20. Cuando se a˜ade un nuevo nodo al ´rbol. ¡olvida todo lo que usted le hab´ ıa ense˜ado con tanto cuidado! n Como ejercicio. guiado por las resa puestas del usuario.adivina)) # a~adir informaci´n nueva al ´rbol n o a arbol. al salir. 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.ponDerecha(Arbol(adivina)) La funci´n si es un auxiliar.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.ponIzquierda(Arbol(animal)) arbol. piense en varias formas en las que podr´ guardar el ıa arbol de conocimiento en un archivo. Una carencia del programa es que. la pregunta sustituye a la carga y los n a dos hijos son el animal nuevo y la carga original.ponCarga(pregunta) indicador = "Si el animal fuera un %s. cu´l ser´a la\ a ı respuesta? " if si(indicador % animal): arbol. a a . u El bucle while interno recorre el ´rbol de arriba a abajo.7 El ´rbol de animales a adivina = arbol.ponDerecha(Arbol(animal)) else: arbol. Implemente la que piense que ´ es m´s f´cil. lo que significa que seguir´ hasta que se o a ejecute la sentencia break cuando el usuario ya no piense en ning´n animal.ponIzquierda(Arbol(adivina)) arbol.

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. hijo: Uno de los nodos a los que apunta un nodo. visitando los hijos de cada a nodo antes del propio nodo. o orden prefijo: Una forma de recorrer un ´rbol. operador binario: Un operador que toma dos operandos. ız: a hoja: Un nodo del extremo inferior de un ´rbol. a a luego la ra´ y luego el sub´rbol derecho. orden infijo: Una forma de recorrer un ´rbol. visitando cada nodo antes que a a sus hijos. a . o dos nodos a a dependientes. sin hijos. u nivel: El conjunto de nodos equidistante de la ra´ ız. uno. visitando el sub´rbol izquierdo. 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. Glosario ´rbol binario: Un ´rbol en el que cada nodo apunta a cero. ız. sin padre. ra´ El nodo superior de un ´rbol. hermanos: Nodos que tienen un padre com´n.8.224 ´ Arboles 20. a padre: El nodo que apunta a un nodo dado. orden postfijo: Una forma de recorrer un ´rbol.

muchas veces los mensajes de error no son .Ap´ndice A e Depuraci´n o En un programa pueden suceder varios tipos de error. 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. Normalmente indican que hay algo err´neo en la sintaxis o o del programa. 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. 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). algunas a t´cnicas son aplicables en m´s de una situaci´n. 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. Ejemplo: omitir los dos puntos al final de una sentencia def nos da el mensaje SyntaxError: invalid syntax. e a o A. El primer paso de la depuraci´n es averiguar con qu´ tipo de error se enfrenta. Ejemplo: una expresi´n puede e o no evaluarse en el orden esperado.1. Desgraciadamente. Errores de sintaxis Los errores de sintaxis suelen ser f´ciles de arreglar una vez que averigua a lo que son. algo redundante. dando un resultado inesperado. o e Aunque las secciones que siguen est´n organizadas por 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.

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

Luego a˜ada gradualmente los trozos del programa nuevo n al que funciona. . ¿Qu´ podr´ ir mal? e ıa A.2. puede enfrentarse a ello empezando de nuevo con un programa nuevo como “Hola. 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. Sin no es intencionado.1. decimos que “se ha colgado”. o Si hay un bucle en particular que le resulta sospechoso de provocar el problema. Esto puede ser o intencionado cuando s´lo planea importar el m´dulo para suministrar clases y o o funciones. Si no est´ seguro. no importa lo que haga. Ahora ejecute (o importe) de nuevo.1.2. y asegurarse de que puede hacer que funcione un programa conocido. 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”. Mi programa se cuelga. 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. Vea tambi´n la secci´n o e o “Flujo de Ejecuci´n” m´s adelante. pruebe a poner un error de a a sintaxis obvio y deliberado al principio del programa. o a A. aseg´rese de que est´ llamando a una funci´n que inicie u a o la ejecuci´n. Si el compilador no encuentra el nuevo error probalemente hay algo equivocado en el modo en que est´ configurado su entorno.2. No consigo ejecutar mi programa. Si un programa se para y parece no hacer nada. Errores en tiempo de ejecuci´n o Una vez que su programa es sint´cticamente correcto. a Si esto ocurre. Python pude importarlo a y al menos comenzar a ejecutarlo. A. Si el compilador dice que hay un error pero usted no lo ve.2 Errores en tiempo de ejecuci´n o 227 A.2. podr´ ser porque ıa usted y el compilador no miran el mismo c´digo. mundo”.1.A. 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 ejecute una desde el indicador interactivo.

y podr´ averiguar por qu´ no a a a e se actualizan correctamente. cuando ejecute el programa. e Si eso no funciona. comience a probar otros bucles y otros m´todos y funciones recursivos. es posible que no comprenda el flujo de ejecuci´n de o su programa. y "condici´n: ". podr´ ver los valores de x e y. Vaya a la secci´n “Bucle Infinito” m´s adelante. En otras palabras. Si ocurre eso. 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 o Por ejamplo: while x > 0 and y < 0 : # hacer algo con x # hacer algo con y print print print "x: ". (x > 0 and y < 0) o Ahora. 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”. 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. En la ultima vuelta el valor de la condici´n deber´ ser false. Si el bucle ´ o ıa sigue ejecut´ndose. deber´ a ıa . x "y: ". Si sospecha que una funci´n o un m´todo est´ causando una recursi´n infinita. 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”. Vaya a la secci´n “Flujo de Ejecuci´n” m´s adelante. ver´ tres l´ a ıneas de salida en cada vuelta del bucle. o Si no funciona ninguno de estos pasos. vaya a la secci´n “Recursi´n Infinita” m´s adeo o a lante. o e a o comience por asegurarse de que hay un caso b´sico. o o a Bucle Infinito Si cree que tiene un bucle infinito y piensa que sabe qu´ bucle provoca el proe blema. tiene usted un bucle infinito.228 Depuraci´n o Ejecute el programa. Si obtiene el primer mensaje pero el segundo no.

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

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

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

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

3. en lugar de: return self. Muchas veces encontramos errores cuando estamos lejos del computador y divagamos. Algunos de los mejores lugares para encontrar errores son los trenes. El proe o e grama no s´lo ser´ correcto (en el sentido de hacer lo que usted prentend´ o a ıa). Primero.eliminaCoincidencias() return cant Ahora ya tiene la oportunidad de mostrar el valor de cant antes de regresar. . ¿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.4. las duchas y la cma.pi). 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. piense en el programa. Los computadores emiten unas ondas que afectan al cerebro provocando estos efectos: Frustraci´n y/o furia. puede usar una variable temporal.3. sino que adem´s ser´ m´s legible para otras personas que no hayan memorizado a a a las reglas de precedencia. lev´ntese y d´ un paseo. 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”).manos[i].3 Errores sem´nticos a y = x / (2 * math. Estoy atascado de verdad y necesito ayuda. Si se encuentra afectado por alguno de estos s´ ıntomas. A. Tengo una funci´n o m´todo que no devuelve lo o e que esperaba. 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).3.A. A. 233 Siempre que no est´ seguro del orden de evaluaci´n. Por ejemplo.manos[i]. intente alejarse del computador durante unos minutos.eliminaCoincidencias() podr´ excribir: ıa cant = self. De nuevo. justo antes de quedarse dormido. utilice par´ntesis. a e Cuando est´ calmado.

Lo que necesita es un par de ojos nuevos.234 Depuraci´n o A. o . y usted deber´ estar ı. 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. Antes de llamar a andie. Sucede. aseg´rese de darles la informaci´n u o que necesitan: Si hay un mensaje de error.3. ¿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´. ıa ıa trabajando con la entrada m´ ınima que provoca el error. No.5. el objetivo no es s´lo hacer que el programa funciones. Deber´ tener sentencias ıa print en los lugares adecuados (y lo que dicen deber´ ser comprensible). de verdad necesito ayuda. El objetivo es o aprender c´mo hacer funcionar al programa. Deıa ber´ entender el problema lo bastante bien como para describirlo sucintamente. a Recuerde. Incluso los mejores programadores se atascan de vez en cuando. A veces trabaja durante tanto tiempo en un programa que no puede ver el error. t´mese un momento para pensar acerca de lo que o podr´ haber hecho para encontrarlo m´s r´pido. ser´ capaz de encontrar el error antes. ı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. La siguiente vez que vea algo ıa a a parecido.

o u Al n´mero superior se se le llama numerador y al inferior se se le llama denou minador.numerador = numerador self. Exploraremos esta posibilidad construyendo una clase Fraccion que funcione de manera muy similar a los tipos num´ricos nativos.denominador = denominador El denominador es opcional. numerador. Una Fraccion con un s´lo par´metro representa un o a n´mero entero. son valores que e u pueden expresrse como la proporci´n entre dos n´meros enteros. Las fracciones. enteros largos y flotantes. 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. La forma natural de hacerlo es “numerador/denominador”: .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. e enteros. denominador=1): self. construimos la fracci´n n/1. tal como 5/6. Si el numerador es n. tambi´n conocidas como n´meros racionales. u o El siguente paso es escribir un m´todo str para que imprima las frace ciones de forma que tenga sentido.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

b) else : return a def obtieneSuma(listaToken) : a = obtieneProducto(listaToken) if tomaToken(listaToken. ’)’) # 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 = obtieneSuma(listaToken) return Arbol(’+’.9.C. 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 . a. ’*’) : b = obtieneProducto(listaToken) return Arbol(’*’. b) else : return a 255 def obtieneNumero(listaToken): if tomaToken(listaToken. None) # devuelve una hoja sin el n´mero u C. None. ’(’) : x = obtieneSuma(listaToken) # obtiene subexpresi´n o tomaToken(listaToken. a.9 Adivina el animal return 0 def obtieneProducto(listaToken) : a = obtieneNumero(listaToken) if tomaToken(listaToken.

tomaIzquierda() # intentar adivinar adivina = arbol.10.256 Listados Completos de Python arbol = raiz while arbol.adivina)) # a~adir informaci´n nueva al ´rbol n o a arbol. denominador=1): m = mcd (numerador.ponDerecha(Arbol(adivina)) def si(preg): from string import lower resp = lower(raw_input(preg)) return (resp[0:1] == ’s’) C.tomaIzquierda() != None: indicador = 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.tomaCarga() + "? " if si(indicador): arbol = arbol.ponCarga(pregunta) indicador = "Si el animal fuera un %s.ponIzquierda(Arbol(animal)) arbol. cu´l ser´a la respuesta? " a ı if si(indicador % animal): arbol. denominador) .tomaDerecha() else: arbol = arbol.ponDerecha(Arbol(animal)) else: arbol.ponIzquierda(Arbol(adivina)) arbol. Fraction class class Fraccion: def __init__(self. numerador.

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

.

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

Python tiene varios m´dulos para permitir a los usuarios conectarse a varios motores de bases o de datos.python.ibiblio. y The Linux Cookbook de Michael Stultz. Las bases de datos son un poco como super ficheros en donde los datos est´n almacenados en esquemas predefinidos. a D. u a o enlaces a otros libros y listas de correo de SIGs (Special Interest Group) a las que se puede unir.. a a Kuphaldt. 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. un conjuto de estudios de casos en Python de Chris Meyers. Tambi´n hay m´dua e o los de Python que le permiten acceder a ficheros remotamente v´ ftp. escritos y editados por estudiantes de institulo.260 Lecturas recomendadas La programaci´n web integra Python en la Internet. Python a for Fun. entonces u tiene una idea de lo que los hilos pueden hacer. Por ejemplo. 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.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. Adem´s est´ Lessons in Electric Circuits de Tony R. tanto Open Source como comerciales..org es el lugar para empezar a su b´squeda de material sobre Python. Getting down with . SWIG (Simplified Wrapper and Interface Generator) es una herramienta para hacer este proceso mucho m´s sencillo. a e . Cuando la velocidad es m´s importante se pueden escribir extensiones a para Python en un lenguaje compilado como C o C++. Encontrar´ ayuda. y ıa m´dulos que le permiten enviar y recibir correos electr´nicos. un conjunto de tutoriales de varios temas sobre inform´tica. 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.1. Tales extensiones forman la base de la mayor´ de m´dulos en la librer´ de Python. con 300 p´ginas de trucos y t´cnicas. ıa o ıa El mecanismo de enlazar funciones y datos es un poco complejo.. 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. y las relaciones entre los a datos le permiten acceder a ellos de varias maneras. El proyecto Open Book Project www. documentaci´n. La programaci´n multi-procesos (multi-hilos) le permite ejecutar varios o procesos (hilos) de ejecuci´n dentro de un unico programa.

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. Python Essential Reference de David M. sin nada de Python. sino tambi´n depurao e ci´n. 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.000 resultados.2.D. ıa a e a Python Pocket Reference de Mark Lutz realmente cabe en el bolsillo.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. e incluso utiliza Python para escribir scripts para aplicaciones tales como Word y Excel. La segunda parte proporciona una introducci´n paso o a paso a temas m´s avanzados incluyendo muchos de los mencionados a anteriormente. Libros recomendados sobre inform´tica en a general Las siguientes sugerencias sobre lecturas adicionales incluyen muchos de los libros favoritos de los autores. m´s de 750 a p´ginas. Entre otras cosas cubre la integraci´n de Python y COM. . Aunque no es tan extensivo como Python Essential Reference es una referencia util para los m´dulos y funciones m´s comunmente usadas. D. Los ejemplos est´n o a principalmente en C++ y Java. La primera parte del libro cubre las caracter´ a ısticas b´sicas del a lenguaje Python. n pero contiene informaci´n sobre el lenguaje en s´ mismo y los m´dulos de o ı o la librer´ est´ndar. Tambi´n est´ muy bien indexado. Mark Lutz ´ o a tambi´n es autor de Programming Python. a Su siguiente libro Learning Python es m´s peque˜o y m´s accesible. uno de los primeros (y m´s e a largos) libros de Python y no est´ dirigido al programador principiante. Estos tratan sobre buenas pr´cticas de prograa maci´n e inform´tica en general. construye una peque˜a aplicaci´n con o n o wxPython. 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. Beazley es un libro peque˜o. testeo y mejora de rendimiento de los programas.

comentarios e indentaci´n (un poco irrelevante en Python). Ambos libros son o ricas fuentes de ideas para proyectos. usando aserciones para encontrar los errores o probando precondiciones y postcondiciones. a por lo que los ejemplos est´n en lenguajes m´s antiguos. algunos con soluciones y otros con pistas. las ilustraciones de Escher u y el teorema de incompletitud de G¨del. Programas similares pueden escribirse en Python usando gr´ficos e hilos. o The New Turing Omnibus de A. o Programming Pearls de Jon Bentley es un libro cl´sico. 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. Tortugas. desde TACs (tomograf´ computerizadas) hasta a ıas algoritmos gen´ticos. a o tales como el buen uso de las convenciones de nombres. que suelen ser intuitivos. Consiste en esa tudios de caso que aparecieron originalmente en la columna del autor en Communications of the ACM. Todos los temas son cortos y entretenidos. 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. o . El libro tambi´n cubre la o e programaci´n por contrato. Simplemente. 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.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. La ejecuci´n del programa demuestra o comportamientos complejos agregados. El demuestra tales patrones en la m´sica de Bach. 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. y programaci´n correcta con o hilos y su sincronizaci´n. El libro es un poco m´s antiguo que los anteriores (1986). Bach de Douglas Hofstadter. 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. Introduce el lenguaje StarLogo. La mayor´ de los programas en el libro fueron desarrollados por estudiantes ıa de colegio e instituto.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. Este libro fue muy popular y le sigui´ un segundo volumen. a G¨del. si encuentra o magia en la recursi´n tambi´n la encontrar´ en este libro superventas. Escher. que permite al usuario escribir programas para agentes. Hay muchos proa a blemas para resolver.

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

or of legal. 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. 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 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. as being those of Invariant Sections. 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. it can be used for any textual work. or political position regarding them. commercial. regardless of subject matter or whether it is published as a printed book.” below. represented in a format whose specification is available to the general public. a Secondary Section may not explain any mathematics. as FrontCover Texts or Back-Cover Texts. Any member of the public is a licensee.1.) The relationship could be a matter of historical connection with the subject or with related matters. and is addressed as “you. We recommend this License principally for works whose purpose is instruction or reference. refers to any such manual or work. if the Document is in part a textbook of mathematics.264 GNU Free Documentation License License is not limited to software manuals. A “Transparent” copy of the Document means a machine-readable copy.” A “Modified Version” of the Document means any work containing the Document or a portion of it. in the notice that says that the Document is released under this License. The “Cover Texts” are certain short passages of text that are listed. philosophical. 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. The “Invariant Sections” are certain Secondary Sections whose titles are designated.” . either copied verbatim. ethical. (For example. The “Document. E. in the notice that says that the Document is released under this License. A copy that is not “Transparent” is called “Opaque.

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful