Curso de Python: 5-Estructuras de control

Estructuras de control
Hasta ahora, el flujo de ejecución de los comandos se ha desarrollado secuencialmente (paso a paso). Las situaciones que tendrán que atender nuestros programas serán impredecibles, y la ejecución de los comandos se tendrá que realizar en base a una circunstancia dada, añadiéndole inteligencia lógica. Esto nos permitirá, por ejemplo, atender esa situación, o iterar (repetir) cierto código mientras se dé (o no) esa situación.

Operadores relacionales
Para determinar una situación (o condición), y proceder en consecuencia, se reduce dicha situación a un resultado VERDADERO (TRUE) ó FALSO (FALSE). Este resultado se obtiene mediante una expresión comparativa (o boolean), que compara dos valores mediante un operador relacional, retornando TRUE o FALSE según el resultado de dicha comparación:
>>> 6 == 7 # ¿son iguales?
False
>>> 'Pedro' != 'Felipe' # ¿son distintos?
True
>>> 100 < 101 # ¿100 es menor que 101?
True
>>> 'P' > 'Z' # ¿P es mayor que Z?
False

Operadores relacionales
a == b  ¿a es igual a b?
a != b  ¿a es distinto de b?
a < b   ¿a es menor que b?
a <= b  ¿a es menor ó igual que b?
a > b   ¿a es mayor que b?
a >= b  ¿a es mayor ó igual que b?

Control de flujo condicional
Imaginemos un caso en el que hay que informar al usuario si un valor es par o impar. Para averiguar esto, calculamos el resto de la división de ese valor entre 2. Si retorna el valor cero, es par. Si no, es impar.
>>> valor = 6
>>> if valor%2==0: # si ... entonces
... print valor, 'es par' # bloque indentado
...
6 es par

Ha de reseñarse que los bloques de código correspondientes a una estructura de código, ya sea condicional, iteracciones, etc., han de estar indentados, es decir, con una profundidad mayor utilizando la sangría o tabulación. Aquí, este bloque de código se ejecutará cuando se cumpla la condición.

Este ejemplo es muy sencillo, y sólo contempla el caso de que el valor sea par. Para que contemple también el caso de que sea impar, habrá que indicar una ejecución alternativa mediante la sentencia else (si no...):
>>> valor = 7
>>> if valor%2==0: # si ... entonces
... print valor, 'es par'
... else: # si no
... print valor, 'es impar'
...
7 es impar

Cuando hay más de dos casos o situaciones, se utilizará la ejecución encadenada elif (abreviatura de else if (si no, si...entonces)), aportando más casos o condiciones:
>>> nota = 7.2
>>> if nota<5: # Si menos de 5
... print 'Nota:',nota,' - SUSPENDIDO'
... elif nota>=5 and nota<7: # Si no, si entre 5 y 6.99
... print 'Nota:',nota,' - APROBADO SUFICIENTE'
... elif (nota>=7 and nota<9): # Si no, si entre 7 y 8.99
... print 'Nota:',nota,' - APROBADO NOTABLE'
... else: # Si no (en otros casos)
... print 'Nota:',nota,' - APROBADO SOBRESALIENTE'
...
Nota: 7.2 – APROBADO NOTABLE

Las comparaciones lógicas pueden ir o no entre paréntesis, los cuales aportan claridad y prioridad.

Operadores lógicos
Se pueden evaluar varias condiciones o expresiones comparativas, relacionando todos los resultados mediante operadores lógicos, y obteniendo un único resultado boolean. El siguiente ejemplo evalúa dos condiciones obligatorias para admitir a una candidata: ser mayor de edad Y ser mujer:
>>> edad, sexo = 19, 'M'
>>> if edad>=18 and sexo=='M':
... print 'ADMITIDA'
... else:
... print 'NO ADMITIDA'
...
ADMITIDA

El siguiente ejemplo requiere que el candidato posea un titulo O una experiencia mínima de cinco años (al menos, uno de los dos requisitos), Y, además (obligatorio), una edad mínima de 30 años.
>>> titulo, experiencia, edad = True, 7, 32
>>> if ((titulo==True or experiencia>=5) and edad>=30):
... print 'ADMITIDO/A'
... else:
... print 'NO ADMITIDO/A'
...
ADMITIDO/A

Operadores lógicos
not (exprCondic)             ¿es no...? (negación)
exprCondic1 and exprCondic2  ¿se cumplen ambas?
exprCondic1 or exprCondic2   ¿se cumple alguna?

