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

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

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

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. 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. ı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 ı. dirigi´ndoe les m´s all´ de donde yo pod´ llevarles. Como pod´ hacer cambios instant´neos cuando alguien encontraba ıa a un error ortogr´fico o un pasaje dif´ a ıcil. o n o . n el proceso. a a Para la segunda mitad del libro. 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. 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. 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. 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.ibiblio. Python simplifica enormemente los ejemplos de programaci´n y facilita la ense˜anza de los conceptos importantes en programaci´n. Oregon. o n en Eugene. 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. 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. y empez´ a colaborar con ´l inmediatamente. acerca de la programaci´n orientada a objetos. o o Recib´ un correo electr´nico de Chris Meyers expresando su inter´s en el liı o e bro.ix partir de ´l me hizo posible hacerlo. La perspectiva de impartir el curso llev´ a Chris haso ta el libro.

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

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

com. escriban a los autores a feedback@thinkpython. Virginia . Por favor.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. Jeffrey Elkner Escuela Secundaria Yortown Arlington.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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. traza inversa: (traceback en ingl´s) Una lista de las funciones en curso de e ejecuci´n. presentadas cuando sucede un error en tiempo de ejecuci´n. o o notaci´n de punto o traza inversa . variable local: variable definida dentro de una funci´n. o o diagrama de pila: Representaci´n gr´fica de una pila de funciones.3. sus variao a bles y los valores a los que se refieren. Las variables locales o s´lo pueden usarse dentro de su funci´n.

.

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

que es una vez 0!. normalmente podr´ escribir o a un programa de Python para evaluarlo. Puesto que 2 no es 0. 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. Si puede escribir una definici´n recursiva de algo.. Puesto que 1 no es 0. que es 2 veces 1!.54 Funciones productivas 0! = 1 n! = n · (n − 1)! Esta definici´n establece que el factoral de 0 es 1. 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. 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. es n multiplicado por el factorial de n − 1. As´ pues. 3! es igual a 3 veces 2 veces 1 vez 1. Puesto que 0 es 0. . Si llamamos a factorial con el valor 3: o Puesto que 3 no es 0. El primer paso es decidir cu´les son los a par´metros para esta funci´n. tomamos la primera rama y devolvemos el valor 1 sin hacer m´s llamadas rea cursivas.. Junt´ndolos todos. 3! es 3 veces 2!. ı a .. y he aqu´ la parte interesante. n. 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. que es 6.9....

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

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

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

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

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

.

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. y la segunda vez su valor es 7. es tentador interpretar una o sentencia como a = b como sentencia de igualdad. 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. ya que la primera vez que imprimimos bruno su valor es 5. = 7 bruno La salida del programa es 5 7.Cap´ ıtulo 6 Iteraci´n o 6. 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.1. 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. bruno print bruno print = 5 bruno. Puesto o que Python usa el s´ ımbolo = para la asignaci´n. Pero no lo es. . es especialmente importante u distinguir entre una sentencia de asignaci´n y una sentencia de igualdad.

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

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

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

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

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

o o cuerpo: Las sentencias que hay dentro de un bucle.10. o Las funciones bien dise˜adas son generalmente utiles para m´s de un pron ´ a grama. Las funciones facilitan tanto la recursividad como la iteraci´n. o bucle: Sentencia o grupo de sentencias que se ejecutan repetidamente hasta que se cumple una condici´n de terminaci´n. 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. 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). que se usan para designar un car´cter no imprimible. nueva l´ ınea: Un car´cter especial que hace que le cursor se mueva al inicio de a la siguiente l´ ınea.72 Iteraci´n o Al dar un nombre a una secuencia de sentencias. depurarlas aisladamente. hace que su programa sea m´s f´cil de leer y depurar. Una vez escritas y depuradas. variable de bucle: Variable que se usa para determinar la condici´n de tero minaci´n de un bucle. 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. 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. . y luego recomponerlas en un todo. puden reutilizarse. a a Dividir un programa largo en funciones le permite separar partes del programa. cursor: Un marcador invisible que sigue el rastro de d´nde se imprimir´ el o a siguiente car´cter. 6. a secuencia de escape: Car´cter de escape (\) seguido por uno o m´s caracteres a a imprimibles. o o bucle infinito: Bucle cuya condici´n de terminaci´n nunca se cumple.

