Next Up Previous Hi Index

Capítulo 4

Comentarios
 

Condiciones y recursión

4.1 El operador de módulo

El operador de módulo trabaja con números enteros (y con expresiones de números enteros) y revela el resto de la división cuando el primer operando se divide por el segundo. En Python, el operador de módulo se representa con el símbolo del tanto por ciento (%). La sintaxis es la misma que para los otros operadores:

>>> cociente= 7 / 3
>>> print cociente
2
>>> resto = 7 % 3
>>> print resto
1
 

De forma que 7 dividido entre 3 es 2, quedándo 1 de resto.

El operador de módulo ha resultado ser muy útil. Por ejemplo, puedes comprobar si un número es divisible entre otro, si x % yes cero, entonces x es divisible entre y.

También, puedes extraer el dígito que se encuentre más a la derecha de un número. Por ejemplo, x % 10 muestra el dígito situado más a la derecha de x (en base 10). Al igual que x % 100 muestra las dos últimas cifras. Comentarios
 

4.2 Expresiones booleanas

Una expresión booleana es una expresión que puede ser verdadera o falsa. En Python, una expresión verdadera tiene valor 1 y una falsa valor 0.

El operador == compara dos valores y formula una expresión booleana.

>>> 5 == 5
1
>>> 5 == 6
0
 

En la primera instrucción, los dos operandos son iguales, así que la expresión obtiene el valor 1 (cierto), mientras que en la segunda instrucción, 5 no es igual a 6, así que le asigna el valor 0 (falso).

El operador == es uno de los operadores de comparación, los otros son:

      x != y               # x no es igual que 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 ies menor o igual que y
 

Aunque, probablemente, estas operaciones te sean familiares, Python utiliza símbolos distintos a los matemáticos. Un error frecuente es usar un solo signo de igual (=) en vez de uno doble (==). Recuerda que = es un operador de tarea y que == es un operador de comparación. Además, no existen expresiones como =< o =>. Comentarios
 

4.3 Operadores lógicos

Existen tres operadores lógicos: and, or, y not. La semántica (significado) de estos operadores es parecida a su significado en inglés (and = y, or = o, not = no). Por ejemplo, x > 0 andx < 10 es una instrucción verdadera solo si x es mayor que 0 y menor que 10.

n%2 == 0 or n%3 == 0 es verdadera si cualquiera de las condiciones es verdad, o sea, si el número es divisible entre 2 o 3.

Finalmente, el operador not niega una expresión booleana, de forma que not(x > y) es verdad si (x > y) es mentira, o sea, si x es menor o igual a y.

En el sentido estricto de la palabra, los operandos de los operadores lógicos deben ser expresiones booleanas, pero Python no es muy estricto. Cualquier número que no sea cero se interpretará como "verdadero".

>>>  x = 5
>>>  x and 1
1
>>>  y = 0
>>>  y and 1
0
 

Generalmente, esta clase de operaciones no son las más apropiadas. Si quieres comparar un valor con cero debes hacerlo explícitamente. Comentarios
 

4.4 Ejecución de una condición

Para lograr un programa útil, casi siempre necesitamos revisar las condiciones y realizar los cambios pertinentes al comportamiento del programa. Las instrucciones condicionales nos permiten poder revisarlas. La manera más sencilla es la instrucción if:

if x > 0:
  print "x es positivo"
 

A la expresión booleana que va después de la instrucción if se le llama condición Si es verdadera, entonces se ejecutará la instrucción requerida. Sino lo es, no ocurrirá nada.

Como otras instrucciones compuestas, La instrucción if está formada por un encabezado y un bloque de instrucciones:

ENCABEZADO:
  PRIMERA INSTRUCCIÓN
  ...
ÚLTIMA INSTRUCCIÓN
 

El encabezado comienza en una nueva línea y termina con dos puntos (:). A las instrucciones indetadas, que van después de los dos puntos, se las conoce como bloque. La primera instrucción que aparezca sin indetar indicará el final del bloque. Un bloque de instrucciones dentro de una instrucción compuesta se llama cuerpo.

No existe un límite de instrucciones que puedan aparecer en el cuerpo de una instrucción if, pero al menos debe haber una. A veces, puede ser útil tener un cuerpo sin instrucciones (normalmente usado para guardar el código que aún no has escrito). En ese caso, puedes usar la instrucción passque no ejecuta ninguna instrucción. Comentarios
 