Bucles for
Un bucle es una iteración o repetición de ejecución de código. En el caso de un bucle for, éste recorre uno a uno los elementos de una secuencia, tomando sus valores y asignándolos a una variable.

El siguiente bucle for repite 3 veces un saludo:
>>> for i in range(3): # para i en secuencia
... print 'Hola, Python'
...
Hola, Python
Hola, Python
Hola, Python

Aunque en cada iteración se asigna el valor de la secuencia a la variable i, éste no se ha utilizado. Un ejemplo sencillo sobre su uso podría ser la tabla de multiplicar:
>>> tabla = 5
>>> for i in range(1,11):
... print i, 'x', tabla, '=', i*tabla
...
1 x 5 = 5
2 x 5 = 10
3 x 5 = 15
4 x 5 = 20
5 x 5 = 25
6 x 5 = 30
7 x 5 = 35
8 x 5 = 40
9 x 5 = 45
10 x 5 = 50

El siguiente ejemplo visualiza las tablas del 1 al 10, mediante dos bucles anidados:
>>> for i in range(1,11):
... for n in range(1,11):
... print n,'x',i,'=',n*i


Bucles while
Los bucles for tienen una iteración calculada o controlada, en base a los elementos de una secuencia. Habrá situaciones en que la iteración sea impredecible, o que los valores no estén en una secuencia. Así pues, la secuencia deja de ser un modelo de iteración válido.

¡Vamos a jugar a adivinar un número!. Ahora el número de veces no está determinado por una secuencia, si no por la habilidad del usuario de acertar el número, que puede darse en más o menos intentos (iteraciones).

Para este caso, lo mejor es un bucle de tipo while, el cual repetirá un bloque de código mientras se cumpla una determinada condición:
>>> numero=50
>>> peticion=0
>>> while (numero!=peticion): # mientras numero!=peticion
... peticion=int(raw_input('Dame un numero entre 0 y 100:'))
... if (peticion<numero):
... print 'El numero a acertar es mas grande'
... elif (peticion>numero):
... print 'El numero a acertar es mas pequeño'

El bucle while se repetirá MIENTRAS el número introducido por teclado (mediante la función raw_input() a la variable peticion), no sea el mismo que el número a acertar. La entrada de datos por teclado se asigna en forma de cadena de texto, por lo que se usa la función int(), para convertir este literal a un número entero y poder compararlo como número. Adicionalmente, se añaden otras condiciones para dar al usuario una pista sobre si el número a acertar es mayor o menor al introducido.

El siguiente ejemplo solicitará un dato que repetirá como un eco hasta que se introduzca el valor 'adios':
>>> while(True): # Bucle infinito
... dato=raw_input('# ')
... print dato*3
... if (dato=='adios'):
... break # Salida del bucle

En este caso, la condición de while significa que se ejecutará siempre. Para salir del bucle, dentro de su código se han de contemplar los casos mediante sentencias if, ejecutando la sentencia break (interrumpir) para salir del bucle. Esto también funciona con los bucles for.

Uniendo bucles y estructuras de control
La secuencia para el bucle for se puede obtener de cualquier estructura de datos (internamente son secuencias), facilitando su tratamiento:

>>> lista = ['Manzana', 'Naranja', 'Platano', 'Melon']
>>> for i in lista:
... print i,'-', len(i)
...
Manzana - 7
Naranja - 7
Platano - 7
Melon - 5

La función enumerate() retorna el índice y el valor de una secuencia:
>>> for indice,valor in enumerate(lista):
... print indice,'-',valor
...
0 - Manzana
1 - Naranja
2 - Platano
3 - Melon

Cuando se trata un diccionario, la secuencia toma el valor de la clave:
>>> notas = {'Alba':8.1, 'Raul':6.5, 'Diana':8.2, 'Sergio':5.7,
'Nerea':8.3, 'Carlos':7.3}
>>> for i in notas:
... print i, '-', notas[i]
...
Alba - 8.1
Raul - 6.5
Diana - 8.7
Sergio - 5.7
Nerea - 8.3
Carlos - 7.3

El ejemplo anterior se puede simplificar gracias a la función iteritems(), la cual toma un iterador sobre el diccionario, obteniendo la clave y el valor correspondientes en cada iteración:
>>> for clave, valor in notas.iteritems():
... print clave, '-', valor


Entregas:

Enlaces de interés:
© commandcat
Maira Gall