Next Up Previous Hi Index

Chapter 4

Condicionales y recursividad

4.1 El operador m�dulo

El operador m�dulo funciona con enteros (y expresiones enteras), y devuelve el resto de dividir el primer operando entre el segundo. En Python, el operador de m�dulo es el signo de tanto por ciento (\texttt{%). La sintaxis es la misma de los otros operadores: \begin{verbatim} >>> cociente = 7 / 3 >>> print cociente 2 >>> resto = 7 % 3 >>> print resto 1 \end{verbatim} As�, 7 dividido entre 3 da 2 con 1 de resto. El operador de m�dulo resulta ser soprendentemente �til. Por ejemplo, puede comprobar si un n�mero es divisible entre otro: si \texttt{x \% y} es cero, entonces \texttt{x} es divisible entre \texttt{y}. Tambi�n puede usar el operador m�dulo para extraer el d�gito m�s a la derecha de un n�mero. Por ejemplo, \texttt{x \% 10} devuelve el d�gito m�s a la derecha de \texttt{x} (en base 10). De forma similar, \texttt{x \% 100} devuelve los dos �ltimos d�gitos. \section{Expresiones booleanas} \index{expresi�n booleana} \index{booleana!expresi�n} \index{operador l�gico} \index{l�gico!operador} Una {\bf expresi�n booleana} es una expresi�n que es cierta o falsa. En Python, una expresi�n que es cierta tiene el valor 1, y una expresi�n que es falsa tiene el valor 0. El operador {\tt ==} compara dos valores y entrega una expresi�n booleana: \beforeverb \begin{verbatim} >>> 5 == 5 1 >>> 5 == 6 0 \end{verbatim} \afterverb % En la primera sentencia, los dos operandos son iguales, as� que la expresi�n se eval�a como 1 (verdadero); en la segunda sentencia, 5 no es igual a 6, as� que obtenemos 0 (falso). El operador {\tt ==} es uno de los {\bf operadores de comparaci�n}; los otros son: \beforeverb \begin{verbatim} x != y # x no es igual a y x > y # x es mayor que y x < y # x es menor que y x >= y # x es mayor o igual que y x <= y # x es menor o igual que y \end{verbatim} \afterverb % Aunque probablemente estas operaciones le resulten familiares, los s�mbolos en Python son diferentes de los matem�ticos. Un error habitual es utilizar un signo igual sencillo ({\tt =}) en lugar del doble ({\tt ==}). Recuerde que {\tt =} es un operador de asignaci�n y {\tt ==} es un operador de comparaci�n. Adem�s, no existen \verb|=<| ni \verb|=>|. \section {Operadores l�gicos} \index{operador l�gico} \index{l�gico!operador} Hay tres {\bf operadores l�gicos}: {\tt and}, {\tt or}, y {\tt not}. La sem�ntica (significado) de estos operadores es similar a sus significados en ingl�s. Por ejemplo, {\tt x > 0 and x < 10} es verdadero s�lo si {\tt x} es mayor que 0 {\em y} menor que 10. {\tt n\%2 == 0 or n\%3 == 0} es verdadero si {\em cualquiera} de las condiciones es verdadera, o sea, si el n�mero es divisible por 2 {\em o} por 3. Finalmente, el operador {\tt not} niega una expresi�n booleana, de forma que {\tt not(x > y)} es cierto si {\tt (x > y)} es falso, o sea, si {\tt x} es menor o igual que {\tt y}. Hablando estrictamente, los operandos de los operadores l�gicos deber�an ser expresiones booleanas, pero Python no es muy estricto. Cualqueir n�mero que no sea cero se interpreta como ``verdadero''. \beforeverb \begin{verbatim} >>> x = 5 >>> x and 1 1 >>> y = 0 >>> y and 1 0 \end{verbatim} \afterverb % En general, este tipo de cosas no se considera buen estilo. Si quiere comparar un valor con cero, deber�a hacerlo expl�citamente. \section{Ejecuci�n condicional} \label{conditional execution} \index{bifurcaci�n condicional} \index{ejecuci�n condicional} Para escribir programas �tiles, casi siempre necesitamos la capacidad de comprobar ciertas condiciones y cambiar el comportamiento del programa en consonancia. Las \textbf{sentencias condicionales} nos dan esta capacidad. La forma m�s sencilla es la sentencia \texttt{if}: \begin{verbatim} if x > 0: print "x es positivo" \end{verbatim} La expresi�n booleana tras el \texttt{if} se llama \textbf{condici�n}. Si es verdadera, entonces la sentencia indentada se ejecuta. Si la condici�n no es verdadera, no pasa nada. \index{sentencias compuestas} \index{sentencias compuestas!cabecera} \index{sentencias compuestas!cuerpo} \index{sentencias compuestas!bloque de sentencias} \index{sentencias!compuestas} Como otras sentencias compuestas, \texttt{if} consta de una cabecera y un bloque de sentencias: \begin{verbatim} CABECERA: PRIMERA SENTENCIA ... ULITMA SENTENCIA \end{verbatim} La cabecera comienza con una nueva l�nea y termina con el signo de dos puntos. Los elementos indentados que siguen se llaman \textbf{bloque} de la sentencia. La primera sentencia no indentada marca el fin del bloque. Un bloque de sentencias dentro de una sentencia compuesta recibe el nombre de \textbf{cuerpo} de la sentencia. \index{bloque} \index{sentencias!bloque} \index{cuerpo} No hay l�mite a la cantidad de sentencias que pueden aparecer en el cuerpo de una sentencia \texttt{if}, pero debe haber al menos una. A veces, es �til tener un cuerpo sin sentencias, (normalmente como reserva de espacio para algo de c�digo que todav�a no ha escrito). En tales casos, puede usted utilizar la sentencia {\tt pass}, que no hace nada. \index{sentencia pass} \index{pass!sentencia} \section{Ejecuci�n alternativa} \label{alternative execution} Una segunda forma de la sentencia \texttt{if} es la ejecuci�n alternativa, en la que hay dos posibilidades, y la condici�n determina cu�l de ellas se ejecuta. La sintaxis tiene este aspecto: \begin{verbatim} if x%2 == 0: print x, "es par" else: print x, "es impar" \end{verbatim} Si el resto cuando se divide \texttt{x} entre 2 es cero, entonces sabemos que \texttt{x} es par, y este programa muestra un mensaje a tal efecto. Si la condici�n es falsa, se ejecuta el segundo lote de sentencias. Puesto que la condici�n debe ser verdadera o falsa, se ejecutar� exactamente una de las alternativas. Llamamos {\bf ramas} a las posibilidades porque son ramas del flujo de ejecuci�n. \index{rama} Como un aparte, si piensa que querr� comprobar con frecuencia la paridad de n�meros, quiz� desee {}``envolver'' este c�digo en una funci�n: \begin{verbatim} def imprimeParidad(x): if x%2 == 0: print x, "es par" else: print x, "es impar" \end{verbatim} Ahora tiene una funci�n llamada \texttt{imprimeParidad} que muestra el mensaje apropiado para cada n�mero entero que usted le pase. Llame a esta funci�n de la manera siguiente: \begin{verbatim} >>> imprimeParidad(17) >>> imprimeParidad(y+1) \end{verbatim} \section{Condiciones encadenadas} \index{condiciones encadenadas} \index{condiciones!encadenadas} A veces hay m�s de dos posibilidades y necesitamos m�s de dos ramas. Una forma de expresar tal computaci�n es un {\bf conditional encadenado}: \begin{verbatim} if x < y: print x, "es menor que", y elif x > y: print x, "es mayor que", y else: print x, "y", y, "son iguales" \end{verbatim} \texttt{elif} es una abreviatura de \char`\"{}else if\char`\"{}. De nuevo, s�lo se ejecutar� una rama. No hay l�mite al n�mero de sentencias \texttt{elif}, pero s�lo se permite una sentencia {\tt else} (que puede omitirse) y debe ser la �ltima rama de la sentencia: \begin{verbatim} if eleccion == 'A': funcionA() elif eleccion == 'B': funcionB() elif eleccion == 'C': funcionC() else: print "Eleccion no valida." \end{verbatim} Las condiciones se comprueban en orden. Si la primera es falsa, se comprueba la siguiente, y as�. Si una de ellas es cierta, se ejecuta la rama correspondiente y termina la sentencia. Incluso si es cierta m�s de una condici�n, s�lo se ejecuta la primera rama verdadera. \begin{quote} {\em Como ejercicio, envuelva estos ejemplos en funciones llamadas {\tt compara(x, y)} y {\tt resuelve(eleccion)}.} \end{quote} \section{Condiciones anidadas} Una condici�n puede estar anidada dentro de otra. Pod�amos haber escrito as� el ejemplo de tricotom�a: \begin{verbatim} ~~if x == y: ~~~~print x, "y", y, "son iguales" ~~else: ~~~~if x < y: ~~~~~~print x, "es menor que", y ~~~~else: ~~~~~~print x, "es mayor que", y \end{verbatim} La condici�n externa que contiene dos ramas. La primera rama contiene una sentencia simple de salida. La segunda rama contiene otra sentencia \texttt{if}, que tiene dos ramas en s� misma. Estas dos ramas son ambas sentencias de salida de datos, aunque podr�an ser igualmente sentencias condicionales. Aunque la indentaci�n de las sentencias hace la estructura evidente, las condiciones anidadas en seguida se vuelven dif�ciles de leer. En general es una buena idea evitarlas cuando pueda. Los operadores l�gicos suelen facilitar un modo de simplificar las sentencias condicionales anidadas. Por ejemplo, podemos reescribir el c�digo siguiente con un s�lo condicional: \beforeverb \begin{verbatim} if 0 < x: if x < 10: print "x es un n�mero positivo de un d�gito." \end{verbatim} \afterverb % La sentencia {\tt print} s�lo se ejecuta si conseguimos superar ambos condicionales, as� que podemos usar el operador {\tt and}: \beforeverb \begin{verbatim} if 0 < x and x < 10: print "x es un n�mero positivo de un d�gito." \end{verbatim} \afterverb % Estos tipos de condiciones son habituales, por lo que Python nos proporciona una sintaxis alternativa similar a la notaci�n matem�tica: \beforeverb \begin{verbatim} if 0 < x < 10: print "x es un n�mero positivo de un d�gito." \end{verbatim} \afterverb % Esta condici�n es sem�nticamente la misma que la expresi�n booleana compuesta y que el condicional anidado. \section{La sentencia \texttt{return} } \index{sentencia return} \index{sentencia!return} La sentencia \texttt{return} le permite terminar la ejecuci�n de una funci�n antes de alcanzar su final. Una raz�n para usarla es detectar una condici�n de error: \begin{verbatim} import math def imprimeLogaritmo(x): if x <= 0: print "Solo numeros positivos, por favor." return result = math.log(x) print "El log de x es", result \end{verbatim} La funci�n \texttt{imprimeLogaritmo} toma un par�metro llamado \texttt{x}. Lo primero que hace es comprobar si \texttt{x} es menor o igual que cero, en cuyo caso muestra un mensaje de error y luego usa \texttt{return} para salir de la funci�n. El flujo de la ejecuci�n vuelve inmediatamente al llamante y no se ejecutan las l�neas restantes de la funci�n. Recuerde que para usar una funci�n del m�dulo math tiene que importarlo. \section{Recursividad} \label{recursion} \index{recursividad} Ya mencionamos que es legal que una funci�n llame a otra, y de ello hemos visto ya varios ejemplos. Olvidamos mencionar que tambi�n es legal que una funci�n se llame a s� misma. Puede no resultar evidente por qu� es bueno esto, pero viene a resultar una de las cosas m�s interesantes y curiosas que puede hacer un programa. Examine por ejemplo la siguiente funci�n: \begin{verbatim} def cuenta_atras(n): if n == 0: print "Despegando!" else: print n cuenta_atras(n-1) \end{verbatim} \texttt{cuenta\_atras} espera que su par�metro, {\tt n}, sea un entero positivo. Si {\tt n} el par�metro es cero, muestra la palabra {}``Despegando!''. En otro caso, muestra {\tt n} y luego llama a la funci�n llamada \texttt{cuenta\_atras} (ella misma) pas�ndole como argumento \texttt{n-1}. �Qu� sucede si llamamos a la funci�n de la siguiente manera? \begin{verbatim} >>> cuenta_atras(3) \end{verbatim} La ejecuci�n de \texttt{cuenta\_atras} comienza con \texttt{n=3}, y puesto que \texttt{n} no es cero, da como salida el valor 3, y luego se llama a s� misma ... \begin{quote} La ejecuci�n de \texttt{cuenta\_atras} comienza con \texttt{n=2}, y puesto que \texttt{n} no es cero, muestra el valor 2 y luego se llama a s� misma ... \begin{quote} La ejecuci�n de \texttt{cuenta\_atras} comienza con \texttt{n=1}, y puesto que \texttt{n} no es cero, muestra el valor 1, y luego se llama a s� misma... \begin{quote} La ejecuci�n de \texttt{cuenta\_atras} comienza con \texttt{n=0}, y puesto que \texttt{n} es cero, muestra la palabra {}``Despegando!'' y luego retorna. \end{quote} La \texttt{cuenta\_atras} que dio \texttt{n=1} retorna. \end{quote} La \texttt{cuenta\_atras} que dio \texttt{n=2} retorna. \end{quote} La \texttt{cuenta\_atras} que dio \texttt{n=3} retorna. Y entonces ya est� de vuelta en \texttt{\_\_main\_\_} (menudo viaje). De manera que la salida completa presenta el siguiente aspecto: \begin{verbatim} 3 2 1 Despegando! \end{verbatim} Como segundo ejemplo, consideremos de nuevo las funciones \texttt{nuevaLinea} and \texttt{tresLineas}. \begin{verbatim} def nuevaLinea(): print def tresLineas(): nuevaLinea() nuevaLinea() nuevaLinea() \end{verbatim} Aunque todas funcionan, no ser�an de mucha ayuda si quisiera mostrar 2 l�neas nuevas o 106. Una mejor alternativa ser�: \begin{verbatim} def nLineas(n): if n > 0: print nLineas(n-1) \end{verbatim} Este programa es parecido a \texttt{cuenta\_atras}; mientras \texttt{n} sea mayor que cero, muestra una nueva l�nea, y luego se llama a s� misma para mostrar \texttt{>n-1} nuevas l�neas m�s. De esta manera, el n�mero total de nuevas l�neas es \texttt{1 + (n-1)}, que si rescata su �lgebra ver� que es \texttt{n}. El proceso por el que una funci�n se llama a s� misma se llama \textbf{recursividad}, y dichas funciones se denominan recursivas. \index{recursividad} \index{funciones!recursivas} \section{Diagramas de pila para funciones recursivas} \index{diagramas de pila} \index{marco de funci�n} \index{marco} El la Secci�n~\ref{stackdiagram} utilizamos un diagrama de pila para representar el estado de un programa durante la llamada de una funci�n. El mismo tipo de diagrama puede hacer m�s f�cil interpretar una funci�n recursiva. Cada vez que se llama a una funci�n, Python crea un nuevo marco para la funci�n, que contiene sus variables locales y par�metros. En el caso de una funci�n recursiva, puede haber m�s de un marco en la pila al mismo tiempo. La figura muestra un diagrama de pila para \texttt{cuenta\_atras}, invocada con \texttt{n = 3}: \vspace{0.1in} \centerline{\includegraphics{../illustrations/stack2.eps} } \vspace{0.1in} Como es habitual, en lo alto de la pila est� el marco de \texttt{\_\_main\_\_}. Est� vac�a porque no hemos ninguna variable sobre \texttt{\_\_main\_\_} ni le hemos pasado ning�n par�metro. Los cuatro marcos de \texttt{cuenta\_atras} tienen valores diferentes para el par�metro \texttt{n}. El fondo de la pila, donde \texttt{n=0}, se llama {\bf caso base}. No hace una llamada recursiva, de manera que no hay m�s marcos. \begin{quote} \emph{Como actividad, dibuje un diagrama de pila para} \texttt{nLineas}\emph{, invocada con el par�metro} \texttt{n=4}. \end{quote} \index{caso base} \index{recursividad!caso base} \section{Recursividad infinita} \index{recursividad!infinita} \index{recursividad infinita} \index{error en tiempo de ejecuci�n} \index{error!en tiempo de ejecuci�n} \index{traza inversa} Si una recursi�n no alcanza nunca el caso base, seguir� haciendo llamadas recursivas para siempre y nunca terminar�. Esta circunstancia se conoce como \textbf{recursividad infinita}, y generalmente no se la considera una buena idea. Este es un programa m�nimo con recursividad infinita: \beforeverb \begin{verbatim} def recurre(): recurre() \end{verbatim} \afterverb % El la mayor�a de los entornos de programaci�n, un programa con recursividad infinita no se ejecutar� realmente para siempre. Python informar� de un mensaje de error cuando se alcance el nivel m�ximo de recursividad: \beforeverb \begin{verbatim} File "", line 2, in recurse (98 repetitions omitted) File "", line 2, in recurse RuntimeError: Maximum recursion depth exceeded \end{verbatim} \afterverb Esta traza inversa es un poco mayor que la que vimos en el cap�tulo anterior. �Cuando sucede el error, hay 100 marcos {\tt recurre} en la pila! \begin{quote} \emph{Como actividad, escriba una funci�n con recursividad infinita y ejec�tela en el int�rprete de Python.} \end{quote} \section{Entrada por teclado} Los programas que hemos escrito hasta ahora son un poco maleducados en el sentido de que no aceptan entradas de datos del usuario. Simplemente hacen lo mismo siempre. Python proporciona funciones internas que obtienen entradas desde el teclado. La m�s sencilla se llama \texttt{raw\_input}. Cuando llamamos a esta funci�n, el programa se detiene y espera a que el usuario escriba algo. Cuando el usuario pulsa la tecla \texttt{Return} o \texttt{Enter}, el programa se reanuda y \texttt{raw\_input} devuelve lo que el usuario escribi� como tipo \texttt{string}: \begin{verbatim} >>> entrada = raw_input () A qu� est�s esperando? >>> print entrada A qu� est�s esperando? \end{verbatim} Antes de llamar a \texttt{raw\_input} es conveniente mostrar un mensaje que le pida al usuario el dato solicitado. Este mensaje se llama {\bf indicador} (prompt en ingl�s). Puede proporcionarle un indicador a \texttt{raw\_input} como argumento: \index{indicador} \begin{verbatim} >>> nombre = raw_input ("C�mo te llamas? ") C�mo te llamas? H�ctor, h�roe de los Troyanos! >>> print nombre H�ctor, h�roe de los Troyanos! \end{verbatim} Si espera que la entrada sea un entero, utilice la funci�n \texttt{input}. Por ejemplo: \begin{verbatim} >>> indicador = \ ... "Cu�l es la velocidad de una golondrina sin carga?\n" >>> velocidad = input (indicador) \end{verbatim} Si el usuario teclea una cadena de n�meros, se convertir� en un entero y se asignar� a \texttt{velocidad}. Por desgracia, si el usuario escribe algo que no sea un d�gito, el programa dar� un error: \begin{verbatim} >>> velocidad = input (indicador) Cu�l es la velocidad de una golondrina sin carga? Se refiere usted a la golondrina europea o a la africana? SyntaxError: invalid syntax \end{verbatim} Para evitar este tipo de error, generalmente es buena idea usar \texttt{raw\_input} para obtener una cadena y usar entonces las funciones de conversi�n para convertir a otros tipos. \section{Glosario} \begin{description} \item [operador~m�dulo:] Operador, se�alado con un signo de tanto por ciento (\texttt{\%}), que trabaja sobre enteros y devuelve el resto cuando un n�mero se divide entre otro. \item[expresi�n booleana:] Una exprersi�n que es cierta o falsa. \item[operador de comparaci�n:] Uno de los operadores que comparan dos valores: {\tt ==}, {\tt !=}, \verb|>|, \verb|<|, {\tt >=} y {\tt <=}. \item[operador l�gico:] Uno de los operadores que combinan expresiones booleanas: {\tt and}, {\tt or} y {\tt not}. \item [sentencia~condicional:] Sentencia que controla el flujo de ejecuci�n de un programa dependiendo de cierta condici�n. \item [condici�n:] La expresi�n booleana de una sentencia condicional que determina qu� rama se ejecutar�. \item [sentencia~compuesta:] Estructura de Python que est� formado por una cabecera y un cuerpo. La cabecera termina en dos puntos (:). El cuerpo tiene una sangr�a con respecto a la cabecera. \item [bloque:] Grupo sentencias consecutivas con el mismo sangrado. \item [cuerpo:] En una sentencia compuesta, el bloque de sentencias que sigue a la cabecera de la sentencia. \item [anidamiento:] Una estructura de programa dentro de otra; por ejemplo, una sentencia condidional dentro de una o ambas ramas de otra sentencia condicional. \item [recursividad:] El proceso de volver a llamar a la funci�n que se est� ejecutando en ese momento. \item [caso~base:] En una funci�n recursiva, la rama de una sentencia condicional que no ocasiona una llamada recursiva. \item [recursividad~infinita:] Funci�n que se llama a s� misma recursivamente sin alcanzar nunca el caso base. A la larga una recursi�n infinita provocar� un error en tiempo de ejecuci�n. \item [indicador:] indicador visual que invita al usuario a introducir datos. \index{operador m�dulo} \index{expresi�n booleana} \index{expresi�n!booleana} \index{sentencia condicional} \index{sentencia!condicional} \index{condici�n} \index{sentencia compuesta} \index{rama} \index{cuerpo} \index{bloque} \index{anidamiento} \index{recursividad} \index{caso base} \index{recursividad infinita} \index{indicador} \end{description} %\end{document}


Next Up Previous Hi Index

" + str + "

Close window

Hosted by www.Geocities.ws

"); } //-->
Hosted by www.Geocities.ws

1