4.5 Ejecución alternativa

La ejecución alternativa es otra forma de la instrucción if en la que hay dos posibilidades y es la condición la que determina cual será ejecutada. La sintaxis queda así:

if x %2 == 0:
  print x, "es par"
else:
  print x, "es impar"
 

Si al dividir x entre 2 el resto es 0, entonces sabremos que x es par, y el programa muestra un mensaje. Si la condición es falsa, se ejecutará la segunda parte de las instrucciones. Como la condición ha de ser verdadera o falsa, solo se podrá ejecutar una de estas alternativas. Las alternativas se conocen como bifurcaciones, porque son bifurcaciones en el flujo de ejecución.

Si necesitas revisar la paridad (si es par o impar) de los números, a menudo tendrás que "envolver" este código en una función:

def printParidad(x):
if x %2 == 0:
  print x, "es par"
else:
  print x, "es impar"
 

Para cualquier valor de x, printParidad, se muestra el mensaje adecuado. Cuando lo llamas, puedes proponer cualquier expresión de número entero como argumento.

>>> printParidad(17)
>>> printParidad(y+1)
 

Comentarios
 

4.6 Condiciones encadenadas

Algunas veces hay más de dos posibilidades y necesitamos más de dos bifurcaciones. Una forma de expresar un cálculo así es la condición encadenada:

if x < y:
  print x, "es menos que", y
elif x > y:
  print x, "es mayor que", y
else:
  print x, "e ", y, "como iguales"
 

elif es la abreviación de "else if". De nuevo, solo se podrá ejecutar una bifurcación. No hay límite de instrucciones elif, pero solo se puede poner una instrucción else (y es opcional). Además deberá ser la última bifurcación en la instrucción:

if opción == 'A':
  funciónA()
elif opción == 'B':
  funciónB()
elif opción == 'C':
  funciónC()
else:
  print "Opción no válida"
 

Cada condición se revisa en orden. Si la primera es falsa, se revisa la siguiente y así hasta el final. Si una de ellas es verdadera, se ejecutará la correspondiente bifurcación, terminándose así la instrucción. Incluso, si más de una condición es verdadera, se ejecutará solo la primera verdadera.

Como ejercicio, sitúa estos ejemplos en las funciones llamadas de comparación (x, y)  y selección (opción).

Comentarios
 

4.7 Condiciones anidadas

Una condición también se puede anidar con otra. Podríamos haber escrito los tres ejemplos de la siguiente forma:

if x == y:
  print x, "e ", y, "como iguales"
else:
if x < y:
  print x, "es menor que", y
else:
  print x, "es mayor que", y
 

La condición más externa contiene dos bifurcaciones. La primera contiene una instrucción simple de salida. La segunda contiene otra instrucción if que tiene dos bifurcaciones. Estas bifurcaciones son instrucciones de salida, pero podrían ser también instrucciones condicionales.

Aunque la indetación de las instrucciones facilita la identificación de su estructura, las condiciones anidadas entorpecen su interpretación. Por lo general, no es mala idea evitarlas, si puedes.

A menudo, los operadores lógicos ofrecen una forma de simplificar las instrucciones de condiciones anidadas. Por ejemplo, podemos reescribir el siguiente código utilizando una sola condición:

if 0 < x:
if x < 10:
  print "x es un dígito positivo de una sola cifra"
 

La instrucción print se ejecutará solo si se cumplen ambas condiciones, de esta forma podemos usar el operador and

if 0 < x and x < 10:
  print "x es un dígito positivo de una sola cifra"
 

Este tipo de condiciones son comunes, así que Python ofrece una sintaxis alternativa que es parecida a las notaciones matemáticas:

if 0 < x < 10:
  print "x es un dígito positivo de una sola cifra"
 

Esta condición es semánticamente igual que la expresión booleana compuesta y la anidada. Comentarios
 

4.8 La instrucción return

La instrucción return te permite finalizar la ejecución de la función antes de que llegues al final. Debes usarla si detectas un error de condición:

import mat

def printLogaritmo(x):
if x <= 0:
  print "Sólo números positivos, por favor".
    return

  resultado = mat.log(x)
  print "El log de x es", resultado
 

