Next Up Previous Hi Index

Chapter 4

\documentclass[oneside,english]{book \usepackage[T1]{fontenc} \usepackage[latin1]{inputenc} \usepackage{babel} \setcounter{secnumdepth}{3} \setcounter{tocdepth}{3} \usepackage{graphics} \makeatletter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands. \providecommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} \makeatother \begin{document} \chapter{Condicionales y recursividad} \section{El operador módulo} \index{operador módulo} \index{módulo!operador} El \textbf{operador módulo} funciona con enteros (y expresiones enteras), y devuelve el \emph{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 resto = 7 % 3 \end{verbatim} El primer operador, división entera, devuelve 2. El segundo operador devuelve 1. 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, Similarly \texttt{x \% 100} devuelve los dos últimos dígitos. \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. \textbf{Las 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 que hay entre el \texttt{if} y el \texttt{:} se llama \textbf{condición}. Si es verdadera, entonces la sentencia indentada se ejecuta. Si la condición no es verdadera, no pasa nada. La condición puede contener alguno de los \emph{operadores de comparación:} \begin{verbatim} x == y # x es igual a y 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 que o igual que y x <= y # x is menor que o igual que y \end{verbatim} Aunque probablemente estas operaciones le resulten familiares, la sintaxis que Python usa es un poco diferente de los símbolos usados en matemáticas. Un error común es usar un único \texttt{=} en lugar de uno doble \texttt{==}. Recuerde que \texttt{=} \emph{es el operador de asignación}, y que \texttt{==} \emph{es un operador de comparación}. Además no esite signo como \texttt{=<} o \texttt{=>}. \section{Sentencias compuestas} \label{compound statements} \index{sentencias compuestas} \index{sentencias compuestas!encabezamiento} \index{sentencias compuestas!cuerpo} \index{sentencias compuestas!bloque de sentencias} \index{sentencias!compuestas} La sentencia \texttt{if} es el segundo ejemplo que hemos visto de \textbf{sentencia compuesta}. El primero fue la definición de función. Todas las sentencias compuestas tienen una sintaxis común: syntax: \begin{verbatim} ENCABEZAMIENTO: PRIMERA SENTENCIA ... ULITMA SENTENCIA \end{verbatim} El encabezamiento comienza con una nueva línea y termina con el signo de dos puntos. Los elementos indentados que siguen se llaman \textbf{cuerpo} de la sentencia o \textbf{bloque} de sentencia. La primera sentencia no indentada marca el fin del bloque. \index{bloque} \index{sentencias!bloque} \index{cuerpo} \index{sentencias!cuerpo} Todas las sentencias del cuerpo se tratan como una unidad. En el caso de una sentencia \texttt{if} se ejecutan o bien todas ellas, o bien ninguna de ellas. \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} emtre 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. 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) \end{verbatim} \section{Ramas múltiples} Otro nombre para la ejecución condicional es el de \textbf{bifurcación condicional}, ya que este tipo de estructuras hace que el flujo de ejecución se divida en diferentes direcciones. A veces querrá comprobar una serie de condiciones relacionadas y elegir una acción entre varias. La siguiente prueba en tricotomía muestra cómo hacer esta ramificación múltiple: \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} Como actividad, envuelva el código de tricotomía anterior en una función llamada \texttt{compara(x, y)}. La sentencia \texttt{elif} (\char`\"{}elif\char`\"{} es una abreviatura de \char`\"{}else if\char`\"{}) puede repetirse tantas veces como sea preciso para elegir entre varias condiciones: \begin{verbatim} if eleccion == 'A': funcionA() elif eleccion == 'B': funcionB() elif eleccion == 'C': funcionC() elif eleccion == 'D': funcionD() else: print "Eleccion no valida." \end{verbatim} \section{Condiciones anidadas} Una condición puede estar anidada dentro de otra. Podíamos haber escrito el código el ejempOne conditional can also be nested within another. We could have written the trichotomy example as: \begin{verbatim} ~~if x == y: ~~~~print x, "and", y, "are equal" ~~else: ~~~~if x < y: ~~~~~~print x, "is less than", y ~~~~else: ~~~~~~print x, "is greater than", y \end{verbatim} Ahora hay una condición externa que contiene dos ramas. La primera rama contiene una sentencia simple de salida, pero la segunda rama contiene otra sentencia \texttt{if}, que tiene dos ramas en sí misma. Afortunadamente, estas dor 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 se vuelven difíciles de leer con rapidez. En general es una buena idea evitarlas cuando pueda. Por otra parte, este tipo de \textbf{anidamiento} es habitual, y lo veremos otra vez, de manera que debe ir acostumbrándose a él. \index{anidamiento} \section{La sentencia \texttt{return} } La sentencia \texttt{return} le permite terminar la ejecución de una función antes de que alcance su fina. 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} Esto define una función llamada \texttt{imprimeLogaritmo} que 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 erroris less than or equal to zero, in which case it displays an error message and then uses \texttt{return} to exit the function. The flow of execution immediately returns to the caller and the remaining lines of the function are not executed. Remember that any time you want to use a function from the math module, you have to import it. \section{Recursividad} \label{recursion} \index{recursión} Ya mencionamos en el último capítulo 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} El nombre de la función es \texttt{cuenta\_atras} y toma un único parámetro. Si el parámetro es cero, muestra la palabra {}``Despegando!''. En otro caso, muestra el parámetro 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 Blastoff! \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 quisieras 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 de llamar a una función en sí se llama \textbf{recursividad}, y dichas funciones se denominan \textbf{recursiv}as. \index{recursion} \index{functions!recursive} \section{Recursividad infinita} \index{recursividad!infinita} \index{recursividad infinita} En los ejemplos de la sección previa, cada vez que se llaman recursivamente las funciones, el argumento disminuye en una unidad, de manera que en algún momento ha de llegar a cero. Cuando el argumento es cero, la función retorna inmediatamente, \emph{sin hacer más llamadas recursivas}. Este caso (en el que la función se completa sin hacer una llamada recursiva) se llama el \textbf{caso base}. \index{recursividad!caso base} 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. El la mayoría de los entornos de programación, un programa con recursividad infinita no se ejecutará realmente para siempre. En vez de eso, se alcanzará el nivel máximo de recursividad y Python informará de un mensaje de error: \begin{verbatim} RuntimeError: Maximum recursion depth exceeded \end{verbatim} \begin{quote} \emph{Como actividad, escriba una función con recursividad infinita y ejecútela en el intérprete de Python de manera que obtenga el mensaje de error anterior.} \end{quote} \section{Diagramas de pila para funciones recursivas} El el capítulo anterior 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, crea una nueva instancia de la función. La instancia contiene las variables y parámetros locales de la función. Cuando la función se completa, dicha instancia desaparece. En el caso de una función recursiva, puede haber más de una instancia 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{stack2.eps} } \vspace{0.1in} Hay una instancia de \texttt{\_\_main\_\_} y cuatro instancias de \texttt{cuenta\_atras}, cada una con un valor diferente del parámetro \texttt{n}. El fondo de la pila, \texttt{cuenta\_atras} con \texttt{n=0}, es el caso base. No hace una llamada recursiva, de manera que no hay más instancias de \texttt{cuenta\_atras}. La instancia de \texttt{\_\_main\_\_} está vacía porque no hemos creado ninguna variable sobre ella ni le hemos pasado ningún parámetro. \begin{quote} \emph{Como actividad, dibuje un diagrama de pila para} \texttt{\emph{nLineas}}\emph{, invocada con el parámetro} \texttt{\emph{n=4}}\emph{.} \end{quote} \section{Entrada por teclado} Los programas que hemos escrito hasta ahora son un poco primitivos 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 \texttt{return} or \texttt{enter}, el programa se reanuda y \texttt{raw\_input} devuelve lo que el usuario escribe como tipo \texttt{string}: \begin{verbatim} >>> entrada = raw_input () A que estas esperando? >>> print entrada A que estas esperando? \end{verbatim} Antes de llamar a \texttt{raw\_input} es conveniente mostrar un mensaje que le pida al usuario el dato por introducir. Este mensaje se llama indicador. Puede proporcionarle un indicador a \texttt{raw\_input} como argumento: \index{indicador} \begin{verbatim} >>> nombre = raw_input ("Como te llamas? ") Como te llamas? Aquiles, heroe de los griegos de Troya! >>> print nombre Aquiles, heroe de los griegos de Troya! \end{verbatim} Si espera que la entrada sea un entero, utilice la función \texttt{input}. Por ejemplo: \begin{verbatim} >>> indicador = "Cual es la velocidad de una golondrina que no hace verano?\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{speed}. Por desgracia, si el usuario escribe algo que no sea un dígito, el programa dará un error: \begin{verbatim} >>> velocidad = input (indicador) Cual es la velocidad de una golondrina que no hace verano? ¿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 que trabaja sobre enteros y devuelve el resto cuando un número se divide entre otro. En python se señala con un signo de tanto por ciento (\texttt{\%}). \item [sentencia~condicional:]Sentencia que controla el flujo de ejecución de un programa dependiendo de cierta condición. \item [sentencia~compuesta:]Estructura de Python que está formado por una cabecera terminada en dos puntos, y un bloque o cuerpo de una o más sentencias que tienen la misma sangría. \item [bloque:]Grupo de una o más sentencias que se tratan como una sentencia única, en el sentido de que se ejecutan todas juntas secuencialmente. En Python el boque de sentencias que constituye el cuerpo de una sentencia compuesta debe estar sangrado la misma cantidad relativa a la cabecera de la sentencia. \item [cuerpo:]En una sentencia compuesta, el bloque de sentencias que sigue a la cabecera de la sentencia. \item [ejecución~condicional:]Flujo de ejecución que puede seguir varios posibles caminos, dependiendo del efecto de las sentencias condicionales. \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 estás ejecutando en ese momento. \item [caso~base:]En una función recursiva, la rama de una sentencia condicional que no ocasiona una llamada recursiva. Si la llamada a una función recursiva no acaba llevando al caso base, el resultado será una recursión infinita. \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 [línea~de~órdenes:]indicador visual que invita al usuario a introducir datos. \index{operador módulo} \index{cuerpo} \index{bloque} \index{sentencia condicional} \index{sentencia compuesta} \index{ejecución condicional} \index{anidamiento} \index{recursividad} \index{caso base} \index{recursividad infinita} \index{línea de órdenes}\end{description} \end{document}


Next Up Previous Hi Index