.)■>! » 1 t, va lo t-g e ia á a W y i *et&kie
*
lu ía Nwnfter:/ P om po ec 1
FIGURA 9.5
Visualización de la variable v a lo r en la función crearAtardecerQ con el Vigilante.
cuando el Vigilante se ejecute, aparecerá el valor de la variable junto con la línea. También podrá ver cuando la variable todavía no tenga un valor (figura 9.5).
9.4.3 Depuración del juego de aventuras Vamos a usar algunas de estas técnicas con el juego de aventuras. El problema que tenemos con el juego de aventuras es que ¡básicamente funciona! No se generan mensajes obvios de error. Al pasar por nuestro proceso de prueba, pudimos descubrir que no estábamos m ane jando bien las entradas inválidas. ¿Qué más podría ser un problema? Veamos lo que ocurre al ejecutar el programa: » > ju g a rJu e g o () ¡Bienvenido a l a casa de aven tu ra¡ En cada saló n le in d ica re n o s h a cia dónde puede i r . Puede avanzar h a cia e l n o rte , s u r , e ste u o e s te , e scrib ie n d o esa d ire c c ió n . E s c rib a ayuda para v o lv e r a m ostrar e s ta in tro d u c c ió n . E s c rib a te rm in a r o s a l i r para te rm in a r e l programa. Usted e stá en e l porche de una e s c a lo fr ia n t e c a sa . Las ventanas están ro ta s . Es una noche o scura y tempestuosa. Puede i r h a cia e l norte y e n tra r en l a c a sa . Si se a tre v e . Usted e s tá en e l re c ib id o r de l a c a s a . Hay te la ra ñ a s en e l rin c ó n . De pronto tie n e una sensación de temor. Hay un p asaje h a cia el norte y o tro h a cia e l e s te . E l porche queda d e trá s de usted h a cia e l s u r . Usted se encuentra en una s a la de e s t a r . Hay s o fá s , s i l l a s y mesas pequeñas. Todo e stá c u b ie rto con polvo y t e la r a ñ a s .
Sección 9.4
T ip s sobre depuración
23 3
De rep ente, escucha un ruido estremecedor en o tro s a ló n . Puede i r h a cia e l norte o h a cia e l o e ste . Usted e stá en e l comedor. Hay re sto s de una comida en l a mesa. No puede id e n t if i c a r lo que e s , y t a l vez no q u ie ra h a c e rlo . ¿Acaso se escuchó un golpe pro veniente del oeste? Puede i r h a cia e l su r o h a cia e l oeste Usted e stá en l a c o c in a . Todas la s s u p e r fic ie s e stán c u b ie rta s con o l l a s , s a rte n e s , pedazos de comida y charcos de sangre. Cree escuchar algo proveniente de la s e s c a le ra s que van h a cia e l lado o este del c u a rto . Se escucha que algo rasp a, como s i se a r r a s t r a r a por e l p is o . Puede i r h a cia e l su r o e l e s te . ¡A d ió s!
¿Qué está mal en el código anterior? He aquí dos problemas que tenemos con esa impresión: 1. Es bastante difícil distinguir un salón del otro. Las descripciones de los salones se con funden unas con otras. 2. No podemos regresar y ver qué escribimos en cada paso anterior. Si fuera un gran mapa con muchos salones, sería conveniente poder regresar y ver qué escribimos antes para ir a distintos salones. Vamos a solucionar el primer problema. Necesitamos que aparezca algún tipo de espacio o separador entre las descripciones de cada salón. ¿En dónde colocamos esa instrucción? Sin duda, tiene que ser dentro del ciclo principal de nivel superior. Podría ir dentro de la función mostrar Salón, tal vez como la primera línea. O podría ir en la función de nivel superior, justo antes o después de mostrar el salón. Tomando en cuenta que es mejor realizar modifi caciones de los detalles en las subfunciones, vamos a cambiar mostrar Salón.
Programa 88: función n o strarS alo n mejorada para el juego de aventuras
def m o s tra rS a lo n (s a lo n ): p ri ntNow("===========") i f saló n == "Po rch e ": m ostrarPorcheO i f saló n == "R e c ib id o r" : m o stra rR e c ib id o r() i f saló n == "C o cin a ": m o strarC ocinaO i f saló n == " S a la D e E s ta r": m ostrarSEO i f saló n == "Comedor": mostrarComedorO
■ Ahora vamos a lidiar con el segundo problema. Debemos im prim irlo que escribió el juga dor. Tenemos que hacer esto después de la llamada a requestStri ng. De nuevo, este cambio podría estar en el ciclo de nivel superior o al principio de el egi rSal on. Ambas opciones po drían funcionar. Esta vez vamos a tomar la otra opción. La función el egi rSal on ya es de por sí bastante complicada. Vamos a responder justo después de que el jugador haga su elección.
234
Capítulo 9
Creación de program as más grandes
Programa 89: función jugarDuego mejorada para el juego de aventuras
d e f ju g a rJu e g o O : ub icació n = "Porche" m o stra rln tro d u c c io n O w h ile not (u b ica ció n == " S a l i r " ) : m o stra rS a lo n (u b ica ció n ) d ire c c ió n = re q u e stS trin g ("¿ C u á l d ire c c ió n ? " ) printNow("Usted e s c r ib ió : "+ d ire c cio n ) u b icació n = e le g irS a lo n (d ire c c io n , u b ica ció n )
Ahora podemos probar nuestro programa depurado. » > jugarJuego O ¡Bienvenido a l a casa de aven tu ra¡ En cada salón le in d ica re n o s h a cia dónde puede i r . Puede avanzar h a cia e l n o rte , s u r , e ste u o e ste , e sc rib ie n d o esa d ire c c ió n . E s c rib a ayuda para v o lv e r a m ostrar e s ta in tro d u c c ió n . E s c rib a te rm in a r o s a l i r para te rm in a r e l programa. Usted e s tá en e l porche de una e s c a lo fr ia n t e c a sa . Las ventanas están ro ta s . Es una noche o scura y tempestuosa. Puede i r h a cia e l norte y e n tra r en l a c a s a . Si se a tre v e . Usted e s c r ib ió : norte Usted e stá en e l re c ib id o r de l a c a s a . Hay te la ra ñ a s en el rin c ó n . De pronto tie n e una sensación de temor. Hay un p asaje h a cia el norte y o tro h a cia e l e s te . E l porche queda d e trá s de usted h a cia e l s u r. Usted e s c r ib ió : este Usted se encuentra en una s a la de e s t a r . Hay s o fá s , s i l l a s y mesas pequeñas. Todo e stá c u b ie rto con polvo y te la r a ñ a s . De rep ente, escucha un ruido estremecedor en o tro s a ló n . Puede i r h a cia e l norte o h a cia e l o e ste . Usted e s c r ib ió : norte Usted e stá en e l comedor. Hay re sto s de una comida en l a mesa. No puede id e n t if i c a r lo que e s , y t a l vez no q u ie ra h a c e rlo . ¿Acaso se escuchó un golpe pro veniente del oeste? Puede i r h a cia e l su r o h a cia e l oeste Usted e s c r ib ió : oeste Usted e s tá en l a c o c in a . Todas la s s u p e r fic ie s e stán c u b ie rta s con o l l a s , s a rte n e s , pedazos de comida y charcos de sangre.
Sección 9.5
A lgoritm os y diseño
23 5
Cree escuchar algo proveniente de la s e s c a le ra s que van h a cia e l lado o este del c u a rto . Se escucha que algo rasp a, como s i se a r r a s t r a r a por e l p is o . Puede i r h a cia e l su r o e l e s te . Usted e s c r ib ió : su r Usted e stá en e l re c ib id o r de l a c a sa . Hay te la ra ñ a s en e l rin c ó n . De pronto tie n e una sensación de temor. Hay un p asaje h a cia el norte y o tro h a cia el e ste . E l porche queda d e trá s de usted h a cia e l s u r . Usted e s c r ib ió : s a l i r ¡A d ió s!
ALGORITMOS Y DISEÑO Los algoritmos son descripciones generales de procesos que pueden implementarse en cual quier lenguaje de programación específico. El conocimiento de los algoritmos es una de las opciones en las cajas de opciones de los programadores profesionales. Hemos visto varios algoritmos hasta ahora: • El algoritmo de muestreo es un proceso que puede usarse para desplazar la frecuencia de un sonido hacia arriba o hacia abajo, o para aumentar o reducir la escala de una imagen. No tenemos que hablar sobre los ciclos ni sobre incrementar índices de origen o de destino para describir el algoritmo de muestreo. Éste funciona modificando la forma en que copiamos muestras o píxeles de un origen a un destino; en vez de tomar cada muestra o pixel, tomamos una de cada dos muestras/pixeles o cada muestra/pixel dos veces, o usamos algún otro patrón de muestreo. • También vimos cómo copiar píxeles o muestras de un origen a un destino. Sólo tene mos que saber en dónde nos encontramos tanto en el origen como en el destino. • Vimos además que mezclar es en esencia lo mismo para píxeles que para muestras. Aplicamos una ponderación a cada uno de los píxeles o muestras a sumar y después su mamos los valores ponderados para crear un sonido mezclado o una imagen mezclada. El rol de los algoritmos en el diseño es permitirnos abstraer una descripción del programa que vamos a diseñar, a un nivel por encima del código básico del programa. Los programadores profesionales conocen muchos algoritmos; esto les permite pensar en los problemas de diseño de los programas en un nivel más alto. Podemos hablar sobre negación de imágenes y cómo reflejar las imágenes negadas sin tener que hablar sobre ciclos ni índices de origen o de destino. Podemos enfocarnos en nombres más abstractos como “reflejar” sin enfocarnos en el código. Los programadores también saben mucho sobre los algoritmos que conocen. Saben cómo hacer los algoritmos eficientes, cuándo no son útiles y cuáles podrían ser las dificultades de éstos. Por ejemplo, sabemos que al aplicar una escala a un sonido, debemos tener cuidado de no traspasar los límites de éste. Hay algoritmos mejores y peores, en términos de la rapidez con la que se ejecutan y qué tanta memoria requieren. En el capítulo 13 hablaremos más sobre la velocidad de los algoritmos. En este programa tomamos decisiones que podrían haber sido diferentes. Por ejemplo, describimos los salones y la forma en que se conectan entre sí en el código del programa.
236
Capítulo 9
Creación de program as más grandes
Podríamos haber guardado las descripciones como cadenas en variables. Incluso podríamos haber usado algunas otras estructuras de datos, como arreglos y secuencias, para describir la forma en que se conectan los salones entre sí. El programa tendría entonces una apariencia muy distinta. Hubiera procesado los datos en las variables más que describir los salones en sí. Al proceso de realizar elecciones entre distintas formas de escribir un programa se le conoce como diseñar el programa. Podemos pensar en el diseño del programa (esto es, las posibles decisiones además de sus fortalezas y debilidades) de una manera totalmente sepa rada del código del programa en sí.
9.6
EJECUCIÓN DE PROGRAMAS FUERA DE JES Los programas en Python pueden ejecutarse de muchas formas. Si crea programas más gran des y complejos, será conveniente poder ejecutarlos fuera de JES. Lo que usted aprenda en este libro podrá usarlo directamente en Python (o Jython). Los comandos como for y pri nt funcionan en Python y en Jython. Las bibliotecas del sistema como ftplib y urllib son idénticas en Python y Jython. Sin embargo, las herram ientas de medios que usamos no están integradas en Python ni en Jython. Es posible usar las bibliotecas de medios en Python. Hay implementaciones de Python como M yro (http://myro.roboteducation.org) que incluyen las mismas funciones de imágenes que en JES. También está la Biblioteca de imágenes de Python (PIL) que proporciona una funcionalidad similar, con funciones que tienen nombres dife rentes. Usted puede usar en Jython las bibliotecas que proporcionamos en este libro. Jython está disponible en http://www.jython.org para la mayoría de los sistemas de computadora. Nuestras bibliotecas de medios funcionan en Jython con sólo unos cuantos comandos adicio nales. La figura 9.6 muestra el uso de la biblioteca de medios en Jython en Linux. He aquí cómo hacemos que las funciones de medios funcionen en Jython tradicional. • Para buscar los módulos a importar m ediante import, Python usa una variable lla mada sys.path (de la biblioteca de sistema integrada sys) que contiene una lista de todos los directorios en donde debe buscar los módulos. Si usted quiere usar la biblioteca de medios de JES en Jython, necesita poner la ubicación de esos archivos de módulos en su variable sys. path (esto es lo que setLibPath hace por usted en JES). Necesita la instrucción import sys para tener acceso a la variable sys.path. I&ra manipular esa variable usamos el método insert, el cual coloca el directorio Sources de JES en su ruta (vea la figura 9.6). En equipos Macintosh hay que hacer referencia al código de Java y Jython dentro de la aplicación de JES, escribiendo algo como sys.path.insert (0,”/users/guzdial/JES.app/Contents/Resources/Java”). • Después necesitamos la instrucción from media import * para que las funciones como pickAFile y makePi cture estén disponibles en Jython. Cabe mencionar que la instrucción from media import * se inserta (lo cual es invisible para usted, el programador estudiante) en su área de programa cada vez que presiona el botón L o a d (Cargar). A sí es como las funciones especiales de medios de JES se ponen a disposición de sus programas.
Sección 9.6
Eile fcdit yiew Jerminal
Ejecución de program as fuera de J E S
23 7
Tafcs tlelp
g u zd ial@ g u zd ia l-la p to p :-S jython Jython 2 .2 .1 on ja v a l.6 .0 _ 0 7 Type "c o p y rig h t" , " c r e d it s " o r " lic e n s e " fo r more In fo rm atio n . » > import sys » > sys.path.insert(0,"/media/WORKINGDOCS/jes-3*1-1/Sources") » > from media import • > » p = m a k e P ic tu re (p ic k A F ile ()) » > show(p) » > show(p)
FIGURA 9.6 Uso de Jython para ejecutar funciones de medios fuera de JE S en Linux.
A continuación le mostramos cómo se genera la imagen de la figura 9.6 desde Linux: guzdial@ guzdial - la p to p :~ \$ jytho n Jython 2 .2 .1 on ja v a l.6 .0 _ 0 7 Type "c o p y rig h t" , " c r e d it s " or " lic e n s e " fo r more in fo rm a tio n . » > im port sys » > s y s . p ath . i n s e r t ( 0 , "/media/MyUSB/je s-4 -O /S o u rc e s") » > from media im port * » > p = m a k e P ic tu re (p ic k A F ile ()) » > show(p)
El Dr. Manuel A. Pérez-Quiñones en Virginia Tech y sus estudiantes descubrieron cómo usar las bibliotecas de medios en Mac OS X con Jython. Iniciaron Jython usando un archivo de shell de UNIX parecido a éste:
238
Capítulo 9
Creación de program as más grandes
# E je cu ció n de jyth o n dentro de JES (asumimos que je s -4 -3 .a p p # e s tá en l a ca rp e ta /A p p lic a tio n s y que jytho n e s tá dentro de la # a p lic a c ió n JE S , lo cual es la c o n fig u ra ció n predeterm inada) # # # # # #
E s ta b le c e r algunas v a r ia b le s ( l a s s ig u ie n te s dos son de mi p ro p ia c re a c ió n , s in s ig n ific a d o e sp e c ia l ap arte de e ste uso) E s ta es l a ru ta en l a Mac en donde se guardan lo s a rch iv o s de ja v a /jy th o n JESH 0M E= "/A p p licatio n s/jes-4 -3.ap p / C o n ten ts/R eso u rces/Java"
# # # # #
E sto s son todos lo s a rch iv o s j a r que usa J E S , todos están en e l d ir e c t o r io sobre JESJARS=$JESHOME/AVIDemo.jar:$ JESHOME/customizer. ja r:$ JE S H O M E /jl1 . 0 . j a r : $JESH0ME/ jm f. j a r : SJESHOM E/junit. j a r : SJESHOME/jython. j a r :$ JESHOME/ medi api a y e r. j a r : $JESH0ME/multi p la y e r . j a r
# e je c u ta r jytho n # algunas de la s opciones e x tra son de l a documentación de jytho n # n e c e s ita c o n fig u ra r v a r ia s r u t a s : CLASSPATH para que ja v a encuentre # a rc h iv o s j a r , y jython.home para que jyth o n encuentre algunos # a rch iv o s de python (por ahora, uno más a co n tin u ació n ) ja v a -Xmx512m -X ssl0 2 4 k -D file.en co d ing = U TF-8 - c la s s p a th $JESJARS: SCLASSPATH -Dpython. home=$JESHOME/jython-2.2 .1 -D p yth o n .execu tab le= ./jyth o n o r g .p y t h o n .ú t il.jy t h o n
Después, dentro de Jython hay que escribir lo siguiente: » > im port sys » > s y s .p a t h .in s e r t ( 0 , " / A p p lic a tio n s / je s - 4 - 3 .a p p / C o n te n ts/R e so u rce s/Ja v a /") > » from media im port * # im p o rta rla s » > #Ahora todo debe fu n cio n a r » > show(makePictu re (p ic k A F ile ( ) ) )
RESUMEN DE PROGRAMACIÓN p rin tN o w
Imprime la entrada de la función de inm ediato mientras que el programa siga ejecutándose. En cambio, p r i nt no im prime la entrada hasta que el programa termine de ejecutarse.
r e q u e s t S t r in g
M uestra un cuadro de diálogo con el indicador de entrada, acepta una cade na del usuario y devuelve esa cadena. También existen en JES las funciones análogas requestNumber, re q u e stln te g e r e incluso re q uestlnteg erlnRange (que restringe el entero introducido para que esté entre dos valores de entrada).
sho w V ars
M uestra todas las variables existentes y sus valores.
w h ile
Itera por las instrucciones en el bloque de instrucciones que sigue después de la instrucción whi 1 e, siempre y cuando la prueba especificada en la instruc ción whi 1 e sea verdadera.
Problem as
239
PROBLEMAS 9.1
Por lo general, no se optimiza un programa (hacer que se ejecute más rápido o con menos uso de memoria) sino hasta después de ejecutarlo y de que esté bien depurado y probado (desde luego que tendremos que volver a probarlo después de cada m o dificación de optimización). He aquí una optimización que podríamos realizar en el juego de aventuras. Hasta ahora, mostrarSalon compara la variable salón con cada posible salón; incluso aunque se asocie antes. Python nos proporciona una forma de probar sólo una vez, mediante el uso de una instrucción el i f en vez de instrucciones i f posteriores. La instrucción el if significa “else if ” . Sólo se evalúa la instrucción el i f si la instrucción i f anterior es falsa. Puede tener tantas instrucciones el i f como desee después de una instrucción i f . Podría usarla de esta forma: i f (sa ló n == " P o rc h e "): m ostrarPorcheO e l i f (sa ló n == " C o c in a " ): m o strarC ocinaO
Vuelva a escribir el método mostrarSalon de una manera más óptima mediante el uso de elif. 9.2
Una función como elegi rSalon es difícil de leer con todas las instrucciones if anidadas. Puede volverse más legible mediante el uso apropiado de comentarios para explicar lo que hace cada sección del código: comprobar el salón y después com pro bar las posibles direcciones en el salón. Agregue comentarios a elegi rSalon para facilitar su lectura.
9.3
Agregue comentarios a todos los métodos para que sea más fácil para alguien más leer la función.
9.4
Agregue otra variable para el jugador, llamada mano. Haga que la mano esté vacía en un principio. Cambie la descripción de modo que haya una “llave” en la sala de estar. Si el jugador escribe el comando 11 ave mientras se encuentra en la sala de estar, la llave se colocará en su mano. Ahora, si el jugador tiene la llave mientras entra a la co cina, tendrá acceso a las escaleras y podrá ir hacia el “oeste” y subir por las escaleras. Tendrá que agregar algunos salones al juego para que esto pueda funcionar.
9.5
Cree la habilidad de b a j a r desde el Porche para explorar un mundo subterráneo secreto.
9.6
Agregue elementos secretos adicionales que el jugador pueda tener en su mano para permitir el acceso a distintos salones, como una linterna para que pueda tener acceso a un túnel debajo del porche.
9.7
Agregue una “bomba” en el comedor. Si el jugador escribe bomba estando en el come dor, ésta se colocará en su mano. Si el jugador escribe bomba al subir por las escaleras en donde se encuentra el Ogro, dejará caer la bomba y el Ogro explotará en pedazos.
9.8
Agregue la habilidad de que el jugador pierda en el juego (tal vez que muera). Cuando el jugador pierda, el juego deberá imprimir lo que ocurrió y después terminará. Tal vez si encuentra el ogro sin la bomba en su mano, el jugador pierda el juego.
9.9
Agregue la habilidad de que el jugador gane el juego. Cuando éste gane, el juego de berá imprimir lo que ocurrió y terminar. Tal vez al encontrar el salón del tesoro secreto bajo el Porche el jugador gane el juego.
240
Capítulo 9
Creación de program as más grandes
9.10 Las descripciones de los salones no tienen que ser sólo verbales. Reproduzca un so nido relevante cuando el jugador entre a un salón específico. Use p l ay de modo que pueda continuar el juego mientras se reproduce el sonido. 9.11 Las descripciones de los salones pueden ser visuales, así como textuales y auditivas. Muestre una imagen relevante al salón al momento de entrar en él. Para obtener pun tos extra, muestre una imagen sólo una vez m ediante show y, si el jugador vuelve a entrar al salón, use repai nt para que vuelva a aparecer la imagen de nuevo. 9.12 Una posible fuente de errores en este juego de aventuras es que los nombres de los salones aparecen en varios lugares. Si Sala de estar se escribe como “SalaDeEstar'’ en un lugar y como “SalaEstar” (sin la palabra “De” en medio) en otro lugar, el juego no funcionará de manera correcta. Entre más salones agregue y entre más lugares haya en donde escriba los nombres de los salones, aumentarán las probabilidades de cometer un error. Hay algunas formas de hacer que este error sea menos probable de ocurrir: • No asigne nombres a los salones con cadenas de caracteres. Use mejor números. Es más fácil escribir y verificar “4” que “ SalaDeEstar”. • Use una variable para Sal aDeEstar y use esa variable para verificar la ubicación. Así no importará si usa números o cadenas (y las cadenas son más fáciles de leer y comprender). Use una de estas técnicas para volver a escribir el juego de aventuras con menos erro res potenciales. 9.13 La función pri ntNow no es la única forma de presentar información al usuario duran te la ejecución de un programa. También podríamos usar la función showlnformati on que recibe una cadena como entrada y luego la muestra en un cuadro de diálogo. En este momento, nuestras subfunciones de mostrarSalon suponen que vamos a mostrar la información del salón por medio de pri ntNow. Si funciones como mos trar Porche devolvieran una cadenacon la descripción, entonces la función most rar Salón podría usar pri ntNow para mostrar la descripción del salón, o showlnformation. Vuelva a escribir las funciones para mostrar los salones de modo que devuelvan una cadena; después modifique most rarSal on para poder cambiar con facilidad en tre imprimir la información de los salones y mostrarla en un cuadro de diálogo. 9.14 Considere el siguiente programa: d ef p ru e b a M e (p ,q ,r): i f q > 50: p r in t r v a lo r - 10 fo r i in r a n g e ( l,p ) : p r in t "Hola" v a lo r = v a lo r - 1 p r in t v a lo r p r in t r
Si ejecutamos pruebaMe (5, 51," ¡Hola también a ti ! " ) , ¿qué imprimirá?
Para profundizar
241
9.15 d e f n u e v a F u n c io n (a , b, c ) : p r in t a l i s t a l = r a n g e (l,5 ) v a lo r = 0 fo r x in l i s t a l : p r in t b
v a lo r = v a lo r +1 p r in t c p r in t v a lo r
Si llama a la función anterior escribiendo nuevaFuncion ("Y o", " t ú " , "m o rsa"), ¿qué imprimirá la computadora?
PARA PROFUNDIZAR En la actualidad los juegos de aventuras se conocen comúnmente como ficción interactiva. Hay sitios Web y archivos en donde podemos descargar y jugar ficción interactiva. Aún mejor, hay lenguajes de programación diseñados de forma especial para crear videojuegos, como Inform 7. Quizás el mejor libro que se haya escrito sobre ingeniería de software sea The M ythicalM anMonth: Essays on Software Engineering, Anniversary Edition (2da edición), por Frederick P. Brooks (Addison-Wesley, 1995). Brooks señala que muchos de los problemas del desarrollo de software son cuestiones de organización. Recomendamos este libro ampliamente.
TEXTO, ARCHIVOS, REDES, BASES DE DATOS Y UNIMEDLA Capítulo 10 Creación y modificación de texto Capítulo 11 Técnicas avanzadas de texto: Web e información Capítulo 12 Creación de texto para Web
CAPÍTULO
10
Creación y modificación de texto
10.1
T E X T O C O M O U N IM ED IA
10.2
C A D E N A S : C R E A C IÓ N Y M A N IP U LA C IÓ N D E C A D E N A S
10.3
M A N IP U LA C IÓ N D E PARTES D E C A D E N A S
10.4
A R C H IV O S : LU G A R ES EN D O N D E P U E D E C O L O C A R SUS C A D E N A S Y O TR A S C O SA S
10.5
LA B IB L IO T E C A ESTÁ N D A R D E PYTH O N
Objetivos de aprendizaje del capítulo Los objetivos de aprendizaje de medios para este capítulo son: • G en erar texto en un estilo de carta m odelo. • M anipular texto estructurado, como listados telefónicos y de direcciones. • G en erar texto con estructuras aleatorias. Los objetivos de ciencias computacionales para e ste capítulo son: • A cce d e r a los com ponentes de objetos m ediante la notación de punto. • M anipular cadenas. • Leer y escribir en archivos. • C om prender las estructuras de los archivos, como los árboles. • Escribir program as que manipulen a otros program as, lo cual conduce a ideas poderosas como los intérpretes y com piladores. • Usar los módulos en la Biblioteca estándar de Python, como las herram ientas random y os. • Tener una idea básica de la funcionalidad disponible en la Biblioteca estándar de Python. • Am pliar la comprensión de la capacidad de im portar elem entos m ediante im p o rt.
10.1
TEXTO COMO UNIMEDIA Nicholas Negroponte, fundador de MIT Media Lab, dijo que la multimedia basada en compu tadora es posible gracias al hecho de que la computadora es en realidad unim edia. pues sólo comprende una cosa: ceros y unos. Podemos usar la computadora para multimedia debido a que es posible codificar cualquier medio como unos y ceros. Él podría haber hablado también sobre el texto como unimedia. Podemos codificar cual quier medio en texto. Esto es mejor que usar ceros y unos, puesto que podemos lee r e 1 texto. Más adelante en este libro asociaremos sonidos al texto y después lo volveremos a asociar a los sonidos, y haremos lo mismo con las imágenes. Pero una vez que tengamos nuestros
244
Sección 10.2
Cadenas: creación y manipulación de cadenas
24 5
medios en texto, no habrá necesidad de regresar al medio original: podemos asociar sonidos al texto y después a imágenes, con lo cual creamos visualizaciones de los sonidos. La mayor parte de World Wide Web consta de texto. Visite cualquier página Web, después vaya al menú de su navegador Web y seleccione “ v e r e l c ó d i g o f u e n t e ” . Lo que aparecerá a continuación es texto. Toda página Web consiste de texto. Este texto hace referencia a las imágenes, sonidos y animaciones que aparecen al ver la página, pero la página en sí está definida como texto. Las palabras en el texto son una notación conocida como Lenguaje de marcación de hipertexto (HTML). Hasta ahora hemos podido arreglárnoslas con unas cuantas ideas de lenguajes de pro gramación. JES se diseñó de modo que podamos realizar todo nuestro trabajo con sonidos e imágenes usando sólo instrucciones de asignación, for, if, print, return y funciones. Pero los lenguajes de programación tienen todavía más características y capacidades que éstas. En este capítulo empezaremos a mostrarle lo que hay dentro de JES para que pueda obtener una mayor capacidad en su programación.
10.2
CADENAS: CREACIÓN Y MANIPULACIÓN DE CADENAS Por lo general el texto se manipula como cadenas. Una cadena es una secuencia de caracte res. Las cadenas se almacenan en memoria como un arreglo, justo igual que los sonidos. Las cadenas son una secuencia contigua de los buzones de correo de la memoria: los buzones que están uno al lado de otro. La cadena “Hola” se almacenaría en cuatro buzones, uno después del otro: un buzón contendría el código binario que representa a la “H”, el siguiente conten dría la “o”, el otro contendría la “1” , etcétera. Las cadenas se definen con secuencias de caracteres encerrados entre comillas. Python es inusual en cuanto a que permite varios tipos distintos de comillas. Podemos usar com i llas sencillas, dobles o incluso triples. Podemos anidar las comillas. Si empezamos una cadena con comillas dobles, entonces podemos usar comillas sencillas dentro de la cadena, ya que ésta no terminará sino hasta el siguiente conjunto de com illas dobles. Si empezamos a escribir una cadena con com illas sencillas, podemos colocar todas las comillas dobles que queramos dentro de la cadena, ya que Python espera la siguiente comilla sencilla para terminar. p r in t ‘ E s ta es una cadena e n tre comí 11 as s e n c i l l a s ’ Esta es una cadena c o m illa s s e n c illa s » > p r in t "E sta es una cadena e n tre c o m illa s dobles" E sta es una cadena e n tre c o m illa s dobles » > p r in t " " " E s t a es una cadena e n tre c o m illa s t r i p l e s " " " Esta es una cadena e n tre c o m illa s t r i p l e s »>
¿Porqué las comillas triples? Porque nos permite incrustar nuevas líneas, espacios y tabuladores en nuestras cadenas. No podemos usarlas con facilidad desde el área de comandos, pero podemos hacerlo en el área del programa. def cadenaLocaO : p r in t """ A s i se usan la s c o m illa s t r i p l e s . ¿Por qué? Observe la s d is t in t a s lin e a s . Porque podemos hacer e s t o ." " "
24 6
Capítulo 10
Creación y m odificación de texto
» > cadenaLocaO Asi se usan la s c o m illa s t r i p l e s . ¿Por qué? Observe la s d is t in t a s lin e a s .
Porque podemos hacer e sto .
El valor de tener tantos tipos distintos de comillas es para facilitar la acción de colocar comillas dentro de las cadenas. Por ejemplo, HTML usa comillas dobles como parte de su notación. Si desea escribir una función de Python que cree páginas de HTML (un uso común para Python), entonces necesitará cadenas que contengan comillas. Como se puede usar cualquiera de estas comillas, podemos incrustar comillas dobles si usamos comillas sencillas para iniciar y terminar la cadena. » > p r in t " " " In v a lid syn tax Your code co n ta in s a t le a s t one syn ta x e r r o r , meaning i t i s not le g a l jy th o n . » > p r in t * " 1 IV
Podemos considerar una cadena como un arreglo o secuencia de caracteres. En realidad es una secuencia: podemos usar una instrucción f o r para recorrer todos los caracteres. » > fo r i in “ Hola” : p r in t i H
0 1 a
En memoria, una cadena es una serie de buzones consecutivos (para continuar con nuestra metáfora de memoria como un departamento de correspondencia), cada uno de los cuales contiene el código binario para el carácter correspondiente. La función o rd () nos da la codi ficación ASCÜ (Código Estándar Estadounidense para el Intercambio de Información) para cada carácter. Así, la cadena “Hola” tiene cuatro buzones, en donde el primero contiene 72, el que sigue 111, después 108 y así, en lo sucesivo. » > cad - "H ola” » > fo r c a r in cad: p r in t o rd (c a r) 72
111 108 97
En JES, ésta es una ligera simplificación. La versión de Python que usamos (Jython) está basada en Java, y en realidad no usa ASCII para codificar sus cadenas sino Unicode, una codificación para caracteres en donde se utilizan dos bytes por cada carácter. Dos bytes nos pro porcionan 65 536 posibles combinaciones. Todos esos posibles códigos adicionales nos permi
Sección 10.2
Cadenas: creación y manipulación de cadenas
24 7
ten ir más allá de un simple alfabeto en latín, además de los signos de puntuación y números. Podemos representar Hiragana, Katakana y otros sistemas de glifos. Lo que esto nos indica es que hay muchos más caracteres posibles de los que pueden escribirse en el teclado. No sólo hay símbolos especiales, sino también caracteres invisibles como los tabuladores y la pulsación de la tecla Intro. Para escribir estos caracteres en Python (y en muchos otros lenguajes, como Java y C) usamos escapes de barra diagonal inversa. Estos escapes consisten en la tecla de barra diagonal inversa \ seguida de un carácter. • \ t es lo mismo que presionar la tecla de tabulación. • \ b es lo mismo que presionar la tecla de retroceso (que no es un carácter muy útil de poner en una cadena, pero igual se puede hacer). Al imprimir \b , aparece como un cuadro en la mayoría de los sistemas; en realidad no puede imprimirse (ver a conti nuación). • \n es lo mismo que presionar la tecla Intro. • \uXXXX en donde XXXX es un código compuesto por dígitos del 0 al 9 y de la A a la F (conocido como número hexadecimal), representa el carácter Unicode con ese código. Puede buscar los códigos en h t t p :/ / w w w .u n i c o d e .o r g / c h a r t s . No es fácil ver glifos de Unicode en JE S,1 pero podemos ver cómo afectan algunos de estos símbolos especiales en la impresión. » > p r in t "h o la \ta to d o s .\nMark" ho la a todo s. Mark
Recuerde que anteriormente en este libro usamos una ‘ r ’ al principio de una cadena de nombre de archivo, por ejemplo: r " C : \ i p-book\m ediaso urces\b arb ara.jp g"
Una ‘ r ’ indica a Python que debe leer la cadena en modo puro. Se ignoran todos los esca pes de barra diagonal inversa. Esto es importante en rutas de Windows, ya que este sistema operativo usa las barras diagonales inversas como delimitadores. Por ejemplo, si su nombre de archivo empieza con ‘b ’, Python vería esa \ b como un carácter de retroceso y no como un delimitador -b. Es fácil sumar cadenas mediante + (lo que se conoce también como concatenación de cadenas) y obtener las longitudes de las cadenas mediante la función 1 e n (). » > hola = "Hola" » > p r in t le n (h o la ) 4
» > mark = " , Mark" » > p r in t len(m ark) 6
» > p r in t hola+mark H ola, Mark » > p r in t 1en (hola+mark) 10
'Puede verlos en CPython, con un comando como p r i n t u”\ u f e e d ”,
24 8
C a p ítu lo lO
10.3
Creación y m odificación de texto
MANIPULACIÓN DE PARTES DE CADENAS Usamos la notación de corchetes ( [ ] ) para hacer referencia a partes de las cadenas. • cad en a [n] devuelve el «-ésimo carácter en la cadena, en donde el prim er carácter en la cadena es cero. • cad en a [ n : m] devuelve una porción de la cadena que empieza en el n-ésimo carácter y llega hasta, pero sin incluir a l m-ésimo carácter [similar a la forma en que trabaja la función ran g e () ]. De manera opcional puede omitir a n o a m. Si omite a n, se consi dera cero (el inicio de la cadena). Si omite a m, se considera como el final de la cadena. Podemos también usar números negativos en cualquier extremo para recortar ciertos caracteres de ese lado. Podemos considerar que los caracteres de la cadena se encuentran en cajas, cada uno con su propio número de índice.
H
0
0
1 2
1
a
3
» > hola = "Hola" » > p r in t h o la [ l] 0 » > p r in t h o la [0 ] H » > p r in t h o la [2 :4 ] la » > p r in t hola Holii » > p r in t h o la [ :2 ] Ho » > p r in t h o la [ 2 :] la » > p r in t h o la [ :] Holii » > p r in t h o l a [ - l : ] A » > p r in t h o l a [ : - l ] Hol
10.3.1
Métodos de cadenas: introducción a los objetos y la notación punto
En realidad, todo en Python es más que un valor: es un objeto. Un objeto combina datos (como un número, una cadena o una lista) con los métodos que pueden actuar sobre ese objeto. Los métodos son como funciones, excepto que no son accesibles en forma global. No podemos ejecutar un método de la forma en que podemos ejecutar pi ckAFi 1 e () o makeSound () . Un método es una función a la que sólo se puede acceder a través de un objeto.
Sección 10.3
M anipulación de partes de cadenas
24 9
En Python, las cadenas son objetos. No son sólo secuencias de caracteres; también tienen métodos que no son accesibles a nivel global, sino que sólo las cadenas los conocen. Para ejecutar un método de una cadena, usamos la notación punto. Escribimos objeto.méto do (). Un método de ejemplo que sólo las cadenas conocen es capital ize(). Este método pone en mayúscula la primera letra de la primera palabra de la cadena que lo invocó. No trabaja sobre una función ni sobre un número. » > prueba="esta es una prueb a." » > p r in t p ru e b a .c a p ita liz e O E s ta es una prueba. » > p r in t c a p ita liz e (p ru e b a ) The e rro r w a s .'c a p ita liz e Ñame not found g lo b a lly . A lo c a l or global ñame could not be found. You need to d e fin e the fu n c tio n or v a r ia b le before you t r y to use i t in any way. » > p r in t 'e s ta es o tra prueba’ .c a p it a liz e O E s ta es o tra prueba » > p r in t 1 2 .c a p it a liz e O In v a lid syn tax Your code co n ta in s a t le a s t one syn ta x e r r o r , meaning i t i s not le g a l jy th o n .
Hay muchos métodos útiles para las cadenas. • startswith (prefijo) devuelve true si la cadena empieza con el prefijo indicado. Recuerde que true en Python puede ser desde 1 hasta cualquier número mayor, y false es cero. » > c a rt a - "E l S r . Mark G uzdial s o l i c i t a su agradable p r e s e n c ia ..." » > p r in t c a r t a .s t a r t s w it h ( " E l S r . " )
1 » > p r in t c a r t a .s t a r t s w it h ( " L a S r a ." )
0 • endswith(sufi jo) devuelve true si la cadena termina con el sufijo indicado. Esta fimción es en especial útil para revisar si un nombre de archivo es del tipo correcto para un programa. » > nom brearchivo= "barbara.jpg" » > i f n o m b re a rc h iv o .e n d s w ith 0 .jp g " ): p r in t "Es una imagen" Es una imagen
• f i n d ( c a d ) , f i n d ( c a d , i n i c i o ) y f i n d ( c a d , i n i c i o , f i n ) encuentran la cad en el objeto cadena y devuelven el número de índice en donde empieza. En las formas opcionales, puede indicarle desde qué número de índice empezar e incluso en dónde dejar de buscar.
250
C a p ítu lo lO
C readó n y m odificación de texto
Esto es muy importante: el método fi nd() devuelve -1 si fracasa. ¿Por qué -1? Porque cualquier valor que sea de 0 a 1 menor que la longitud de la cadena podría ser un índice válido en donde podría encontrarse una cadena de búsqueda. » > p r in t c a rta E l S r . Mark G uzdial s o l i c i t a su agradable p r e s e n c ia ... » > p r in t c a rt a .fin d (" M a rk " ) 7 » > p r in t c a r t a .f in d (" G u z d ia l" ) 12 » > p r in t le n (" G u z d ia l") 7 » > p r in t c a rta [7 :1 2 + 7 ] Mark G uzdial » > p r in t c a r t a .f in d ( " f r e d " )
-1 También existe rfi nd(buscarcadena) (y las mismas variaciones con parámetros opcio nales), que busca desde el final de la cadena hacia el frente. • upper() cambia la cadena a mayúsculas. • 1 ower ( ) cambia la cadena a minúsculas. • swapcaseO convierte todas las mayúsculas en minúsculas y viceversa. • t i t i e O convierte sólo los primeros caracteres en mayúsculas y el resto en minúsculas. Estos métodos pueden colocarse en cascada: uno modifica el resultado de otro. » > cadena="Esta es una prueba de A lg o ." » > p r in t cadena.swapcaseO eSTA ES UNA PRUEBA DE aLGO. » > p r in t c a d e n a .title O .s w a p c a s e O eSTA eS uNA pRUEBA dE aLGO.
• isalphaO devuelve t rué si la cadena no está vacía y contiene sólo letras: sin núme ros ni signos de puntuación. • i sdi gi t () devuelve trué si la cadena no está vacía y contiene sólo números. Puede usar esta función para verificar los resultados de una búsqueda. Suponga que necesita escribir un programa para buscar los precios de algunas acciones. Desea analizar un precio actual, no el nombre de una acción. Si no lo recibe en forma correcta, tal vez su programa podría comprar o vender acciones que usted no desee. Podría usar isdi gi t () para verificar su resultado de manera automática. • repl ace (búsqueda, reemplazo) busca la cadena llamada búsqueda y la reemplaza con la cadena reempl azo. Devuelve el resultado pero no cambia la cadena original. » > p r in t c a rta E l S r . Mark G uzdial s o l i c i t a su agradable p r e s e n c ia ... » > c a r t a .r e p la c e ( " a " ," ! " ) ‘ El S r . M !rk G u z d iil s o l i c i t ! su !g r !d !b le p re s e n c i! . . . * » > p r in t c a rta E l S r . Mark G uzdial s o l i c i t a su agradable p r e s e n c ia ...
Sección 10.3
M anipulación de partes de cadenas
251
10.3.2 Listas: texto poderoso y estructurado Las listas son estructuras muy poderosas que podemos considerar como un tipo de texto estructurado. Las listas se definen con corchetes y comas entre sus elementos; pueden con tener casi cualquier cosa, incluso sublistas. Al igual que las cadenas, podemos hacer refe rencia a las partes con notaciones de corchetes y podemos sumarlas con el símbolo +. Las listas son también secuencias, por lo que podemos usar un ciclo f o r con ellas para recorrer sus piezas. » > mi L ista = [" E ste " , " e s” , "u n ", 12] » > p r in t mi L is t a [ ‘ E s t e ’ , ‘ e s \ ‘ un’ , 12] » > p r in t m iL is t a [0 ] E ste » > fo r i in mi L i s t a : p r in t i E ste es un 12
» > p r in t mi L is t a + ["De verdad"] [ ‘ E s t e ’ , ‘ e s 1, ‘ un’ , 12, ‘ De verd ad ’ ] » > o t r a L is t a = [" e s t a " , " t ie n e " , [" u n a " , [" s u b " ,"1 i s t a " ] ] ] » > p r in t o tra L i s ta [ ‘ e s t a ’ , ‘ t ie n e ’ , [ ‘ una’ , [ ‘ sub’ , ‘ l i s t a ’ ] ] ] » > p r in t o t r a L is t a [ 0 ] e sta » > p r in t o t r a L is t a [ 2 ] [ ‘ una’ , [ ‘ sub’ , ‘ l i s t a ’ ] ] » > p r in t o t r a L is t a [ 2 ] [1] [ ‘ sub’ , ‘ l i s t a ’ ] » > p r in t o t r a L is t a [ 2 ] [1 ] [0] sub » > p r in t o t r a L is t a [ 2 ] [1 ] [0 ] [2] b
Las listas pueden usar el siguiente conjunto de métodos; las cadenas no pueden usarlos. •
a p p e n d (a lg o ) coloca a lg o al final de la lista.
•
remove ( a l go ) elimina a l go de la lista si está ahí.
•
s o r t () coloca la lista en orden alfabético.
•
r e v e r s e () invierte la lista.
•
c o u n t (a l go) nos indica el número de veces que está a l go en la lista.
•
max () y mi n () son funciones que hemos visto antes; reciben una lista como entrada y nos proporcionan los valores máximo y mínimo en la lista. » > l i s t a = [" o s o " ," m a n z a n a " ," g a to " ," e le fa n te " , "p erro ","m an zana"] » > lis t a .s o r t ( ) » > p r in t l i s t a [ ’ e le fa n t e ’ , ’ g ato ’ , ’ manzana’ , ’ manzana’ , ’ oso ’ , ’ p e rro ’ ] » > l i s t a , re ve r se ( )
25 2
C a p ítu lo lO
Creación y m odificación de texto
» > p r in t l i s t a [ 'p e r r o ', 'o s o * , 'm anzana', 'm anzana', 'g a to * , 'e le f a n t e '] » > p r in t l i s t a .c o u n t ( ’ manzana’ ) 2
Uno de los métodos más importantes para las cadenas, sp l i t (d e l i mi t a d o r ) , convierte una cadena en una lista de subcadenas, separándola con base en una cadena delimitadora que usted le proporcione. Esto nos permite convertir las cadenas en listas. » > p r in t c a r t a . s p l i t ( " " ) [ ' E l ' , ' S r . ' , 'M a rk ', 'G u z d ia l', ' s o l i c i t a ' , 'a g ra d a b le ', ‘ p r e s e n c ia ...* ]
's u ',
Mediante el uso de sp l i t ( ) podemos procesar texto con formato: texto en donde la sepa ración entre las partes es un carácter bien definido, como el texto delimitado por fabuladores o el texto delimitado por comas de una hoja de cálculo. He aquí un ejemplo del uso de texto estructurado para guardar una agenda telefónica. Esta agenda tiene líneas separadas por nue vas líneas y partes separadas por signos de dos puntos. Podemos dividir con base en las nuevas líneas y después tomar en cuenta los signos de dos puntos para obtener una lista de sublistas. Las búsquedas por esta lista se pueden realizar con un ciclo f o r simple.
P ro g ram a 9 0 : una aplicación simple de agenda telefónica
def a g e n d a te le fo n ic a O : retu rn II II II M ary:893-0234:Agente in m o b ilia r io : Pedro:897-2033:0perador de m aquinaria: Pablo:234-2342:Bo leado r p ro fe s io n a l:" " " d ef t e le fo n o s O : te le fo n o s = a g e n d ate le fo n icaO lis t a t e le f o n o s = t e l e f o n o s .s p l i t ( ‘ \ n ’ ) n u e v a lis ta te le fo n o s = [] fo r l i s t a in lis t a t e le f o n o s : n u e v a lis ta te le fo n o s = n u e v a lis ta te le fo n o s + [ l i s t a . s p l i t ( " : " ) ] re tu rn n u e v a lis ta te le fo n o s def b u sc a rT e le fo n o (p e rso n a ): fo r gente in t e le fo n o s O : i f gente[0 ] == persona: p r in t " E l número te le fó n ic o d e ", p e rs o n a ," e s " ,g e n te [l]
Cómo funciona Hay tres funciones en este programa: una para proporcionar el texto de los teléfonos, la otra para crear la lista de teléfonos y la tercera para buscar un número telefónico. • La primera función se llama a g e n d a te l efo n i ca; es la que crea el texto estructurado y b devuelve, usando comillas triples para poder dar formato a las líneas con caracteres de nueva línea. El formato es: nombre, dos puntos, número telefónico, dos puntos y empleo, luego dos puntos y el fin de la línea.
Sección 10.4
Archivos: lugares en donde puede colocar sus cadenas y otras cosas
25 3
» > p r in t ag e n d ate lefo n icaO M ary:893-0234:Agente in m o b ilia r io : Pedro:897-2033:0perador de m aquinaria: Pab1o:234-2342:Boleador p ro fe s io n a l:
• La segunda función se llama tel efonos; devuelve una lista de todos los teléfonos. Accede a la lista telefónica mediante agendatelefonica y luego la divide en varias líneas. El resultado de spl it es una lista que consiste en una cadena con signos de dos puntos. A continuación, el ciclo en tel efonos separa cada lista usando spl it con base en los signos de dos puntos. Lo que la función tel efonos devuelve es una lista de listas. » > p r in t te le fo n o s O [ [ ” ] , [ ’ Mary’ , ’ 893-0234’ , 'Agente in m o b ilia r io ’ , ” ] , ['P e d r o ', '8 9 7 -2 0 3 3 ', 'Operador de m aq u in aria’ , ” ] , ['P a b lo ', '234-2342*, 'Boleador p r o fe s io n a l’ , ” ] ]
Por último, la tercera función se llama buscarTel efono; recibe un nombre como entrada y busca el número telefónico correspondiente. Itera sobre todas las sublistas que devuelve tel efonos y busca el teléfono en donde el primer elemento en la sublista (número de índice 0) sea el nombre introducido. Después imprime el resultado » > b u sc a rT e le fo n o (’ Pedro’ ) El número te le fó n ic o de Pedro es 897-2033
10.3.3 Las cadenas no tienen fuente Las cadenas no tienen una fuente (apariencia característica de las letras) ni un estilo (por lo general negrita, cursiva, subrayado y otros efectos que se aplican a la cadena) asociados. La información de la fuente y el estilo se agregan a las cadenas mediante el uso de procesadores de palabras y otros programas. Por lo general, se codifican como tiradas de estilo (style runs). Una tirada de estilo es una representación separada de la información de la fuente y el es tilo, con índices en la cadena para mostrar en dónde deben realizarse los cambios. Por ejem plo, El v i e j o zorro café corre podría codificarse como [[negrita 0 7][cursiva 15 18]]. Piense en las cadenas con tiradas de estilo. ¿Cómo llamamos a esta combinación de información relacionada? Es evidente que no es un solo valor. ¿Podríamos codificar la cadena con las tiradas de estilo en una lista compleja? Claro; ¡podemos hacer casi cualquier cosa con las listas! La mayor parte del software que maneja texto con formato codifica las cadenas con ti radas de estilo como un objeto. Los objetos tienen datos asociados, tal vez en varias partes (como las cadenas y las tiradas de estilo). Los objetos saben cómo actuar con sus datos, usando métodos que sólo los objetos de ese tipo conocen. Si varios objetos conocen el mis mo nombre del método, es probable que haga lo mismo pero tal vez no de la misma forma. Esto es sólo un indicio. Hablaremos con más detalle sobre los objetos en secciones pos teriores.
10.4 ARCHIVOS: LUGARES EN DONDE PUEDE COLOCAR SUS CADENAS Y OTRAS COSAS Los archivos son extensas colecciones de bytes en el disco duro, las cuales tienen un nom bre asignado. Por lo general los archivos tienen un nombre base y un sufijo de archivo. El
25 4
Capítulo 10
Creación y m odificación de texto
archivo barbarajpg tiene el nombre base “barbara” y un sufijo de archivo “jpg” , el cual nos indica que el archivo es una imagen JPEG. Los archivos se agrupan en directorios (también conocidos como carpetas). Los direc torios pueden contener otros directorios además de archivos. Hay un directorio base en la computadora, el cual se conoce como directorio raíz. En una computadora que utiliza el sistema operativo Windows, el directorio base es similar a C :\. A la descripción completa de los directorios que debemos visitar para llegar a un archivo específico partiendo desde el directorio base se le conoce como ruta. » > arch ivo = p ickA Fi 1 e () » > p r in t a rc h iv o C :\ i p-book\medi asources\640x480. jpg
La ruta que se imprime nos indica cómo ir desde el directorio raíz hasta el archivo 640x480.jpg. Empezamos en C :\, seleccionamos el directorio ip-book y después el direc torio mediasources. A esta estructura la denominamos árbol (figura 10.1). A C :\ le llamamos la raíz del árbol. Este árbol tiene ramas en donde están los subdirectorios. Cualquier directorio puede contener más directorios (ramas) o archivos, los cuales se conocen como hojas. Exceptuan do la raíz, cada nodo del árbol (rama u hoja) tiene un solo nodo rama padre, aunque un padre puede tener varios nodos ramas y hojas hijos. Necesitamos saber acerca de los directorios y archivos si vamos a manipular archivos, en especial muchos de ellos. Si lidiamos con un sitio Web grande, vamos a estar trabajando con muchos archivos. Si vamos a usar video, tendremos cerca de 30 archivos (cuadros individua les) por cada segundo de video. En realidad no es conveniente escribir una línea de código para abrir cada cuadro de video. Es mejor escribir programas que recorran estructuras de directorios para procesar archivos Web o de video. También podemos representar los árboles en listas. Como las listas pueden contener sublistas, así como los directorios pueden contener subdirectorios, la codificación es bastante fácil de realizar. El punto importante es que las listas nos permiten representar relaciones jerárquicas complejas, como los árboles (figura 10.2).
C:
¡pbook
mediasources
640x480.jpg FIGU RA 10.1 D ia g ra m a d e un á rb o l d e d ire c to rio s.
Windows
MediaTools
beach.jpg
Sección 10.4
Archivos: lugares en donde puede colocar sus cadenas y otras cosas
25 5
árbol
sublista
/ \
H ojal
Hoja2
sublista
sublista
sublista
Hoja3
Hoja4
Hoja5
FIGURA 10.2 Diagrama para una lista.
» > árbol = [["H o jal","H o ja2 "], [["H oja3"], [,,Hoja4"] , "Hoja5"]] » > p r in t árbol [ [ ’ H o ja l’ , ’ H oja2’ ] , » > p r in t árbol [0] [ ’ H o ja l’ , ’ H oja2’ ] » > p r in t árbol [1]
[ [ ’ H oja3’ ] ,
[ ’ H oja4’ ] ,
’ H oja5’ ] ]
[ [ ’HojaB’] , [ ’Hoja4’] , ’Hoja5’] » > p r in t árbol [1 ] [0] [ ’ H oja3’ ] » > p r in t árbol [1 ] [1]
[ ’Hoja4’] » > p r in t árbol [1 ] [2] Hoja5
10.4.1
Apertura y manipulación de archivos
Abrimos archivos para leer o escribir en ellos. Para ello usamos una función llamada open (nomb r e a rc h i v o , como). El nombre de archivo puede ser una ruta com pleta o sólo un nombre de archivo base y un sufijo. Si usted no proporciona una ruta, el archivo se abrirá en el directorio actual de JES. La entrada como es una cadena que describe lo que deseamos hacer con el archivo. • “rt” significa “leer el archivo como texto; traducir los bytes en caracteres para m f \ • “wt” significa “escribir en el archivo como texto” . • “rb” y “wb” significa “leer y escribir bytes” (respectivamente). Se utilizan estas opcio nes si vamos a manipular archivos binarios (como JPEG, WAV, Word o Excel). La función open ( ) devuelve un objeto archivo que podemos usar para manipular el archi vo. El objeto archivo puede usar un conjunto de métodos. • a r c h i v o . re a d () lee todo el archivo como una cadena gigante (si abrió el archivo para escribir, no trate de leer de él). • a r c h i v o . re a d l i nes O lee todo el archivo y lo coloca en una lista, en donde cada ele mento es una sola línea. Sólo podemos usar r e a d ( ) o r e a d l i n e s O una vez p orcada apertura de archivo.
256
C a p ítu lo lO
C readó n y m odificación de texto
• a r c h iv o .w r i te (u n a c a d e n a ) escribe u n acad en a en el archivo (si abrió el archivo para lectura, no trate de escribir en él). • a r c h i v o . e l o s e () cierra el archivo. Si escribe datos en el archivo, al cerrarlo se ase gurará de que todos los datos se escriban en el disco. Si lee datos del archivo, al ce rrarlo se liberará la memoria que se usó para manipular el archivo. En cualquier caso es buena idea cerrar sus archivos cuando termine de usarlos. Una vez que cerramos un archivo, no es posible leer o escribir en él sino hasta que volvemos a abrirlo. A continuación veremos ejemplos de cómo abrir un archivo de programa que escribimos antes y leerlo como una cadena, y también como una lista de cadenas. » > program a=pickAFi1e() » > p r in t programa C:\ip-book\program as\im agenChica.py » > archivo=open(program a, " r t " ) » > contení do=archivo. read O » > p r in t contenido def im ag e n ch icaO : 1i enzo=makePi cture(getM edi aPath("6 4 0 x 4 8 0 .jp g " )) a d d T e x t(lie n z o ,1 0 ,5 0 ,"Esto no es una imagen") addLi ne(1 i enzo,1 0 ,2 0 ,3 0 0 ,5 0 ) a d d R e c t F ille d (lie n z o ,0 ,2 0 0 ,3 0 0 ,5 0 0 ,y e llo w ) addRect(1 i enzo,1 0 ,2 1 0 ,2 9 0 ,4 9 0 ) re tu rn lie n z o » > a r c h iv o .e lo s e () » > archivo=open(program a, " r t " ) » > 1 in e a s = a rc h iv o .re a d 1 in e s () » > p r in t lin e a s [ ’ def im agenchicaO : \ n ’ , * 1 ienzo = m akeP ictu re (g etM ed iaP ath ("6 4 0x4 8 0.jp g "))\n ’ , * a d d T e xt(T ie n z o ,1 0 ,5 0 ,"Esto no es una im ag en")\n’ , * a d d L in e (lie n z o ,1 0 ,2 0 ,3 0 0 ,5 0 )\n ’ , * a d d R e c tF ille d (T ie n z o ,0 ,2 0 0 ,3 0 0 ,5 0 0 ,y e H o w )\n ’ , * a d d R e c t(lie n z o ,1 0 ,2 1 0 ,2 9 0 ,4 9 0 )\n ’ , * re tu rn lie n z o ’ ] » > f ile .c lo s e O
He aquí un ejemplo de cómo escribir un archivo gracioso. El carácter \n crea las nuevas líneas en el archivo. »> »> »> »>
e s c rib írA rc h iv o = o p e n (" m ia rc h iv o .tx t " ," w t" ) e s c r ib ír A r c h iv o .w r it e ( " E s t o es algo de t e x t o ." ) e s c r ib ír A r c h iv o .w r it e ( " E s t o es un poco m á s.\n ") e s c r ib ír A r c h iv o .w r it e ( " Y ahora term inam os.\n \ n F IN ." )
» > e s c r ib í r A r c h iv o .e lo s e () » > e s c r ib í rA rc h iv o = o p e n ("m ia rc h iv o .tx t", " r t " ) » > p r in t e s c r ib í rA rc h iv o . re a d () Esto es algo de t e x to .E s to es un poco más. Y ahora terminamos. FIN . » > e s c r ib í r A rc h iv o .c lo s e Q
Sección 10.4
Archivos: lugares en donde puede colocar sus cadenas y otras cosas
25 7
10.4.2 Generación de cartas modelo No sólo podemos escribir programas para desglosar el texto estructurado, sino que también podemos escribir programas para ensamblar texto estructurado. Uno de los textos estructu rados clásicos que toóos conocemos son las cartas modelo, o “spam”. Los verdaderos buenos escritores de spam (si acaso no es una contradicción de términos) llenan los detalles que de verdad se dirigen a usted en el mensaje. ¿Y cómo hacen esto? Es bastante sencillo: tienen una función que toma la entrada relevante y la inserta en los lugares correctos.
P ro g ram a 9 1 : un generador de cartas m odelo
def cartaM odelo(sexo, a p e l1i do, c i udad, c o lo rO jo s ): a rc h iv o = o p e n C c a rta M o d e lo .tx t", "w t") a r c h iv o .w rite (" Q u e rid " ) i f sexo=="F": a r c h iv o .w r it e (" a S ra . " + a p e llid o + ":\n " ) i f sexo=="M": a r c h iv o .w r ite (" o S r . "+apel1id o + " :\n ” ) a r c h iv o .w r ite (" L e e sc rib o para re c o rd a rle l a o fe rta ") a rc h iv o .w rite (" q u e le enviamos l a semana pasada. Todos en " ) a rc h iv o .w rite (c iu d a d + " saben lo excepcional que es e s ta o fe rta " ) a r c h iv o .w r it e (" (e n e sp e c ia l lo s que tienen encantadores o jo s c o lo r "+ c o lo r0 jo s + "). " ) a rch iv o .w rite ("E sp e ra m o s escuchar n o tic ia s suyas p ro n to .\n ") a r c h iv o .w rite (" S in c e ra m e n te ,\n " ) a r c h iv o .w r it e ( " L ic . Tramposo,\nAbogado") a r c h iv o . c lo s e Q
Cómo funciona Esta función recibe el sexo, apellido (nombre de familia), ciudad y color de ojos como entra da. Abre un archivo llamado cartaModelo.txt y después escribe una apertura personalizada con el sexo del destinatario. Escribe varias líneas de texto, insertando la entrada en los luga res correctos. Después cierra el archivo. Al ejecutar este programa con ca rtaM o d elo ("M ", " G u z d ia l" , " D e c a tu r" , " c a f é " ) , genera lo siguiente: Querido S r . G u z d ia l: Le e sc rib o para re c o rd a rle l a o fe rta que le enviamos la semana pasada. Todos en Decatur saben lo excep cio nal que es e sta o fe rta (en e sp e cia l lo s que tie n e n encantadores o jo s c o lo r c a f é ) . Esperamos escuchar n o t ic ia s suyas pronto. Sinceram ente, L i c . Tramposo, Abogado
10.4.3 Escritura de programas Ahora vamos a empezar a usar archivos. Nuestro primer programa hará algo interesante: es cribiremos un programa para modificar otro programa. Leeremos el archivo imagenChica.py
258
C a p ítu lo lO
Creación y m odificación de texto
y modificaremos la cadena de texto que se inserta en la imagen. Usaremos find() para buscar la función addText ( ) y luego buscaremos cada una de las comillas dobles. Después escribiremos un nuevo archivo con todo lo que contiene imagenChica.py hasta la primera comilla doble, insertaremos nuestra nueva cadena y colocaremos el resto del archivo desde la segunda comilla doble hasta el final.
fro g ra m a 9 2 : un programa para modificar el programa inagenChica
def m o d ificarC hica(no m brearchivo,n uevaC ad en a): # Obtener e l contenido del a r c h iv o o r ig in a l archivoProgram a="im agenChica.py" a r c h iv o = o p e n (a rch iv o P ro g ra m a ,"rt") contenido = a r c h iv o .r e a d ( ) a r c h i v o .c l o s e ( )
# Ahora, en co n trar e l lu g a r c o rre c to para co lo ca r n u e stra nueva cadena posAgregar = c o n te n id o .fin d ("a d d T e x t") #C om illa doble después de addText prim eraCo m illa = c o n t e n id o .f in d ( * p o s A g r e g a r ) #Com illa doble después de p rim eraC o m illa u ltim aC o m illa = c o n t e n id o .f in d ( .p r im e r a C o m i11a+1) # C rear nuestro nuevo a r c h iv o nuevoArchivo = open(nom brearchivo,"w t") n u e vo A rch ivo .w rite(co n te n id o [:p rim eraC o m i1 1 a+ l]) # in c lu y e l a c o m illa nuevoA rchivo.w rite(nuevaCadena) n u e vo A rch ivo .w rite (c o n te n id o [u ltim a C o m illa :]) n u e v o A rc h iv o .e lo se ()
Cómo funciona Este programa abre el archivo imagenChica.py (el nombre asum e que está en el directorio JES, ya que no se proporciona ninguna ruta). Lee todo como una gran cadena y después cierra el archivo. Mediante el uso del método fi nd encuentra la posición de addText, de la primera comilla doble y de la última comilla doble. Después abre un nuevo archivo (para es cribir texto: “wt”) y escribe todo lo del programa imagenChica.py hasta la primera comilla doble. Luego escribe la cadena de entrada y a continuación escribe el resto del programa, partiendo de la última comilla doble. De esta forma, reemplaza la cadena que se agrega. Por último, cierra el nuevo archivo. Al ejecutar este programa con modifi carChi ca("muestra.py", "Esta es una mues tra de cómo modificar un programa"),obtenemos muestra.py: def im ag e n ch icaO : 1i enzo=makePi cture(getM edi aP ath("640x480. jp g " )) a d d T e x t(T ie n z o ,1 0 ,5 0 ,"E sta es una muestra de cómo m o d ifica r un programa") addLi ne(1 i enzo,1 0 ,2 0 ,3 0 0 ,5 0 ) ad d R ectFi11ed(1 ie n z o ,0 ,2 0 0 ,3 0 0 ,5 0 0 ,y e l1ow) addRect(1 i enzo,1 0 ,2 1 0 ,2 9 0 ,4 9 0 ) re tu rn lie n z o
Así es como funcionan los programas de dibujos basados en vectores. Al modificar una lí nea en AutoCAD, Flash o Illustrator, en realidad cambiamos la representación subyacente de
Sección 10.4
Archivos: lugares en donde puede colocar sus cadenas y otras cosas
259
la imagen; en un sentido real, un pequeño programa cuya ejecución produce la imagen con la que trabajamos. Al modificar la línea, en realidad estamos modificando el programa, que después se vuelve a ejecutar para mostrarnos la imagen actualizada. ¿Es lento este proceso? Las computadoras son tan rápidas que ni siquiera lo notamos. Es muy importante poder manipular texto para recopilar datos en Internet. La mayoría de Internet consiste tan sólo en texto. Vaya a su página Web favorita y use la opción V i e w S o u r c e (V e r C ó d ig o F u e n t e ) ( o algo parecido) en el menú. Ése es el texto que define la página que vemos en el navegador. Más adelante aprenderemos a descargar páginas directa mente desde Internet, pero por ahora supongamos que tenemos páginas o archivos de Inter net guardados (descargados) en el disco duro y realizaremos búsquedas desde ahí. Por ejemplo, hay lugares en Internet de donde podemos obtener secuencias de nucleótidos asociados con cosas como parásitos. Yo encontré un archivo de este tipo que tiene la siguiente apariencia: > Schisto unique AA825099 gcttagatgtcagattgagcacgatgatcgattg accgtg agatcg acga gatgcgcagatcgagatctgcatacagatgatgaccatag tgtacg > Schisto unique mancons0736 t tc tc g c tc a c a c ta g a a g c a a g a c a a ttta c a c ta tta tta tta tta tt a c c a tta tta tta tta tta tta c ta tta tta tta tta tta c ta tta ttta c ta c g tc g c tttttc a c tc c c ttta ttc tc a a a ttg tg ta tc c ttc c ttt
Suponga que tenemos una subsecuencia (como “ttgtgta”) y queremos saber de qué pa rásito forma parte. Si leemos este archivo y lo colocamos en una cadena, podríamos bus car la subsecuencia. Si está ahí (es decir, si el resultado de f i n d no es igual <> a -1 ), retrocedemos desde ahí para encontrar el que comienza el nombre de cada parásito y luego avanzamos hacia el fin de línea (carácter de nueva línea) para obtener el nombre del archivo. Si no encontramos la subsecuencia (si f i n d ( ) devuelve un -1 ), entonces no se encuentra ahí.
Programa 93: buscar una subsecuencia en secuencias de nucleótidos de parásitos
def b u sc a rS e c u e n c ia (se c ): arch ivo Se cu e n cia s = g e tM e d ia P a th ("p a ra s ito s .tx t" ) a r c h iv o = o p e n (a rc h iv o S e c u e n c ia s ,"rt" ) secu en cias = a r c h iv o .r e a d ( ) a r c h iv o .c lo s e O
# Buscar l a secuencia ubicaSec = s e c u e n c ia s .fin d (s e c ) # p r in t "Se encontró e n :" ,u b ic a S e c i f ubicaSec o - 1 : # Ahora, buscar e l ">" con e l nombre de l a secuencia ubicaNombre = s e c u e n c ia s .rfin d (" > " ,0 ,u b ic a S e c ) # p r in t "Nombre en:".ubicaNom bre f in lin e a = se cu e n cia s.fin d ("\n ",u b ic a N o m b re ) p r in t "Se encontró en ".se c u e n c ia s[u b ic a N o m b re :fin lin e a ] i f ubicaSec == - 1 : p r in t "No se encontró"
260
C a p ítu lo lO
Creación y m odificación de texto
Cómo funciona La función buscarSecuencia recibe una parte de una secuencia como entrada. Abre el archivo parasitos.txt (en la carpeta de medios especificada mediante setMediaPath), lee todos los datos y los coloca en la cadena secuenci as. Para buscar la secuencia en la cadena secuencias usamos find. Si se encuentra (es decir, que el resultado no sea -1 ), entonces buscamos hacia atrás partiendo desde donde encontramos la secuencia (ubicaSec) hacia el principio de la cadena (0) para encontrar el “>” que inicia la secuencia. Luego buscamos hacia delante partiendo desde el signo “m ayor que” hasta el final de la línea (“\n”). Esto nos indica en qué parte de la cadena secuencias original podemos encontrar el nombre del parásito del que proviene nuestra subsecuencia de entrada. Leemos todo el contenido del archivo y lo colocamos en una cadena grande, y después pro cesamos esa cadena. Pero, si tenemos archivos muy grandes tal vez sea más conveniente procesar el contenido una línea a la vez. Para ello podemos usar la función readl ines, que devuelve una lista de cadenas con una cadena por cada línea del archivo. Por ejemplo, si de sea modificar cada ocurrencia de una cadena en un archivo, podría usar la siguiente función.
fro g ra m a 9 4 : reemplazo de todas las ocurrencias de una palabra en un archivo
def reem plazarPalabra(nom breArchivo, p alab raO ri g , palabraReem p): a r c h iv o = o p en (n o m b reA rch ivo ,"rt") arch iv o S a l = open ( " s a l- " + nom breA rchivo,"w t") fo r lin e a in a r c h i v o . r e a d lin e s ( ) : nuevaLinea = lin e a .re p la c e (p a la b ra O rig ,p a la b ra R e e m p ); a r c h iv o S a l.w rite (n u e v a L in e a ) a r c h i v o .c l o s e ( )
a r c h iv o S a l.c ió s e O
Hay programas que vagan por Internet, recopilando información de páginas Web. Por ejem plo, la página de noticias de Google (http://news. googl e . com) no está escrita por reporte ros. Google tiene programas que obtienen los encabezados de otros sitios de noticias. ¿Y cómo funcionan estos programas? Lo único que hacen es descargar páginas de Internet y extraer las piezas deseadas. Por ejemplo, digamos que usted desea escribir una función para obtener la temperatura actual, leyéndola de una página del clima local. En Atlanta, una buena página del clima es http://www.ajc.com/weather: la página del clima de Atlanta Journal-Constitution. Al examinar el código fuente podemos descubrir en dónde aparece la temperatura actual en la página y cuáles son las características clave del texto a su alrededor para extraer sólo la temperatura. A continuación le mostramos la parte relevante de la página que Mark encontró un día:
inicia un párrafo y
lo termina. Las páginas Web tienen varias partes y éstas se anidan entre sí. La primera es doctype en la parte superior de la página y anuncia el tipo de página (es decir, si el navegador debería tratar de interpretarla como HTML, XHTML, CSS u otra cosa). Después del tipo de docu mento vienen un encabezado (< h e a d > .. .< /h e a d > ) y un cuerpo (< b o d y > .. .). El encabezado puede contener información como el título anidado en su interior: el título se acaba antes de que termine el encabezado. El cuerpo tiene muchas piezas anidadas en su in terior, como encabezados (hl empieza y termina antes de que termine el cuerpo) y párrafos. Todo el cuerpo y el encabezado se anidan dentro de un conjunto de etiquetas < h tm l> .. . < / htm l>. La figura 12.1 muestra el código fuente de una página Web simple y la figura 12.2 muestra cómo aparece la página en Internet Explorer. Pruebe esto por su cuenta. Escriba el código en JES, guárdelo con un sufijo de archivo .html y luego ábralo en un navegador Web. La única diferencia entre este archivo y cualquier página Web es que el primero se encuentra en su disco. Si estuviera en un servidor Web, sería una página Web. _________________________________ \ sí,Este es un párrafo en la página No im porta en dónde Web más simple posible.
coloca los retornos __________________________ de carro ni los espacios adicionalesEste es un párrafo en la página Web
más simple posible.
Este es un párrafo en la página Web < br/> más sim ple posible.
Aquí está un vínculo a < a href= i* i 4 4 r t , / / 4 i 1'http://www.cc.gatech.edii/~niark.guz d ial/"> M ark Guzdial
. • Podemos crear listas con viñetas (listas desordenadas) y listas numeradas (listas orde nadas) si usamos las etiquetas
A1go de te x to simp1e.
¡Ho1a! Soy """+ n o n b re + """. E s ta es mi página de i n i c i o . Este es mi in t e r é s : """+ in teres+ """< /p > """) a r c h iv o .c lo s e O
Sección 12.2
Escritura de program as para generar H TM L
29 5
Así, al ejecutar crear P a g in a ln i c ió (" B a rb " , " c a b a llo s " ) se creará la siguiente página:
¡Hola! Soy B arb. E s ta es mi página de i n i c i o . Este es mi in t e r é s : caballos
¡Hola! Soy ,,,,"+no■lbre+"", , . E s ta es mi página de i n i c i o . E ste es mi in t e r é s : IV IV IV , • - 4 . - . - - - , IV IV IV . IV IV IV N + in teres+
)) a r c h iv o .c lo s e O d ef d o cty p e O : re tu rn ‘ * def t it l e ( c a d e n a t it u lo ) : re tu rn "< htm l> < head > < title> "+ cad enatitulo + "< /titlex/head > " def body(cadenacuerpo): re tu rn ""+cadenacuerpo+""Nombre del archivo: anthony.jpg<¡mage src="anthony.jpg"height='TOO,'/x / p >
Nombre del archivo: archjpg-ámage src="arch.jpg,lheight=,T00"/>
Nombre del archivo: arthurs-seatjpg
Norabre del archivo: barbara.jpg<¡mage src="barbara.jpg"height=,TOO"/x/p>
Norabre del archivo: beach.jpg<ámage src=" beach.jpg "height=’'100 ’'/x /p >
Nombre del archivo: bigben.jpg<ámage src="bigben.jpg''height="l 00 " /x /p >
FIGURA 12.7 Creación de una página de miniaturas. Fuente: Captura de pantalla de Internet Explorer 8. Copyright © 2009 por Microsoft Corporation. Reimpreso con permiso.
Podemos obtener contenido para nuestras páginas Web de cualquier lugar que nos guste. A continuación veremos un programa que puede extraer información de un directorio propor cionado como entrada, para luego generar una página índice de esas imágenes (figura 12.7). No vamos a listar a d o c ty p e O ni a las demás funciones utilitarias en este ejemplo; sólo nos enfocaremos en la parte que nos importa. Y así es como deberíamos considerarlo: sólo la parte que nos importa; escribimos d o c ty p e O una vez y luego nos olvidamos de ello.
P ro g ram a 11 1: generación de una página de miniaturas
import os def crearPag inaM u estra(d i r e c t o r io ) : archivo M uestras.o p en(d i re c to rio + "//m u e stra s. htm l" , "w t") a rc h i voMuest r a s . w rite (d o c ty p e O ) a rc h iv o M u e s tra s .w r ite (titie (" M u e s tr a s de " + d ire c to rio )) # Ahora, vamos a c re a r l a cadena que form ará e l cuerpo. muestras="
Nombre del a rc h iv o : "+ archivo muestras=muestras+’
¡Hola! Soy """+ nonbre+ """. E s ta es mi página de in i c i o . E sto s son mis in t e r e s e s : """+ fb A ctiv id a d e sIn te re se s(fb N o m b re )+ """< /p > """)) a r c h iv o .c lo s e O def fb A c tiv id a d e s In te re s e s (n o n b re ): im port u r l l i b # Podría i r a r r ib a también in t e re s e s = "" conexión = u r llib .u r lo p e n ( " h ttp ://w w w .facebook.com/ "+nonbre+"?ref=pb") fb = conexió n. re a d () conexión. c lo s e O a c t ln ic io = f b .f in d ( " a c t iv it ie s _ a n d _ in t e r e s t s " ) ubicPagina = a c t ln ic io # Lugar de in i c io para buscar páginas i f a c t ln ic io o - 1 : # ¿Encontramos A c tiv id a d e s e in te re s e s ? ubicPagina = f b .f i n d ( " http://w w w .faceb o ok.co m /pages/",ub icPag) w h ile (u b icP a g in a o - 1 ) : in t e r e s ln ic io = ubicPagina+30 # Para " http://w w w .facebook.com / pages/" in t e r e s F in = f b .f in d ( " / " ,i n t e r e s I n ic io + l ) Ín t e r e s = f b [ in t e r e s I n ic io :in t e r e s F in ] i f not (" fo o t e r " in Í n t e r e s ) : in te re s e s = in t e r e s e s + f b [ in t e r e s In ic io :in t e r e s F in ] + " ," ubicPagina = f b .f in d ( " h t t p / / www.facebook.com/pages/" , ubicPagina+1) e ls e : ubicPagina = -1 re tu rn i n t e r e s e s [ :- l ]
,Recuerda el generador de enunciados aleatorios? También podemos agregarlo.
Programa 113: generador de páginas de inicio con enunciados aleatorios
im port u r l l i b im port random d ef c re a rP a g in a In ic io (n o m b re , fbNombre): archivo=open("C:/U sers/M arkGuzdial/D ocum ents/pagin a in ic io .h t m l" , "w t") a rc h iv o .w rite (d o c ty p e O ) a r c h iv o .w r it e ( t it le ( " P á g in a de in i c i o de"+nonbre)) a r c h iv o .w rite (b o d y (" " "
29 7
298
Capítulo 12
Creación de texto para la W eb
¡Hola! Soy ,,""+nonbre+""". E s ta es mi página de i n i c i o . Esto s son mis in t e r e s e s : ,M,,,+ fbA ctividadesIntereses(fbN om bre)+ """< /p> < p> Reflexión a le a t o r ia del di a : +enunciado()+"
")) a r c h iv o .c lo s e O d ef e n u n cia d o (): s u s ta n tiv o s = ["M ark” , " A l i c i a " , "M a ria ", " L a t r ic e " , " Jo s é " , "C o re y", "Teshaun"] verbos = [" c o r r e " , " p a tin a " , " c a n ta " , " b r in c a " , " s a l t a " , " t r e p a " ," d is c u t e " , " r íe " ] fr a s e s = ["en un á r b o l" , "sobre un tro n c o ", "muy f u e r t e " ,"alre d e d o r del a rb u sto ", "m ientras le e e l p e rió d ic o "] fr a s e s = fr a s e s + ["muy m a l", "m ie n tras p a t in a " ,"en vez de c a l i f i c a r " , "m ie n tras e s c rib e en In t e r n e t " ] re tu rn ra n d o m .ch o ice (su sta n tivo s)+ " "+random .choice(verbos)+ " "+ ra n d o m .c h o ic e (fra se s)+ "." def fb A c tiv id a d e sln te re se s (n o m b re ): im port u r l l i b # Po dría i r a r r ib a también in te re s e s = "" conexión = u r llib .u r lo p e n ( " h ttp ://w w w .facebook.com/ "+nonbre+"?ref=pb") fb = c o n e x ió n .re a d () c o n e x ió n .c ió s e O a c t ln ic io = f b .f in d ( " a c t iv it ie s _ a n d _ in t e r e s t s " ) ubicPagina = a c t ln ic io # Lugar de in i c io para buscar páginas i f a c t ln ic io o - 1 : # ¿Encontramos A c tiv id a d e s e in te re s e s ? ubicPagina = f b .f i n d ( " http ://w w w .faceb o ok.co m /pages/",ub icPag) w h ile (u b icP a g in a o - 1 ) : in t e r e s ln ic io = ubicPagina+30 # Para " http://w ww .facebook.com / pages/" in t e r e s F in = f b .f in d ( " / " ,i n t e r e s I n ic io + l ) ín t e r e s = f b [ in t e r e s I n ic io :in t e r e s F in ] i f not (" fo o t e r " in ín t e r e s ) : in te re s e s = in t e r e s e s + f b [ in t e r e s In ic io :in t e r e s F in ] + " ," ubicPagina = f b .f in d ( " h t t p / / www.facebook.com/pages/" , ubicPagina+1) el se: ubicPagina - -1 re tu rn i n t e r e s e s [ :- l ] ~l Estas líneas del program a deben continuar con las siguientes líneas. Un solo com ando en Python no puede dividirse en varias líneas.¡Hola! Soy """+no■tbre+",,,,. E s ta es mi página de in i c i o . E sto s son mis in t e r e s e s : ,M,"+ fbA cti vid ad esIntereses(fb N o m b re)+ ",M,
Reflexión a le a t o r ia del d ia : " " "+enunci ado( ) + " " "
'M,,,+db [ “ hi s t o r i a ,,]+ ,,
")) a r c h iv o .c lo s e O d b .c lo s e O # El re s t o , como enunciadoO , de lo s ejemplos a n te rio re s"+cadena+"
" def t it l e ( c a d e n a t it u lo ) : re tu rn " < titie > "+ c a d e n a titu lo + "< /titie > " d ef fin B o d y O : re tu rn ,," d ef fin H TM L(): re tu rn ""Nombre del a rc h iv o : "+archivo+"
" muestras=muestras+’
La acción de dividir las piezas de esta forma es parte de la abstracción procedural. Los pasos en la abstracción procedural son: • Declarar el problema. Averiguar lo que desea hacer. • Dividirlo en subproblemas. • Seguir dividiendo los subproblemas en problemas más pequeños hasta que sepa cómo escribir el programa que resuelva ese problema más pequeño. • Su objetivo es que la función principal indique en esencia a todas las subfunciones qué deben hacer. Cada subfunción debe realizar una y sólo una tarea lógica. Podemos pensar en la abstracción procedural como llenar un árbol de funciones (vea la fi gura 15.1). Realizar modificaciones es cuestión de cambiar un nodo (función) en este árbol y realizar adiciones es cuestión de agregar un nodo. Por ejemplo, para agregar la funcionalidad de manejar archivos WAV en nuestra página de muestras sólo hay que cambiar la función e n tr a d aAr c h iv o cuando se divide de esta forma (figura 15.2).
FIGU RA 15.1 Una jerarquía de funciones para crear una página de muestras.
O e a r u n a p ág in a de m u estra*
A b rir u n archivo d e HTM L
B tcrib ir la decta r a d ó n D ocType
B u r i h i r d títu lo
C re a r d cuerpo
E sc rib ir d cu erp o
* f t o c o a r c ad a JP E G ,
P ro c e sa r ca d a WAV J
L
J
FIGU RA 15.2 Cambiar el programa sólo es cuestión de realizar un ligero cambio en la jerarquía.
15.2
PROGRAMACIÓN FUNCIONAL MEDIANTE ASOCIACIÓN (MAP) Y REDUCCIÓN (REDUCE) Si está dispuesto a confiar en sus funciones, puede escribir menos líneas de código y lograr escribir los mismos programas. Cuando llega a comprender las funciones de verdad y confía en
Sección 15.2
Program ación funcional m ediante asociación (map) y reducción (reduce)
359
que realizarán lo que usted les indicó, puede hacer cosas sorprendentes en unas cuantas líneas de código. Podemos escribir funciones que apliquen otras funciones a los datos, e incluso ha gan que se llamen a sí mismas en un proceso conocido como recursividad. Las funciones son sólo nombres que se asocian con valores que son piezas de código, en vez de listas, secuencias, números o cadenas. Para invocar o llamar a una función declaramos su nombre seguido de las entradas entre paréntesis. Sin ellos, el nombre de la función aún tiene un valor: es el código de la función. Las funciones también pueden ser datos: ¡pueden pasarse como entradas a otras funciones! p r in t crearPaginaM uestra
La función appl y O recibe otra función como entrada, además de las entradas (como una secuencia o lista) para esa función. En sentido literal, appl y () aplica la función a la entrada. def h o la (a lg u ie n ): p r in t " H o la ," , alg u ie n » > h o la("M a rk") H ola, Mark » > a p p ly (h o la , ["M a rk "]) H ola, Mark » > a p p ly (h o la ,[ " B e t t y " ]) H ola, B e tty
Hay una función más útil que recibe otras como entrada: su nombre es map(). Es una función que recibe una función y una secuencia como entradas. Sólo que map aplica la fun ción a cada entrada en la secuencia y devuelve cualquier cosa que devuelva la función para cada entrada. » > m ap(hola, [" M a rk "," B e tty "," M a tth e w " ,"Je n n y "]) H ola, Mark H ola, B e tty H ola, Matthew H ola, Jenny [None, None, None, None]
La función fi 1ter () también recibe una función y una secuencia como entradas. Aplica la función a cada elemento de la secuencia. Si el valor de retorno de la función en ese ele mento es verdadero (1), entonces el filtro devuelve ese elemento. Si el valor de retorno es falso (0), entonces el filtro omite ese elemento. Podemos usar fi lter() para extraer con rapidez ciertos datos que sean de nuestro interés. def rEnNombre(unNombre): # fin d devuelve -1 cuando no encuentra nada i f u n N o m b re .fin d ("r") == - 1 : re tu rn 0 # s i no es -1 entonces encontró algo i f u n N o m b re .fin d ("r") != - 1 : re tu rn 1
360
Capítulo 15
Program ación funcional
» > rEnNombre("Enero") 1 » > rEnN o m bre("Julio ")
0 > » f i 1ter(rEnN om bre, ["M ark", " B e t t y " , "Matthew", "Je n n y " ]) [ ’ Mark’ ]
Podemos reescribir la función rEnNombreO anterior (una función que devuelve verda dero si la palabra de entrada contiene una ‘r ’) de una manera mucho más corta. En realidad las expresiones se evalúan en 1 o 0 (verdadero o falso). Podemos realizar operaciones sobre estos valores lógicos. Uno de estos operadores lógicos es not: devuelve lo opuesto de su valor de entrada. Entonces aquí está rEnNombreO escrita usando operadores lógicos. def rEnNombre2(unNombre): re tu rn n o t(u n N o m b re .fin d ("r") == -1 ) > » f i 1ter(rEnNom bre2, ["M ark", " B e t t y " , "Matthew", " Je n n y " ]) [ ’ Mark’ ]
La función reduce( ) también recibe una función y una secuencia, sólo que reduce combina los resultados. A continuación le mostramos un ejemplo donde sumamos el total de todos los números: 1 + 2, después (1 + 2) + 3, luego (1 + 2 + 3) + 4 y, por último, ( 1 + 2 + 3 + 4) + 5. El total hasta ese punto se pasa como la entrada a. d ef s u m a r(a ,b ): re tu rn a+b » > reduce(sum ar, [ 1 , 2 , 3 , 4 , 5 ] ) 15
Analicemos de nuevo el ejemplo: ¿acaso no parece un desperdicio tener que crear esa fun ción sumar, puesto que es tan pequeña y casi no hace nada? Resulta ser que no tenemos que asignar un nombre a una función para poder usarla. A una función sin nombre se le conoce como 1ambda. Éste es un término muy antiguo en ciencias computacionales, que se remonta a uno de los lenguajes de programación originales: Lisp. En cualquier parte donde se utilice el nombre de una función, podemos sustituirlo por una 1ambda. La sintaxis de una 1ambda es la palabra 1ambda seguida de variables de entrada separadas por comas, después un signo de dos puntos y luego el cuerpo de la función. Ahora veremos algunos ejemplos, incluyendo el ejemplo anterior de reduce recreado con 1ambda. Como podemos ver, es posible definir funciones que sean casi idénticas a las que se escriben en el área del programa si se asigna un nombre a una lambda. » > reduce(lambda a ,b :a + b , [ 1 , 2 , 3 , 4 , 5 ] ) 15 » > (lambda a :" H o la ,"+ a )(" M a rk " ) ’ H ola.M ark’ » > f=lambda a :" H o la , "+a »> f < function
Podemos realizar cálculos reales por medio de reduce y lambda. He aquí una función que calcula el factorial del número que recibe. El factorial de un número n es el producto
Sección 15.2
Program ación funcional m ediante asociación (map) y reducción (reduce)
361
de todos los enteros positivos menores o iguales a n. Por ejemplo, el factorial de 4 es (4 * 3 *
2 * 1).
Programa 140: cálculo del factorial m ediante el uso de lanbda y reduce
def f a c t o r ia l( a ) : re tu rn reduce(lambda a ,b :a * b , r a n g e (l,a + l))
Cómo funciona Es más fácil leer este programa de derecha a izquierda. Lo primero que hacemos es crear una lista de todos los números desde 1 hasta a con la instrucción range(l,a+l). Después usamos reduce para aplicar una función (la 1ambda) que multiplica todos los números en la lista de entrada, uno por el siguiente, por el siguiente y así hasta terminar. » > f a c t o r ia l (2 ) 2
» > f a c t o r ia l (S ) 6 » > f a c t o r ia l (4 ) 24 » > f a c t o r ia l (1 0 ) S628800
Tal vez esté pensando en este momento: “M uy bien, se ve que map, filter y reduce podrían ser útiles. Tal vez. Algunas veces. Pero ¿por qué rayos querría alguien usar apply? Es lo mismo que sólo escribir la función nosotros mismos, ¿o no?”. Esto es cierto, aunque en sí podemos crear map, fi 1ter y reduce si usamos appl y. Podemos literalmente crear cualquier versión de estas funciones que deseemos si usamos apply. def m iM a p (fu n c io n ,lis t a ): fo r i in l i s t a : a p p ly ( f u n c io n ,[ i] ) » > miMap(hola, ["P e d ro ","P a b lo ” ," V ilm a " ," B e t t y ” ] ) H ola, Pedro H ola, Pablo H ola, Vilm a H ola, B e tty
Este estilo de programación se conoce como program ación funcional. Lo que hemos estado haciendo en Python hasta ahora podría llamarse programación p o r procedimientos, ya que nos enfocamos en definir procedimientos, o programación interactiva debido a que en esencia indicamos a la computadora que realice acciones y modifique los valores de variables (lo que también se conoce como estado). En la programación funcional las ideas clave son enfocarse en las funciones como datos y en las funciones que usen otras funciones como entrada. La programación funcional es sorprendentemente poderosa. Aplicamos capas sobre capas de funciones a otras funciones y terminamos haciendo mucho en unas cuantas líneas de código
36 2
Capítulo 15
Program ación funcional
de programa. La programación funcional se usa en la creación de sistemas de inteligencia artificial y en la construcción de prototipos. Éstas son áreas en donde los problemas son di fíciles y no están bien definidos, por lo que es conveniente poder hacer mucho con sólo unas cuantas líneas de código de programa; incluso aunque esas líneas sean bastante difíciles de leer para la mayoría de la gente.
15.3
PROGRAMACIÓN FUNCIONAL PARA MULTIMEDIA ¿Recuerda la función para convertir a Katie en pelirroja (programa 36, página 110)? Aquí está de nuevo: d ef c o n v e rtírE n R o jo (): ca fe = m akeC olo r(42,25,15) a rch iv o = "C :/ip -b o o k /m e d ia so u rce s/ka tie F a n cy.jp g " i magen=makePi ctu re (a rc h iv o ) fo r px in g e tP ix e ls (im a g e n ): c o lo r = g e tC o lo r(p x) i f d is t a n c e (c o lo r,c a fe )< 5 0 .0 : n iv e lro jo = in t(g e tR e d (p x )* 2 ) n iv e l azu l= g etB lu e(p x) n iv e l verde=getGreen(px) se tC o lo r(p x,m a k e C o lo r(n iv e l r o jo ,n iv e l a z u l, n iv e l v e rd e )) show(imagen) return(im agen)
Podemos escribirlo como una sola línea de código de programa. Necesitamos dos fun ciones utilitarias: una que verifique un pixel individual para ver si deseamos convertirlo en rojo y otra que realice esa acción. Nuestra línea individual de código de programa filtra los píxeles que coinciden con nuestro criterio de cambio y después asocia la función de cambio a esos píxeles. En la programación funcional no escribimos funciones con ciclos extensos. En vez de ello escribimos funciones pequeñas y las aplicamos a los datos. Es como si llevá ramos la función a los datos, en vez de hacer que la función vaya y obtenga todos los datos.
P ro g ram a 14 1: convertir el cabello en rojo, m edíante programación funcional
def co n v e rtí rC ab eTlo R o jo (im ag ): m ap(converti rEnR o jo , f i 1t e r ( v e r i f i c a rP i x e l , g etPi x e ls (im a g ))) def v e r i f ic a r P ix e l ( u n P ix e l) : ca fe = m akeC olo r(42,25,15) re tu rn d ista n c e (g e tC o 1 o r(u n P ix e l) , c a f e ) <50.0 def c o n v e rtírE n R o jo (u n P ix e l): s e tR e d (u n P ix e l,g e tR e d (u n P ix e l)* 2 )
Cómo funciona La función c o n v e r tí rEnRo jo recibe un pixel individual y duplica su porcentaje de nivel de rojo. La función v e r i f i c a rP i xel devuelve verdadero o falso si un pixel de entrada está lo
Sección 15.3
Program ación funcional para m ultim edia
363
bastante cerca del color café. La función convertí rCabel loRo jo recibe una imagen como entrada y luego aplica veri fi carPi xel mediante fi 1ter a todos los píxeles en la imagen de entrada (usando getPi xel s). Si el pixel es lo bastante café, fi 1ter lo devuelve. Después usamos map para aplicar convertí rEnRo jo a todos los píxeles devueltos por fi 1ter. A sí es como se usa: » > imag=makePi cture(getM ediaPath( " K a tie F a n c y .jp g " )) » > m ap (co n ve rtirEn R o jo , f i l t e r ( v e r i f i c a r P i x e l , g e t P ix e ls (im a g )))
15.3.1
Manipulación de medios sin cambiar de estado
Otro aspecto importante de la programación funcional es el de programar sin estado. N ues tras funciones de manipulación de colores (por ejemplo) modifican el objeto que se provee a la función como entrada. Los buenos programas funcionales no hacen eso. Si va a modificar un objeto, un buen programa funcional realiza una copia del objeto, luego lo modifica y devuelve el objeto copiado. La ventaja es que podemos anidar funciones, pasando la salida de una a la entrada de la otra, así como podemos anidar las funciones matemáticas. Nadie espera que seno(coseno(x)) modifique a x más de lo que seno(x) modifica a x. Las funciones en el estilo de programación funcional deben trabajar de la misma forma. Decimos que estas funciones no tienen efectos secundarios. Las funciones sólo hacen lo que se supone deben hacer y devuelven un resultado. No modifican las entradas de ninguna forma. Veamos cómo sería crear funciones de manipulación de medios que no cambien el estado.
Programa 142: modificación de colores sin cambiar la imagen
def red u cirR o jo (u n alm ag en ): imagDev - m akeEm ptyPicture(getW idth(unaIm agen),getH eight(unaIm agen)) fo r x in range(getW idth(unaIm agen)): fo r y in rang e(g etH eig ht(unaIm ag en)): p ix e lO rig = g e tP ix e lA t(u n a Im a g e n ,x ,y ) p ixe lD e v = g e tP ix e lA t(im a g D e v ,x ,y ) s e t C o lo r(p ix e lD e v ,g e tC o lo r(p ix e lO rig )) se tR e d (p ixe lD e v , 0 .8 * g e tR e d (p ix e lO rig )) re tu rn imagDev def aum entarAzul(unalm agen): imagDev = m akeEm ptyPicture(getW idth(unaIm agen),getH eight(unaIm agen)) fo r x in range(getW idth(unaIm agen)): fo r y in rang e(g etH eig ht(unaIm ag en)): p ix e lO rig = g e tP ix e lA t(u n a Im a g e n ,x ,y ) p ixe lD e v = g e tP ix e lA t(im a g D e v ,x ,y ) s e t C o lo r(p ix e lD e v ,g e tC o lo r(p ix e lO rig )) s e tB lu e (p ix e lD e v , 1 .2 * g e t B lu e (p ix e lO rig )) re tu rn imagDev
364
Capítulo 15
Program ación funcional
Cómo funciona Ambas funciones tienen la misma estructura básica Se crea un objeto a devolver (imagDev) del mismo tamaño que la imagen de entrada. Para cada pixel en la imagen de entrada, copia mos el color al pixel correspondiente en la imagen imagDev. Después reducimos el rojo o aumentamos el azul. Por último, devolvemos la imagDev. Podemos aplicar estas funciones a una imagen sin cambiar la imagen original. Podemos anidar las funciones de cualquier forma que deseemos. Ahora las funciones son mucho más parecidas a las funciones matemáticas. »> »> »> »> »>
15.4
nuevalmag = au m entarA zu l(re d u cirR o jo (im ag )) show(nuevalmag) sh o w (red u cirR o jo (im a g )) sho w (red u cirR o jo (au m e n tarA zu l(im ag ))) show(aum entarAzul(im ag))
RECURSIVIDAD: UNA IDEA PODEROSA La recursividad implica escribir funciones que se llamen a sí mismas. En vez de escribir ciclos, escribimos una función que itera al llamarse a sí misma una y otra vez sin detenerse. Cuando escribimos una función recursiva, siempre tenemos al menos dos partes: • Qué hacer cuando termine (por ejemplo, cuando se procesa el último elemento en los datos), y • Qué hacer cuando los datos son más grandes, lo cual por lo general implica procesar un elemento de los datos y luego volver a llamar la función para lidiar con el resto. Vamos a explorar la recursividad con algunas funciones textuales simples, antes de atacar los medios con recursividad. Considere la forma en que podríamos escribir una función que haga lo siguiente: » > a b a jo A rrib a ("H o la ") Hola o la la a la o la Hola
La recursividad puede ser algo difícil de digerir mentalmente. En realidad depende de que confiemos en nuestras funciones. ¿Hace la función lo que se supone debe hacer? Entonces sólo hay que llamarla y hará lo correcto. Vamos a hablar sobre la recursividad de tres formas para ayudarle a comprender este concepto. La primera forma es la abstracción procedural: dividir el problema en las piezas más pequeñas que podamos escribir con facilidad como funciones y reutilizarlas lo más que se pueda.
Sección 15.4
Recursividad: una idea poderosa
365
Consideremos la función abajoArriba para palabras de un solo carácter. Eso es fácil: def abajoArribal(palabra): p r in t palab ra
» > a b a jo A r r ib a l( " I" )
Ahora veamos abajoArriba para palabras de dos caracteres. Reutilizaremos a b a jo Arri b a l porque ya la tenemos. def a b a jo A rrib a 2 (p a la b ra ): p r in t palab ra a b a jo A r r ib a l( p a la b r a [ l:] ) p r in t palab ra » > a b a jo A rrib a 2 (" tu ") tu u tu » > a b a jo A rrib a 2 ("y o ")
Ahora para palabras de tres caracteres: def a b a jo A rrib a 3 (p a la b ra ): p r in t palab ra a b a jo A rrib a 2 (p a l a b ra [ 1 : ] ) p r in t palab ra » > a b a jo A rrib a3 ("p o p ") pop op P op pop » > a b a jo A rrib a 3 (" to s " ) to s os s os to s
¿Ya descubrió el patrón? Vamos a probarlo: def p ru e b a A b a jo A rrib a (p a la b ra ): p r in t p alab ra p ru e b a A b a jo A rrib a (p a la b ra [l:]) p r in t p alab ra
36 6
Capítulo 15
Program ación funcional
» > p ru e b a A b a jo A rrib a ("h o la") hola o la la a The e rro r w a s :ja v a .la n g .S ta c k O v e rflo w E rro r I wasn’ t able to do what you wanted. The e rro r ja v a .la n g .S ta c k O v e rflo w E rro r has occured Please check Tiñe 101 o f C:\ip -b oo k\p rogram s\ fu n c tio n a l
El error es un poco distinto en Python regular, pero en esencia significa lo mismo: » > p ru e b a A b a jo A rrib a ("h o la") F i l e "< std in> ", lin e 3, in pruebaAbajoArriba F i l e "< std in> ", lin e 3, in pruebaAbajoArriba R untim eErro r: máximum re c u rsio n depth exceeded
¿Qué ocurrió? Al llegar a un carácter, seguimos llamando a pruebaArribaAbajo en forma repetida hasta quedamos sin memoria en un área conocida como la Pila. Necesitamos poder decir a nuestra función: “Si nos queda un solo carácter, sólo imprímelo y no te vuelvas a llamar a ti misma”. La siguiente función se ejecuta sin problemas.
frogram a 143: función a rrib a A b a jo recursiva
def a b a jo A rr ib a (p a la b ra ): p r in t palab ra i f le n (p a la b ra )= = l: re tu rn a b a jo A r r ib a (p a la b r a [l:] ) p r in t palab ra
■ He aquí nuestra segunda forma de pensar sobre la recursividad: ¡el infalible rastreo! In sertaremos comentarios con sangrías. » > a b a jo A rrib a ("H o la ")
1 en (p a l ab ra) no es 1, por lo que imprimimos la palabra
Hola Ahora llamamos a a b a jo A rrib a (" o la " ) Todavía no es un carácter, por lo que se imprime
Ahora llamamos a a b a jo A rr ib a (" la " ) Todavía no es un carácter, por lo que se imprime
Sección 15.4
Recursividad: una idea poderosa
367
la Ahora llamamos a a b a jo A r r ib a (" a " )
¡Es un carácter! Lo imprime y regresa mediante r e tu rn
a Ahora a b a jo A r r ib a (" la " ) continúa a partir de su llamada a a b a jo A rr ib a (" a " ) Imprime de nuevo y termina.
la Ahora a b a jo A r r ib a (" o la " ) continúa. Imprime y termina.
o la Por último, ahora puede ejecutarse la última línea de la función a b a jo A r r ib a (" H o la n) original.
H ola
Una tercera forma de pensar en esto es imaginar la invocación a una función como si fuera un elfo: una persona pequeña dentro de la computadora que va a hacer lo que usted le ordene. He aquí las instrucciones de ab a joA r r i ba para los elfos: 1. Aceptar una palabra como entrada. 2. Si la palabra tiene sólo un carácter, escribirla en la pantalla y terminar. Detenerse y sentarse. 3. Escriba su palabra en la pantalla. 4. Contrate otro elfo para que haga las mismas instrucciones y dé a ese elfo su palabra menos el primer carácter. 5. Espere hasta que el elfo que contrató termine. 6. Escriba su palabra en la pantalla de nuevo. Listo. Le sugiero probar esto en su propia clase; es divertido y ayuda a que la recursividad tenga sentido. Funciona de manera similar a esto: • Empezamos contratando a nuestro primer elfo con la entrada “Ahora”.
368
Capítulo 15
Program ación funcional
/ \ Ahora
(Considere esto como la abstracción de un elfo). El elfo que lleva la palabra “Ahora” sigue las instrucciones. Acepta la palabra como en trada, ve que tiene más de un carácter y escribe en la pantalla: Ahora. Después contrata a un nuevo elfo y le proporciona la entrada “hora” .
/ \ Ahora
hora
El elfo que lleva “hora” acepta la entrada, ve que tiene más de un carácter y la escribe en la pantalla (hora, justo debajo de Ahora). Después contrata un nuevo elfo y le en trega la entrada “ora” .
Ahora
hora
En este punto podemos hacer unas cuantas observaciones. Cada elfo sólo está cons ciente del elfo a su izquierda: el que contrató. Tiene que esperar a que ese elfo termine para que a su vez pueda terminar. Cuando los elfos empiezan a terminar, los primeros en terminar serán los que están a la derecha, que fueron los últimos contratados. A esto le llamamos pila: los elfos se “apilan” de izquierda a derecha y el último en entrar es el primero en salir. Si la entrada original fuera una palabra muy grande (por ejemplo, “supercalifragilisticoexpialidoso”), podríamos considerar que no haya espacio suficiente para que todos tos elfos se apilen. A esto le llamamos desbordamiento de pila: es el error que Python nos proporciona si la recursividad se vuelve demasiado profunda (es decir, demasiados elfos). Imagine que continuamos la simulación. Contratamos elfos para “ra” y “a”. El elfo de ‘V ’ escribe su a y luego se sienta.
Sección 15.4
Recursividad: una idea poderosa
36 9
Ahora el elfo de “ra” termina. Escribe r a en la pantalla (que está debajo de la a, que a su vez está debajo de ra). Y el elfo de “ra” se sienta. Esto nos deja con tres elfos más que esperan sus turnos.
Ahora
Hora
El elfo de “ora” escribe o r a y se sienta.
/ \ hora
El elfo de “hora” ha estado esperando a que el elfo de “ora” termine. Escribe h o ra en la pantalla y se sienta.
/ \ A hora
• Por último, el elfo de “Ahora” escribe Ahora por segunda vez y se sienta. Ahora la pila está vacía. ¿Por qué usar programación funcional y recursividad? Porque nos permite hacer mucho en muy pocas líneas de código. Es una técnica muy útil para lidiar con problemas difíciles. Es posible implementar cualquier tipo de ciclo con la recursividad. Muchas personas sienten que es la forma más flexible, elegante y poderosa de iterar.
15.4.1
Recorridos recursivos de directorios
La primera estructura recursiva que vimos en este libro fue un árbol de directorios. Una carpeta puede contener otras carpetas y así en lo sucesivo, hasta cualquier nivel de carpetas. La forma más sencilla de recorrer (tocar todos los archivos) una estructura de directorios es mediante un método recursivo.
370
Capítulo 15
Program ación funcional
Sabemos cómo obtener todos los archivos en un directorio, mediante os.1istdi r. El desafío es identificar cuáles de estos archivos son directorios. Por fortuna, Java sabe cómo lidiar con esto mediante su objeto File, que podemos usar con facilidad desde Jython. Al encontrar un directorio, podemos procesarlo justo igual que como con el primer directorio solicitado.
P ro g ram a 1 4 4 : impresión de todos los nombres de archivos en un árbol de directorios
im port os im port j a v a .i o . F i l e as F i l e def im p rim irT o d o sL o sA rc h iv o s(d ire c to rio ): a rc h iv o s = o s .l i s t d i r ( d i r e c t o r i o ) fo r a rc h iv o in a rc h iv o s : nombrecompleto = d ire c to rio + "/"+ a rc h iv o i f e sD irecto rio (n o m b reco m p leto ): imprimi rTodosLosArchivos(nom brecompleto) el se: p r in t nombrecompleto def e sD ire c to rio (n o m b re a rc h iv o ): e stad o arch ivo = File (n o m b re a rc h iv o ) re tu rn e s ta d o a rc h iv o .is D ire c t o ry Q
Cómo funciona Necesitaremos el módulo os de Python y la clase java, io. File de Java. Para impri mi rTodosLosArchivos en un di rectorio especificado, obtenemos una lista de todos los archivos en el directorio usando os.1i stdi r. Para cada uno de esos archivos, agregamos el directorio y el nombre de archivo para obtener una ruta completa. Luego preguntamos si es un directorio mediante la función esDi rectorio. Usamos el objeto File de Java para preguntar si es un directorio y luego devolvemos esa respuesta. Por lo general en este libro, cuando tenemos que evaluar dos cosas, usamos dos instruc ciones if. Por ende, escribiríamos la primera función anterior de la siguiente forma: def imprimi rTo dosLosA rchivo s(di r e c t o r io ) : a rc h iv o s = o s . l i s t d i r ( d i r e c t o r i o ) fo r a rc h iv o in a rc h iv o s : nombrecompleto = d ire c to rio + "/"+ a rc h iv o i f esD irecto rio (n o m b reco m p leto ): imprimi rTodosLosArchivos(nom brecompleto) i f not esD irecto rio (n o m b reco m p leto ): p r in t nombrecompleto
Sin embargo, cada evaluación de esDi rectori o requiere una operación de archivos b as tante compleja. Esto implica una cantidad considerable de tiempo del procesador. En vez de hacerlo de manera repetitiva, decimos: “Si no es un directorio, o de lo contrario (el se), hacer esto” . De esta forma usamos la instrucción el se, que no es tan legible como las ins trucciones if dobles, pero evita que repitamos una evaluación y es, por consecuencia, más eficiente. Vamos a probar esta función en la carpeta que se muestra en la figura 15.3.
Sección 15.4
© © -I
Buscar carpeta Muestra
C:\ip-book\mediasources\carpetaMuestraj
Organizar ▼ %
^ Abrir
Incluir en biblioteca ▼
Compartir con ▼
»
371
f> |
¿i » ES ©
Sitios recientes
M H jy
Bibliotecas [ 5 Documentos ifci,] Imágenes
sonidos
Música 9
Recursividad: una idea poderosa
blue-m ark.jpg
Videos
II
¿ y
Grupo en el hogar blueMotorcycle.j I® Equipo
butterfly.jpg
P9
4 b Disco local (C:) ^
Mac OS X Lion Ext on
i-r* Macintosh H D 1 on 'o
FIGU RA 15.3 Contenido de la carpeta Muestra.
» > im p rim írTo d o sLo sA rchivo s("C :/ip -b o o k/m ed iaso urces/carp etaM uestra") C :/ip-b o o k/m ed iasources/carp etaM uestra/b lue-m ark.jp g C :/ i p-book/medi asou rces/carpetaM uestra/blueM oto r c y c le . j pg C :/ i p-book/medi a s o u rc e s/c a rp e ta M u e stra /b u tte rfly . jpg C :/ip-b o o k/m ediasources/carpetaM uestra/im agenes/b each-sm aller.jp g C:/ip-book/m ediasources/carpetaM uestra/im agenes/beach.jpg C:/ip-book/m ediasources/carpetaM uestra/im agenes/bgfram e.jpg C:/ip-book/m ediasources/carpetaM uestra/im agenes/bigben.jpg C:/ip-b o o k/m ediasources/carp etaM uestra/im agenes/b lueShrub.jpg C :/ip-bo o k/m ediasources/carpetaM uestra/im agenes/b rid ge.jp g C:/ip-book/m ediasources/carpetaM uestra/sonidos/bassoon-c4.w av C:/ip-book/m ediasources/carpetaM uestra/sonidos/bassoon-e4.w av C :/ip-book/m ediasources/carpetaM uestra/sonidos/bassoon-g4.w av
15.4.2 Funciones multimedia recursivas Podemos pensar en escribir funciones multimedia como reduci rRojo () en forma recursi va, de la siguiente manera.
37 2
Capítulo 15
Program ación funcional
Programa 145: reducción de color rojo en forma recursíva
def re d u c irR o jo R (u n a L is ta ): i f u n a L ista == [ ] : # v a c ia re tu rn setRed(unaLi s t a [ 0 ] , getRed(unaLi s t a [ 0 ] ) * 0 . 8) reduci r R o jo R (u n a l_ is t a [ l:])
■ Cómo funciona Si la lista de entrada de píxeles está vacía, entonces nos detenemos (return). De lo contra rio, tomamos el primer pixel en la lista (unaLista[0 ]) y reducimos su nivel de rojo en un 20% (lo multiplicamos por 0.8). Después llamamos a reduci rR ojoR con el resto de la lista (unaLista[l:]). Esta versión se invoca de la siguiente manera: reducirRojoR(getPixels(imagen)). Advertencia: esto no funciona ni siquiera para imágenes de un tamaño razonable. Python (y el lenguaje Java detrás de Jython) no espera una recursividad de este nivel de profundidad, por lo que se quedará sin memoria. No obstante, sí funciona con imágenes verdaderamente pequeñas. En realidad esta versión de reduci rRo jo tiene dos problemas: • En primer lugar, se ejecuta de manera recursiva para cada pixel. Esto se traduce en cientos de miles de veces. • En segundo lugar, pasa toda la lista de píxeles para cada llamada. Esto significa, para cada pixel procesado, una copia de todos los píxeles que también están almacenados en memoria y representa una enorme cantidad de esta. Podemos escribir esta función de una manera distinta, de modo que podamos corregir el segundo problema. Es posible evitar pasar toda la lista de píxeles si declaramos la variable que contiene la lista de píxeles como glob al. A sí la variable se comparte entre las funciones.
Programa 146: fundón red uci rRo jo recursiva con una variable global
pi xelesDeUnaImagen=[] def reducirR ojoR (un alm agen): global pixelesDeUnalmagen pi xelesDeUnaImagen=getPi xels(unalm agen) re d u c irR o jo P o rln d ic e (1 en (p ixelesD eU naIm ag en )-l) def reduci rR o jo P o rln d i c e ( i ndi c e ) : global pixelesDeUnalmagen p ix e l = pixelesD eU nalm agen[indice] se tR e d C p ixe l, 0 .8 * g e tR e d (p ix e l)) i f Ín d ic e = = 0 : # v a c ía re tu rn re d u c irR o jo P o rIn d ic e (in d ic e - 1)
Cómo fundona Primero creamos la variable pixelesDeUnalmagen fuera de cualquier función. Las ins trucciones global indican a Python que pixelesDeUnalmagen debe definirse al nivel de
Problem as
373
archivo (módulo), no sólo a nivel local de esta función. La función reduci rRojoR coloca todos los píxeles en pi xel esDeUnalmagen y después llama a la función ayudante reduci rRojoPorlndi ce con el último índice en la lista de píxeles de la imagen, la longitud (1en) de la lista menos uno. La función reduci rRo joPo rlndi ce obtiene el pixel en el índice especi ficado y reduce su nivel de rojo al 80%. Si el índice es cero, el primero de todos los píxeles, sólo ejecutamos return y nos detenemos. Si no es cero, seguimos reduciendo el nivel de rojo por uno menos que el índice actual. El problema es que esta versión aún se ejecuta en forma recursiva para cada pixel. Incluso con imágenes relativamente pequeñas (640 x 480), la pila se desborda antes de completar el procesamiento de la imagen. En general es difícil realizar el procesamiento pixel por pixel, tal vez hasta sea algo imposible de hacer en Jython.
RESUMEN DE PROGRAMACIÓN A continuación mostramos algunas de las funciones y piezas de programación que vimos en este capítulo.
PROGRAMACIÓN FUNCIONAL apply
Recibe como entrada una función y una lista com o entrada para esa función, donde la lista tiene tantos elementos como los que la función reciba como entrada. Llama a la función con base en la entrada.
map
Recibe como entrada una función y una lista de varias entradas a esa función. Llam a a la fun ción sobre cada una de las entradas y devuelve una lista de las salidas (valores de retomo).
filter
Recibe com o entrada una función y una lista de varias entradas a esa función. Llam a a la función sobre cada uno de los elementos de la lista y devuelve el elemento de entrada si la función devuelve verdadero (un valor distinto de cero) para ese elemento.
reduce
Recibe com o entrada una función, la cual recibe dos entradas y una lista de varias entradas a esa función. La función se aplica a los primeros dos elementos de la lista; después el re sultado de eso se usa com o entrada con el siguiente elemento de la lista, luego el resultado de eso se usa com o entrada con el siguiente elem ento de la lista, y así en lo sucesivo. Al final se devuelve el resultado total.
else:
Después de una instrucción i f, ejecuta el siguiente bloque de código sólo si la prueba en la instrucción i f esfalsa.
global
Las variables listadas después de la instrucción global hacen referencia a una variable creada antes de esta función, a nivel de archivo (o módulo). Esto nos permite compartir una referencia a un objeto, en vez de duplicarlo.
PROBLEMAS 15.1
Ahora veamos un acertijo. Suponga que tiene seis bloques. Uno de ellos pesa más que el otro. Tiene una pesa a su disposición, pero sólo puede usarla dos veces. Encuentre el bloque más pesado, (a) Escriba su proceso como un algoritmo, (b) ¿Qué tipo de búsque da es esta?
15.2
Escriba una función para calcular el valor de Fibonacci de un número. El número Fibonacci de 0 es 0 y el de 1 es 1. El número Fibonacci de n es Fib(ri) = Fib{n - 2) + Fib(n - 1 ) .
374
Capítulo 15
Program ación funcional
15.3 Escriba una función para convertir grados Celsius a Fahrenheit. 15.4 Escriba una función para calcular el índice de masa corporal de una persona, dados su peso y altura. 15.5
Escriba una función para calcular una propina del 20 por ciento.
15.6 Busque el triángulo de Sierpinski. Escriba una función recursiva para crear el triángu lo de Sierpinski. 15.7
Busque el copo de nieve de Koch. Escriba una función recursiva para crear el copo de nieve de Koch.
15.8
Cambie la función convertí rCabelloRojo de programación funcional en el pro grama 141 (página 362) de modo que esté escrita en sólo una línea, registrando las funciones utilitarias como funciones 1ambda.
15.9
Describa lo que hace esta función. Pruebe con distintos números como entrada. d ef prueba(num ): i f num > 0 : re tu rn prueba(num -l) el se: re tu rn 0
15.10 Describa lo que hace esta función. Pruebe con distintos números como entrada. d ef prueba(num ): i f num > 0 : re tu rn prueba(num -l) + num e ls e : re tu rn 0
15.11 Describa lo que hace esta función. Pruebe con distintos números como entrada. d ef prueba(num ): i f num > 0 : re tu rn prueba(num -l) * num el se: re tu rn 0
15.12 Describa lo que hace esta función. Pruebe con distintos números como entrada. d ef prueba(num ): i f num > 0 : re tu rn num - prueba(num -l) e ls e : re tu rn 0
15.13 Describa lo que hace esta función. Pruebe con distintos números como entrada. d ef prueba(num ): i f num > 0 : re tu rn prueba(num-2) * prueba(num -l) e ls e : re tu rn 0
Problem as
375
15.14 Escriba un método recursivo para listar todos los archivos en un directorio y en todos los subdirectorios. 15.15 Pruebe a escribir a r r i b aA b ajo (): » > a rrib a A b a jo ("H o la ") Hola Hol Ho H Ho Hol Hola
Intente escribir la función tanto recursiva como no recursiva. ¿Cuál es más fácil? ¿Por qué? 15.16 Pruebe a escribir algunos de nuestros ejemplos de sonidos e imágenes de los primeros capítulos mediante programación funcional, usando estructuras como f i l t e r y map.
CAPÍTULO
16
Programación orientada a objetos
16.1
H IS T O R IA D E LO S O B JE T O S
16.2
T R A B A JO C O N T O R T U G A S
16.3
EN S E Ñ A R N U EV O S T R U C O S A LAS TO R T U G A S
16.4
U N A P R E S E N T A C IÓ N O R IE N TA D A A O B JE T O S
16.5
M ED IO S O R IEN TA D O S A O B JE T O S
16.6
LA C A JA J O E
16.7
¿PO R Q U É O B JE T O S ?
Objetivos de aprendizaje del capítulo • Usar la program ación orientada a objetos para que los program as sean más fáciles de desarrollar en equipos, más robustos y fáciles de depurar. • Com prender las características de los program as orientados a objetos, como polim orfis mo, encapsulam iento, herencia y agregación. • Poder elegir entre distintos estilos de program ación para distintos fines.
16.1
HISTORIA DE LOS OBJETOS El estilo más común de programación en la actualidad es la program ación orientada a objetos. Vamos a definirla en contraste con la programación por procedimientos que hemos realizado hasta ahora. En las décadas de 1960 y 1970, la programación por procedimientos era la forma dom i nante de programación. Las personas usaban la abstracción procedural y definían muchas funciones en niveles altos y bajos. Además reutilizaban sus funciones en donde fuera posi ble. Esto funcionaba bastante bien, hasta cierto punto. A medida que los programas se vol vían grandes y complejos, con muchos programadores trabajando en ellos al mismo tiempo, la programación por procedimientos empezó a sufrir conflictos. Los programadores tuvieron problemas con los conflictos de los procedimientos. Las per sonas escribían programas que modificaban datos en formas que otras personas no espera ban. Usaban los mismos nombres para las funciones y descubrían que su código no podía integrarse en un programa extenso. También hubo problemas al pensar sobre los programas y las tareas que se suponía debían realizar. Los procedimientos tratan sobre los verbos: dicen a la computadora que haga esto
37 6
Sección 16.1
Historia de los objetos
377
o aquello. Pero no está claro si esa es la forma en que las personas piensan mejor sobre los problemas. La programación orientada a objetos es programación orientada a sustantivos. Para crear un programa orientado a objetos, primero hay que pensar qué son los sustantivos en c\ do minio del problema: ¿qué son las personas y cosas que forman parte de este problema y su solución? Al proceso de identificar los objetos, lo que cada uno de ellos sabe (respecto al problema) y lo que tiene que hacer se le denomina análisis orientado a objetos. La programación de una manera orientada a objetos significa que se definen variables (variables de instancia) y funciones (métodos) para los objetos. En la mayoría de los len guajes orientados a objetos, los programas tienen muy pocas (o incluso ninguna) funciones o variables globales: cosas que pueden utilizarse en cualquier parte. En Smalltalk, el lenguaje de programación orientada a objetos original, los objetos sólo pueden realizar cosas si piden a otro objeto que realice las cosas por medio de sus métodos. Adele Goldberg, una pionera de la programación orientada a objetos, nombró esto como “Preguntar sin tocar” . No podemos “tocar” los datos y hacer todo lo que queramos con ellos; lo que hacemos es “pedir” a los objetos que manipulen sus datos por medio de sus métodos. Esto es un buen objetivo, incluso en lenguajes como Python o Java, en donde los objetos pueden manipular los datos de otros objetos en forma directa. El término programación orientada a objetos lo inventó Alan Kay, un brillante personaje multidisciplinario: posee títulos universitarios en matemáticas y biología, un doctorado en ciencias computacionales y ha sido guitarrista de jazz profesional. En 2004 recibió el Premio Turing de la ACM, algo así como el Premio Nobel de la computación. Kay vio la progra mación orientada a objetos como una forma de desarrollar software que en verdad pudiera escalar a sistemas grandes. Describió los objetos como algo parecido a las células biológicas que trabajan juntas en formas bien definidas para hacer que todo el organismo trabaje. Al igual que las células, los objetos podrían: • Ayudar a lidiar con la complejidad al distribuir la responsabilidad de las tareas entre muchos objetos, en vez de un programa extenso. • Apoyar la robustez al hacer que los objetos trabajen relativamente en forma indepen diente. • Apoyar la reutilización ya que cada objeto provee servicios a otros objetos (tareas que el objeto realizaparaotrosobjetos,accesiblespormedio de sus métodos), al igual que los obje tos en el mundo real. La noción de partir de sustantivos es parte de la visión de Kay. El software, dijo él, es en realidad una simulación del mundo. Al hacer que el software modele el mundo, nos queda más claro cómo crear software. Analizamos el mundo y la forma en que funciona, para luego copiar eso en el software. Las cosas en el mundo conocen cosas; éstas se convierten en variables de instancia. Las cosas en el mundo pueden hacer cosas; éstas se convierten en métodos. Cabe mencionar que ya hemos estado usando objetos. Las imágenes, los sonidos, las muestras y los colores son todos objetos. Nuestras listas de píxeles y muestras son ejemplos de agregación, que significa crear colecciones de objetos. Las funciones que hemos utiliza do en realidad sólo cubren los métodos subyacentes. Podemos llamar a los métodos de los objetos en forma directa, lo cual haremos más adelante en el capítulo.
378
Capítulo 16
16.2
Program ación orientada a objetos
T R A B A JO CON TO R TU G A S Seymour Papert en el MTT utilizó tortugas robot para ayudar a los niños a pensar cómo especificar procedimientos a finales de la década de 1960. La tortuga tenía una pluma en su parte media, que podía levantar y bajar para dejar un rastro de sus movimientos. A medida que empezaron a surgir las pantallas de gráficos, utilizó una tortuga virtual en una pantalla de computadora en vez de una computadora robótica. Parte del soporte de medios en JES ofrece objetos de tortugas de gráficos. Las tortugas son una excelente introducción a las ideas de los objetos. Manipulamos objetos tortuga que se desplazan por un mundo. Las tortugas saben cómo moverse y girar. Tienen una pluma en su parte media que deja un rastro para mostrar sus movimientos. El mundo lleva la cuenta de las tortugas que viven en él.
16.2.1
Clases y objetos
¿Cómo sabe la computadora lo que quiere decir una tortuga y un mundo? Tenemos que definir qué es una tortuga, qué es lo que conoce y lo que puede hacer. Tenemos que definir qué es un mundo, lo que conoce y lo que puede hacer. Para hacer esto en Python definimos clases. Una clase define lo que los tipos u objetos (instancias) de esa clase saben y pueden hacer. El paquete de medios para JES define clases que a su vez definen lo que queremos decir con una tortuga y un mundo. Los programas orientados a objetos consisten de objetos. Creamos objetos a partir de clases. La clase sabe lo que cada objeto de esa clase necesita vigilar y lo que debe ser capaz de hacer. Podemos considerar una clase como una fábrica de objetos. La fábrica puede crear muchos objetos. Una clase es también como un molde para galletas. Podemos hacer muchas galletas a partir de un molde y todas tendrán la misma forma. O podemos considerar la clase como un plano de construcción y los objetos como las casas que podemos crear con base en ese plano. Para crear e inicializar un mundo, utilizamos makeWorld(). Para crear un objeto tor tuga, utilizamos makeTurtle(world). Esta función es muy similar a makePicture y makeSound : hay cierto patrón aquí, pero introduciremos uno nuevo, una sintaxis más están dar de Python en unos minutos. Ahora vamos a crear un nuevo objeto mundo. » > makeWorldO
Esta instrucción crea un objeto mundo y visualiza una ventana que muestra ese mundo. Comienza sólo como una imagen blanca en un marco titulado “World”. Pero no podemos hacer referencia a él, puesto que no le hemos asignado un nombre. En este caso nombraremos t i e r r a al objeto mundo que acabamos de crear, y luego vamos a crear un objeto tortuga en el mundo llamado t i e r r a . A ese objeto tortuga lo lla maremos t i n a . » > t i e r r a = makeW orldO » > t i n a = m a k e T u r t le ( t ie r r a ) » > p r in t t i n a No ñame t u r t l e a t 320, 240 heading 0 .0 .
El objeto tortuga aparece en el centro del mundo (320 240) y con dirección hacia el norte (una orientación de 0) (figura 16.1). Todavía no hemos asignado un nombre a la tortuga.
Sección 16.2
W orld
Trabajo con tortugas
□
37 9
X
FIGURA 16.1 C re a ció n d e una to rtu g a en e l m u n d o .
JES nos permite crear muchas tortugas. Cada nueva tortuga aparecerá en el centro del mundo. »>
sue = m a k e T u r t le ( t ie r r a )
16.2.2 Envío de mensajes a los objetos Para pedir a la tortuga que haga cosas enviamos un mensaje al objeto tortuga, lo cual también consideramos como llamar a un método de un objeto. Para ello usamos la notación punto. En esta notación, para pedir a un objeto que haga algo especificamos el nombre de ese objeto y luego un V, seguido de la función a ejecutar (nombre, fu n c ió n (1 is ta P a rá m e tro s )). En la sección 10.3.1 vimos la notación punto con las cadenas. » > tin a .fo rw a rd O » > t in a .t u r n R ig h t O » > tin a .fo rw a rd O
Observe que sólo se mueve la tortuga a la que pedimos realizar las acciones (figura 16.2). Podemos hacer que la otra se mueva si también le pedimos que haga cosas. »> »>
s u e .t u r n L e f t O s u e .fo rw a r d (5 0 )
Cabe mencionar que cada tortuga tiene un color distinto (figura 16.3). Como podemos ver, las tortugas saben cómo girar a la izquierda y a la derecha, mediante el uso de t u r n L e f tO y tu r n R ig h tQ . También pueden avanzar en la dirección en la que se encuentran
380
Capítulo 16
Program ación orientada a objetos
World
*
FIGU RA 16.2 Se le p id e a una to rtu g a q u e se m u e va y g ire m ie n tra s la o tra se q u e d a q u ie ta .
World
FIGU RA 16.3 D e s p u é s d e q u e se m u e ve la se g u n d a to rtu g a .
□ x
Sección 16.2
W orld
Trabajo con tortugas
381
D X
FIGURA 16.4 G ira r c ie rta c a n tid a d e s p e c ific a d a (- 4 5 ).
orientadas mediante forw ard O. De manera predeterminada avanzan 100 píxeles, pero tam bién podemos especificar cuántos píxeles deben avanzar: forward(50). Las tortugas saben cómo girar cierto número de grados también. Los montos positivos giran a la tortuga a la derecha y los negativos a la izquierda (figura 16.4). » > t i n a .t u r n ( - 4 5 ) » > t i n a. fo rw a rd O
16.2.3 Los objetos controlan su estado En la programación orientada a objetos, enviamos mensajes para pedir a los objetos que hagan cosas. Los objetos pueden rehusarse a hacer lo que usted les pide. Un objeto debe rehusarse si usted le pide algo que haga que sus datos sean incorrectos. El mundo en el que se encuentran las tortugas es de 640 píxeles de ancho por 480 píxeles de alto. ¿Qué ocurre si usted trata de decirle a la tortuga que vaya más allá del fin del mundo? » > mundol = makeWorldO » > t o r t u g a l = m ak eT u rtle (m u n d o l) » > t o r t u g a l.f o r w a r d (4 0 0 ) » > p r in t t o r t u g a l No ñame t u r t l e a t 320, 0 heading 0 . 0 .
Las tortugas se posicionan por primera vez en (320, 240) con orientación hacia el norte (arriba). En el mundo la posición superior izquierda es (0, 0). El eje x aumenta a la derecha y el eje y aumenta hacia abajo. Al pedir a la tortuga que avance 400, le estamos pidiendo que vaya a (320, 240 -400), lo que produciría una posición de (320, -160). Pero la tortuga
38 2
Capítulo 16
Program ación orientada a objetos
" World
_n x
FIGU RA 16.5 U na to rtu g a a ta s c a d a e n la o rilla d e l m u n d o .
se rehúsa a salir del mundo y mejor se detiene cuando el centro de la tortuga está en (320, 0) (figura 16.5). Esto significa que no perderemos de vista a ninguna de nuestras tortugas. El objetivo de este ejercicio es mostrar al lector cómo es que los métodos controlan el ac ceso a los datos del objeto. Si no desea que las variables tengan ciertos valores en sus datos, puede controlar esta opción por medio de los métodos. Estos métodos sirven como la puerta de enlace y como guardián para los datos del objeto. Las tortugas pueden hacer muchas otras cosas además de avanzar y girar. Como tal vez haya notado, cuando las tortugas se mueven dibujan una línea que es del mismo color que la tortuga Puede pedir a la tortuga que levante la pluma mediante el uso depenUpO. Puede pe dir a la tortuga que baje la pluma usando penDown ( ) . Puede pedir a la tortuga que se mueva a una posición específica si utiliza moveTo ( x , y ) . Si la pluma está abajo cuando usted le pida que se mueva a una nueva posición, la tortuga dibujará una línea desde la posición anterior hasta la nueva posición (figura 16.6). »> »> »> »> »> »>
mundoX = m akeW orld() to rtu g a X = m akeTurtle(m undoX) to rtu g a X .p e n U p () to rtu g aX .m o ve T o ( 0 ,0 ) to rtu g aX .p e n D o w n () to rtu g a X .m o v e T o (6 3 9 ,479)
Para cambiar el color de una tortuga use s e t C o l o r ( c o l o r ) . Para que deje de di bujar use s e t V i s i b l e ( f a l s e ) . Puede cambiar el grosor de la pluma mediante
setPenWidth(anchura).
Sección 16.3
Enseñar nuevos trucos a las tortugas
383
FIGURA 16.6 Uso de la tortuga para dibujar una línea diagonal.
16.3
ENSEÑAR NUEVOS TRUCOS A LAS TORTUGAS Ya definimos una clase tortuga (Tu rtl e) por usted. Pero ¿qué tal si desea crear su propio tipo de tortuga y enseñarle nuevos trucos? Podemos crear un nuevo tipo de tortuga que entienda cómo hacer todas las cosas que una tortuga sabe hacer, y tenemos la posibilidad de agregar nueva funcionalidad. A esto se le conoce como crear una subclase. A sí como los hijos he redan el color de los ojos de sus padres, nuestra subclase heredará todas las cosas que las tortugas conocen y pueden hacer. A una subclase también se le conoce como clase hija y la clase de la que hereda se llama clase padre o supe reíase. Vamos a llamar a nuestra subclase To rtugaChi ca. Agregaremos un método que permita a nuestra tortuga dibujar un cuadrado. Los métodos se definen justo igual que las funciones, sólo que están dentro de la clase. En Python los métodos siempre reciben como entrada una referencia al objeto de la clase en la que se invocó a ese método (por lo general se llama sel f). Para dibujar un cuadrado nuestra tortuga girará a la derecha y avanzará 4 veces. Cabe mencionar que heredamos la habilidad de girar a la derecha y avanzar de la clase Tu rtl e.
P ro g ram a 14 7 definición de una subclase
c la s s T o rtu g a C h ic a (T u r tle ): def d ib u ja rC u a d ra d o (s e lf): fo r i in ra n g e (0 ,4 ): s e l f .tu rn R ig h tO s e l f .fo rw a rd Q
384
Capítulo 16
Program ación orientada a objetos
Como To rtugaChi caes un tipo de tortuga (Tu rtl e),podemos usarla en forma muy pareci da. Sólo que necesitaremos crear esa To rtugaChi ca d e una nueva forma. Hemos estado usan do makePi cture, makeSound, makeWorl d y makeTu rtl e para crear nuestros objetos. Éstas son funciones que creamos para facilitar la creación de esos objetos. Pero, la verdadera forma de crear un nuevo objeto en Python es mediante el uso de NombreCl ase(l istaParámetros). Para crear un mundo podemos usar objMundo = World( ) y para crear una TortugaChica podemos usar objTortuga = TortugaChi ca(objMundo). » > t i e r r a = W orld() » > audaz = T o rtu g a C h ic a (tie rra ) » > audaz.dibujarC uadrado O
Ahora nuestra TortugaChica sabe cómo dibujar un cuadrado (figura 16.7). Pero sólo puede dibujar cuadrados con un tamaño de 100. Sería agradable poder dibujar cuadrados de distintos tamaños. Podemos agregar otra función que reciba un parámetro y especifique la anchura del cuadrado.
~ World
FIGURA 16.7 Dibujo de un cuadrado con nuestra TortugaChica.
P ro g ram a 1 4 8 : definición de una subclase
c la s s T o rtu g a C h ic a (T u r tle ): def d ib u ja rC u a d ra d o (s e lf): fo r i in ra n g e (0 ,4 ):
Sección 16.3
Enseñar nuevos trucos a las tortugas
385
s e l f .tu rn R ig h tO s e lf.fo rw a rd C ) def d ib u ja rC u a d ra d o (s e lf, ancho): fo r i in range( 0 , 4 ) : s e l f .tu rn R ig h tO s e l f . forw ard(ancho)
Puede usar esto para dibujar cuadrados de distintos tamaños (figura 16.8). »> »> »> »> »>
marte = W orld() t in a = To rtu g aC h ica(m arte) tin a .d ib u ja rC u a d ra d o (3 0 ) tin a .d ib u ja rC u a d ra d o (lS O ) tin a.d ib u ja rC u a d ra d o (lO O )
•» World
ife— I
FIGU RA 16.8 Cómo dibujar cuadrados de distintos tamaños.
16.3.1
Redefinición de un método existente de la clase tortuga
Una subclase puede redefinir un método que ya exista en la superclase. Podríamos hacer esto para crear una forma especializada del método existente. A continuación veremos la clase TortugaConfundida, que redefine los métodos forward y turnde modo que ejecute los métodos forward y turn de laclase Turtle,pero
38 6
Capítulo 16
Program ación orientada a objetos
con una cantidad aleatoria. Podemos usarla como una tortuga normal, sólo que no avanzará ni girará tanto como se le solicite. El siguiente ejemplo hará que tont ita avance alrededor de 100 y gire cerca de 90 grados. »> »> »> »>
pluton = W orldO t o n t it a = TortugaConfundida(pluton) t o n t it a .fo r w a r d (100) t o n t it a .t u r n ( 9 0 )
P ro g ram a 14 9: T o rtu g a C o n fu n d id a , que avanza y gira una cantidad aleatoria
im port random c la s s T o rtu g a C o n fu n d id a (T u rtle ): d ef fo rw a rd (s e lf,n u m ): T u rtle .fo rw a rd (s e lf,in t(n u m * ra n d o m .ra n d o m ())) d ef t u r n (s e lf,n u m ): T u r t le .t u r n ( s e l f ,int(num *random . random Q))
Cómo funciona Declaramos la clase To rtugaConf undi da como una subclase de Tu rtl e. Definimos nuevos métodos en TortugaConfundida: forward y turn. Al igual que cualquier otro método, reciben sel f y cualquiera que sea la entrada para el método. En estos casos, la entrada para ambos métodos es un número num. Lo que queremos hacer es llamar a la superclase (en este caso, Tu rtl e) y pedirle que ejecute las funciones forward y turn normales, pero con la entrada multiplicada por un número aleatorio. El cuerpo de cada método es una sola línea, pero bastante complicada. • Tenemos que decirle a Python que invoque de manera explícita el método fo rw a rd de Turtle. • Tenemos que pasar self, de modo que se utilicen y actualicen los datos del objeto correcto. • Multiplicamos el num de entrada por random. random(),pero necesitamos convertirlo en un entero (mediante int). El número aleatorio devuelto estará entre 0 y 1 (un núm e ro de punto flotante), pero necesitamos un entero para forward y turn.
16.3.2 Uso de tortugas para realizar más acciones Las tortugas tienen varios métodos que permiten realizar efectos gráficos interesantes. Por ejemplo, las tortugas están conscientes de las otras tortugas a su alrededor. Pueden voltear hacia otra tortuga mediante turnToFace(otraTortuga) para cambiar su orientación de modo que la tortuga esté “viendo” a otra tortuga (de modo que, si sigue avanzando, alcanzará a la otra tortuga). En el siguiente ejemplo establecemos cuatro tortugas (al,bo, cy y di) en cuatro esquinas de un cuadrado para después hacer que cada una se mueva en forma repetida hacia la tortuga que está a su izquierda. El resultado se muestra en la figura 16.9.
Sección 16.3
FIGURA 16.9 Cuatro tortugas persiguiéndose entre sí.
P ro g ram a 1 5 0 : persecución de tortugas
def perseguí r ( ) : # E s ta b le c e r la s cuatro to rtu g a s t i e r r a = W orld() al = T u r t le (t ie r r a ) bo = T u r t l e ( t i e r r a ) cy - T u r t l e ( t i e r r a ) di = T u r t l e ( t i e r r a ) a l .penUpO a l .m oveTo(10,10) al.penDow n() bo. penUpO bo. moveTo(10,400) bo.penDown() c y . penUpO c y . moveTo(4 0 0 ,1 0 ) cy.penDownO di .penUpO di.m oveTo(4 0 0,4 00 ) di.penDown() # Ahora, p erseg u irse durante 300 pasos fo r i in range(0 ,3 0 0 ):
Enseñar nuevos trucos a las tortugas
387
38 8
Capítulo 16
Program ación orientada a objetos
perseguí perseguí perseguí perseguí
r T o r tu g a (a l,c y ) r T o rtu g a (c y ,d í) r T o rtu g a (d í, bo) rT o rtu g a (b o ,a 1 )
def p e r s e g u ír T o r t u g a (t l,t 2 ): t l.t u r n T o F a c e ( t 2 ) t l.f o r w a r d ( 4 )
Cómo funciona Aquí la función principal es perseguí r(). Las primeras líneas crean un mundo y a las cuatro tortugas. Después colocan a cada una de ellas en las esquinas (10, 10), (10, 400), (400, 400) y (400, 10). Durante 300 pasos (un número relativamente arbitrario), se instruye a cada tortuga para que “persiga” (perseguí rTortuga) a la que está a su lado, en sentido de las manecillas del reloj. Así, la tortuga que empieza en (10, 10) (al) recibe instrucciones para perseguir a la tortuga que empieza en (400, 10) (cy). Perseguir significa que la primera tortuga debe voltear a ver a la segunda tortuga y luego avanzar cuatro pasos (pruebe con distintos valores; a nosotros nos gustó más el efecto de 4). En un momento dado, las tortugas realizarán una espiral hacia el centro. Estas funciones son valiosas para crear simulaciones. Imagine que tenemos tortugas color café actuando como ciervos y tortugas grises como lobos. Los lobos voltearían hacia los cier vos (turnToFace) al momento de verlos y empezarían a perseguirlos. Para escapar, los ciervos podrían voltear a ver (turnToFace) a u n lobo acechante, para luego girar 180 grados y correr. Las simulaciones son uno de los usos más poderosos e intuitivos de las computadoras.
Idea de ciencias com putacionales: los parám etros funcionan un poco distinto con los objetos
Básicamente, al invocar una función y pasarle un número como entrada, la variable parámetro (la variable local que acepta la entrada) recibe una cop ia de ese número. Al modificar la variable local no se modifica la variable de entrada. Analicemos la función perseguí rTortuga. Al invocar la función con perseguí rT o rtu g a (a l ,c y ) , cam biam os la posición y la orientación de la tortuga llamada a l. ¿Por qué es tan diferente? En realidad no lo es. En sí, la variable a l no contiene una tortuga, sino una referencia a ésta. Considérelo como una dirección (en memoria) de la ubicación del objeto tortuga. Si realiza una copia de una dirección, esa dirección aún hace referencia al mismo lugar. Se está manipulando la misma tortuga dentro y fuera de la función. Aún no podemos lograr que a l haga referencia a un nuevo objeto desde el interior de una función como p e rs e g u í r T o r tu g a . Sólo podemos modificar el objeto al que al hace referencia.
■ Las tortugas también saben cómo soltar (drop) imágenes. Cuando una tortuga suelta una imagen, permanece en la esquina superior izquierda de la imagen, sin importar la orientación de la tortuga (vea la figura 16.10). »> »> »> »> »> »>
# Sele ccio n é l a imagen B a rb a ra .jp g para e ste ejemplo p = m a k e P ictu re (p ick A F ile O ) # Observe que aquí creamos lo s o b jeto s mundo y to rtu g a tie rra = W o rld () t o r t u g a = T u r t le (t ie r r a ) to rtuga.drop C p)
Sección 16.3
Enseñar nuevos trucos a las tortugas
389
FIGURA 16.10 Cómo soltar una imagen en un mundo.
También podemos colocar tortugas en imágenes, al igual que en instancias de mundos. Al colocar una tortuga en una imagen, su cuerpo no aparece de manera predeterminada (aunque podemos hacerla visible) de modo que no se confunda con la imagen. Pero la pluma está abajo y podemos dibujar. Colocar una tortuga en una imagen significa que podemos crear gráficos interesantes encima de imágenes existentes, o usar imágenes existentes en nuestras manipulaciones de tortugas. Una de nuestras técnicas favoritas es girar una imagen: hacer que la tortuga se mueva un poco, gire un poco, suelte una copia de la imagen, y luego repita estos pasos. En la figura 16.11 podrá ver un ejemplo. A continuación le mostramos el código con el que se creó esa figura. Invocamos la función con la misma imagen de Barb del ejemplo anterior, show(gi rarllnalmagen(p)). P ro g ram a 15 1: cómo girar una imagen al soltarla de una tortuga girando
def girarU nalm agen(unaim ag): lie n z o - m akeEm ptyPicture(640,480) ted = T u r t le ( lie n z o ) fo r i in ra n g e (0 ,3 6 0 ): ted.drop(unaim ag) te d .fo rw a rd (lO ) te d .t u rn (2 0 ) re tu rn lie n z o
390
Capítulo 16
Program ación orientada a objetos
None
a a -iW
FIGU RA 16.11 Cómo soltar una imagen sobre una imagen, mientras se mueve y gira.
16.4
UNA PRESENTACIÓN ORIENTADA A OBJETOS Vamos a usar técnicas orientadas a objetos para crear una presentación con diapositivas. Di gamos que queremos mostrar una imagen, después reproducir cierto sonido y luego esperar hasta que termine el sonido antes de avanzar a la siguiente imagen. Usaremos la función (que mencionamos en uno de los primeros capítulos del libro) blockingPlayf), que reproduce un sonido y espera a que termine antes de ejecutar la siguiente instrucción.
P ro g ram a 1 5 2 : presentación con diapositivas como una sola función grande
def re p ro d u c irP re s e n ta c io n (): imag = m a ke P ictu re (g e tM e d ia P a th ("b a rb a ra .jp g ")) sonido = m akeSound(getM ediaPath("bassoon-c4.wav")) show(imag) b lo ck in g P Ia y (so n id o ) imag = m a ke P ictu re(g etM ed iaP a th ("b e ach .jp g ")) sonido - m akeSound(getM ediaPath("bassoon-e4.wav")) show(imag) b lo ck i n g P Iay(so n i do) imag = m a ke P ictu re (g e tM e d ia P a th ("ch u rch .jp g ")) sonido = makeSound(getMediaPath(,,bassoon-g4.w av"))
Sección 16.4
Una presentación orientada a objetos
391
show(imag) b lo ck in g P la y (so n id o ) imag = m a ke P ictu re (g e tM e d ia P a th ("ju n g le 2 .jp g ")) sonido = makeSound(getMedi a P a th C b a sso o n -c 4 .w a v")) show(imag) b lo ck in g P la y (so n id o )
■ Éste no es un programa muy bueno desde ninguna perspectiva. Desde la perspectiva de programación por procedimientos, aquí hay una cantidad exagerada de código duplicado. Sería agradable deshacernos de él. Desde una perspectiva orientada a la programación, de beríamos tener objetos diapositivas. Como dijimos antes, los objetos constan de dos partes. Los objetos conocen cosas: éstas se convierten en variables de instancia. Los objetos pueden hacer cosas: éstas se convierten en métodos. Vamos a acceder a ambos elementos mediante el uso de la notación punto. Entonces ¿qué es lo que conoce una diapositiva? Conoce tanto su imagen como su soni do. ¿Qué puede hacer una diapositiva? Puede mostrarse a sí misma, al mostrar su imagen y reproducir su sonido. Para definir un objeto diapositiva en Python (y en muchos otros lenguajes de progra mación orientados a objetos, incluyendo Java y C++), debemos definir una clase llamada Di aposi ti va. Ya vimos algunas definiciones de clases. Ahora lo repasaremos de nuevo, con lentitud: vamos a crear una clase desde cero. Como ya vimos antes, una clase define las variables de instancia y los métodos para un conjunto de objetos; es decir, lo que cada objeto de esa clase conoce y puede hacer. Cada ob jeto de la clase es una instancia de ella. Para crear varias diapositivas vamos a crear múltiples instancias de la clase Di aposi ti va. Esto es lo que se conoce como agregación: colecciones de objetos, así como nuestros cuerpos podrían crear varias células del riñón o del corazón, cada una de las cuales sabe cómo hacer ciertas tareas. Para crear una clase en Python, empezamos con: c la s s D ia p o s itiv a :
Después de esta instrucción se colocan con sangría los métodos para crear nuevas dia positivas y reproducirlas. Vamos a agregar un método llamado mostrar() a nuestra clase Diapositiva: c la s s D ia p o s itiv a : d ef m o s t r a r ( s e lf ) : show Cself.im agen) b lo c k in g P la y (s e lf.s o n id o )
Para crear nuevas instancias, invocamos el nombre de la clase como una función. Para definir nuevas variables de instancia sólo tenemos que asignarlas. Ahora veamos cómo crear una diapositiva y proporcionarle tanto una imagen como un sonido. »> »> »> »>
di aposi t i val=Di aposi t i v a () d ia p o s itiv a l.im a g e n = m a ke P ictu re (g e tM e d ia P a th ("b a rb a ra .jp g ")) d ia p o s itiv a l.s o n id o = m akeSound(getM ediaPath("bassoon-c4.wav")) d ia p o s it iv a l.m o s t r a r ()
La función di aposi ti val. mostrar () muestra la imagen y reproduce el sonido. ¿Qué es esto de sel f ? Al ejecutar objeto.método ( ) , Python busca el método en la clase del ob jeto y después lo invoca, usando el objeto de instancia como entrada. El estilo de Python es
39 2
Capítulo 16
Program ación orientada a objetos
llamar a esta variable de entrada sel f (puesto que es el objeto en sí mismo). Como tenemos el objeto en la variable sel f, podemos entonces acceder a su imagen y a su sonido al decir self .imagen y self .sonido. Pero esto es aún bastante difícil de usar si tenemos que establecer todas las variables desde el área de comandos. ¿Cómo podríamos hacerlo más sencillo? ¿Qué tal si pudiéramos pasar el sonido y la imagen de las diapositivas como entradas para la clase Diapositiva, como si la clase fuera una función verdadera? Podemos hacerlo si definimos algo que se conoce como constructor. Para crear nuevas instancias con algunas entradas, debemos definir una función llama da — i n i t — . Se escribe “guión bajo-guión bajo-i-n-i-t-guión bajo-guión bajo” . Éste es el nombre predefinido en Python para un método que inicializa nuevos objetos. Nuestro méto do — ini t— necesita tres entradas: la instancia en sí (porque todos los métodos la reciben), una imagen y un sonido.
Pro g ram a 1 5 3 : Una clase D ia p o s itiv a
c la s s D ia p o s itiv a : d ef - .in it - - (s e lf ,a r c h iv o Im a g e n ,a r c h iv o S o n id o ): se lf.im a g e n = m akePicture(archivolm agen) s e lf.s o n id o = makeSound(archivoSonido) d ef m o s t r a r ( s e lf ) : sh o w (self.im ag en ) b lo c k in g P la y (s e lf.s o n id o )
Podemos usar nuestra clase Di apos i t i va para definir una diapositiva de la siguiente forma.
fro g ra m a 1 5 4 : Reproducción de una presentación con diapositivas, usando nuestra clase D ia p o s itiv a
def re p ro d u c irP re s e n ta c io n 2 (): archlmag = g e tM e d ia P a th ("b a rb ara .jp g ") archSon = getM ediaPath("bassoon-c4.w av") d ia p o s it iv a l = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) archlmag = g etM ed iaPath("b each.jp g ") archSon = getM ediaPath("bassoon-e4.w av") d ia p o s itiv a 2 = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) archlmag = g etM ed ia P a th ("ch u rch .jp g ") archSon = getM ediaPath("bassoon-g4.w av") d ia p o s itiv a 3 = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) archlmag = g e tM e d ia P a th ("ju n g le 2 .jp g ") archSon = getM ediaPath("bassoon-c4.w av") d ia p o s itiv a 4 = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) d ia p o s it iv a l.m o s t r a r ( ) d ia p o s itiv a 2 .m o s t ra r() d ia p o s itiv a 3 .m o s tra r( ) d ia p o s itiv a 4 .m o s t ra r()
■ Una de las características de Python que lo hacen tan poderoso es que podemos mezclar los estilos de programación orientado a objetos y funcional. Ahora las diapositivas son objetos
Sección 16.4
Una presentación orientada a objetos
393
que pueden almacenarse en listas con facilidad, al igual que cualquier otro tipo de objeto de Python. Ahora veamos un ejemplo de la misma presentación en donde usamos map para mostrar las diapositivas.
fro g ra m a 155: presentación, en objetos y funciones
def m o s tra rD ia p o s itiv a (u n a D ia p o s itiv a ): u n a D ia p o siti v a .m o s tra r( ) def re p ro d u c irP re s e n ta c io n 3 (): archlmag = g e tM e d ia P a th ("b a rb ara .jp g ") archSon = getM ediaPath("bassoon-c4.w av") d ia p o s it iv a l = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) archlmag = g etM ed iaPath("b each.jp g ") archSon = getM ediaPath("bassoon-e4.w av") d ia p o s itiv a 2 = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) archlmag = g e tM e d ia P a th C ch u rch .jp g ") archSon = getM ediaPath("bassoon-g4.w av") d ia p o s itiv a 3 = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) archlmag = getM ediaPath("ju n g le 2 .jp g " ) archSon = getM ediaPath("bassoon-c4.w av") d ia p o s itiv a 4 = D ia p o sitiv a (a rc h Im a g ,a rch S o n ) m a p (m o stra rD iap o sitiva, [ d ia p o s it iv a l,d ia p o s it iv a 2 ,d ia p o s it iv a 3 ,d ia p o s it iv a 4 ] )
¿Acaso es más fácil escribir la versión orientada a objetos de la presentación? Sin duda tiene menos código duplicado. Presenta la encapsulación en cuanto a que los datos y el comportamiento del objeto se definen en un solo lugar, de modo que cualquier modificación en uno sea fácil de realizar en el otro. A la capacidad de usar muchos objetos (como listas de ellos) se le conoce como agregación. Ésta es una idea poderosa. No siempre tenemos que definir nuevas clases: a menudo es posible usar las estructuras poderosas que conocemos, como las listas con objetos existentes, para generar un impacto considerable.
16.4.1
Cómo hacer la clase Diapositiva más orientada a objetos
¿Qué ocurre si necesitamos cambiar la imagen o el sonido de alguna clase? Podemos hacer lo. Sólo tenemos que cambiar las variables de instancia imagen o soni do. Pero si piensa en ello, se dará cuenta que no es algo muy seguro. ¿Qué tal si alguien más usa la presentación y decide guardar películas en la variable imagen? Podría ser fácil ponerla en funcionamiento, pero ahora tenemos dos usos distintos para la misma variable. Lo que nos conviene en realidad es tener un método que maneje la acción de obtener o establecer una variable. Y si existe la posibilidad de que se guarden los datos incorrectos en la variable, podemos cambiar el método para establecer esa variable de modo que verifique el valor, para asegurarnos de que sea del tipo correcto y válido, antes de establecer esa varia ble. Para que esto funcione, todos los que usen la clase tienen que estar de acuerdo en usar los métodos para obtener y establecer las variables de instancia y no manipularlas de manera directa. En lenguajes como Java, podemos pedir al compilador que mantenga las variables de instancia privadas (mediante prívate) y no permita usos que traten de manipularlas en forma directa. En Python, lo mejor que podemos hacer es crear los métodos para establecer y obtener y tan sólo fomentar su uso.
394
Capítulo 16
Program ación orientada a objetos
A estos métodos los llamamos setters y getters. He aquí una versión de la clase en donde defi nimos setters y getters para las dos variables de instancia; como puede ver, son bastante simples. Observe cómo cambiamos los métodos show e incluso i ni t de modo que podamos usar lo más que sea posible los métodos setter y getter en vez del acceso directo a las variables de instancia. Éste es el estilo de programación al que se refería Adele Goldberg cuando hablaba sobre “Preguntar sin tocar” .
Programa 156: clase D i a p o s i t i v a con g etters y setters
c la s s D ia p o s itiv a : d ef i n i t ( s e l f , archivolm agen, a rc h iv o S o n id o ): se lf.se tIm a g e n (m a k e P ic tu re (a rch iv o Im a g e n )) se lf.setSo n id o (m ake So u n d (a rch ivo So n id o )) def g e tlm a g e n (s e lf): re tu rn se lf.im a g e n def g e t S o n id o (s e lf): re tu rn s e lf.s o n id o def s e tlm a g e n (s e lf, nuevalm agen): se lf.im a g e n = nuevalmagen def se tS o n id o (se lf,n u e v o S o n id o ): s e lf.s o n id o = nuevoSonido def m o s t r a r ( s e lf ) : sh o w (se lf .getlm agenO ) b lo c k in g P la y C s e lf .g e tS o n id o O )
Una de las ventajas de esta clase modificada es que no tenemos que cambiar nada en nuestra función re p ro d u c i r P re se n ta c io n 3 .F u n c io n a a s íd e simple, aun y cuando realiza mos varias modificaciones en cuanto a la forma en que funciona la clase Di a p o s i t i va. De cimos que la función re p ro d u c i rDi a p o si t i va3 y la clase Di a p o s i t i va están débilmente acopladas. Funcionan en conjunto y de maneras bien definidas, pero es posible cambiar el funcionamiento interno de una sin afectar a la otra.
16.5 MEDIOS ORIENTADOS A OBJETOS Como dijimos antes, hemos estado usando objetos en todo el libro. Creamos objetos Pieture con la función makePicture. También podemos crear una imagen mediante el cons tructor normal de Python. » > im a g = P ictu re (g e tM e d ia P a th ("b a rb a ra .jp g ")) » > imag.showO
He aquí cómo se define la Junción s h o w O . Puede ignorar a rai se y — el ass— . El punto clave es que lo único que hace la función es ejecutar el método show de la imagen existente. d ef s h o w (p ic tu re ): i f not p ic t u r e e la s s — == P ic t u r e : p r in t "sh o w C p ictu re): Inp u t i s not a p ic tu re " r a is e V a lu e E rro r p ic tu re .sh o w O
Sección 16.5
M edios orientados a objetos
395
Podríamos tener otras clases que también sepan cómo usar la función show. Los objetos pueden tener sus propios métodos con nombres que también utilicen otros objetos. Es mucho más poderoso que cada uno de estos métodos con el mismo nombre puedan lograr el mis mo objetivo, sólo que en distintas formas. Definimos una clase para las diapositivas y éstas sabían cómo usar la función mostrar. Tanto para las diapositivas como para las imágenes, el método mostrar() dice: “Muestra el objeto”. Pero lo que ocurre en realidad es distinto en cada caso: las imágenes sólo se muestran a sí mismas, pero las diapositivas muestran sus imágenes y reproducen sus sonidos.
Idea de ciencias computacionales: polimorfismo A la técnica de usar el mismo nombre para invocar distintos métodos que logran el mismo objetivo se le conoce como polimorfismo. Es algo muy poderoso para el programador. Sólo tenemos que decir a un objeto que use la función m o strar(): no tenemos que preocuparnos por saber cuál es el método específico que se va a ejecutar y ni siquiera tenemos que saber con exactitud qué objeto es al que le decimos que se muestre. Usted el programador tan sólo tiene que especificar su objetivo, que es mostrar el objeto. El programa orientado a objetos se encarga del resto.
Hay varios ejemplos de polimorfismo integrado en los métodos que usamos en JE S.1Por ejemplo, tanto los píxeles como los colores saben acerca de los métodos set Red, getRed, setBlue, getBlue, setGreen y getGreen. Esto nos permite manipular los colores de los píxeles sin tener que extraer los objetos color por separado. Podríamos haber definido las funciones para recibir ambos tipos de entrada o proveer distintas funciones para cada tipo de entrada, pero ambas opciones son confusas. Esto es fácil de hacer con métodos. »> »> »> »>
im ag= Picture(getM ediaPath("'barbara, jp g " )) imag.showO p ix e l = i mag. getPi xe l (1 0 0 ,2 0 0 ) p r in t p ix e l .g e tR e d ()
73
» > c o lo r = p ix e l .g e tC o lo r() » > p r in t c o lo r.g e tR e d () 73
El método write() es otro ejemplo. Se define el método wri te (nombre archivo) para imágenes y para sonidos. ¿Alguna vez confundió wri tePi ctureToO con writeSound To()? ¿No sería más fácil escribir siempre wri te (nombrearchi vo)? Esto explica por qué el método se llama igual en ambas clases y por qué el polimorfismo es tan poderoso (tal vez se pregunte por qué no introdujimos esta técnica desde un principio. Pero ¿estaba usted listo en el capítulo 2 para hablar sobre la notación punto y los métodos polimórficos?). En general, hay en realidad mucho más métodos definidos en JES que funciones. O dicho de manera más específica, hay varios métodos para dibujar sobre imágenes que no están disponibles como funciones.
1Recuerde que JES es un entorno para program ar en Jython, el cual es un tipo específico de Python. L os soportes de medios forman parte de lo que ofrece JES: no pertenecen al núcleo de Python.
39 6
Capítulo 16
Program ación orientada a objetos
FIGURA 16.12
Ejemplos de métodos de rectángulos. • C o m o e s d e e sp e ra r, la s im á g e n e s c o n o c e n i mag. ad d R e ct ( c o l o r , x , y , anchu r a , a l t u r a ) , i m a g .a d d R e c t F i l l e d ( c o l o r , x , y , a n c h u r a , a l t u r a ) , im a g .a d d O va l ( c o l o r , x , y , a n c h u r a , a l t u r a ) e im a g . a d d O v a lF i11e d ( c o l o r , x , y , a n c h u r a , a ltu r a ).
En la figura 16.12 podrá ver ejemplos de métodos de rectángulos dibujados a partir del siguiente ejemplo. »> »> »> »> »>
imag=Pi cture(getM edi aPath("640x480. jp g " ) ) i mag. addRect F i 11 ed (o range, 1 0 ,1 0 ,1 0 0 ,1 0 0 ) im ag .a d d R e ct(b lu e ,200,200, 50,50) imag.show( ) i mag. w ri te (" n u e v o s re c ts .jp g " )
En la figura 16.13 podrá ver ejemplos de óvalos dibujados a partir del siguiente ejemplo. »> »> »> »> »>
i mag=Pi ctu re (getMedi aPath ( "640x480. j pg") ) imag.addOval (g re e n ,2 0 0 ,2 0 0 ,50,50) i mag. addOval F i 11 ed (magenta, 1 0 ,1 0 ,1 0 0 ,1 0 0 ) imag.showO im a g .w rit e (" o v a lo s .jp g " )
• Las imágenes también conocen los arcos. Éstos son, en sentido literal, partes de un círculo. Los dos métodos son im ag. a d d A r c ( c o lo r , x , y, a n c h u r a ,a l t u r a , a n g u lo ln ic , an g ul o A rc o ) e i mag . addAr c F i 11 ed ( c o l o r , x , y, a n c h u ra , a l t u r a , an g ul o l n i c , a n g u lo A r c o ). Dibujan arcos con ángulos basados en el valor de a n g u lo A rc o , en donde an g ul o l n i c es el punto de partida. Cero grados son las 3 en punto en la carátula del reloj. Un arco positivo se cuenta en sentido contrario a las manecillas del reloj y un arco negativo es en sentido a favor de las manecillas del reloj. El centro del círculo es la parte media del rectángulo definido por (jc, y) con la anchu r a y a l t u r a dadas. • Ahora también podemos dibujar líneas coloreadas, mediante el uso de i mag. addLi ne( c o lo r ,x l,y l,x 2 ,y 2 ) .
Sección 16.5
M edios orientados a objetos
FIGURA 16.13 Ejemplos de métodos de óvalos.
FIGURA 16.14 Ejemplos de métodos de arcos.
En la figura 16.14 podrá ver ejemplos de arcos y líneas dibujadas a partir del guiente ejemplo. »> »> »> »> »> »> »> »>
imag=Pi cture(getM edi aP ath ("640X480. jp g " ) ) i mag. addArc ( re d , 1 0 ,1 0 ,1 0 0 ,1 0 0 ,5 ,4 5 ) imag.showO i mag. addArcFi 11 ed (g re e n , 2 0 0 ,1 0 0 ,2 0 0 ,1 0 0 ,1 ,9 0 ) im a g .re p a in tO i mag. addLi ne (b l ue, 4 0 0 ,4 0 0 ,6 0 0 ,4 0 0 ) imag. re p a in tO i mag. w ri te (" a r c o s - lin e a s , jp g ")
398
Capítulo 16
Program ación orientada a objetos
• El texto en Java puede tener estilos, pero éstos se limitan a asegurar que todas las plataformas puedan duplicarlos. Uno de los que podríamos esperar ver es im ag. a d d T e x t( c o lo r ,x ,y ,c a d e n a ) . También está im a g .a d d T e x tW ith S ty le (c o lo r,x , y , c a d e n a , e s t i l o ) , el cual obtiene un estilo creado de m a k e S ty le (f u e n te , é n f a s is ,ta m a ñ o ) . El parámetro f u e n te es s a n s S e r i f , s e r i f o mono. El parámetro énfasis es i t a l i c, bol d o pl a i n, o la suma de éstos para obtener combinaciones (por ejemplo, i t a l i c+bol d). El parámetro tam año es un tamaño de punto. En la figura 16.15 podrá ver ejemplos de texto dibujado a partir del siguiente ejemplo. » > im ag=Picture(getM ediaPath("6 4 0 x 4 8 0 .jp g " )) » > im a g .a d d T e x t(re d ,1 0 ,1 0 0 ,"E s ta es una cadena r o ja " ) » > im ag .a d d T e xtW ith S tyle (g re e n ,1 0 ,2 0 0 ," E s ta es una cadena en n e g rit a , c u r s iv a , verde y g ra n d e ",m a k e S ty le (sa n sS e rif, b o ld + it a lic ,1 8 ) ) » > im a g .a d d T e x tW ith S ty le (b lu e ,1 0 ,3 0 0 ,"E sta es una cadena a z u l, más grande, só lo c u r s iv a , s e r i f " , m a k e S t y l e ( s e r i f , i t a l i c , 2 4 )) » > im a g .w r it e (" te x t o .jp g " )
Estaosunacadenaennegrita, cursiva, voreto yg¡ Esta es ana cadena azul, más grande, sólo cursiva, serif
FIGU RA 16.15 Ejemplos de métodos de texto.
Las funciones de medios que escribimos en capítulos anteriores pueden volver a escribir se en forma de métodos. Tendremos que crear una subclase de la clase P ic t u r e y agregar el método a esa clase.
P ro g ram a 1 5 7 : creación de un atardecer usando un m étodo
c la s s M iIm a g e n (P ictu re ): d ef c r e a r A t a r d e c e r (s e lf ): fo r p in g e t P i x e l s ( s e l f ) : p .s e t B lu e ( in t ( p .g e t B lu e ( ) * 0 .7 ) ) p .s e tG re e n (in t (p .g e t G re e n ()* 0 .7 ))
Sección 16.6
La caja Jo e
399
Este programa puede usarse así: »> »> »> »>
imag = M iIm agen(g etM ed iaPath("b each.jp g")) i mag. expío re ( ) im a g .c re a rA ta rd e c e rO i mag. expío re ( )
También podemos crear nuevas subclases de la clase Sound y nuevos métodos para traba jar con objetos sonido. Los métodos para acceder a los valores de una muestra de sonido son g etS am p leV a lu e () y g e tS a m p le V a lu e A t(in d ic e ).
Programa 158: invertir un sonido con un m étodo c la s s M iSonido(Sound): d ef i n v e r t í r ( s e l f ) : de stin o = S o u n d (se lf .g e tL e n g th O ) in d ice O rig e n = s e lf.g e tL e n g th O - 1 fo r in d ice D e stin o in rang e(0, d e s ti no. g e tLe n g th O ) : valo rO rig e n = s e l f . g etSam p leV alueA t(indiceO rigen ) d e sti no. setSam pleV alueA t(i ndi ceD esti no, v a lo rO ri gen) ind iceO rig en = in d iceO rig e n - 1 re tu rn d estino
■ Podemos usar el programa anterior de la siguiente forma: »> »> »> »>
16.6
sonido = M iSo nido (getM ediaPath ("alw ays.w av")) so n id o .e x p lo re O d estin o = s o n id o .in v e r t ír ( ) d e s tin o .e x p lo re O
LA CAJA JO E Adele Goldberg y Alan Kay desarrollaron el ejemplo más antiguo utilizado para enseñar programación orientada a objetos. A este método se le conoce como La caja Joe. No hay nada nuevo en este ejemplo, aunque ofrece un ejemplo diferente desde otra perspectiva, por lo que vale la pena revisarlo. Imagine que tiene una clase llamada Ca j a, como la que se muestra a continuación: c la s s C a ja : d ef — i n i t — ( s e l f ) : s e l f .esta b lecerC o lo rP red e te rm in ad o O self.tam = 1 0 s e lf.p o s ic = (1 0 ,1 0 ) d ef e sta b le c e rC o lo rP re d e te rm in a d o (s e lf): s e lf .c o l o r = red d ef d i b u j a r ( s e l f ,l i e n z o ) : a d d R e c tF ille d (lie n z o , s e l f . p o s i c [ 0 ] , s e l f . p o s ic [ l] ,s e lf .t a m , s e l f . t a m ,s e lf .c o lo r )
400
Capítulo 16
Program ación orientada a objetos
¿Qué verá si ejecuta el siguiente código? »> >» »> »>
lien zo = makeEmptyPicture(400,200) joe = C aja() jo e . di bu j a r (lien z o ) show(lienzo) Vamos a rastrearlo. • Es obvio que la primera línea sólo crea un 1ienzo blanco con 400 píxeles de ancho y 200 píxeles de alto. • Al crear a j oe, se invoca el método — ini t__. Luego se invoca el método establ ecerColorPredetermi nado sobre joe, por lo que recibe el color predeterminado rojo. Al ejecutarse sel f .color=red, se crea la variable de instancia color para joe y ob tiene un valor de rojo. Regresamos a — ini t— , en donde joe recibe un tamaño de 10 y una posición de (10,10) (tam y pos ic se convierten en nuevas variables de instancia). • Cuando se le pide a joe que se dibuje a sí mismo en el lienzo, se dibuja como un rectángulo rojo relleno (addRectFi 11 ed) en la posición x 10 y la posición y 10, con un tamaño de 10 píxeles de cada lado.
Podríamos agregar un método a Caja que nos permita hacer que joe cambie su tamaño. c la s s Caja: def in it (s e lf): self.estab lecerC o lo rP red eterm in ad o () s e l f . tam=10 self.p o sic= (1 0 ,1 0 ) def estab le cerC o lo rP re d eterm in ad o (se lf): s e lf .c o lo r = red def d ib u ja r ( s e lf ,lie n z o ) : a d d R ectF illed (lien zo , s e l f .p o s i c [ 0 ] ,s e l f . p o s i c [ l ] , s e lf.ta m , s e lf .ta m ,s e lf .c o lo r ) def c r e c e r ( s e lf ,ta m ) : s e l f . tam = self. tam+tam Ahora podemos pedir a Joe que crezca mediante la función crecer. Un número negativo como - 2 provocará que joe se encoja. Un número positivo hará que joe crezca; aunque tendríamos que agregar un método mover si queremos que crezca mucho y pueda caber todavía en el lienzo. Considere ahora el siguiente código que se agrega en la misma área del programa. c la ss C a ja T riste (C a ja ): def estab le cerC o lo rP re d eterm in ad o (se lf): se lf.c o lo r= b lu e Observe que CajaTriste lista a Caja como una superclase (clase padre). Esto significa que CajaTriste hereda todos los métodos de Caja. ¿Qué veremos al ejecutar el siguiente código? » > jan e = C a ja T r is t e O » > ja n e .d ib u ja r (lie n z o ) » > r e p a in t(lie n z o )
Sección 16.7
¿Po r qué objetos?
401
Vamos a rastrearlo: • Al crear a jane como una Ca jaTri ste, se ejecuta el método __i ni t__ en la clase Ca ja. • Lo primero que ocurre en __i ni t— es que llamamos a establ ecerColorPredetermi nado en el objeto de entrada self. Ahora ese objeto es j ane. Por ende, invocamos a establecerColorPredetermi nado de jane. Decimos que establecerColorPredetermi nado de CajaTri ste redefine al método de Caja con el mismo nombre. • El método establ ecerColorPredetermi nado de jane estab le ced co lo ren azul. • Después regresamos a ejecutar el resto del método — ini t— de Caja. Establecemos el tamaño de jane en 10 y su posición en (10,10). • Cuando pedimos a jane que se dibuje, aparece como un cuadrado azul de 10 x 10 en la posición (10,10). Si no movemos o aumentamos el tamaño de j oe, éste desaparecerá al momento que jane se dibuje encima de él. Cabe mencionar que joe y jane son distintos tipos de Caja. lle n e n las mismas variables de instancia (pero distintos valores para las mismas variables) y en su mayoría conocen las mismas cosas. Por ejemplo, como ambas conocen el método dibujar, decimos que di bujar es polimórfico. La palabra polimórfico significa muchas formas. Una CajaTri ste (jane) es un poco distinta en cuanto a la forma en que se comporta al momento de su creación, de modo que conoce algunas cosas de manera distinta. Joe y Jane resaltan algunas de las ideas básicas de la programación orientada a objetos: herencia, especialización en subclases y variables de instancia compartidas, al tiempo que tienen distintos valores en sus variables de instancia.
16.7
¿POR QUÉ OBJETOS? Un rol para los objetos es reducir el número de nombres que tenemos que recordar. Por medio del polimorfismo, sólo tenemos que recordar el nombre y el objetivo, no todas las diversas funciones globales. Pero lo más importante es que los objetos encapsulan los datos y el comportamiento. Imagine que desea cambiar el nombre de una variable de instancia y después todos los méto dos que usan esa variable. Es mucho por cambiar. ¿Qué tal si olvida uno? Sería conveniente cambiarlos todos en un solo lugar. Los objetos reducen el acoplamiento entre los componentes del programa; esto es, qué tanto dependen unos de otros. Imagine que tiene varias funciones y todas usan la misma variable global. Si cambia una función de modo que almacene algo ligeramente diferente en esa variable, todas las demás funciones también deberán actualizarse o de lo contrarío no funcionarán. A esto se le conoce como acoplamiento Juerte. Los objetos que sólo usan métodos sobre otros objetos (sin acceso directo a las variables de instancia) tienen un aco plamiento más débil. El acceso está bien definido y se puede modificar con facilidad en un solo lugar. Los cambios en un objeto no exigen cambios en otros objetos. Una ventaja del acoplamiento débil es la facilidad para desarrollar en contextos de equi pos. Es posible tener a distintas personas trabajando en diferentes clases. Mientras que todos estén de acuerdo en la forma en que funcionará el acceso a través de los métodos, nadie tendrá qué saber cómo funcionan los métodos de los demás. La programación orientada a objetos puede ser especialmente útil al trabajar en equipos. La agregación es también un beneficio considerable de los sistemas de objetos. Es posible tener muchos objetos que realicen cosas útiles. ¿Desea más? ¡Sólo hay que crearlos!
402
Capítulo 16
Program ación orientada a objetos
Los objetos de Python son similares a los objetos de muchos lenguajes. No obstante, una de las diferencias considerables está en el acceso a las variables de instancia. En Python, cualquier objeto puede acceder a las variables de instancia de cualquier otro objeto y mani pularlas. Esto no es cierto en lenguajes como Java, C++ o Smalltalk. En estos otros lenguajes está limitado el acceso a las variables de instancia desde otros objetos, e incluso puede eli minarse por completo: así sólo es posible acceder a las variables de instancia de los objetos por medio de métodos getter y setter. La h erencia es otra gran parte de los sistemas de objetos. Como vimos con los ejemplos de la tortuga y la caja, podemos declarar que una clase (clase padre) será heredada por otra clase (clase hija) (lo que también se conoce como superclase y subclase). La herencia ofrece un polimorfismo al instante: las instancias de la hija obtienen de manera automática todos los datos y el comportamiento de la clase padre. Así, la hija puede agregar más comporta miento y datos a lo que la clase padre tenía. A esto se le conoce como hacer que la hija sea una especialización de la clase padre. Por ejemplo, la instancia de un rectángulo en tercera dimensión podría conocer y hacer todo lo que hace una instancia de rectángulo m ediante la instrucción class Rectangulo3D(Rectangulo). La herencia es muy popular en el mundo orientado a objetos, aunque tiene sus ventajas y desventajas. Reduce aún más la duplicación de código, lo cual es algo bueno. En la práctica real, la herencia no se utiliza tanto como muchas otras de las ventajas de la programación orientada a objetos (como la agregación y la encapsulación), además de que puede ser con fusa. ¿Cuál método se está ejecutando cuando escribimos el código siguiente? Es invisible desde aquí, y si está equivocado, puede ser difícil averiguar en dónde está equivocado. miCaja = Rectangulo3D() m iC a ja .d ib u ja rO
Entonces, ¿cuándo hay que usar objetos? Debemos definir nuestras propias clases cuando tenemos datos y comportamiento que deseamos definir para todas las instancias del grupo (como imágenes y sonidos). Debemos usar objetos existentes todo el tiempo. Son muy pode rosos. Si usted no se siente cómodo con la notación punto y las ideas de los objetos, puede seguir usando funciones: trabajan muy bien. Los objetos son más convenientes en sistemas más complejos.
RESUMEN DE PROGRAMACIÓN Algunas de las piezas de programación que vimos en este capítulo.
PROGRAMACIÓN ORIENTADA A OBJETOS class
Nos permite definir una clase. La palabra clave c l a s s recibe el nombre de una clase y una superclase opcional entre paréntesis, y term ina con un signo de dos puntos. Después le siguen los métodos de la clase, con sangría dentro del bloque de la clase.
_ _ i ni t _
E nombre del método invocado sobre un objeto al momento de su creación. No se requiere tener uno.
Problem as
403
MÉTODOS DE GRÁFICOS addRect, addRectFilled
Los métodos en la clase Pi c t u r e para dibujar rectángulos y rectángu los rellenos.
addOval, addOvalFilled
Los métodos en la clase Pi c t u r e para dibujar óvalos y óvalos rellenos.
addArc, addArcFilled
Los métodos en la clase Pi c t u r e para dibujar arcos y arcos rellenos.
addText, addTextWithStyle
Los métodos en la clase Pi c t u r e para dibujar texto y texto con elem en tos de estilo (como negrita o sans serif).
addLine
El método en la clase Pi c t u r e para dibujar una línea.
getRed, getGreen, getBlue
Los métodos de los objetos P ix e l y C o lo r para obtener los com po nentes de color rojo, verde y azul.
setRed, setGreen, setBlue
Los métodos de los objetos Pi x e l y Col o r para establecer los com po nentes de color rojo, verde y azul.
PROBLEMAS 16.1
Responda a las siguientes preguntas. • ¿Cuál es la diferencia entre una instancia y una clase? • ¿En qué difieren las funciones y los métodos? • ¿En qué difiere la programación orientada a objetos de la programación por proce dimientos? • ¿Qué es el polimorfismo? • ¿Qué es la encapsulación? • ¿Qué es la agregación? • ¿Qué es un constructor? • ¿Cómo influyen las células biológicas en el desarrollo de la idea de los objetos?
16.2
Responda a las siguientes preguntas. • ¿Qué es la herencia? • ¿Qué es una superclase? • ¿Qué es una subclase? • ¿Qué métodos hereda una clase hija? • ¿Qué variables de instancia (campos) hereda una clase hija?
16.3
Agregue un método a la clase T o rtu g a para dibujar un triangulo equilátero.
16.4
Agregue un método a la clase T o rtu g a para dibujar un rectángulo con base en una anchura y altura específicas.
16.5
Agregue un método a la clase T o rtu g a para dibujar una casa simple. Puede tener un rectángulo para la casa y un triángulo equilátero para el techo.
404
Capítulo 16
Program ación orientada a objetos
16.6 Agregue un método a la clase T o rtu g a para dibujar una calle de casas. 16.7 Agregue un método a la clase T o rtu g a para dibujar una letra. 16.8 Agregue un método a la clase T o rtu g a para dibujar sus iniciales. 16.9 Cree una película con varias tortugas moviéndose en cada cuadro. 16.10 Agregue otro constructor a la clase Di a p o si t i v a que reciba sólo el nombre de archi vo de una imagen. 16.11 Cree una clase llamada P re se n t a c i on que contenga una lista de diapositivas y m ues tre una diapositiva a la vez. 16.12 Cree una clase llamada Panel C ari c a tu r a s que reciba un arreglo de objetos Pi c t u re y muestre las imágenes de izquierda a derecha. También debe tener un título y un autor, además de mostrar el título en el borde superior izquierdo y el autor en el borde superior derecho. 16.13 Cree una clase llamada E s tu d ia n te . Cada estudiante debe tener un nombre y una imagen. Agregue un método llamado m o s tra r que muestre la imagen del estudiante. 16.14 Agregue un campo a la clase Presentación que contenga el título y modifique el método mostrar, para que primero muestre una imagen en blanco con el título en ella. 16.15 Cree una clase llamada ListaReproduccion que reciba una lista de sonidos y los reproduzca uno a la vez. 16.16 Use los métodos en la clase Pi c t u r e para dibujar una cara sonriente. 16.17 Use los métodos en la clase Pi c t u r e para dibujar un arcoíris. 16.18 Vuelva a escribir las funciones espejo como métodos en la clase Mi Image n. 16.19 Realice algunas modificaciones a la caja Joe. • Agregue un método a C a ja llamado s e tC o lo r que reciba un color como entrada y luego haga que el color de entrada sea el nuevo color de la caja (¿tal vez e s t a b l e c e rC o lo rP re d e te rm in a d o debería llamar a s e tC o lo r? ) • Agregue un método a C a ja llamado setT am anio que reciba un número como en trada y luego lo asigne como el nuevo tamaño para la caja. • Agregue un método a Ca j a llamado s e tP o s i c i on que reciba una lista o tupia como parámetro y después la asigne como la nueva posición para la caja. • Modifique —i n i t__ de modo que use setT am an io y s e t P o s ic i o n en vez de es tablecer de manera directa las variables de instancia. *16.20 Termine el ejemplo de la caja Joe. a) Implemente crecer y mover. El método mover debe recibir como entrada una distancia relativa como (-10,15) para moverse 10 píxeles a la izquierda (posición x) y 15 píxeles hacia abajo (posición y). b) Dibuje patrones al crear a joe y jane; después mueva un poco y dibuje, aumente un poco el tamaño y dibuje, luego vuelva a pintar el nuevo lienzo. 16.21 Cree una película con cajas que aumenten y reduzcan su tamaño.
^Problema más desafiante.
Para profundizar
40 5
PARA PROFUNDIZAR Queda mucho más qué hacer con Python en cuanto a explorar los estilos de programación por procedimientos, funcional y orientada a objetos. Mark recomienda los libros de Mark Lutz (en especial [30]) y Richard Hightower [24] como excelentes introducciones a los ám bitos más extensos de Python. También podría explorar algunos de los tutoriales en el sitio Web de Python (h ttp ://w w w . python .o rg ).
APÉNDICE
A
Referencia rápida de Python
A.1
V A R IA B LES
A .2
C R E A C IÓ N D E F U N C IO N E S
A .3
C IC L O S Y C O N D IC IO N A L E S
A .4
O P E R A D O R E S Y FU N C IO N E S D E R E P R E S E N TA C IÓ N
A .5
F U N C IO N E S N U M ÉR IC A S
A .6
O P E R A C IO N E S D E S E C U E N C IA
A .7
CAD EN AS D E ESCAPE
A .8
M ÉTO D O S D E C A D E N A Ú TILES
A .9
A R C H IV O S
A .1 0
LISTAS
A .1 1
D IC C IO N A R IO S , T A B LA S HASH O A R R E G L O S A S O C IA T IV O S
A .1 2
M Ó D U LO S E X T E R N O S
A .1 3
C LA S E S
A . 14
M ÉTO D O S FU N C IO N A LE S
A.1
VARIABLES Las variables empiezan con una letra y pueden ser cualquier palabra, excepto una de las palabras reservadas, las cuales son: a n d , a s s e r t , b r e a k , c l a s s , c o n t in u é , d e f , d e l , e l i f , e l s e , e x c e p t , e x e c , f i n a l l y , f o r , fro m , g l o b a l, i f , im p o r t , i n , i s , la m b d a , n o t , o r , p a s s , p r i n t , r a i s e , r e t u r n , t r y , w h i l e , y i e l d . Podemos usar p r i n t para mostrar el valor de una expresión (por ejemplo, una variable). Si sólo escribimos la variable sin p r i n t , obtendremos la representación interna: las funcio
nes y objetos nos dicen en qué parte de la memoria se encuentran y las cadenas aparecen con sus comillas. » > x - 10 » > p r in t x 10 40 7
408
Apéndice A
Referencia rápida de Python
»> x
10 » > y=’ cadena’ » > p r in t y cadena »> y 'cad ena’ » > p= m akePicture(pickAFi 1 e ()) » > p r in t p P ic t u r e , filen am e C :\ip -b o o k\m ed iaso urces\ 7 in x 9 5 in .jp g heigh t 684 w idth 504 »> p
A.2
CREACIÓN DE FUNCIONES Para definir funciones usamos d e f. Por ejemplo d e f x ( a , b ) : define una función llamada “x” que recibe dos valores de entrada, los cuales están enlazados a las variables “a” y “b” . El cuerpo de la función sigue después de la instrucción d e f y lleva sangría. La función puede devolver valores mediante el uso de la instrucción r e t u r n .
A .3 CICLOS Y CONDICIONALES Creamos la mayoría de los ciclos mediante el uso de f o r , que recibe una variable índice y una lista. El cuerpo del ciclo se ejecuta una vez por cada elemento de la lista. »>
fo r p in [ 1 , 2 , 3 ] : p r in t p
1 2
3
Con frecuencia, la lista en un ciclo f o r se genera mediante el uso de una función rang e. Esta función puede recibir una, dos o tres entradas. Con una entrada, el rango es desde cero hasta la entrada menos uno. Con dos, el rango empieza en la primera entrada y se detiene antes de la segunda. Con tres, el rango empieza en la primera, avanza a intervalos según la tercera y termina antes de la segunda. »> [0 , »> [1 ,
range (4 ) 1 , 2 , 3] range (1 ,4 ) 2 , 3]
Sección A .4
O perad ores y funciones de representación
40 9
» > r a n g e (l,4 ,2 ) [1 , 3]
El ciclo w h ile recibe una expresión lógica y ejecuta su bloque siempre y cuando la ex presión lógica sea verdadera. »> x = 1 » > w h ile x < 5: p r in t x
x = x + 1
1 2
3 4
Una instrucción b re a k termina de inmediato el ciclo actual. Una instrucción i f recibe una expresión lógica y la evalúa. Si es verdadera, se ejecuta el bloque de la instrucción i f. Si es falsa, se ejecuta la cláusula e l se: , en caso de que exista una. » > i f a < b: p r in t "a es menor"
...
el se: p r in t "b es menor"
A.4
OPERADORES Y FUNCIONES DE REPRESENTACIÓN J. _ * T ) >
<,
>,
í
/
==,
* /»
Suma, resta, multiplicación, división y exponenciación. El orden de precedencia es algebraico.
*
<»,
> =
Los operadores lógicos menor que, mayor que, igual a, menor o igual a, mayor o igual a.
O , !=
Los operadores lógicos de desigualdad (ambos son equi valentes)
and, o r, n o t
Los conjuntivos lógicos and, o r y n o t.
in t O
Devuelve la parte entera de la entrada (número de punto flotante o cadena).
f lo a t O
Devuelve una versión de punto flotante de la entrada.
strO
Devuelve una representación de cadena de la entrada.
o rd Q
Dado un carácter de entrada, devuelve la representación numérica en ASCII.
410
Apéndice A
A.5
A.6
Referencia rápida de Python
FUNCIONES NUMÉRICAS a b s()
Valor absoluto.
s in ( )
Seno.
c o s()
Coseno.
max()
Valor máximo de las entradas (incluyendo una lista).
m in()
Valor mínimo de las entradas (incluyendo una lista).
le n ( )
Devuelve la longitud de la secuencia de entrada.
OPERACIONES DE SECUENCIA Las secuencias (cadenas, listas, tupias) pueden sumarse o concatenarse (por ejemplo, s i +
52). Es posible acceder a los elementos de una secuencia mediante el uso de porciones: seq [n] accede al «-ésimo elemento de la lista (el primer elemento es cero), seq [ n : m] accede a los elementos desde el fl-ésimo hasta, pero sin incluir, el m-úsimo. seq [: m] accede a los elementos desde el inicio hasta, pero sin incluir, el m-ésimo, seq [ n : ] accede a los elementos desde el n-ésimo hasta el final de la secuencia.
A .7 CADENAS DE ESCAPE \t
Carácter de tabulación
\b
Retroceso
\n
Nueva línea
\r
Retorno
\uXXXX
Carácter Unicode, XXXX hexadecimal
Coloque una ‘Y* antes de una cadena, como en r"C:\mediasources", para manipular una cadena en modo puro, ignorando los escapes.
A .8 MÉTODOS DE CADENA ÚTILES • count (sub): devuelve el número de veces que aparece sub en la cadena. • find(sub): devuelve el índice en donde aparece sub en la cadena, o devuelve -1 si no se encuentra, find puede recibir un punto inicial opcional y un punto final también opcional, rfi nd recibe las mismas entradas pero trabaja de derecha a izquierda. • upper(), lowerQ:convierte la cadena asó lo mayúsculas o minúsculas.
Sección A.1
M ódulos externos
411
• i s a l p h a ( ) , i s d i g i t ( ) : devuelven verdadero si todos los caracteres en la cadena son alfabéticos o todos son numéricos, respectivamente.
A.9
•
r e p l a c e ( s . r ) : sustituye todas las instancias de “s” con ‘Y* en la cadena.
•
s p l i t ( d ) : devuelve una lista de cadenas en donde el carácter d es el punto de división.
ARCHIVOS Los archivos se abren mediante open con dos entradas: el nombre de archivo y un modo de archivo. El modo de archivo es “r” para lectura, “w” para escritura y “a” para añadir, conca tenado con una “t” para texto o una “b” para binario. Los métodos de archivos son: •
re a d ( ) : devuelve todo el archivo como una cadena.
•
r e a d l i n e s ( ) : devuelve todo el archivo como una lista de cadenas delimitadas por salto de línea.
• w r i t e ( s ) : escribe la cadena s en el archivo.
A .10
LISTAS Las listas se indexan como las secuencias mediante el uso de “ [ ] ”. Se concatenan mediante +. Los métodos de listas son: •
a p p e n d (b ): añade el elemento b a una lista.
•
remove ( b ) : retira el elemento b de la lista.
• so r t O : ordena la lista. •
r e v e r s e f ) : invierte la lista.
• c o u n t ( s ) : devuelve el número de veces que aparece el elemento s en la lista.
A.11 DICCIONARIOS, TABLAS HASH O ARREGLOS ASOCIATIVOS Los diccionarios se crean con {}. Es posible acceder a ellos mediante una clave. » > d = { 'g a t o ’ : 'D ia n a * , ' p e r r o ' F i d o * } » > p r in t d ['g a t o * : 'D ia n a * , 'p e r r o ': ’ F id o ’ } » > p r in t d .k e y s O [ 'g a t o * , 'p e r r o '] » > p r in t d [ ’ g ato ’ ] Diana
A .12
MÓDULOS EXTERNOS Para acceder a los módulos se utiliza im p o rt. También se pueden introducir como un alias; por ejemplo, im p o rt j a v a x . sw in g como sw in g . Es posible importar piezas específicas sin necesidad de la notación punto para acceder a ellas, si usamos fro m módulo im p o rt n i , n2. Podemos importar y acceder a todas las piezas de un módulo sin la notación punto, si usamos fro m módulo im p o rt *.
412
Apéndice A
Referencia rápida de Python
A .13 CLASES Las clases se crean mediante la palabra clave e l a s s seguida del nombre de la clase y una superclase opcional entre paréntesis (una o más). Después se escriben los métodos con san gría. Los constructores (que se invocan al momento de crear una nueva instancia de la clase) deben llam arse i n i t . Puede tener más de un constructor en una clase de Python siem pre y cuando reciban distintos parámetros.
A .14
MÉTODOS FUNCIONALES a p p ly
Recibe una función y una lista com o entrada para esa función, en donde la lista tiene tantos elementos como los que reciba la función de entrada. Invoca a la función con la entrada.
map
Recibe una función y una lista de varias entradas para esa función. Invoca a la función con cada una de las entradas y devuelve una lista de las salidas (valores return).
filt e r
Recibe una función y una lista de varias entradas para esa función. Invoca a la función con cada uno de los elementos de la lista y de vuelve el elemento de entrada si la función devuelve verdadero (un valor distinto de cero) para ese elemento.
reduce
Recibe una función que tiene dos entradas y una lista de varias entradas para esa función. Ésta se aplica a los primeros dos elem en tos de la lista y el resultado se usa com o entrada con el siguiente elem ento de la lista; después el resultado de esto se utiliza como entrada con el siguiente elemento y así, en lo sucesivo. El resultado total se devuelve al final.
Bibliografía 1. AAUW, Tech-Savvy: Educating Girls in the New Computer Age, Asociación estadouni dense de la Fundación de educación para mujeres universitarias, Nueva York, 2000. 2 . H a r o l d A b e l s o n , G e r a l d J a y S u s s m a n y J u l i e S u s s m a n , Structure and Interpreta
ron o f Computer Programs, 2 a edición, MIT Press, Cambridge, MA, 1996. 3 . K e n A b e r n e t h y y T o m A l l e n , Exploring the Digital Domain: An Introduction to
Computing with Multimedia and Networking, PWS Publishing, Boston, 1998. 4. ACM/IEEE, Computing Curriculum 2001, h ttp ://w w w .a c m .o rg /s ig c s e /c c 2 0 0 1 (2001 ).
5. B e t h A d e l s o n y E l l i o t S o l o w a y , ‘T h e Role o f Domain Experience in Software Design” , IEEE Transactions on Software Engineering SE-11 (1985), no. 11,1351-1360. 6. J e n s B e n n e d s e n y M i c h a e l E. C a s p e r s e n , “Failure Rates in Introductory Program ming” , SIGCSE Bulletin 39 (2007), no. 2, 32-36. 7. R i c h a r d B o u l a n g e r (ed.), The Csound Book: Perspectives in Synthesis, Soimd Design, Signal Processing, and Programming, MTT Press, Cambridge, MA, 2000. 8. A m y B r u c k m a n , “Situated Support for Learning: Storm’s Weekend with Rachael”, Jo urnal o fth e Learning Sciences 9 (2000), no. 3,329-372. 9. J o h n T. B r u e r , Schools fo r Thought: A Science o f Learning in the Classroom, MIT R-ess, Cambridge, MA, 1993. 10. A l a n J. D ix , J a n e t E. F i n l a y , G r e g o r y D. A b o w d y R u s s e l l B e a l e , Human-Computer Interaction, 2a. edición, Prentice Hall, Upper Saddle River, NJ, 1998. 11. C h a r l e s D o d g e y T h o m a s A . J e r s e , Computer Music: Synthesis, Composition, and
Performance, Schirmer-Thomson Learning, Nueva York, 1997. 12. M a t t h i a s F e l l e i s e n , R o b e r t B r u c e F i n d l e r , M a t t h e w F l a t t y S h r i r a m K r i s h n a m u r t h i , How to Design Programs: An Introduction to Programming and Compu ting, MIT Press, Cambridge, MA, 2 0 0 1 .
13. A n n E. F l e u r y , “Encapsulation and Reuse as Viewed by Java Students” , Proceedings o f the 32nd SIGCSE Technical Symposium on Computer Science Education (2001), pp. 189-193. 14. J a m e s D. F o l e y , A n d r i e s V a n D a m y S t e v e n K. F e i n e r , Introduction to Computer Graphics, Addison Wesley, Reading, MA, 1993. 15. A n d r e a F o r t e y M a r k G u z d i a l , Computers fo r Communication, Not Calculation:
Media as a Motivation and Context fo r Learning, HICSS 2004, Big Island, HI, IEEE Computer Society 2004. 16. D a n n y G o o d m a n , JavaScript & DHTML Cookbook, O ’Reilly & Associates, Sebastapol, CA, 2003.
413
414
Bibliografía
17. M a r t i n G r e e n b e r g e r , “Computers and the World o f the Future” , grabaciones transcri tas de conferencias en la Sloan School o f Business Administration, abril de 1961, MIT R-ess, Cambridge MA, 1962. 18. R a s h i G u p t a , Making Use o f Python, Wiley, Nueva York, 2 0 0 2 .
19. M a r k G u z d i a l , Squeak: Object-Oriented Design with Multimedia Applications, Prentice Hall, Englewood, NJ, 2001. 20. M a r k G u z d i a l y K im R o s e (eds.), Squeak, Open Personal Computingfor Multimedia, R-entice Hall, Englewood, NJ, 2001. 2 1 . M a r k G u z d i a l y A l l i s o n E l l i o t T e w , “Imagineering Inauthentic Legitímate Peri-
pheral Participation: An Instructíonal Design Approach for Motivating Computing Education” , artículo presentado en el Seminario internacional de investigación sobre educa ción computacional, Canterbury, Reino Unido, ACM, Nueva York, 2 0 0 6 . 22. I d i t H a r e l y S e y m o u r P a p e r t , “Software Design as a Leaming Environment” , Inte ractive Leam ing Environments 1 (1990), no. 1, 1-32. 23. B r i a n H a r v e y , Computer Science Logo Style, 2a. edición, vol. liSym bolic Computing, MIT Press, Cambridge, MA, 1997. 24. R i c h a r d H i g h t o w e r , Python Programming with the Java Class Libraries, AddisonWesley, Reading, MA, 2003. 25 . D a n I n g a l l s , T e d K a e h l e r , J o h n M a l o n e y , S c o t t W a l l a c e y A l a n K a y , “Back
to the Future: The Story o f Squeak, a Practical Smalltalk W ritten in Itself”, OOPSLA’97 Conference Proceedings, ACM, Atlanta, GA, 1 9 9 7 , pp. 3 1 8 -3 2 6 . 26. J a n e t K o l o d n e r , Case-Based Reasoning, Morgan Kaufmann, San Mateo, CA, 1993. 27. H e a t h e r P e r r y , L a u r e n R i c h y M a r k G u z d i a l , “A C S 1 Course Designed to Address Jnterests o f Women” , ACM SIGCSE Conference 2004, Norfolk, VA, ACM, Nueva York, 2004, pp. 190-194. 28. M a r g a r e t L i v i n g s t o n e , Vision and Art: The Biology o f Seeing, Harry N. Abrams, Nueva York, 2002. 29. F r e d e r i k L u n d h , Python Standard Library, O ’Reilly and Associates, Sebastapol, CA, 2001. 30. M a r k L u t z CA, 2003.
y
D a v id A s c h e r , Leaming Python, O’Reilly & Associates, Sebastopol,
31 . J a n e M a r g o l i s y A l l a n F i s h e r , Unlocking the Clubhouse: Women in Computing,
MIT Press, Cambridge, MA, 2002. 32. D a n O l s e n , Developing User Interfaces, M organ Kaufmann Publishers, San Mateo, CA, 1998. 33 . M i t c h e l R e s n i c k , Turtles, Termites, and Traffic Jams: Explorations in M assively Para-
llel Microworlds, MIT Press, Cambridge, MA, 1997. 34. J e a n n e t t e W in g , “Computatíonal Thinking” , Communications o f the AC M 49 (2006), no. 3,33-35. 35. C u r t ís R o a d s , The Computer Music Tutorial, MIT Press, Cambridge, MA, 1996. 36. R o b e r t S l o a n y P a t r i c k T r o y , “CS 0.5: A Better Approach to Introductory Computer Science for Majors” , Proceedings o fthe 39th SIGCSE Technical Symposium on Compu ter Science Education, ACM Press, Nueva York, 2008, pp. 271-275.
Bibliografía
41 5
37. A l l is o n E l l i o t T e w , C h a r l e s F o w l e r y M a r k G u z d i a l , “Tracking an Innovation in Introductory CS Education from a Research University to aTwo-Year College” , Proceedings o fth e 36th SIGCSE Technical Symposiutn on Computer Science Education, ACM IVess, Nueva York, 2005, pp. 416-420.
Indice ÍN D IC E SÍM B O L O S # , 87 ,1 8 1 *, 53 \n , 3 0 ,2 4 7 \t, 247 \u , 247 class , 394 init , 3 9 2 ,4 0 2 = , 28 0 0 ,3 4 2
A abajo A rriba, 3 6 5 ,3 6 7 ab s, 23, 3 7 ,1 2 1 abstracción, 9, 3 4 ,1 8 5 procedural, 2 1 8 ,2 9 5 ,3 1 9 , 358, 364, 376 reutilización, 218 subfunciones, 218 abstracto, 235 acoplada, 394 acoplam iento, 401 d éb il, 401 fuerte, 401 acorde m usical, 198 acordes, 198 actual, 230 addA rc, 403 addA rcFilled, 403 ad d L in e(im ag en ,x l,y l,x 2 ,y 2 ), 132, 139 addL ine, 403 addO val, 403 addO valF illed, 403 a d d R ect(),3 1 6 addR ect(im agen,x 1,y 1a n c h u ra , altura), 132, 139 addR ect, 403 addR ectFilled(im agen,x 1,y 1a n c h u ra , altura,color), 1 3 2 ,1 3 9 addT ext(im agen,x,y,cadena), 1 3 2 ,1 3 9 addT ext, 3 1 6 ,4 0 3 addT extW ithStyle, 403 A dobe Photoshop, 12
agregación, 3 7 7 ,3 9 3 ,4 0 1 agudeza, 42 AIFF, 2 5 ,2 1 2 alcance, 5 8 ,1 6 2 , 1 7 8 ,1 8 8 glo b al, 5 8 ,1 9 0 , 192 local, 58 alfabeto en L atín, 247 álgebra, 19 algoritm o, x ix ,4 , 8 ,1 6 8 , 1 8 7 ,2 0 2 , 2 3 5 ,3 4 1 de optim izació n , 348 d iseñ o , 235 esp acio , 342 m ezcla, 235 m u estreo , 235 reflejo, 187 tiem p o , 342 algoritm os, 3 algoritm os d e ord en am ien to , 343 alias, 162 alt, 292 am plitud, 146,161 análisis orientado a o b jeto s, 377 ancla, 292 etiqueta, 2 9 2 ,2 9 3 anidar, 7 6 ,2 4 5 anim aciones, 313, 314 anydbm , 300 append, 266 append(algo), 251 A pple Q uick T im e P lay e r P ro , 161 apply, 373 applyO , 359 aprendizaje d e m áquina, 349 árbol, 358 en listas, 254 hijos, 254 hoja, 254 pad re, 254 ram a, 254 archivo, 18, 2 5 3 ,3 7 0 ap ertu ra, 255 lectu ra, 255 m éto d o s, 2 5 5 ,4 1 0 ruta, 18 archivo.closeO , 256
archivo.read(), 255 archivo.readlinesO , 255 archivo.w rite(unacadena), 256 archivos b in ario s, 255 arcos, 396 argum entos d e palabras clave, 328 o p cio n ales, 328 arm ó n ico s, 148 arreglo, 1 7 ,4 1 ,5 4 , 1 5 4 ,1 8 0 asociativos, 302 b id im e n sio n a l,4 1 co p ia, 180 d e caracteres, 245 e lem en to , 1 5 4 ,1 5 5 ín d ice, 155 n o tació n , 7 6 ,1 7 5 u n idim ensional, 41 am b aA b ajo O , 375 asum e, 35 ataque, caíd a y sostenido (A SD ) envoltura, 215 A udacity, 12 aum entar V olum en, 161 A utoC A D , 133 avance paso a paso , 57 avanzar, 259 AVI, 314, 315 azul, 11
B bajo consum o d e en erg ía, 4 barras diagonales inversas, 30 bases d e d ato s, 4 ,2 9 9 c o n ex ió n , 305 p ara c re a r p áginas W eb, 307 tab las, 301 B em ers-L ee, T im , 272 B iblioteca d e im ágenes d e P ython (PAL), 236 bibliotecas estab le ce r rutas, 184 B ig-O , n o tació n , 342 b inario, 9 b it, 8, 170 417
418
índice
com o inform ación, 170 d e signo, 153 blockingPlay, 159,171 blockingPlayO , 390 bloque, 3 1 ,5 4 a n id a d o ,55 BM P, 134 botón load (cargar), 20 B rando, M arión, 161 break, 2 8 0 ,2 8 6 ,4 0 8 brilloC om binar, 330 brilloP ixel, 328 B rooks, Fred erick P., 241 bus del sistem a, 352 buscarS ecuencia, 260 B ush, Vannevar, 273 búsqueda b in aria, 346 lineal, 345 b y te, 8 ,9 , 17
C C, 7 C + + , 6 ,1 8 ,4 0 2 cadena, 1 7 ,2 2 ,2 9 ,3 7 , 2 4 5 ,2 5 3 búsqueda, 249, 250 concatenación, 247 subcadena, 248 vacía, 23 cadena [n:m ], 2 4 8 ,2 6 6 cadena[n], 248, 266 ca ja Jo e, 399 cálculo, 13 calendario, 265 cam biarF ondo, 126, 3 2 1 ,3 2 2 cam biarR ojo, 66 cam biar V olum en, 167 cam bio d e color, 61 cam pos, 299 can al, 43 canal alfa, 44 capitalizeO , 249 carácter, 245 carga, 20 carpetas, 254 cartas m odelo, 257 caso p rom edio, 346 C D , 11 cebollas, 270 células, 377
chrom akey, 1 2 7 ,1 3 0 ,2 2 5 ,2 2 6 ,3 2 4 ciclo, 147 for, 54, 5 5 ,7 5 , 1 6 1 ,1 6 5 infinito, 279 o iterar, 161 w h ile, 2 2 0 ,2 7 9 ,4 0 8 ciclos, 407 p o r seg u n d o , 147 ciencias co m p u tacio n ales, 12, 335 clase, 3 7 8 ,3 8 4 ,4 0 2 ,4 1 1 hija, 3 8 3 ,4 0 2 in stan cias, 384 NP, 348 P, 347, 348 pad re, 3 8 3 ,4 0 2 claves, 300 cliente, 272 C M Y K , m odelo d e color, 43 codificación de lon g itu d de tirad a (R L E ), 134 codificaciones, 8 ,9 , 24 código, 17 C ódigo estándar estadounidense para el intercam bio d e inform ación (A S C II), 1 0 ,2 3 ,2 4 6 o b te n e r la asig n ació n , 23 co llage, 94 color, 1 1 ,4 3 ,7 1 ,1 1 3 d istan cia, 108 sepia, 113 com andos, 3 0 ,3 1 com entario, 181 com illas, 22 d o b les, 2 4 5 ,2 4 6 sen cillas, 245, 246 trip le, 245 com paración e n tre co p ia y referencia, 92 com pilador, 3 3 7 ,3 3 9 ,3 4 0 com plejidad, 377 com plem ento a d o s, 154 oom presión, 134, 146 co n p érd id as, 4 1 , 1 3 4 ,2 1 2 sin p érd id as, 4 1 , 1 3 4 ,2 1 2 oom prim ido, 1 9 ,4 1 ,4 6 com putación d e m ed io s, xviii, 10-12 integrada (em bedded com puting), 351 so cial, 5 com putadora, 8
condiciones lím ite, 228 conexión, 305 constan tes, 5 ,7 2 constructor, 3 9 2 ,4 1 1 consulta, 301 conversión a n aló g ica a digital (A D C ), 151 d ig ital a an aló g ica (D A C ), 152 coordenadas, 42 c artesian as, 108 copiado, 34, 86 copiar, 1 8 4 ,3 1 9 corchetes, 175 count, 266 count(algo), 251 crearA tardecer, 64 C row ther, W illiam , 218 C S ound, 215 cuadrado, 208 cuadros clave, 314 p o r segundo (fp s), 314 cuerpo d e la fu n ció n , 31 cursiva, 398 cursor, 305
D datetim e, 265 datos, 1 7 ,3 5 9 declaración d e u n a variable, 26 def, 3 1 ,3 4 , 37 definición d e fu n cio n es, 31 d elim itador d e ruta, 2 4 ,2 6 2 d elim itadores, 247 depuración, 1 6 6 ,1 6 9 ,2 1 7 , 2 2 6 ,2 2 8 , 229 uso d e instrucciones p rin t, 85 desacoplada, 221 descargado, 259 descom posición del problem a, 295 descom posición je rárq u ic a, 65 destino, 8 6 ,2 9 2 detección d e b o rd es, 120 diccionarios, 3 0 2 ,4 1 0 diente d e sierra, 148 difum inado, 1 1 8 ,1 2 0 D igital, 11 d igitalización, 11 digitalización d e m edios
índice
¿ p o rq u é ? , 12 color, 43 im ágenes, 42 sonidos, 151 d irecciones IP, 271 directorio de servidor, 272 raíz, 254 directorios, 18, 254 disco d u ro , 18,351 discos, 18 diseño, 216 abajo-arriba, 2 1 7 ,2 2 5 algoritm o y, 235 distancia, 108 eu clidiana, 108 división, 150, 248 D octor, 265 doctype, 290 dom inio, 377 d e frecuencia, 150 del tiem p o , 150 D ream fall, 218 drop, 388 D V D , 314 D ynabook, 14
E e c o , 196 editor, 19 de sonido, 149 educación liberal, 13 efectos colaterales, 2 7 ,6 5 , 8 4 ,3 6 3 El P adrino, 161 elegirSalon, 2 2 0 -2 2 2 ,2 2 7 , 233 elem ento, 155 de im agen, 1 1 ,4 2 elfo , 367 elif, 239, 282 E liza, 265 else, 1 3 6 ,3 5 5 ,3 7 0 ,3 7 3 e lse:, 373 em ail, 265 em palm e, 177 en cascada, 250 endsw ith, 266 endsw ith(sufijo), 249 ensam blador, 336 a lte ro , 1 7 ,2 2 , 2 9 ,3 7 , 200 escritu ra, 22
entorno, 8 entradas, 2 3 ,3 1 enunciados aleato rio s, 264 envoltura, 215 errores, 157 bugs, 2 1 7 ,2 2 9 co m p aració n entre ex p erto y norm al, 157 escala d e g rises, 4 6 ,6 9 escalaG risesN uevo, 115 escalas, 100 escapes d e b arra diagonal inversa, 247 d e cad en as, 409 escribirC uadro(), 320 esD irectorio, 370 espacio, 342 espacio d e intercam bio, 352 especialización, 402 especificación, 135 estado, 361 estados d e inform ación, 170 esteganografía, 284 estilo, 253 estructuras d e d atos, 4 ,2 3 6 Ethernet, 271 etiquetas, 290 evaluación, 2 9 ,3 4 execute, 305 explore(im agen), 56 expresión, 2 2 , 28, 30 lóg ica, 108 extensión d e archivo, 24
F E acebook, 4 ,5 , 273 falso, 249 fetchoneO , 306 ficción in teractiva, 241 filter, 373 filter(), 359 filtro, 211 f in d ,266 findO, 250 find(cad), 249 find(caddnicio), 249 find(cad,inicio,fin), 249 física, color, 11 F lash, 133 float, 286
419
floatO , 279 flujo d e c o n tro l, 63 for, 2 3 6 ,4 0 7 for pixel in g etP ixels(im agen), 54 form ato d e p elícu la, 314 frecuencia, 1 4 6 ,1 4 7 , 152 en voz, 170 from m edia im p o rt *, 1 8 4 ,2 3 6 from m iS onido im p o rt * ,1 8 5 from m ódulo im p o rt *, 263 from m ódulo im p o rt no m b re, 262 FTP, 272 ftplib, 2 3 6 ,2 7 6 ,2 8 6 fuente, 253 có m o se define, 133 fuertem ente tipificado, 18 función d e copia g en eral, 97 in t, 199 funciones, 22, 2 9 ,6 3 ,6 4 ,3 5 5 ,3 5 9 , 407 a rg u m en to s, 34 ay u d an te s, 122 cu án d o c re a r una, 36 definición, 31 g ra n u la rid a d ,356 invocación, 29 lam b d a, 360 llam ad as, 29 n u m éricas, 409 p arám etro s, 34 valores d e en trad a, 34 variables d e en trad a, 34 funciones u tilitarias, 82, 296 reu tilizació n , 28 fundam ental, 148
G general, 63 generan, 339 getB lue, 7 1 ,3 9 5 ,4 0 3 getC olor, 4 8 ,7 1 g etG reen, 7 1 ,3 9 5 ,4 0 3 g etH eight, 4 7 ,7 1 g etL ength, 171 getM ediaPA th(nom breA rchivoB a se), 213 getM ediaP ath(nom breB ase), 82, 105, 194 getM ediaP ath, 83, 194
420
índice
getPixel, 4 7 , 71 getPixels, 4 7 , 5 4 ,7 1 ,7 6 getR ed, 4 8 ,7 1 ,3 9 5 ,4 0 3 g etS am pleO bjectA t, 172 g etS am ples, 1 5 6 ,1 6 1 , 171 getSam ple V alué, 156 getSam pleV alueA t, 1 5 7 ,1 7 2 , 174 g etS am plingR ate(destino), 178 g etS am plingR ate, 158, 171 getSound, 172 getters, 393 get V alué, 172 get W idth, 4 7 ,7 1 g e tX ,4 7 ,7 1 ,1 2 9 get Y, 4 7 ,7 1 , 129 G IF, 2 4 ,1 3 4 gigabyte, 351 gigahertz (G H z), 337 girar im ágenes, 98 g lifo , 247 global, 5 8 ,1 9 0 ,1 9 2 ,2 3 0 ,3 5 5 , 372, 3 7 3 ,3 7 7 G odel, K urt, 284 G oldberg, A d ele, 3 7 7 ,3 9 9 G oogle, 7 ,2 6 0 C h ro m e, 12 N ew s, 296 gopher, 273 grabaciones análogas, 212 d ig itales, 212 fonográficas, 11 gráficos, 5 G uerra F ría, 272
H hardw are, 151 d e la com putadora, 151 heredados, 402 heredar, 383 herencia, 4 0 0 ,4 0 2 herram ienta d e dibujo, 135 d e im ag en, 51 para pintar, 135 H ertz, 147 heurística, 349, 354 hexadecim al, 2 4 7 ,2 9 1 H ipertexto, 272 H iragana, 247
H itchiker’s G u id e to th e G alaxy, 218 hojas, 254 de estilo en cascad a, 289 H SB , m odelo d e color, 43 HSV, m odelo d e co lo r, 43 HTM L scrap in g , 276 H TTP, 272
I identificador, 18 if, 1 0 8 ,2 0 1 ,2 0 7 ,2 1 3 ,3 7 0 ,4 0 8 else, 136 im ag, 26 im agen, 25, 2 6 ,3 7 ,4 1 ,7 1 co n v ertir en so nid o , 281 m akeP ictureO , 25, 26 reco rte, 316 show , 26 im ágenes, dib u jar so b re, 131 im port, 2 2 1 ,2 6 1 , 262 im port m ódulo as nuevonom bre, 263 im portación, 184 im portar un m ó d u lo , 261 im prim irT odosL osA rchivos, 370 in, 304 índice, 155, 174 d e m u estra, 201 indiceA rchivo, 279 índices, 299 indiceS onido, 279, 281 Industrial L ig h t & M ag ic, 7 Inform , 241 Ingalls, D an, 173 ingeniería d e softw are, 4 , 1 3 ,2 1 6 inicializa, 392 insert, 236 instancia, 391 int, 1 7 1 ,1 9 9 ,2 0 0 ,2 1 3 ,2 7 9 Intel, 10 inteligencia, 5 artificial, 5 ,2 6 5 ,3 4 9 intensidad, 6 9 ,1 4 7 intercam biar, 352 interfaces hum ano-com putadora, 5 interfaz, 5 dig ital d e instrum entos m usicales,
212
Internet, 271 interpretado, 337 intérprete, 338 intervalo d e m uestreo, 202 d e to n o , 148 in tratables, 348 invocación a u n a fu n ció n , 367 isalpha, 266 isalphaO , 250 isdigit, 266 isdigitO , 250
J JA R, archivo, 305 Java, 6, 8 ,1 8 , 3 4 0 ,4 0 2 java.aw t.event, 263 jav a.io .F ile, 370 jerarq u ía, 65 JE S, 8, 1 9 ,1 5 9 ,1 8 4 , 3 4 1 ,3 4 9 área d e co m an d o s, 20 á rea del p ro g ram a, 20 c arg a, 20 co m p u tació n d e m ed io s en,
21 e jec u ció n d e program as fu era de, 236 e jec u ció n lenta, 20 e rro r co m ú n , 32 funciones d e m ed io s, 184 h erram ienta d e im ag en , 52 in icio , 20 M ediaT ools, 149 p ro g ram ació n en , 19, 20 se ejecu ta co n len titu d , 20 selecto r d e co lo res en , 45 sistem a d e ay u d a, 50 JM V, 314 JP E G , 2 4 ,4 1 ,4 8 ,1 3 4 ,2 8 5 ju eg o d e aventuras, 2 1 8 ,2 3 2 ju g arJu eg o , 221 ju g arJu eg o (), 224 Jython, 8 ,1 9 , 2 3 6 ,3 4 0
K K aehler, Ted, 173 K atakana, 247 Kay, A lan , 1 7 3 ,3 7 7 ,3 9 9 kilobytes, 46
índice
L lam bda, 3 6 0 ,3 6 1 len(), 247 lenguaje d e m arcado, 290 d e program ación, 6 ,1 7 ensam blador, 336 m áquina, 3 3 6 ,3 4 1 L enguaje d e m arcación d e hipertexto (H T M L ), 2 4 5 ,2 4 6 , 2 7 2 ,2 8 9 , 290, 294 Ley d e M oore, 10 lineasH orizontales, 131 lineas V erticales, 131 L isp , 7 lista, 2 5 1 ,2 8 2 ,4 1 0 búsqueda, 304 listas desordenadas, 293 ordenadas, 293 listdir(), 262 L oad P rogram (cargar pro g ram a), botón, 20 local, 58, 188 localizadores uniform es d e recu rso s, 272 low er, 266 low er(), 250 lum inancia, 4 2 ,4 4 ,6 9 ,7 0 ,3 2 6 luz visible, 43
M m ailto, 273 m akeC olor, 4 8 ,6 9 ,7 2 m akeD arker, 72 m akeE m ptyP icture, 10 3 ,3 1 6 m akeE m ptyPicture(anchura, altu ra), 105 m akeE m ptyS ound, 1 7 8 ,1 7 9 , 203 m akeE m ptySoundO ongitudE n M uestras), 178 m akeE m ptySoundB ySeconds, 281 m akeL ighter, 6 8 , 72 m akePicture, 2 5 ,3 7 ,4 7 lo q u e hace, 47 m akeSound, 2 7 ,3 7 , 156,171 lo q u e hace, 156 m akeSoundO , 248 m akeStyleQ , 398
m akeStyle(fuente,énfasis,tam año), 398 m akeT urtle, 378 m akeW orld, 378 M aloney, Jo h n , 173 m anipulación d e m ed io s, 363 m anipular m ed io s, 12 m antenim iento, 217 m ap, 359, 3 7 3 ,3 9 3 m apas de b its, 41 M áquina d e T uring, 348 virtu al, 3 4 0 ,3 4 1 virtual d e Java, 340 m arcador d e p o sició n , 66 m áscara, 130 m ath, 265 m atriz, 41 m ax, 168, 1 7 1 ,2 5 1 ,2 6 6 m áxim o, encontrar, 168 M ediaTools, 5 1 ,5 3 ,1 4 9 ,1 5 9 ap licació n , 53 herram ientas d e im ag en , 51 herram ientas d e so n id o , 149 JE S M ediaT ools, 159 M edios d ig itales, 11 m egabyte, 46 m egahertz (M H z), 337 m ejor caso , 345 M em ex, 273 m em oria, 9 , 1 9 ,2 0 , 351 cach é, 351 d e acceso aleatorio (R A M ), 351 m étodos, 2 4 8 ,2 5 3 ,3 7 7 , 3 8 3 ,3 9 1 d e cad en as, 409 fu n cio n ales, 411 setters y g etters, 393 m ezcla, 235 im ág en es, 122, 123 so n id o s, 195 M icrosoft Internet E x p lo rer, 12 P ow erP oint, 12 W ord, 12 M ID I, 212 m ilm agen, 35 m in, 251, 266 m odelo, 377 m ódem , 270 modo ex p erto , 157
421
pu ro , 247 m odulación p o r codificación de pulsos (P C M ), 154 m odulador-dem odulador, 270 m ódulo, 6 2 ,2 6 1 ,4 1 0 m ono, 398 m ontaje, 313 M onty P y th o n , 19 M oore, G o rd o n , 10 m o strarlntroduccion, 220, 221 m ostrarS alon, 2 2 0 -2 2 2 ,2 3 3 m ostrarS E , 222 M P3, 212 M P4, 212 M P E G , 314 M P E G -3 ,212 m uestras, 1 5 2 ,1 7 0 , 190 m uestreo, 1 0 0 ,2 0 0 -2 0 2 ,2 3 5 m ultiplicador, 168 m úsica p o r co m p u tad o ra, 5 M yro, 236 M yS Q L , 305
N navegador, 273, 291 navegadores B raille, 292 d e au d io , 292 negativo d e la im ag en , 68 negociación (h an d sh ak e), 271 negrita, 398 N egroponte, N ich o las, 244 N elson, Ted, 272 nivel d e p resió n d e so n id o , 147 nodo, 254 nom bre b ase, 253 d e archivo, 24, 37 d e archivo b ase, 24 d e archivo co m p leto , 23 glo b al, 23 local, 23 nom bre d e archivo ruta, 18 nom bres d e d o m in io , 271 n o t, 360 notación d e com plem ento a d o s, 153 norm alización, 168 notación pun to, 2 4 9 ,3 7 9 , 391 núcleos, 350
42 2
índice
nudos, 4 núm ero d e punto flotante, 1 4 ,2 2 , 37 N yquist, teorem a d e, 152 aplicaciones, 153
O objeto d e sonido, 155 referencia, 388 o bjetos, 1 5 6 ,2 4 8 ,2 5 3 ,3 8 1 ,4 0 1 clase, 378 creació n , 378 de m uestra, 156 enviar m ensajes a, 379 im agen, 41 rehusarse, 381 ocultar inform ación en una im agen, 284 ogros, 270 ojo rojo, 111 ondas cuadradas, 207 senoidales, 1 4 6 ,2 0 3 ,2 0 5 triangulares, 210 open(), 255 open(nom brearchivo,cóm o), 255 operaciones de secuencia, 409 operadores y funciones de representación, 408 optim ización, 2 3 9 ,3 4 4 o rd , 37 o rd (), 246 ord (d e o rd in al), 23 ordenam iento d e burbuja, 343 ordenar, 2 5 1 ,2 6 6 ordinal, 23 origen, 86 o s, 262, 2 6 5 ,2 6 6 con la clase F ile d e Java, 370 os.listdir, 324 os.listdir(), 262
P página de m iniaturas, 296 índice, 296 palabras reservadas, 1 8 ,4 0 6 P apert, Seym our, 378 paquete, 270, 272 paralelo, 350
parám etro, 188 parám etros, 112 d e alcan ce, 188 PC M , 154 pegado, 34 películas, 3 1 3 ,3 1 4 penD ow n(), 382 pensam iento com putacional, 13 penU p(), 382 peor caso , 346 percepción, 44 P e rlis,A la n , 13 perseguir, 388 persistencia d e la visió n , 313 Photoshop, 3 4 1 ,3 4 9 pickA C olor, 48, 72 pickA File, 2 3 ,2 7 ,3 3 ,3 7 , 171 pico, 150 Pila, 366 pixelación, 118 píxeles, 1 1 ,4 1 ,7 1 pixelización, 4 3 , 104 plain, 398 play, 2 7 ,3 7 ,1 5 9 , 171 playA tR ate, 171 playA tR ateD ur, 171 playM ovie(película), 315 playN ote, 213 polim orfism o, 3 9 5 ,4 0 1 POP, 272 porcentaje, 53 Portal, 218 posterización, 115 R s ts c rip t, 133 R e m io T u rin g d e la A C M , 1 3 ,3 7 7 presentación con diapositivas, orientada a o b jeto s, 390 prim erA rchivo, 329 print, 22, 3 7 ,2 1 9 , 2 2 9 ,2 3 6 print show (im agen), 27 printN ow , 2 1 9 ,2 2 2 , 2 2 4 ,2 2 9 , 238 prívate, 393 R o b le m a d e la p arad a, 348 R o b le m a del vendedor am bulante, 344 procedim ientos, 218 procesador, 336 n ú cleo , 350 proceso, 3 , 8, 13 program a, 3 , 4 , 8 , 1 6 ,1 7 ,3 1 ,6 4 , 139, 257
definición, 17 gen eral, 34 p ru eb a, 60 p rogram ación, 217 im perativa, 361 o rien tad a a o b jeto s, 3 7 6 ,3 7 7 o rien tad a a sustantivos, 377 p o r proced im ien to s, 3 6 1 ,3 7 6 program ación fu n cio n al, 361, 369 p ara m ed io s, 362 propiedades em erg en tes, 5 protocolo, 270 P roveedor d e servicios d e Internet a S P ),2 7 1 p rueba, 1 6 4 ,2 1 7 ,2 2 6 ,2 2 8 de la caja d e cristal, 226 de la caja n eg ra, 226 de m étodos, 169 m éto d o s, 164 uso d e instrucciones prin t, 85 psicoacústica, 147 pulsos, 350 P ython, 6 -8 , 1 9 ,3 2 ,2 3 6 definición d e funciones, 31 ex tensió n para, 32 uso de m ayúsculas, 23 P ython 3.0, 22
Q q u icksort, 343 Q uickT im e, 314
R ‘Yb” y “w b ” , 255 raise, 394 raíz, 254 random , 263, 2 6 5 ,2 6 6 random (), 263 random .choiceO , 263 range, 7 5 ,1 0 5 ,1 7 5 , 1 9 1 ,4 0 7 intervalo negativo, 137 rangos d e dato s, 6 rarefacciones, 146 rastrear, 57 rastreo, 166 uso d e instrucciones p rin t, 85 raw _input, 220 read, 255 receta, 3 ,5 , 8, 3 1 ,6 4
índice router, 271 row count, 306 ruido, 150, 211 ruta, 1 8 ,2 4 ,2 5 4 , 272
com putacional, 3, 8 recorrer, 369 recorrido, 57 recortar, 1 8 4 ,3 1 6 ,3 1 9 recorte, 8 9 ,1 5 4 , 169 recursividad, 364, 369 red, 4 redefine, 401 reduce, 3 6 1 ,3 7 3 reduce(), 360 reducirR ojo, 372 reducirR ojoP órlndice, 373 reducirV olum en, 166 reem plazo de un c o lo r con otro, 108, 109 referencia, 388 referencias, 92 refinación d e requerim ientos, 217 reflejo, 187 reflejo d e im agen, 78 reglas, 264 regresar, 62 rem o ve, 266 rem ove(algo), 251 rE nN om breO , 360 repaint, 48 repisa, 300 replace, 266 replace(búsqueda^eem plazo), 250 representación vectorial, 133 representaciones gráficas d e m apas de bits, 134 requerim ientos, 217 requestlnteger, 238 requestlntegerlnR ange, 238 requestN um ber, 238 requestS tring, 2 1 9 ,2 3 3 , 238
setPixel(), 316 setR ed, 4 8 ,6 2 ,7 1 ,3 9 5 ,4 0 3
restoA rchivos, 329 resultados, 29 retroceder, 259 return, 6 6 , 84, 167 reutilizable, 63 reutilización de có d ig o , 184 reutilizar, 377 reverse(), 251 reverse, 266 rfind(buscarcadena), 250 R G B , m odelo d e color, 43 R oads, C urtís, 17 3 ,2 1 5 robustez, 377 rojo, 11
setSam pleV alué, 1 5 6 ,1 7 2 setSam pleV alueA t, 158, 1 7 2 ,1 7 5 setters, 393 set V alué, 172 setV isible(false), 382 SG M L , 289 S hannon, C lau d e, 284 show, 2 5 ,3 6 , 3 7 ,4 7 , 394 show lnform ation, 240 show Vars, 2 3 0 ,2 3 8 sím bolo, 18 sím bolos, 16 Sim pleH T TPServer, 265 sim ulación, 264, 377
s salidas, 23 sangría, 32 sansSerif, 398 S chem e, 6 , 7 scraping, 276 p an talla, 276 W eb, 276 screen scrap in g , 276 SD R A M , 351 secuencia, 7 6 ,1 7 6 selección, 108 self, 383, 391 señal an aló g ica, 151 separador de ruta, 24 serif, 398 servicios, 377 servidor, 272 servidores d e nom bres d e dom inio, 271 s e tB lu e ,7 1 ,3 9 5 ,403 se tC o lo r,4 6 , 6 8 ,7 1 setC olor(color), 382 setG reen, 7 1 ,3 9 5 ,4 0 3 setL ibPath(ruta), 185 setL ibPath, 185, 236 setM ediaP ath(directorio), 105 setM ediaPath, 8 3 ,1 0 5 , 1 9 4 ,2 1 3 setPenW idth(anchura), 382
423
sim ulaciones, 388 sin , 265 sintaxis, 31 síntesis aditiva, 203 F M o síntesis p o r m o dulación de frecuencias, 211 sustractiva, 211 sintetizadores, 198 sistem a d e archivos, 18 operativo, 18 sistem as, 5 inteligentes, 5 Sm alltalk, 3 7 7 ,4 0 2 SMTP, 272 softw are, 4 sonido, 3 7 ,1 4 5 ,1 9 0 al revés, 186 am p litu d , 1 4 6 ,1 4 7 au m e n ta r el volum en, 161 codificar, 151 có m o m anipular, 156 d ecib e les, 147 em p alm e, 177 frecu en cia, 146 in ten sid ad , 147 m akeS oundO , 27 m an ip u lació n , 156 n o rm alizació n , 167 nuevo, 179 playO , 27 re d u c irv o lu m e n , 166 ton o , 147, 148 visu alizació n , 280 volum en, 147, 1 6 1 ,1 6 6 sonidos, 170 spam , 257 split, 266 sp lit(delim itador), 252 SQ L, 304 cursor, 305 sqrt, 265 S queak, 6 ,1 7 3 src=, 292 startsw ith(prefijo), 249 startsw ith, 266 Stop, bo tó n , 21 str, 277, 286 subcadena, 248 subclase, 383
424
índice
subfunciones, 6 5 ,2 1 8 , 2 2 1 ,2 9 5 subíndice, 176 subprogram a, 180 subreceta, 168, 180 co p ia d e arreglos, 180 m uestreo, 200 sufijo d e archivo, 253 Sun, 20 superclase, 383 sustitución, 29, 34 sustracción d e fondo, 1 2 5 ,2 2 5 , 226 sw apcaseO , 250 sys.path, 236
T T, 6 , 7 tabla hash, 302 tabulador, 32 tam años de m uestra, 1 5 3 ,1 6 9 , teclados d e m uestreo, 198 teléfonos celu lares, 4 teletipo, 317 tem peram ento igual, 147 Teorem a d e incom pletitud, 284 teoría, 5 teoría d e la inform ación, 284 terabyte, 351 texto co n fo rm ato , 252 delim itado p o r co m as, 252 delim itado p o r tabulad o res, 252 estilo , 398 estructurad o, 251 tiem po, 342 real, 149 Tlm B ern ers-L ee, 273 tipos, 16, 1 8 ,2 2 arreglo d e en tero s, 17 b y te, 17 cad en a, 17 definición, 18 en tero , 17 punto flotante, 18 tiradas de estilo , 253 title(), 250 tono sepia, 113
Tortuga C o n fu n d id a, 385 turnT oF ace, 386 T ortugaC hica, 3 8 3 ,3 8 4 T ortugaC onfiindida, 385 tortugas, 378 d ro p , 388 en señ arles nuevos tru co s, 383 trabajo en red, 5 ,2 7 0 transform ación, 86 transform ada d e F ourier, 150 transistor, 10 transparencia, 44 true, 249 TrueType, 133 tupia, 306 T uring, A lan, 348
d e relo j, 350 velocidad d e m u estreo , 1 5 3 ,1 5 8 en síntesis aditiva, 204 ventana (de tiem p o ), 150 verbos, 376 verde, 11 vibrato, 196 video, 3 1 3 ,3 2 6 d e orig en , 322 m an ip u lació n , 323 p roceso abajo -arrib a, 326 vinculación, 28 vista d e espectro, 150 d e señ al, 149 visualización del so n id o , 2 4 5 ,2 8 0 volum en, 1 4 7 ,1 6 6
turnToFace, 386 Twitter, 5
volverse dig ital, 11
u um bral, 328 U nicode, 246 unim edia, 2 4 4 ,2 7 7 unión, 301, 303 U N IX , sh ell, 237 upper, 250, 266 U R L , 272 urllib, 236, 2 7 3 ,2 7 5 ,2 8 6 uso d e m ayúsculas, 23
V valM uestra, 211 valor ab so lu to , 121 d e um b ral, 113 valores ló g ico s, 360 al c rea r p elícu las, 326 van R o ssu m , G u id o , 19 variable d e instancia, 3 0 6 ,3 7 7 ,3 9 1 , 400 privadas, 393 setters y g etters, 393 variables, 19, 2 6 ,3 4 ,4 0 6 velocidad de cu ad ro , 313
W “w t” , 255 W allace, S cott, 173 W atcher, 21, 230 WAV, 2 4 ,1 6 1 ,2 1 2 W eb, 2 7 2 ,2 7 3 Web scrap in g , 276 W eizenbaum , Jo sep h , 265 w hile, 2 3 8 ,2 8 6 W i-Fi, 271 W ing, Jean n ette, 13 W oods, D on, 218 W orld W ide W eb, 5 ,2 4 5 ,2 7 2 w ritePictureT o, 4 8 , 71 w riteSoundT o, 157,171 w riteTo(), 395 w riteTo(nom brearchivo), 395 W W W , 2 4 5 ,2 7 2
X X H T M L , 289 X M L , 289
z zipfile, 265 Z ork, 218
Intro d ucción a la com putación y program ación con Python Esta nueva edición de Introducción a lacomputación yprogramación con Python se enfoca en la manipulación de imágenes, sonido, texto y películas, tal como lo harían los profesionales, pero con programas escritos por estudiantes. La mayoría de las personas utiliza aplicaciones de nivel profesional para realizar este tipo de manipulaciones, pero saber cómo escribir programas propios significa que se puede hacer más de lo que cualquier aplicación permite; de esta manera el poder de expresión no se verá limitado por la capacidad del software que se utilice. La metodología de computación en losmedios que maneja este libro parte de las razones por las que muchas personas utilizan las computadoras: manipular imágenes, explorar en busca de música digital, ver y crear páginas Web o realizar videos; y explica la programación y la computación en términos de estas actividades. Entre las múltiples actualizaciones y mejoras de esta edición sobresalen las siguientes. •
Más términos de ciencias de la computación en los capítulos iniciales.
•
Una presentación más temprana y con mayor detalle de las instrucciones de condición, incluyendo e/se y elif.
•
Una sección sobre funciones y parámetros, donde se explica cuándo usar retorno y cuándo no.
•
Una explicación más profunda sobre cómo funcionan las variables, en especial con respecto a los objetos.
•
Más información sobre el reflejo de imágenes, con un ejemplo más generalizado.
•
Ejemplos Web actualizados con referencias para acceder a sitios interesantes y modernos.
•
Más información sobre las diferencias entre los formatos de imágenes.
•
Una actualización de la sección sobre hardware y redes para relacionarla con el hardware más reciente, incluyendo los procesadores multinúcleo y los teléfonos móviles.
•
Una definición más clara de lo que puede hacerse en Jython y CPython, en comparación con JES. Para obtener más información sobre este libro, visite: www.pearsonenespanol.com/guzdial
Sign In