La función printLogaritmo utiliza un parámetro llamado x. La primera operación que realiza es revisar si x es menor o igual que 0, en caso de serlo, se mostrará un mensaje de error y utilizará la instrucción return para salir de la función. El flujo de la ejecución devolverá inmediatamente a la función inicial que había llamado a ésta y no se ejecutarán el resto de las líneas de la función.

No olvides que para utilizar una función del módulo de matemáticas debes importarla Comentarios
 

4.9 Recursión

Hemos mencionado que es legítimo que una función llame a otra y ya has visto varios ejemplos. Sin embargo, no hemos mencionado que también es legítimo que una función se llame a sí misma. Puede no estar claro porqué este hecho es algo útil, pero ha resultado ser una de las "cosas" más mágicas e interesantes que un programa puede hacer. Por ejemplo, observa la siguiente función:

def cuenta atrás(n):
if n == 0:
  print "¡Despegue!"
  else:
    print n
    cuenta atrás(n-1)
 

cuenta atrás espera que el parámetro, n, sea un número entero positivo. si n es 0, nos devuelve la palabra "¡Despegue!" De lo contrario, nos devolverá n y, entonces, llamará a una función conocida como     auto     cuenta atrás que tiene n-1 como argumento.

¿Qué sucede si llamamos a esta función de la siguiente forma?:

>>> cuenta atrás(3)
 

La ejecución de la función cuenta atrás comienza con n=3, y, como n no es 0, nos devuelve el valor 3 y se llama a sí misma...

La ejecución de la función cuenta atrás comienza con n=2,y, como n no es 0, nos devuelve el valor 2 y se llama a sí misma...

La ejecución de la función cuenta atrás comienza con n=1, y, como n no es 0, nos devuelve el valor 1 y se llama a sí misma...

La ejecución de la función cuenta atrás  comienza con n=0,y, como n no es 0, nos devuelve la palabra "¡Despegue!" y vuelve.

La función cuenta atrás conn=1 vuelve

La función cuenta atrás con n=2 vuelve

La función cuenta atrás con n=3 vuelve

Y entonces estarás de vuelta en __main__ (menudo paseo). De esta forma, el resultado final queda así:

3
2
1
¡Despegue!
 

Como segundo ejemplo, vuelve a mirar las funciones nuevaLinea y tresLineas:

def nuevalinea(n):
  print

def
tresLineas():
  nuevaLinea()
  nuevaLinea()
  nuevaLinea()
 

A pesar de todo este trabajo, no nos serán de gran ayuda si queremos producir 2 nuevas líneas o 106. Una alternativa mejor podría ser ésta:

def nLineas(n):
if n > 0:
    print
   nLineas(n-1)
 

Este programa es parecido a cuenta atrás, ya que mientras n sea mayor que 0, producirá una nueva línea y se llamará a sí mismo para producir n-1 nuevas líneas adicionales. De este modo, el número total de nuevas líneas es 1 + (n -1) que, si no te has equivocado con el álgebra, da n.

El proceso mediante el cual una función se llama a sí misma se conoce como recursión y se dice que son funciones recursivas. Comentarios
 

4.10 Diagramas de pila para funciones recursivas

En lasección 3.11 hemos empleado un diagrama de pila para representar el estado de un programa durante una llamada a función. El mismo tipo de diagrama puede ayudarnos a interpretar una función recursiva.

Cada vez que se llama a una función, Python crea un nuevo marco de función que contiene los parámetros y variables locales de la función. Para que se ejecute una función recursiva, debe haber más de un marco en la pila al mismo tiempo.

Esta figura muestra un diagrama de pila para ejecutar la función cuenta atrás llamada con n = 3:

Como es habitual, la parte superior de la pila es el marco para __main__. Está vacío porque no hemos creado ninguna variable en __main__ ni le hemos indicado ningún parámetro.

Los cuatro marcos de cuenta atrás tienen diferentes valores para los parámetros n. Al final de la pila, donde se encuentra n=0, se le conoce como caso base. No hace ninguna llamada recursiva, así que no hay más marcos.

Como ejercicio, dibuja un diagrama de pila para la función nLineas  llamada con n=4.

Comentarios

4.11 Recursión infinita

Si una recursión nunca alcanza un caso base, seguirá mandando llamadas recursivas para siempre, y el programa no tendrá fin. Esto se conoce como recursión infinita, y generalmente no se considera una buena idea. Aquí se muestra un programa con una recursión infinita:

defrecurse():
  recurse()
 

En la mayoría de los entornos de programación, un programa con una recursión infinita no se ejecutará para siempre. Python notifica un mensaje de error cuando se alcanza el límite máximo de recursión:

  File "<stdin>", line 2, in recurse
  (98 repetitions omitted)
  File "<stdin>", line 2, in recurse
RuntimeError: Maximum recursion depth exceeded

Este ejemplo es un poco más grande que el que vimos en el capítulo anterior. ¡Cuando se produce un error, hay 100 estructuras de recursión en la pila!.

Como ejercicio, escribe una función con recursión infinita y ejecútala en el intérprete de Python.

Comentarios

4.12 Entradas del teclado

Los programas que has escrito hasta aquí han sido un poco elementales en el sentido de que no aceptan entradas del usuario. Repiten siempre lo mismo.

Python facilita funciones incorporadas que aceptan entradas del teclado. La más fácil se conoce como raw_input. Cuando se invoca esta función, el programa se para y espera a que el usuario escriba algo. Cuando el usuario presiona la teclas de Retorno o Intro, el programa continua, y las raw_input devuelven lo que el usuario escribió en forma de cadena:

>>> entrada = raw_input ()
What are you waiting for?
>>> print entrada
What are you waiting for?
 

Antes de llamar a la entrada simple, es una buena idea crear un mensaje que le diga al usuario qué es lo que tiene que introducir. Este mensaje de llama indicador. Podemos facilitar un indicador que sustituya a la raw_input:

>>> nombre = raw_input ("¿Cuál... es tu nombre? ")
¿Cuál...es tu nombre? ¡Arturo, rey de los británicos!
>>> print nombre
¡Arturo, rey de los británicos!
 

Si suponemos que la respuesta va a ser un número entero, podemos usar la función de entrada, la cual interpreta la respuesta como un valor de Python:

línea de órdenes = "¿Cuál...es la velocidad aérea de una golondrina sin cargamento?\n"
velocidad = input(indicador)
 

Si el usuario escribe una cadena de dígitos, ésta se convierte en un número entero y se le asignará velocidad. Desafortunadamente, si el usuario escribe un carácter que no es un dígito, el programa se bloquea:

>>> velocidad = input (indicador)
¿Cuál...es la velocidad aérea de una golondrina sin cargamento?
¿ A cuál te refieres, a una africana o a una europea?
Error de sintaxis: sintaxis inválida
 

Para evitar este tipo de errores, se recomienda usar las entradas simples para obtener una cadena y luego usar las funciones de conversión para convertirlas en otros tipos. Comentarios

4.13 Glosario

operador de módulo
Es un operador, que se indica con el signo del tanto por ciento (%), que trabaja con enteros y decimales que muestra el resto cuando un número se divide por otro.
expresión booleana
Es una expresión que puede ser verdadera o falsa
operador de comparación
Es uno de los operadores que compara dos valores: ==!=><>=, y <=.
operador lógico
Es uno de los operadores que combina dos expresiones booleanas: andornot.
instrucción condicional
Es una instrucción que controla el curso de una ejecución y que depende de algunas condiciones.
condición
La expresión booleana es una instrucción condicional que determina qué estructura se ejecuta.
instrucción compuesta
Es una instrucción que tiene un encabezado y un cuerpo de mensaje. El encabezado acaba con dos puntos (:). El cuerpo de mensaje sangrado con respecto al encabezado encabezado.
bloque
Es un grupo de instrucciones consecutivas con la misma estructura.
cuerpo de mensaje
El bloque es una instrucción compuesta que sigue al encabezado.
anidación
Es una estructura de un programa dentro de otra, como pueden ser las instrucciones condicionales dentro de la estructura de otra instrucción condicional.
recursión
Es el proceso de llamar a un función que se está llamando a sí misma en ese momento.
caso base
Es la estructura de una instrucción condicional en una función recursiva que no es el resultado de una llamada recursiva.
recursión infinita
Es una función que se llama a sí misma recursivamente sin que ésta haya alcanzado nunca un caso base. Muchas veces, una recursión infinita causa un error de ejecución.
línea de órdenes
Es una entrada visual que le dice al usuario que introduzca datos.


Next Up Previous Hi Index


Next Up Previous Hi Index