Apéndice R — Estructuras de datos concisas.

Objetivo. Explicar como se construyen estructuras de datos en una sola línea de código (comprehensions).

R.1 Listas concisas

En matemáticas podemos definir un conjunto como sigue:

\[S = \{x^2 : x \in (0, 1, 2, \dots, 9)\} = \{0, 1, 4, \dots, 81\}\]

En Python es posible crear este conjunto usando lo que conoce como list comprehensions (generación corta de listas) como sigue:

S = [x**2 for x in range(10)]
print(S)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Las listas concisas son usadas para construir listas de una manera muy corta, natural y fácil, como lo hace un matemático. La forma precisa de construir listas concisas es como sigue:

[ expresion for i in S if predicado ]

Donde expresion es una expresión que se va a aplicar a cada elemento i de la secuencia S; opcionalmente, es posible aplicar el predicado antes de aplicar la expresion a cada elemento i.

Ejemplo R.1:

Usando listas concisas, crear el siguiente conjunto:

\[ M = \{\sqrt{x} : x \in (1,2,3,4,5,6,7,8,9,10) \;\; \text{y} \;\; x \;\; \text{es par}\} = \{ \sqrt{2}, \sqrt{4}, \sqrt{6}, \sqrt{8}, \sqrt{10}) \} \]

from math import sqrt

M = [sqrt(x) for x in range(1,11) if x % 2 == 0]
print(M)
[1.4142135623730951, 2.0, 2.449489742783178, 2.8284271247461903, 3.1622776601683795]

En el ejemplo anterior se distingue lo siguiente:

  1. La secuencia de entrada: range(1,11) es equivalente a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].

  2. La etiqueta x que representa los miembros de la secuencia de entrada.

  3. La expresión de predicado: if x % 2 == 0.

  4. La expresión de salida sqrt(x) que produce los elementos de la lista final, los cuales provienen de los miembros de la secuencia de entrada que satisfacen el predicado.

.

Ejemplo R.2:

Obtener todos los números enteros de la siguiente lista [1,'4',9,'luiggi',0,4,('mike','dela+')], elevarlos al cuadrado y poner el resultado en una lista.

lista = [1,'4',9,'luiggi',0,4,('mike','dela+')]

resultado = [x**2 for x in lista if isinstance(x, int)]

print( resultado )
[1, 81, 0, 16]

.

Ejemplo R.3:

Crear la siguiente lista: \[V = (2^0,2^1,2^2, \dots, 2^{12}) = (1, 2, 4, 8, \dots, 4096) \]

[2**x for x in range(13)]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]

.

Ejemplo R.4:

Transformar la siguiente lista grados Celsius [0, 22.5, 40,100] a grados Fahrenheit y viceversa.

Celsius \(\to\) Fahrenheit: \(f = (c * 9/5) + 32\)

c = [0, 22.5, 40,100]

f = [(9/5)*t + 32 for t in c]

print(f)
[32.0, 72.5, 104.0, 212.0]

Fahrenheit \(\to\) Celsius: \(c = (5/9) * (f - 32)\)

cn = [(5/9)*(t - 32) for t in f]

print(cn)
[0.0, 22.5, 40.0, 100.0]

Observa que en ambos ejemplos la expresión es la fórmula de conversión entre grados.

R.1.1 Anidado de listas concisas.

Ejemplo R.5:

Crear la siguiente lista:

\[M = \{\sqrt{x} \, |\, x \in S \text{ y } x \text{ impar }\}\]

con

\[S = \{x^2 : x \in (0 \dots 9)\} = \{0, 1, 4, \dots, 81\}\]

Este ejemplo se puede realizar como sigue:

S = [x**2 for x in range(0,10)]
M = [sqrt(x) for x in S if x % 2]
print('S = {}'.format(S))
print('M = {}'.format(M))
S = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
M = [1.0, 3.0, 5.0, 7.0, 9.0]

Sin embargo, es posible anidar las listas concisas como sigue:

M = [sqrt(x) for x in [x**2 for x in range(0,10)] if x % 2]
print('M = {}'.format(M))
M = [1.0, 3.0, 5.0, 7.0, 9.0]

.

Ejemplo R.6:

Sea una matriz identidad de tamaño \(n \times n\) :

\[ \left[ \begin{matrix} 1 & 0 & 0 & \dots & 0 \\ 0 & 1 & 0 & \dots & 0 \\ 0 & 0 & 1 & \dots & 0 \\ \vdots&\vdots&\vdots&\ddots&\vdots \\ 0 & 0 & 0 & \dots & 1 \\ \end{matrix} \right] \]

En Python esta matriz se puede representar por la siguiente lista:

[[1,0,0, ... , 0],
 [0,1,0, ... , 0],
 [0,0,1, ... , 0],
 ................,     
 [0,0,0, ... , 1]]
  • Usando list comprehensions anidados se puede obtener dicha lista:
n = 8
[[1 if col == row else 0 for col in range(0,n)] for row in range(0,n)]
[[1, 0, 0, 0, 0, 0, 0, 0],
 [0, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 1]]

Observa que en este caso la expresión de salida es una lista concisa: * [1 if col == row else 0 for col in range(0,n)] .

Además, la expresión de salida de esta última lista concisa es el operador ternario: * 1 if col == row else 0

.

Ejemplo R.7:

Calcular números primos en el rango [2,50].

En este ejercicio se usa el algoritmo conocido como criba de Eratóstenes. Primero se encuentran todos aquellos números que tengan algún múltiplo. En este caso solo vamos a buscar en el intervalo \([2,50]\).

La siguiente lista concisa calcula los múltiplos de i (prueba cambiando el valor de i a \(2,3,4,5,6,7\) y observa el resultado):

i = 3
[j for j in range(i*2, 50, i)]
[6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48]

Ahora, para variar el valor de i en el conjunto \(\{2,3,4,5,6,7\}\) con una lista concisa se puede hacer lo siguiente:

[i for i in range(2,8)]
[2, 3, 4, 5, 6, 7]

Usando las dos listas concisas creadas antes, generamos todos aquellos números en el intervalo \([2,50]\) que tienen al menos un múltiplo (y que por lo tanto no son primos)

noprimos = [j for i in range(2,8) for j in range(i*2, 50, i)]
print('NO primos: \n{}'.format(noprimos))
NO primos: 
[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 10, 15, 20, 25, 30, 35, 40, 45, 12, 18, 24, 30, 36, 42, 48, 14, 21, 28, 35, 42, 49]

Para encontrar los primos usamos una lista concisa verificando los números que faltan en la lista de noprimos, esos serán los números primos que estamos buscando:

primos = [x for x in range(2,50) if x not in noprimos]
print('Primos: \n{}'.format(primos))
Primos: 
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Juntando todo:

[x for x in range(2,50) if x not in [j for i in range(2,8) for j in range(i*2, 50, i)]]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

R.1.2 Listas concisas con elementos no numéricos.

Las listas también pueden contener otro tipo de elementos, no solo números. Por ejemplo:

mensaje = 'La vida no es la que uno vivió, sino la que uno recuerda'
print(mensaje)
La vida no es la que uno vivió, sino la que uno recuerda
palabras = mensaje.split()
print(palabras,end='')
['La', 'vida', 'no', 'es', 'la', 'que', 'uno', 'vivió,', 'sino', 'la', 'que', 'uno', 'recuerda']

Vamos a crear una lista cuyos elementos contienen cada palabra de la lista anterior en mayúsculas, en forma de título y su longitud, estos tres elementos agregados en una tupla:

tabla = [(w.upper(), w.title(), len(w)) for w in palabras]
print(tabla)
[('LA', 'La', 2), ('VIDA', 'Vida', 4), ('NO', 'No', 2), ('ES', 'Es', 2), ('LA', 'La', 2), ('QUE', 'Que', 3), ('UNO', 'Uno', 3), ('VIVIÓ,', 'Vivió,', 6), ('SINO', 'Sino', 4), ('LA', 'La', 2), ('QUE', 'Que', 3), ('UNO', 'Uno', 3), ('RECUERDA', 'Recuerda', 8)]

R.2 Conjuntos concisos

Al igual que las listas concisas, también es posible crear conjuntos usando los mismos principios , la única diferencia es que la secuencia que resulta es un objeto de tiposet.

Definición.

{expression(variable) for variable in input_set [predicate][, …]}
  1. expression : Es una expresión opcional de salida que produce los miembros del nuevo conjunto a partir de los miembros del conjunto de entrada que satisfacen el predicate.

  2. variable : Es una variable requerida que representa los miembros del conjunto de entrada.

  3. input_set: Representa la secuencia de entrada. (requerido).

  4. predicate : Expresión opcional que actúa como un filtro sobre los miembros del conjunto de entrada.

  5. [, …] : Otra comprehension anidada opcional.

Ejemplo R.8:

Supongamos que deseamos organizar una lista de nombres de tal manera que no haya repeticiones, que los nombres tengan más de un caracter y que su representación sea con la primera letra mayúscula y las demás minúsculas. Por ejemplo, una lista aceptable sería ['Luis', 'Juan', 'Angie', 'Pedro', 'María', 'Diana'].

  • Leer una lista de nombres del archivo nombres.txt y procesarlos para obtener una lista similar a la descrita.
# Abrimos el archivo en modo lectura
archivo = open('./nombres.txt','r')

# Leemos la lista de nombres y los ponemos en una lista
lista_nombres = archivo.read().split()

# Vemos la lista de nombres
print(lista_nombres)
['A', 'LuCas', 'Sidronio', 'Michelle', 'a', 'ANGIE', 'Luis', 'lucas', 'MICHelle', 'PedrO', 'PEPE', 'Manu', 'luis', 'diana', 'sidronio', 'pepe', 'a', 'a', 'b']
# Procesamos las palabras como se requiere
nombres_set = {nombre[0].upper() + nombre[1:].lower() 
               for nombre in lista_nombres 
               if len(nombre) > 1 }
print(nombres_set)
{'Pedro', 'Pepe', 'Lucas', 'Angie', 'Michelle', 'Manu', 'Sidronio', 'Diana', 'Luis'}
# Transformamos el conjunto a una lista
nombres = list(nombres_set)
print(nombres)

.

Ejemplo R.9:

Observa los siguientes ejemplos de conjuntos concisos y explica su funcionamiento.

