Control de ejecución
Contents
Control de ejecución#
Los programas usualmente se ejecutan corriendo cada instrucción en el orden en que aparecen
Pero en ocasiones, necesitamos ejecutar las instrucciones de otra manera.
Para ello, usamos instrucciones de control de ejecución:
if, elif, else
ejecuta algunas instrucciones una vez, pero solo si cierta condición es verdaderawhile
ejecuta algunas instrucciones varias veces, solo mientras que cierta condición sea verdaderafor
ejecuta algunas instrucciones varias veces, iterando sobre un iterablecontinue
brinca a la siguiente iteraciónde un buclewhile
ofor
break
detiene la ejecución de un buclewhile
ofor
Ejecución condicional con if
#
La palabra clave
if
evalua una expresión para obtener un valorTrue
oFalse
.Esto permite que un programa proceda en diferentes direcciones de acuerdo con el resultado del test.
La expresión evaluada debe ser seguida de dos puntos
:
, luego las instrucciones que se evaluan si el test es verdadero deben escribirse en líneas separadas e indentadas respecto a la línea que contiene elif
.El tamaño de la indentación no es importante, pero debe ser el mismo en cada línea.
Por tanto, la sintaxis se ve así:
if test-expression:
statements-to-execute-when-test-expression-is-True
statements-to-execute-when-test-expression-is-True
Por ejemplo, para determinar si un número m
es par o impar:
m = 7
if m % 2 == 0:
print('m es par')
else:
print('m es impar')
El test no necesariamente tiene que ser un boolean. El número 0
, el valor None
, y un texto vacío ''
, lista vacía []
, tupla vacía ()
o conjunto vacío {}
, todos son interpretados como False
.
if m % 5:
print('m no es divisible entre 5')
else:
print('m es divisible entre 5')
horas = 10
if horas < 12:
ampm = 'a.m.'
else:
ampm = 'p.m.'
ampm
Examinando condiciones#
Algunas veces necesitamos asignar un valor dependiendo de una condición, como así
if testExpression:
x = ifTrueThis
else:
x = ifFalseThis
Esto es equivalente a :
x = ifTrueThis if testExpression else ifFalseThis
Por ejemplo, el código anterior, en el que queremos definir una variable que depende de una condición, podemos escribirlo más compacto así:
ampm1 = 'a.m.' if horas < 12 else 'p.m.'
ampm1
Otro ejemplo
n = 18
z = "n is " + ("impar" if n % 2 else "par")
z
Iterando while
true i#
Un bucle es una pieza de código que automáticamente se repite.
Una ejecución completa de todas las instrucciones dentro de un bucle se llama una “iteración”.
El tamaño del buche se controla con un test condicional que se ejecuta dentro del bucle.
Mientras que la expresión evaluada sea
True
el bucle continuará –– hasta que la expresión seaFalse
, punto en el cual el bucle termina.En programas de Python, la palabra clave
while
crea un bucle. Es seguida por la expresion a evaluar y dos puntos:
.Las instrucciones que se deben evaluar cuando el test pasa (sea
True
) deben seguir abajo en líneas separadas, y cada línea debe estar indentada con el mismo espacio respecto a la línea que tiene elwhile
.Este bloque de instrucciones debe incluir una instrucción que en algún momento cambie el resultado del test a
False
— de lo contrario el bucle será infinito.Por tanto, la sintaxis se ve así:
while test-expression :
statements-to-execute-when-test-expression-is-True
statements-to-execute-when-test-expression-is-True
Por ejemplo, para obtener la serie de Fibonacci hasta 100
a, b = 0, 1
while b < 100:
print(b, end=', ')
a, b = b, a + b
Un enfoque distinto, pero que incluye el primer elemento que se pasa de 100
fib = [1, 1]
while fib[-1]<100:
fib.append(fib[-2] + fib[-1])
else:
fib.pop()
fib
La función range
#
Algunas veces necesitamos iterar sobre los enteros. Podemos generarlos con la función range
.
range(6)
Para ahorrar memoria, range
retorna sus elementos uno a la vez, solo cuando se necesita, para evitar usar demasiada memoria. Por ejemplo
import sys
N = 1_000
print(f'{sys.getsizeof(range(N))=}')
print(f'{sys.getsizeof(list(range(N)))=}')
print(f'{sys.getsizeof(range(1000*N))=}')
print(f'{sys.getsizeof(list(range(1000*N)))=}')
En los ejemplos que siguen convertimos objetos range
en listas únicamente para poder imprimir sus elementos.
range(n)
retorna enteros de 0
a n-1
list(range(6))
range(m, n)
retorna enteros de m
a n-1
list(range(2,8))
range(m, n, s)
retorna enteros de m
a n-1
, de s
en s
list(range(2,9,3))
También podemos crear un range
con el orden invertido:
list(range(4, 0,-1))
Iterando sobre los elementos de un iterable: for
#
En Python la palabra clave for
itera sobre todos los elementos de cualquier iterable que aparezca luego de la palabra clave in
.
La sintaxis se ve así:
for item in iterable :
statements-to-execute-on-each-iteration
statements-to-execute-on-each-iteration
Ejemplos de iterables:
rangos
listas, tuplas, conjutos, diccionarios
textos
archivos de texto
arreglos de números
Iterando sobre textos#
for letra in 'abcd':
print(letra.upper())
Iterando sobre enteros#
for k in range(1, 6):
print(k**2)
Iterando líneas de un archivo de texto#
with open("../data/HimnoNacional.txt", 'r', encoding='utf-8') as archivo_himno:
for linea in archivo_himno:
print(linea, sep='')
temp = open("../data/HimnoNacional.txt", 'r', encoding='utf-8')
dir(temp)
temp = open("../data/HimnoNacional.txt", 'r', encoding='utf-8')
dir(temp)
['_CHUNK_SIZE',
'__class__',
'__del__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__enter__',
'__eq__',
'__exit__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__lt__',
'__ne__',
'__new__',
'__next__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'_checkClosed',
'_checkReadable',
'_checkSeekable',
'_checkWritable',
'_finalizing',
'buffer',
'close',
'closed',
'detach',
'encoding',
'errors',
'fileno',
'flush',
'isatty',
'line_buffering',
'mode',
'name',
'newlines',
'read',
'readable',
'readline',
'readlines',
'reconfigure',
'seek',
'seekable',
'tell',
'truncate',
'writable',
'write',
'write_through',
'writelines']
Iterando los elemetos de un diccionario#
king = {'name': 'John Snow',
'age': 24,
'home': 'Castle Black',
'lover': 'Ygritte',
'knows': None}
for llave, valor in king.items():
print(f'king["{llave}"] = {valor}')
enumerate#
En ocasiones, además de iterar los elemento de una colección, necesitamos llevar cuenta del número de iteración. Una forma de hacerlo es ésta:
eltexto = 'abcde'
# esta es la forma "fea" que tendríamos que usar en otros lenguajes de programación
for i in range(len(eltexto)):
letra = eltexto[i]
print(f'iteración {i} da por resultado {letra}')
Como esta situación es tan común, Python tiene una forma elegante de hacerlo, usando la función enumerate
eltexto = 'abcde'
# esta es la forma elegante usando Python
for i, letra in enumerate(eltexto):
print(f'iteración {i} da por resultado {letra}')
zip#
De manera similar, en ocasiones debemos iterar sobre dos o más colecciones en paralelo. Una forma es
quantities = [3, 2, 4, 6]
fruits = ('apple','banana','coconut')
# este código dará un error, porque las colecciones no son del mismo tamaño!
for i in range(len(quantities)):
n = quantities[i]
fruit = fruits[i]
print(f'{n} {fruit}s')
Para iterar dos iterables en paralelo, es más elegante y fácil que usemos zip
quantities = [3, 2, 4, 8]
fruits = ('apple','banana','coconut')
for n, fruit in zip(quantities,fruits):
print(f'{n} {fruit}s')
List comprehensions#
List comprehension es una manera elegante de definir una lista basado en otra colección (un iterable).
Generalmente son más compactas y rápidas que los bucles tradicionales.
No obstante, debemos evitar list comprenhension demasiado largas para que el código sea claro.
Caso más sencillo#
A veces necesitamos hacer una lista de elementos a partir de otro iterable, como con este código
lst = list()
for item in iterable:
lst.append(expression)
Esto puede hacer más sucintamente con
lst = [expression for item in iterable]
Por ejemplo, para obtener una lista de los cuadrados de los números del 1 al 14:
%%timeit
miscuadrados = []
for k in range(1,15):
miscuadrados.append(k**2)
miscuadrados
Este código es más sencillo de entender, y más compacto. Además, usualmente es más rápido.
%%timeit
miscuadrados2 = [k**2 for k in range(1,15)]
miscuadrados2
[k**2 for k in range(1,15) if k%2==1]
Otro ejemplo: para contar las letras en una lista de palabras
frutas = ['apple','banana','carrot','grape','kiwi']
[len(palabra) for palabra in frutas]
Caso con un condicional#
A veces necesitamos además que se satisfaga alguna condición en la iteración, como con este código
lst = list()
for item in iterable:
if conditional:
lst.append(expression)
Esto puede hacer más sucintamente con
lst = [expression for item in iterable if conditional]
Por ejemplo, para generar los cuadrados de los números pares menores que 12
%%timeit
lista1 = list()
for k in range(1,12):
if k % 2 == 0:
lista1.append(k**2)
lista1
Esta es una versión más compacta:
%%timeit
lista2 = [k**2 for k in range(1, 12) if not k%2]
lista2