Control de flujo¶
Estructura if-elif-else¶
Normalmente, nuestro código se ejecuta de arriba a abajo linea por linea o sentencia por sentencia.
Sin embargo, a veces es necesario ejecutar partes de nuestro código bajo ciertas condiciones.
De esta forma conseguimos que algunas partes que no deben de ejecutarse siempre no se ejecuten.
La sintaxis es:
- if condition:
- code
- code
- elif condition:
- code
- code
- else:
- code
- code
Algunos ejemplos son:
- No ejecutar un código si los datos introducidos no son válidos.
- Si un dato tiene un valor concreto, ejecutar una sección del código concreta.
Ejemplo 1 | if¶
Si un dato está entre 0 y 10 lo elevamos al cuadrado. En otro caso nada.
n : int = -1
if 0 <= n <= 10:
n = n ** 2
n
-1
n : int = 3
if 0 <= n <= 10:
n = n ** 2
n
9
Ejemplo 2 | if-else¶
Si un dato está entre 0 y 10 lo elevamos al cuadrado. En otro caso al cubo.
n : int = -2
if 0 <= n <= 10:
n = n ** 2
else:
n **= 3
n
-8
n : int = 3
if 0 <= n <= 10:
n = n ** 2
else:
n **= 3
n
9
Ejemplo 3 | if-elif-else¶
Si una lista está vacía, creamos una lista con un elemento cualquiera.
Si no esta vacía y contiene solo el numero 1, vaciamos la lista.
En otro caso creamos una lista con los numeros desde el 0 hasta el 9.
lista : list = []
if lista == []:
lista = [1]
elif lista == [1]:
lista = []
else:
lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lista
[1]
lista : list = [1]
if lista == []:
lista = [1]
elif lista == [1]:
lista = []
else:
lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lista
[]
lista : list = [2]
if lista == []:
lista = [1]
elif lista == [1]:
lista = []
else:
lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lista
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Ejemplo 4 | Combinación de condiciones¶
Este ejempo muetra un caso en el que necesitamos anidar varias condiciones (estructura if-elif-else).
Además, debemos usar operaciones (and, or, not) cuando tenemos 2 o más condiciones dentro de un if o de un elif.
- Si un número es menor que 100
- Si es par y multiplo de 5 entonces lo elevamos al cuadrado.
- Si es multiplo de 3 le restamos 3.
- En otro caso le cambiamos el signo.
- Si es par y multiplo de 5 entonces lo elevamos al cuadrado.
- Si es mayor que 100 pero menor que 1000
- Si es impar lo multiplicamos por 2
- En otro caso no hacemos nada
- En otro caso no hacemos nada
numero : int = 11
if numero < 100:
if numero % 2 == 0 and numero % 5 == 0:
numero = numero ** 2
elif numero % 3:
numero -= 3
else:
numero = -numero
elif 100 < numero < 1000:
if numero % 2 == 0:
numero *= 2
numero
8
numero : int = 12
if numero < 100:
if numero % 2 == 0 and numero % 5 == 0:
numero = numero ** 2
elif numero % 3:
numero -= 3
else:
numero = -numero
elif 100 < numero < 1000:
if numero % 2 == 0:
numero *= 2
numero
-12
numero : int = 10
if numero < 100:
if numero % 2 == 0 and numero % 5 == 0:
numero = numero ** 2
elif numero % 3:
numero -= 3
else:
numero = -numero
elif 100 < numero < 1000:
if numero % 2 == 0:
numero *= 2
numero
100
Ejercicios¶
- Usa la estructura if-elif-else con otros tipos de datos con y sin operadores de comparación
Estructuras while y for¶
En la sección anterior comentamos que nuestro código normalmente se ejecuta en secuencial de arriba a abajo.
Decíamos que con la estructura if-elif-else podemos controlar qué partes de nuestro código se ejecutan según una serie de condiciones.
En otras ocasiones necesitamos ejecutar varias veces un mismo bloque de código. Sin embargo, es muy engorroso escribir una y otra vez lo mismo.
Cuando lo que nuestro código hace no cambia, es decir, las líneas de código son las mismas pero tenemos que ejecutarlas varias veces usamos los bucles.
Cuando sabemos cuántas veces ejecutaremos una misma sección de código, usamos el bucle for.
Este en python funciona recorriendo una variable iterable. Es decir, podemos leer cada elemento de la misma sin necesidad de indicar qué elemento queremos leer.
El bucle for indica por nosotros que queremos leer el siguiente elemento en caso de haber más. Independientemente de cual sea ese elemento.
Sintaxis:
- for element in iterable:
- code
- else:
- code
Cuando no sabemos cuántas veces ejecutaremos una misma sección de código, usamos el bucle while.
En este indicamos una condición y mientras se cumpla dicha condición, el bucle ejecutará lo que haya dentro del mismo.
Sintaxis:
- while condition:
- code
- else:
- code
NOTA:
En la sintaxis vemos que hay una parte adicional else. Esta parte es opcional y sirve para ejecutar una porción de código después de que el bucle termine.
Solo se ejecuta esta parte si el bucle finalizó sin problemas. Es decir, no ocurrió ningún error que pare la ejecución del mismo de forma inesperada.
Ejemplo 1 | for¶
Obtener la suma de los elementos de una lista
suma : int = 0
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
suma += i
suma
45
Obtener claves de un diccionario
claves : list = []
for key in {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5}:
claves += [key]
claves
['a', 'b', 'c', 'd', 'e']
Ejemplo 2 | for con condicionales¶
Obtener la suma de los elementos pares, los múltiplos de 3 y los impares en 3 variables separadas, de una lista.
suma_pares : int = 0
suma_multiplos_3 : int = 0
suma_impares : int = 0
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
if i % 2 == 0:
suma_pares += i
else:
suma_impares += i
if i % 3 == 0:
suma_multiplos_3 += i
suma_pares, suma_multiplos_3, suma_impares
(20, 18, 25)
Ejemplo 3 | for con bucles anidados¶
Dada una lista de palabras, generar una lista indicando el número de letras tiene cada palabra
numero_letras_por_palabra : list = []
for palabra in ['hola', 'mundo', 'arbol', 'cigüeña']:
numero_caracteres = 0
for caracter in palabra:
numero_caracteres += 1
else:
numero_letras_por_palabra += [(palabra, numero_caracteres)]
numero_letras_por_palabra
[('hola', 4), ('mundo', 5), ('arbol', 5), ('cigüeña', 7)]
Ejemplo 4 | while¶
Dado un número:
- Si es par, lo elevamos al cuadrado y sumamos 1
- Si es impar, lo dividimos entre 3 y multiplicamos por 2
Repetir la operación mientras el número sea menor que 100 y el número de veces que se realiza la operación de arriba es menor que 10
numero : int = 2
iteraciones : int = 0
while numero < 100 and iteraciones < 10:
if numero % 2 == 0:
numero = (numero ** 2) + 1
else:
numero = (numero // 3) * 2
iteraciones += 1
else:
iteraciones = 0
numero
2
numero : int = 3
iteraciones : int = 0
while numero < 100 and iteraciones < 10:
if numero % 2 == 0:
numero = (numero ** 2) + 1
else:
numero = (numero // 3) * 2
iteraciones += 1
else:
iteraciones = 0
numero
5
Compresión de listas (Avanzado)¶
De normal, escribir un bucle for es una estructura lenta.
A veces interesa más usar compresión de listas que equivale a un bucle for.
La sintaxis normal es:
- [item for item in iterable] -> Genera una lista
- {key : value for item in iterable} -> Genera un diccionario
- (item for item in iterable) -> Podemos pensar que esto genera una tupla pero NO!!!. Genera un tipo de dato especial llamado generador. Es un elemento iterable, pero no está no está específicamente almacenado en memoria por lo que no podemos acceder directamente a un dato concreto. Tenemos que recorrer y cada dato se irá generando.
Sin compresión listas
lista : list = []
for i in range(10):
lista.append(i ** 2)
lista
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
diccionario : dict = {}
for i in lista:
diccionario[i] = i ** 3
diccionario
{0: 0,
1: 1,
4: 64,
9: 729,
16: 4096,
25: 15625,
36: 46656,
49: 117649,
64: 262144,
81: 531441}
Con compresión de listas
lista : list = [i ** 2 for i in range(10)]
lista
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
diccionario : dict = {i : i ** 3 for i in lista}
diccionario
{0: 0,
1: 1,
4: 64,
9: 729,
16: 4096,
25: 15625,
36: 46656,
49: 117649,
64: 262144,
81: 531441}
Rizando el rizo¶
Como todo, mejor no abusar, pero al igual que los bucles se pueden anidar y escribir un bucle dentro de un bucle, podemos hacer los mismo con la compresión de listas.
Sin compresión de listas
matriz : list = []
for i in range(3):
row = []
for j in range(3):
row += [0]
matriz += [row]
matriz
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Con compresión de listas
matriz : list = [[j + 1 + i * 3 for j in range(3)] for i in range(3)]
matriz
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Ejercicios¶
- Dada una lista de números cualquiera
- Crea una lista nueva con los números impares de la misma
- Crea una lista nueva con los números pares de la misma
- Crea una lista con todos números que sea distintos (que no se repitan)
- Dado un string, sustituye las minúsculas por mayúsculas
Estructura try-except-else-finally¶
En informática existen al menos 3 tipos de errores básicos:
- Error sintáxtico: No hemos escrito bien alguna parte del código según lo requiere nuestro lenguaje.
- Error lógico: A la hora de programar hay algo que se nos pasó por alto y aunque el código esté bien escrito, el resultado que obtendremos no tiene que ser el deseado.
- Error en tiempo de ejecución: Durante la ejecución de nuestro código, algo inesperado ocurre y nuestro código termina la ejecución de manera forzada.
Sea cual sea el tipo de error al que nos enfrentemos, a veces necesitamos que nuestro código siga funcionando.
Un ejemplo sería abrir 2 archivos y que uno de ellos no exista.
Si el otro si existe quizás nos interese procesar el que si existe y ya veremos que pasa con el que falta.
Para tener un mayor control sobre qué ocurre en nuestro código, existe la estructura try-except-else-finally.
Sintaxis:
- try:
- code
- except:
- code
- else:
- code
- finally:
- code
No necesariamente tienen que estar las 4 partes presentes en un código. Normalmente se suele escribir más la estructura:
- try:
- code
- except:
- code
El significado de cada parte es el siguiente:
- try:
- Encierra el código que queremos ejecutar. Si algo falla, se salta a except en caso de que esté escrita esa parte.
- except:
- Captura lo que se conoce como excepción.
- Podemos escribir simplemente except: y escribir un código que gestione el error como un mensaje indicando que algo falló o escribir except Exception as alias.
- except ExceptionType as alias:
- Con esta sintaxis estamos indicando que solo queremos controlar la excepción que hemos indicado. Si ocurre otra que no hayamos indicado, el código seguirá fallando y podría pararse la ejecución.
- else:
- Permite definir una parte de código que se ejecutará en caso de la parte dentro de try se haya ejecutado correctamente.
- finally:
- Permite definir una parte de código que sí o sí se ejecutará independientemente de si ocurre algún error o no.
Ejemplo 1 | Error descontrolado¶
1 + 'a'
'Ejecución sin errores'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) c:\Users\sergi\Documents\repos\python_course\tutoriales\03_control_de_flujo.ipynb Cell 46 line 1 ----> <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/03_control_de_flujo.ipynb#X63sZmlsZQ%3D%3D?line=0'>1</a> 1 + 'a' <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/03_control_de_flujo.ipynb#X63sZmlsZQ%3D%3D?line=2'>3</a> 'Ejecución sin errores' TypeError: unsupported operand type(s) for +: 'int' and 'str'
Ejemplo 2 | Manejo de la situación del ejemplo 1¶
Por normal general no podemos realizar operaciones entre distintos tipos de datos.
En el caso de arriba vemos que no podemos sumar un número con una letra.
try:
1 + 'a'
except:
pass
'Ejecución sin errores'
'Ejecución sin errores'
Ejemplo 3 | Capturar una excepción específica¶
En este caso vamos a tratar solo de controlar la excepción FileNotFoundError. Esta ocurre cuando queremos abrir un archivo pero python no lo encuentra. Es normal que cuando se ejecute este código nos salte un error porque la excepción que ocurre es TypeError porque no estamos abriendo archivos, estamos realizando operaciones entre datos de distinto tipo.
try:
1 + 'a'
except FileNotFoundError as e:
pass
'Ejecución sin errores'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) c:\Users\sergi\Documents\repos\python_course\tutoriales\03_control_de_flujo.ipynb Cell 50 line 2 <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/03_control_de_flujo.ipynb#Y101sZmlsZQ%3D%3D?line=0'>1</a> try: ----> <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/03_control_de_flujo.ipynb#Y101sZmlsZQ%3D%3D?line=1'>2</a> 1 + 'a' <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/03_control_de_flujo.ipynb#Y101sZmlsZQ%3D%3D?line=2'>3</a> except FileNotFoundError as e: <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/03_control_de_flujo.ipynb#Y101sZmlsZQ%3D%3D?line=3'>4</a> pass TypeError: unsupported operand type(s) for +: 'int' and 'str'
Ejemplo 4 | Manejo de multiples excepciones de manera específica¶
try:
1 + 'a'
except (FileNotFoundError, TypeError) as e:
pass
'Ejecución sin errores'
'Ejecución sin errores'
Ejemplo 5 | Aplicación estructura try-except-else-finally¶
Caso (a)
numero_else : int = 1
numero_finally : int = 1
try:
1 + 'a'
except (FileNotFoundError, TypeError) as e:
pass
else:
numero_else = 2
finally:
numero_finally = -1
'Ejecución sin errores', numero_else, numero_finally
('Ejecución sin errores', 1, -1)
Caso (b)
numero_else : int = 1
numero_finally : int = 1
try:
1 + 1
except (FileNotFoundError, TypeError) as e:
pass
else:
numero_else = 2
finally:
numero_finally = -1
'Ejecución sin errores', numero_else, numero_finally
('Ejecución sin errores', 2, -1)