{s for s in [1, 2, 1, 0]}
{0, 1, 2}
{s**2 for s in [1, 2, 1, 0]}
{0, 1, 4}
{s**2 for s in range(10)}
{0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
{s for s in range(10) if s % 2}
{1, 3, 5, 7, 9}
{(m, n) for n in range(2) for m in range(3, 5)}
{(3, 0), (3, 1), (4, 0), (4, 1)}

R.3 Diccionarios concisos

  • Similar a las listas y conjuntos concisos, es posible crear un diccionario de manera concisa.

  • Permite transformar un diccionario en otro diccionario.

  • Durante esta transformación, los objetos dentro del diccionario original pueden ser incluidos o no en el nuevo diccionario dependiendo de una condición.

  • Cada objeto en el nuevo diccionario puede ser transformado como sea requerido.

Definición.

Creación de un diccionario a partir de una secuencia:

{__:__ for x in secuencia if condición}

Creación de un diccionario a partir de los valores de otro diccionario:

{key:value for (key,value) in dictonary.items() if condición}
Ejemplo R.10:

Crear un diccionario a partir de un rango de enteros.

{str(x):x for x in range(0,5)}
{'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}
{str(x):x for x in range(0,10) if x % 2}
{'1': 1, '3': 3, '5': 5, '7': 7, '9': 9}
{str(x):x for x in range(0,10) if not x % 2}
{'0': 0, '2': 2, '4': 4, '6': 6, '8': 8}

.

Ejemplo R.11:

Multiplicar por \(2\) el valor (value) de cada entrada (item) de un diccionario:

Recuerda como funcionan los diccionarios:

dicc = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
print(dicc.keys())   # Función para obtener las claves
print(dicc.values()) # Función para obtener los valores
print(dicc.items())  # Función para obtener los items
dict_keys(['a', 'b', 'c', 'd'])
dict_values([1, 2, 3, 4])
dict_items([('a', 1), ('b', 2), ('c', 3), ('d', 4)])

Para crear el diccionario del ejemplo hacemos lo siguiente:

# Definición del diccionario
dicc = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

# Multiplicación por 2 de los valores del diccionario
dicc_doble = {k:v*2 for (k,v) in dicc.items()}

# Mostramos el resultado
print(dicc)
print(dicc_doble)
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
{'a': 2, 'b': 4, 'c': 6, 'd': 8, 'e': 10}

.

Ejemplo R.12:

Duplicar la clave (key) de cada entrada (item) del diccionario dicc del ejemplo anterior:

print(dicc)
dict1_keys = {k*2:v for (k,v) in dicc.items()}
print(dict1_keys)
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
{'aa': 1, 'bb': 2, 'cc': 3, 'dd': 4, 'ee': 5}

.

Ejemplo R.13:

Crear un diccionario donde la clave sea un número divisible por 2 en un rango de 0 a 10 y sus valores sean el cuadrado de la clave.

# La forma tradicional
dicc = {} # Diccionario vacio

for n in range(11):
    if n%2==0:
        dicc[n] = n**2 # Agregamos los elementos

print(dicc)
{0: 0, 2: 4, 4: 16, 6: 36, 8: 64, 10: 100}
# Usando dict comprehensions
dicc_smart = {n:n**2 for n in range(11) if n%2 == 0}

print(dicc_smart)
{0: 0, 2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

.

Ejemplo R.14:

Intercambiar las claves y los valores en un diccionario.

a_dict = {'a': 1, 'b': 2, 'c': 3}
print(a_dict)

{value:key for key, value in a_dict.items()}
{'a': 1, 'b': 2, 'c': 3}
{1: 'a', 2: 'b', 3: 'c'}
# OJO: No siempre es posible hacer lo anterior.
a_dict = {'a': [1, 2, 3], 'b': 4, 'c': 5}
{value:key for key, value in a_dict.items()}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[41], line 3
      1 # OJO: No siempre es posible hacer lo anterior.
      2 a_dict = {'a': [1, 2, 3], 'b': 4, 'c': 5}
----> 3 {value:key for key, value in a_dict.items()}

TypeError: unhashable type: 'list'

.

Ejemplo R.15:

Convertir el siguiente diccionario que contiene valores de grados Fahrenheit {'t1':32.0, 't2':72.5, 't3':104.0, 't4':212.0} a otro diccionario que contenga los correspondientes valores en grados Celsius.

# Diccionario con grados Farenheit
fahrenheit_dict = {'t1':32.0, 't2':72.5, 't3':104.0, 't4':212.0}

# Transformación usando dict comprehensions !
celsius_smart = {k:(5/9)*(v-32) for (k,v) in fahrenheit_dict.items()}

print(fahrenheit_dict)
print(celsius_smart)
{'t1': 32.0, 't2': 72.5, 't3': 104.0, 't4': 212.0}
{'t1': 0.0, 't2': 22.5, 't3': 40.0, 't4': 100.0}

.

Ejemplo R.16:

Dado un diccionario, cuyos valores son enteros, crear un nuevo diccionario cuyos valores sean mayores que 2.

a_dict = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6, 'g':7, 'h':8}
print(a_dict)

a_dict_cond = { k:v for (k,v) in a_dict.items() if v > 2 }
print(a_dict_cond)
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8}
{'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8}

.

Ejemplo R.17:

Dado un diccionario, cuyos valores son enteros, crear un nuevo diccionario cuyos valores sean mayores que 2 y que además sean pares.

a_dict_cond2 = { k:v for (k,v) in a_dict.items() if (v > 2) and (v % 2) == 0}
print(a_dict_cond2)
{'d': 4, 'f': 6, 'h': 8}

.

Ejemplo R.18:

Dado un diccionario, cuyos valores son enteros, crear un nuevo diccionario cuyos valores sean mayores que 2 y que además sean pares y divisibles por 3.

# La forma tradicional
a_dict_cond3_loop = {}

for (k,v) in a_dict.items():
    if (v>=2 and v%2 == 0 and v%3 == 0):
        a_dict_cond3_loop[k] = v

print(a_dict_cond3_loop)
{'f': 6}
# Usando dict comprehensions
a_dict_cond3 = {k:v for (k,v) in a_dict.items() if v>2 if v%2 == 0 if v%3 == 0}

print(a_dict_cond3)
{'f': 6}

.

Ejemplo R.19:

Apartir de un diccionario con valores enteros, identificar los valores pares y los impares, y sustituir los valores por etiquetas par e impar segun corresponda.

print(a_dict) 

# usamos el diccionario a_dict como entrada
a_dict_else = { k:('par' if v%2==0 else 'impar') for (k,v) in a_dict.items()}

print(a_dict_else)
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8}
{'a': 'impar', 'b': 'par', 'c': 'impar', 'd': 'par', 'e': 'impar', 'f': 'par', 'g': 'impar', 'h': 'par'}

.

Ejemplo R.20:

Dado el siguiente diccionario:

adic = {'primero':{'a':1}, 'segundo':{'b':2}, 'tercero':{'c':3}}

Crear el siguiente nuevo diccionario:

{'primero': {'a': 3.1415}, 'segundo': {'b': 6.283}, 'tercero': {'c': 9.4245}}

Observa que los valores de los diccionarios internos (3.1415, 6.283, 9.4245) se obtienen múltiplicando \(3.1416\) por el valor de cada item de esos diccionarios.

# La forma tradicional sería:
adic = {'primero':{'a':1}, 'segundo':{'b':2}, 'tercero':{'c':3}}
print(adic)
pi = 3.1415

for (ek, ev) in adic.items():
    for (ik, iv) in ev.items():
        ev.update({ik: iv * pi})

print(adic)
{'primero': {'a': 1}, 'segundo': {'b': 2}, 'tercero': {'c': 3}}
{'primero': {'a': 3.1415}, 'segundo': {'b': 6.283}, 'tercero': {'c': 9.4245}}
# con dict comprehensions
adic = {'primero':{'a':1}, 'segundo':{'b':2}, 'tercero':{'c':3}}
pi = 3.1415
bdic = {e_k:{i_k:i_v*pi for (i_k, i_v) in e_v.items()} for (e_k, e_v) in adic.items()}

print(adic)
print(bdic)
{'primero': {'a': 1}, 'segundo': {'b': 2}, 'tercero': {'c': 3}}
{'primero': {'a': 3.1415}, 'segundo': {'b': 6.283}, 'tercero': {'c': 9.4245}}

.

Ejemplo R.21:

Es posible usar las listas y diccionarios concisos para revisar la lista de archivos de un directorio y sus características.

# importamos módulos con herramientas para el sistema operativo
import os, glob

# Creamos una lista concisa con datos de los archivos
metadata = [(f, os.stat(f)) for f in glob.glob('*.ipynb')]

for i in metadata:
    print(i, end=2*'\n')
('01_variables_objetos.ipynb', os.stat_result(st_mode=33206, st_ino=2533274790608036, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=30633, st_atime=1767130620, st_mtime=1767130620, st_ctime=1763601907))

('02_tipos_basicos.ipynb', os.stat_result(st_mode=33206, st_ino=15481123719298213, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=25772, st_atime=1767128278, st_mtime=1767128278, st_ctime=1763601907))

('03_operadores.ipynb', os.stat_result(st_mode=33206, st_ino=4222124650871975, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=30352, st_atime=1767056922, st_mtime=1767056922, st_ctime=1763601907))

('04_expresiones_declaraciones.ipynb', os.stat_result(st_mode=33206, st_ino=9007199254953128, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=8717, st_atime=1767129058, st_mtime=1767129058, st_ctime=1763601907))

('05_cadenas.ipynb', os.stat_result(st_mode=33206, st_ino=7318349394689194, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=53784, st_atime=1767216927, st_mtime=1767216927, st_ctime=1763601907))

('06_input.ipynb', os.stat_result(st_mode=33206, st_ino=6755399441267885, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=10667, st_atime=1767139321, st_mtime=1767139321, st_ctime=1763601907))

('07_archivos.ipynb', os.stat_result(st_mode=33206, st_ino=10696049115451108, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=14201, st_atime=1767139722, st_mtime=1767139722, st_ctime=1767137418))

('08_control_de_flujo.ipynb', os.stat_result(st_mode=33206, st_ino=10977524091927728, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=33684, st_atime=1767211604, st_mtime=1767211604, st_ctime=1763601907))

('09_listas.ipynb', os.stat_result(st_mode=33206, st_ino=8162774324821170, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=44943, st_atime=1767297525, st_mtime=1767297525, st_ctime=1763601907))

('10_tuplas.ipynb', os.stat_result(st_mode=33206, st_ino=16325548649430195, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=16459, st_atime=1767297534, st_mtime=1767297534, st_ctime=1763601907))

('11_conjuntos.ipynb', os.stat_result(st_mode=33206, st_ino=6192449487846580, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=13580, st_atime=1767297544, st_mtime=1767297544, st_ctime=1763601907))

('12_diccionarios.ipynb', os.stat_result(st_mode=33206, st_ino=9570149208374453, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=16883, st_atime=1767297558, st_mtime=1767297558, st_ctime=1763601907))

('13_ds_casting.ipynb', os.stat_result(st_mode=33206, st_ino=21673573206932664, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=10287, st_atime=1767220207, st_mtime=1767220207, st_ctime=1763601907))

('14_ds_traversing.ipynb', os.stat_result(st_mode=33206, st_ino=6192449487846593, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=15774, st_atime=1767220210, st_mtime=1767220210, st_ctime=1763601907))

('15_funciones.ipynb', os.stat_result(st_mode=33206, st_ino=7318349394689222, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=15687, st_atime=1767299183, st_mtime=1767299183, st_ctime=1763601907))

('16_lambda_expressions.ipynb', os.stat_result(st_mode=33206, st_ino=7036874417978573, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=16158, st_atime=1767300195, st_mtime=1767300195, st_ctime=1763601907))

('17_excepciones.ipynb', os.stat_result(st_mode=33206, st_ino=7599824371399886, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=33923, st_atime=1767300714, st_mtime=1767300714, st_ctime=1763601907))

('18_comprehensions.ipynb', os.stat_result(st_mode=33206, st_ino=10696049115217108, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=41024, st_atime=1767301989, st_mtime=1767301989, st_ctime=1763601907))

('19_iterables_map_filter_reduce.ipynb', os.stat_result(st_mode=33206, st_ino=6192449487846613, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=36760, st_atime=1767301917, st_mtime=1767301917, st_ctime=1763601907))

('20_decoradores.ipynb', os.stat_result(st_mode=33206, st_ino=7318349394689239, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=17950, st_atime=1763601907, st_mtime=1763601907, st_ctime=1763601907))

('21_iteradores_generadores.ipynb', os.stat_result(st_mode=33206, st_ino=11258999068638430, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=18672, st_atime=1763601907, st_mtime=1763601907, st_ctime=1763601907))

('22_funciones_y_docstring.ipynb', os.stat_result(st_mode=33206, st_ino=12384898975481058, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=35285, st_atime=1763601907, st_mtime=1763601907, st_ctime=1763601907))

('23_import.ipynb', os.stat_result(st_mode=33206, st_ino=6473924464557284, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=20361, st_atime=1767051444, st_mtime=1767051444, st_ctime=1763601907))

('Untitled.ipynb', os.stat_result(st_mode=33206, st_ino=3377699721426515, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=72, st_atime=1767137403, st_mtime=1767137403, st_ctime=1767137403))
metadata_dict = {f:os.stat(f) for f in glob.glob('*.ipynb')}
for i in metadata_dict.keys():
    print(i)
01_variables_objetos.ipynb
02_tipos_basicos.ipynb
03_operadores.ipynb
04_expresiones_declaraciones.ipynb
05_cadenas.ipynb
06_input.ipynb
07_archivos.ipynb
08_control_de_flujo.ipynb
09_listas.ipynb
10_tuplas.ipynb
11_conjuntos.ipynb
12_diccionarios.ipynb
13_ds_casting.ipynb
14_ds_traversing.ipynb
15_funciones.ipynb
16_lambda_expressions.ipynb
17_excepciones.ipynb
18_comprehensions.ipynb
19_iterables_map_filter_reduce.ipynb
20_decoradores.ipynb
21_iteradores_generadores.ipynb
22_funciones_y_docstring.ipynb
23_import.ipynb
Untitled.ipynb
for i in metadata_dict.values():
    print(i, end=2*'\n')
os.stat_result(st_mode=33206, st_ino=2533274790608036, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=30633, st_atime=1767130620, st_mtime=1767130620, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=15481123719298213, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=25772, st_atime=1767128278, st_mtime=1767128278, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=4222124650871975, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=30352, st_atime=1767056922, st_mtime=1767056922, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=9007199254953128, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=8717, st_atime=1767129058, st_mtime=1767129058, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=7318349394689194, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=53784, st_atime=1767216927, st_mtime=1767216927, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=6755399441267885, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=10667, st_atime=1767139321, st_mtime=1767139321, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=10696049115451108, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=14201, st_atime=1767139722, st_mtime=1767139722, st_ctime=1767137418)

os.stat_result(st_mode=33206, st_ino=10977524091927728, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=33684, st_atime=1767211604, st_mtime=1767211604, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=8162774324821170, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=44943, st_atime=1767297525, st_mtime=1767297525, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=16325548649430195, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=16459, st_atime=1767297534, st_mtime=1767297534, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=6192449487846580, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=13580, st_atime=1767297544, st_mtime=1767297544, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=9570149208374453, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=16883, st_atime=1767297558, st_mtime=1767297558, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=21673573206932664, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=10287, st_atime=1767220207, st_mtime=1767220207, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=6192449487846593, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=15774, st_atime=1767220210, st_mtime=1767220210, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=7318349394689222, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=15687, st_atime=1767299183, st_mtime=1767299183, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=7036874417978573, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=16158, st_atime=1767300195, st_mtime=1767300195, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=7599824371399886, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=33923, st_atime=1767300714, st_mtime=1767300714, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=10696049115217108, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=41024, st_atime=1767301989, st_mtime=1767301989, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=6192449487846613, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=36760, st_atime=1767301917, st_mtime=1767301917, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=7318349394689239, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=17950, st_atime=1763601907, st_mtime=1763601907, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=11258999068638430, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=18672, st_atime=1763601907, st_mtime=1763601907, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=12384898975481058, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=35285, st_atime=1763601907, st_mtime=1763601907, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=6473924464557284, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=20361, st_atime=1767051444, st_mtime=1767051444, st_ctime=1763601907)

os.stat_result(st_mode=33206, st_ino=3377699721426515, st_dev=4933377520409029438, st_nlink=1, st_uid=0, st_gid=0, st_size=72, st_atime=1767137403, st_mtime=1767137403, st_ctime=1767137403)
metadata_dict['18_comprehensions.ipynb'].st_size
41024

R.4 Ejemplos adicionales.

Ejemplo R.22:

Eliminar los números duplicados de la siguiente lista.

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
numeros
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
# Una manera es:
numeros_unicos = []
for n in numeros:
    if n not in numeros_unicos:
        numeros_unicos.append(n)
numeros_unicos
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Otra forma mas pythonica!
numeros_unicos_easy = list(set(numeros))
numeros_unicos_easy
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

.

Ejemplo R.23:

Eliminar objetos duplicados de una lista de diccionarios.

datos = [
  {'id': 10, 'nombre': 'luis', 'edad':25},
  {'id': 11, 'nombre': 'eva', 'edad':34},
  {'id': 12, 'nombre': 'gabo', 'edad':53},
  {'id': 13, 'nombre': 'rubén', 'edad':27},
  {'id': 14, 'nombre': 'juan', 'edad':29},
  {'id': 12, 'nombre': 'gabo', 'edad':53},
  {'id': 11, 'nombre': 'eva', 'edad':34},
  {'id': 12, 'nombre': 'gabo', 'edad':53},
  {'id': 13, 'nombre': 'rubén', 'edad':27},
  {'id': 14, 'nombre': 'juan', 'edad':29},
]

print(datos)
[{'id': 10, 'nombre': 'luis', 'edad': 25}, {'id': 11, 'nombre': 'eva', 'edad': 34}, {'id': 12, 'nombre': 'gabo', 'edad': 53}, {'id': 13, 'nombre': 'rubén', 'edad': 27}, {'id': 14, 'nombre': 'juan', 'edad': 29}, {'id': 12, 'nombre': 'gabo', 'edad': 53}, {'id': 11, 'nombre': 'eva', 'edad': 34}, {'id': 12, 'nombre': 'gabo', 'edad': 53}, {'id': 13, 'nombre': 'rubén', 'edad': 27}, {'id': 14, 'nombre': 'juan', 'edad': 29}]
# La forma tradicional
objetos_unicos = []
for d in datos:
    dato_existe = False
    for ou in objetos_unicos:
        if ou['id'] == d['id']:
          dato_existe = True
          break
    if not dato_existe:
        objetos_unicos.append(d)

for i in objetos_unicos:
    print(i)
{'id': 10, 'nombre': 'luis', 'edad': 25}
{'id': 11, 'nombre': 'eva', 'edad': 34}
{'id': 12, 'nombre': 'gabo', 'edad': 53}
{'id': 13, 'nombre': 'rubén', 'edad': 27}
{'id': 14, 'nombre': 'juan', 'edad': 29}
# Una mejor manera.
objetos_unicos_easy = { d['id']:d for d in datos }.values()

for i in objetos_unicos_easy:
    print(i)
{'id': 10, 'nombre': 'luis', 'edad': 25}
{'id': 11, 'nombre': 'eva', 'edad': 34}
{'id': 12, 'nombre': 'gabo', 'edad': 53}
{'id': 13, 'nombre': 'rubén', 'edad': 27}
{'id': 14, 'nombre': 'juan', 'edad': 29}

.

Ejemplo R.24:

Considera el siguiente diccionario:

mcase = {'z':23, 'a':30, 'b':21, 'A':78, 'Z':4, 'C':43, 'B':89}
  • Sumar los valores que corresponden a la misma letra, sin importar si es mayúscula o minúscula.

  • Construir un diccionario cuyas claves sean solo letras minúsculas y sus valores sean la suma antes calculada.

mcase = {'z':23, 'a':30, 'b':21, 'A':78, 'Z':4, 'C':43, 'B':89}
mcase_freq = {k.lower() : 
              mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
              for k in mcase.keys()}
print(mcase_freq)
{'z': 27, 'a': 108, 'b': 110, 'c': 43}