hemos mostrado un estilo de desarrollo basado en desarrollar c´digo para o hacer cosas simples y espec´ ıficas.6. m´s apto para reutilio o a a a zarse y algunas veces incluso m´s f´cil de escribir. y luego encapsularlas y generalizarlas. 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.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).

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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. Conteo Un buen enfoque sobre problemas como ´ste es dividir el problema en subproe blemas que encajen en un esquema computacional que hayamos visto antes. a .360371157682 0. u 9. queremos recorrer una lista de n´meros y contar el n´mero de u u veces que un valor cae en un intervalo dado.498048560109 0.800367163582 103 Se supone que los n´meros generados por random est´n distribuidos uniformeu a mente. deber´ u ıamos tener m´s o menos el mismo n´mero en todos. Eso nos suena.6 Conteo >>> listaAleatorios(8) 0. Esto no cambia el programa. En este caso. Queremos ver si num est´ entre los valores de minimo y maximo. lo que significa que cada valor es igualmente probable.275119183077 0.328578797631 0. No estamos interesados en encono trar letras.6. En la Secci´n 7.15156642489 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.9. ıa As´ podemos hacerlo copiando el programa viejo y adapt´ndolo al problema ı. 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. a actual. s´lo lo hace m´s legible.759199803101 0. 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. o a El segundo paso es cambiar la comprobaci´n.810894847068 0.

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

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

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

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

.

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

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

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.

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

.

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

.

o sigue: class Hora: pass Podemos crear un nuevo objeto Hora y asignar atributos para contener las horas. 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. Hora Como otro ejemplo de un tipo definido por el usuario.horas = 11 hora. .1.minutos = 59 hora.segundos = 30 El diagrama de estado del objeto Hora es as´ ı: time hour minute second 11 59 30 A modo de ejercicio.Cap´ ıtulo 13 Clases y funciones 13. escriba una funci´n imprimeHora que acepo te un objeto Hora como argumento y lo imprima en el formato horas:minutos:segundos.

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

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

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

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

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

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

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. a o . algoritmo: Un conjunto de instrucciones para solucionar una clase de problemas por medio de un proceso mec´nico sin intervenci´n de inteligencia.

una sintaxis alternativa para cosas que ya hemos hecho. no nos hemos aprovechado de las caracter´ ısticas que Python nos ofrece para dar soporte a la programaci´n orientada a objetos. No es f´cil definir la programaci´n orientada a objetos. pero ya hemos visto a o algunas de sus caracter´ ısticas: Los programas se hacen a base de definiciones de objetos y definiciones de funciones. Caracter´ ısticas de la orientaci´n a objetos o Python es un lenguaje de programaci´n orientado a objetos. 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. De forma similar. ponden con el tipo de cosas que la gente hace con las horas. En su mayor´ proporcionan ıa. . Cada definici´n de un objeto se corresponde con un objeto o concepto del o mundo real.Cap´ ıtulo 14 Clases y m´todos e 14.1. a Hasta ahora. estas caracter´ ısticas no son necesarias. 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. Hablando estrico tamente. y las funciones que operan en ese objeto se corresponden con las formas en que interact´an los objetos del mundo real. pero en muchos casos. u Por ejemplo. y la mayor parte de la computaci´n se expresa en t´rminos de o e operaciones sobre objetos.

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

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

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

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

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

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

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

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

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

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

e polim´rfica: Una funci´n que puede operar sobra m´s de un tipo. <. -. o la funci´n se puede aplicar a ese tipo. >. programaci´n orientada a objetos: Un estilo de programaci´n en el que los o o datos y las operaciones que los manipulan est´n organizadas en clases y a m´todos.160 Clases y m´todos e 14. como clases definidas por el usuario y herencia. *. 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. que facilitan la programaci´n o orientada a objetos. Glosario lenguaje orientado a objetos: Un lenguaje que ofrece caracter´ ısticas. 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 . sobrecarga de operadores: Ampliar los operadores internos (+.) de modo que trabajen con tipos definidos por el usuario. imponer: Reemplazar una opci´n por omisi´n. etc. producto interno: Una operaci´n definida en ´lgebra lineal que multiplica o a dos Puntos y entrega un valor num´rico. Si todas las o o a operaciones realizadas dentro de una funci´n se pueden aplicar a un tipo.10. 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. 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

siguiente # separar el segundo nodo del resto de la lista segundo. quitan o reordenan los nodos.siguiente = segundo. 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.7. Obviamente. Modificar listas Hay dos formas de modificar una lista enlazada. podemos cambiar la carga de uno de los nodos.siguiente = None return segundo De nuevo. 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 ı. n Como ejemplo.17. 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. .7 Modificar listas 189 17. estamos usando variables temporales para hacer m´s legible el c´digo.siguiente # hacer que el primer noda apunte al tercero primero.

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

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

singleton: Lista enlazada con un solo nodo.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. Glosario referencia incrustada: Es una referencia almacenada en un atributo de un objeto. e Si hay alg´n tramo significativo de c´digo en el que el invariante se ve violado. Por ejemplo. . carga: Datos contenidos en un nodo. 17. comprobar la integridad de las estructuras de o datos y la detecci´n de errores. se viola el invariante. enlace: Referencia incrustada usada para enlazar un objeto con otro. idealmente deber´ cumplirse en todos los objetos en todo momento. 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. A este tipo de requisitos los llamaremos invariantes porque. en medio de agregaPrimero. Se acepta este tipo de violaci´n. lista enlazada: Estructura de datos que implementa una colecci´n por medio o de una secuencia de nodos enlazados. normalmente implementado como un objeto que contiene una referencia a otro objeto del mismo tipo. de modo que no se realicen operaciones que dependan del invariante. despu´s de a˜adir el nodo e n paro antes de incrementar la longitud. nodo: Elemento de una lista. 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. condici´n previa: Afirmaci´n que debe ser cierta para que un m´todo funcioo o e ne correctamente. a menudo es imposible modificar un objeto sin violar un o invariante durante al menos un corto espacio de tiempo.11. Normalmente. o Una cosa que a veces confunde respecto a los invariantes es que en ocasiones son violados.

11 Glosario 193 envoltorio: M´todo que act´a como mediador entre un m´todo invocador y e u e m´todo ayudante. haciendo a menudo su invocaci´n m´s f´cil o menos e o a a proclive a errores. e o invariante: Afirmaci´n que deber´ ser cierta para un objeto en todo momento o ıa (excepto tal vez cuando se est´ modificando el objeto). a .17. 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.

.

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Entonces a˜ade un nodo al ´rbol n a con la nueva pregunta y el nuevo animal.222 Est´s pensando en un animal? n a Este es el ´rbol que construye este di´logo: a a ´ Arboles Can it fly? n Does it bark? n cat y dog y bird Al principio de cada ronda. pide al usuario el nombre del nuevo animal y una pregunta que distinga al intento fallido del nuevo animal. ´ 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. el programa empieza en lo alto del ´rbol y hace la a primera pregunta. intenta adivinar.tomaDerecha() else: arbol = arbol. Si falla.tomaIzquierda() # intentar adivinar . En ese momento.tomaCarga() + "? " if si(indicador): arbol = arbol.tomaIzquierda() != None: indicador = arbol. se mueve al hijo de la izquierda o de la derecha y sigue hasta que llega a un nodo hoja. Dependiendo de la respuesta.

7 El ´rbol de animales a adivina = arbol. Si la respuesta comienza con s o S.20. imprime un indicador y acepta una entrada del o usuario.adivina)) # a~adir informaci´n nueva al ´rbol n o a arbol. Una carencia del programa es que. Cuando se a˜ade un nuevo nodo al ´rbol. guiado por las resa puestas del usuario.ponIzquierda(Arbol(adivina)) arbol. al salir.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. 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(animal)) arbol. la pregunta sustituye a la carga y los n a dos hijos son el animal nuevo y la carga original. cu´l ser´a la\ a ı respuesta? " if si(indicador % animal): arbol.ponDerecha(Arbol(adivina)) La funci´n si es un auxiliar. la funci´n devuelve verdadero: o def si(preg): from string import lower resp = lower(raw_input(preg)) return (resp[0] == ’s’) La condici´n del bucle externo es 1. ¡olvida todo lo que usted le hab´ ıa ense˜ado con tanto cuidado! n Como ejercicio. u El bucle while interno recorre el ´rbol de arriba a abajo. piense en varias formas en las que podr´ guardar el ıa arbol de conocimiento en un archivo. a a .ponDerecha(Arbol(animal)) else: arbol.ponCarga(pregunta) indicador = "Si el animal fuera un %s.

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

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

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

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

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

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

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

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

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

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

ser´ capaz de encontrar el error antes. Sucede. Deıa ber´ entender el problema lo bastante bien como para describirlo sucintamente. aseg´rese de darles la informaci´n u o que necesitan: Si hay un mensaje de error. ıa Cuando llame a alguien para que le ayude. La siguiente vez que vea algo ıa a a parecido. o . A veces trabaja durante tanto tiempo en un programa que no puede ver el error. a Recuerde. El objetivo es o aprender c´mo hacer funcionar al programa. No. aseg´rese de que ha agotado las t´cnicas explicadas u e aqu´ Su programa deber´ ser tan simple como sea posible.5. Antes de llamar a andie. 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).234 Depuraci´n o A. 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. Incluso los mejores programadores se atascan de vez en cuando.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. t´mese un momento para pensar acerca de lo que o podr´ haber hecho para encontrarlo m´s r´pido. de verdad necesito ayuda. Lo que necesita es un par de ojos nuevos.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful