Este tutorial adapta pedagógicamente el Día 26. Las secciones 📝 Ejercicio original del curso provienen de los archivos del curso. Los retos 🟢🟡🟠🔴 y el proyecto extra son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.
Nota sobre las verificaciones: los ejemplos se ejecutaron con Python 3.14 y pandas 3.0.6. El archivo
nato_phonetic_alphabet.csvdel curso no está en la carpeta; se usó una versión reducida con las columnasletterycode, que son las que nombra la lección202. Los puntajes aleatorios de la lección199cambian en cada ejecución, así que los tuyos no coincidirán con los de este tutorial.
Nota sobre los ejercicios de práctica: la lección
197menciona una serie de ejercicios de código ("flexiones de código") sobre comprensiones. Esos ejercicios no están en la carpeta, así que no se reproducen aquí. En su lugar, cada tema incluye retos creados para esta adaptación.
Tabla de contenidos
- Antes de empezar
- Comprensión de listas
- Comprensión de listas condicional
- Aplicarlo al juego de los estados
- Comprensión de diccionarios
- Recorrer un DataFrame de pandas con
iterrows - 🚀 Proyecto del día: el deletreador con el alfabeto de la OTAN
- 🌟 Proyecto extra: el codificador Morse de la emisora escolar
- 🧩 Comprueba lo aprendido
- 🤖 Programar con apoyo de IA
- 🛠️ Correcciones técnicas al material original
- 📋 Matriz de trazabilidad
- 📦 Evidencias de aprendizaje del Día 26
0. Antes de empezar
(Fuente: 196 - Day 26 Goals- what you will make by the end of the day.md)
Hoy aprenderemos las comprensiones de listas y de diccionarios. El curso las presenta como una característica muy propia de Python que reduce mucho el código cuando trabajamos con listas y diccionarios.
El proyecto del día surge de un problema real: cuando deletreas tu nombre por teléfono, la otra persona puede confundir letras que suenan parecido (¿dijiste B o V? ¿M o N?). El alfabeto fonético de la OTAN asigna una palabra a cada letra: A de Alfa, N de November, G de Golf… Construiremos un programa de consola que recibe una palabra y devuelve la lista de palabras clave para deletrearla.
💡 Para pensar: ¿dónde has tenido que deletrear algo? En una llamada al banco, al dictar tu correo electrónico, al dar el número de una placa… En Colombia es común decir "B de burro" o "V de vaca". El alfabeto OTAN es la versión estandarizada internacionalmente.
Prerequisito general: listas y
append(Día 4), buclesforyrange(Día 5), diccionarios y.items()(Día 9), métodos de strings como.upper()(Día 8),random.randint(Día 4), pandas,read_csvy DataFrames (Día 25) y el juego de los estados (Día 25).
1. Comprensión de listas
(Fuente: 197 - How to Create Lists using List Comprehension.md)
🎯 Objetivo de aprendizaje
- Crear una lista nueva a partir de otra secuencia en una sola línea.
- Leer una comprensión de listas usando el patrón de palabras clave del curso.
🧠 ¿Qué aprenderemos?
Una comprensión de listas (list comprehension) es una forma corta de crear una lista nueva a partir de otra secuencia. Hasta hoy lo hacíamos con un bucle for y append.
📖 Explicación conceptual
El problema: tenemos [1, 2, 3] y queremos una lista con cada número aumentado en 1.
Con lo que ya sabemos (4 líneas):
numbers = [1, 2, 3]
new_list = []
for n in numbers:
add_1 = n + 1
new_list.append(add_1)
# new_list → [2, 3, 4]Con una comprensión (1 línea):
new_numbers = [n + 1 for n in numbers] # [2, 3, 4] (verificado)El método de palabras clave del curso. Angela recomienda escribir primero el patrón con palabras genéricas y luego reemplazarlas una por una:
new_list = [new_item for item in list]| Palabra clave | ¿Qué es? | En el ejemplo |
|---|---|---|
list |
La secuencia que vamos a recorrer | numbers |
item |
El nombre que le damos a cada elemento (cualquiera, pero úsalo igual en todo el patrón) | n |
new_item |
La expresión que calcula cada elemento de la lista nueva | n + 1 |
Orden de lectura sugerido: empieza por la parte de la derecha ("para cada n en numbers") y termina por la izquierda ("agrega n + 1").
No solo con listas. El nombre dice "listas", pero funciona con cualquier secuencia: strings, range, tuplas… El curso lo explica así: estas estructuras tienen un orden, y la comprensión las recorre en ese orden.
💡 Consejo del curso: para practicar, usa la consola de Python de PyCharm en lugar de
main.py. Ahí escribes línea por línea y ves el valor de cada variable en el panel de la derecha. El curso incluso muestra cómo corregir un valor desde ese panel (clic derecho → Set Value).
📝 Ejercicio original del curso 1: las letras de un nombre
Enunciado: con name = "Angela", ¿qué contendrá esta lista? Piensa la respuesta antes de ejecutarla.
name = "Angela"
letters_list = [letter for letter in name]Ver resultado
['A', 'n', 'g', 'e', 'l', 'a'] (verificado). El new_item es la misma letra, sin modificar: la comprensión simplemente separa el string en letras.
📝 Ejercicio original del curso 2: duplicar un rango
Enunciado: usando range(1, 5), crea range_list en la que cada número esté multiplicado por 2. El resultado debe ser [2, 4, 6, 8].
Pista del curso: recuerda que range(1, 5) va de 1 a 4; el 5 no se incluye.
🔍 Antes de programar
- ¿Cuál es la
listen este caso? (Pista: no es una lista.) - ¿Qué nombre le darás a cada
item? - ¿Qué expresión produce cada
new_item?
⚠️ Errores frecuentes
| Error | Qué ocurre | Solución |
|---|---|---|
Usar paréntesis: (n + 1 for n in numbers) |
No obtienes una lista, sino un "generador" que se imprime como <generator object ...> |
Las comprensiones de listas van entre corchetes [ ] |
Nombres distintos: [num + 1 for n in numbers] |
NameError: name 'num' is not defined |
Usa el mismo nombre en new_item y en item |
Olvidar asignar el resultado: [n + 1 for n in numbers] sola en un archivo |
La lista se crea y se pierde | Guárdala en una variable: new_numbers = [...] |
Pensar que range(1, 5) incluye el 5 |
Resultado con un elemento de menos o de más | El final de range no se incluye |
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1 — Aplicación: con
temperaturas_c = [12, 18, 25, 31], createmperaturas_fconvirtiendo cada valor a Fahrenheit (c * 9 / 5 + 32). - 🟡 Reto 2 — Ampliación: con
frase = "Python es genial", crea una lista con la longitud de cada palabra. (Pista: primero convierte la frase en una lista de palabras con un método de strings que ya conoces.) - 🟠 Reto 3 — Desafío: con
notas = ["4.5", "3.2", "2.8"](strings, como si vinieran de un archivo), crea una lista de números decimales y calcula el promedio en la línea siguiente. - 🔴 Reto 4 — Pensamiento computacional: tienes una lista con los nombres de los estudiantes del curso, escritos de cualquier manera (
" ana maría ","CARLOS","luisa"). Diseña una comprensión que los deje todos limpios y con mayúscula inicial. Luego explica: ¿qué pasa con un nombre como"maría josé de la hoz"si usas.title()? ¿Es un resultado aceptable?
2. Comprensión de listas condicional
(Fuente: 197 - How to Create Lists using List Comprehension.md, segunda parte)
🎯 Objetivo de aprendizaje
- Filtrar elementos de una secuencia dentro de una comprensión.
- Combinar filtro y transformación en la misma línea.
📖 Explicación conceptual
El patrón se amplía con dos palabras clave más: if y una prueba (test).
new_list = [new_item for item in list if test]El new_item solo se agrega si la prueba da True.
Ejemplo del curso: nombres cortos (4 letras o menos).
names = ["Alex", "Beth", "Caroline", "Dave", "Eleanor", "Freddie"]
short_names = [name for name in names if len(name) < 5]
# ['Alex', 'Beth', 'Dave'] (verificado)Cómo se ejecuta: Python recorre cada name; revisa si len(name) < 5; si se cumple, agrega name (sin modificar) a la lista nueva.
Detalle del curso: en la lista original había un error de escritura, "Elanor", y Angela lo corrige desde el panel de variables de la consola. El nombre correcto es "Eleanor".
📝 Ejercicio original del curso: nombres largos en mayúsculas
Enunciado: con la misma lista names, crea long_names con los nombres de 5 letras o más, convertidos a mayúsculas. Resultado esperado: ['CAROLINE', 'ELEANOR', 'FREDDIE'].
🔍 Antes de programar
- ¿Qué parte del patrón hace el filtro? ¿Qué parte hace la transformación?
- "5 letras o más" se escribe
len(name) >= 5olen(name) > 4. ¿Da lo mismolen(name) > 5? (Ver la nota técnica.)
🛠️ Nota técnica: en la solución del curso la prueba es
len(name) > 5, aunque el enunciado dice "5 letras o más". Con esta lista el resultado es el mismo, porque ningún nombre tiene exactamente 5 letras. Pero si agregas"Bruno"a la lista,> 5lo deja por fuera y>= 5lo incluye. Lección: prueba siempre los casos límite.
⚠️ Errores frecuentes
| Error | Qué ocurre | Solución |
|---|---|---|
Poner el if antes del for: [name if len(name) < 5 for name in names] |
SyntaxError |
Para filtrar, el if va al final |
Confundir < con <= |
Se pierden o sobran los casos límite | Escribe un caso de prueba con el valor exacto del límite |
Transformar en la prueba: if len(name.upper()) > 5 esperando mayúsculas |
La lista sale sin cambios | La transformación va en new_item, la prueba solo decide si entra |
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: con
numeros = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55], crea una lista solo con los pares. - 🟡 Reto 2: con una lista de correos
["ana@colegio.edu.co", "luis@gmail.com", "sofi@colegio.edu.co"], obtén solo el usuario (lo que va antes de@) de los correos institucionales. - 🟠 Reto 3: con
notas = {"Ana": 4.2, "Luis": 2.9, "Sofía": 3.0}, crea una lista con los nombres de quienes aprobaron (nota ≥ 3.0). (Pista: puedes recorrernotas.items().) - 🔴 Reto 4 — Pensamiento computacional: dos listas,
inscritos_futboleinscritos_robotica. Con una comprensión, obtén quiénes están en ambos clubes. Luego obtén quiénes están solo en robótica. ¿Qué pasa si un nombre está escrito con mayúscula en una lista y en minúscula en la otra? Propón una solución.
3. Aplicarlo al juego de los estados
(Fuente: 198 - Apply List Comprehension to the U.S. States Game.md)
📝 Ejercicio original del curso
Enunciado: abre tu juego de los estados de EE. UU. (Día 25). En la parte donde el usuario escribe exit, reemplaza el bucle que construye missing_states por una comprensión de listas y reduce el código en 3 o 4 líneas.
El código del Día 25:
missing_states = []
for state in all_states:
if state not in guessed_states:
missing_states.append(state)🔍 Antes de programar
- ¿Cuál es la
list? ¿Cuál es elitem? - ¿Cuál es la prueba?
- ¿El
new_itemse modifica o queda igual?
Solución del curso (en palabras): la lista es all_states, cada elemento es un state, la prueba es state not in guessed_states y el nuevo elemento es el mismo state.
Reflexión del curso: la línea nueva no solo es más corta, también se lee casi como una frase: "agrega cada estado de todos los estados si no está entre los adivinados".
💡 Conexión: en el tutorial del Día 25 se anunció esta mejora. Si hiciste el proyecto extra de los departamentos de Colombia, aplica el mismo cambio allí.
Reto adicional (creado para esta adaptación)
- 🟠 Reto: en el mismo juego, reescribe con comprensiones otras dos partes del código que usen un bucle para construir una lista. Si no encuentras ninguna, escribe una comprensión que produzca la lista de estados adivinados que empiezan por "New".
4. Comprensión de diccionarios
(Fuente: 199 - How to use Dictionary Comprehension.md)
🎯 Objetivo de aprendizaje
- Crear un diccionario a partir de una lista.
- Crear un diccionario filtrando otro diccionario.
📖 Explicación conceptual
La idea es la misma, pero ahora se crea un diccionario. Por eso se usan llaves { } y cada elemento es un par clave: valor.
Patrón 1 — desde una lista (o cualquier iterable):
new_dict = {new_key: new_value for item in list}Patrón 2 — desde otro diccionario:
new_dict = {new_key: new_value for (key, value) in dict.items()}Patrón 3 — con condición:
new_dict = {new_key: new_value for (key, value) in dict.items() if test}Recuerda (Día 9):
.items()es un método: lleva paréntesis. Devuelve cada par clave-valor para que lo separemos enkeyyvalue.
📝 Ejercicio original del curso 1: puntajes aleatorios
Enunciado: a partir de la lista de nombres, crea students_scores, un diccionario en el que cada estudiante tenga un puntaje aleatorio entre 1 y 100.
import random
names = ["Alex", "Beth", "Caroline", "Dave", "Eleanor", "Freddie"]
students_scores = {student: random.randint(1, 100) for student in names}
# Ejemplo de una ejecución: {'Alex': 18, 'Beth': 73, 'Caroline': 98, ...}Comentario del curso (con humor): "Profesores, espero que esta no sea la forma en que ponen las notas".
📝 Ejercicio original del curso 2: estudiantes que aprobaron
Enunciado: a partir de students_scores, crea passed_students con los estudiantes que obtuvieron 60 o más, conservando su puntaje.
🔍 Antes de programar
- ¿Por qué aquí se usa
.items()y en el ejercicio anterior no? - ¿Qué nombres vas a dar a la clave y al valor? (El curso usa
studentyscore.) - ¿La clave y el valor del diccionario nuevo cambian, o son los mismos?
Solución del curso (en palabras): recorrer students_scores.items() separando (student, score), conservar student: score y agregar la prueba if score >= 60.
⚠️ Errores frecuentes
| Error | Qué ocurre | Solución |
|---|---|---|
Olvidar los paréntesis: students_scores.items |
TypeError: 'builtin_function_or_method' object is not iterable |
.items() |
Recorrer el diccionario sin .items() y pedir dos variables |
ValueError: too many values to unpack (o recorre solo las claves) |
Usa for (key, value) in dict.items() |
| Usar corchetes en lugar de llaves | Se crea una lista, no un diccionario | Diccionario → { } |
Olvidar import random |
NameError: name 'random' is not defined |
Importa el módulo al inicio |
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: con
palabras = ["sol", "montaña", "río"], crea un diccionario{palabra: cantidad_de_letras}. - 🟡 Reto 2: con
precios_usd = {"cuaderno": 2.5, "lápiz": 0.4, "calculadora": 12}, creaprecios_copconvirtiendo a pesos colombianos. Consulta la tasa de cambio del día en una fuente confiable y cítala. - 🟠 Reto 3: con
temperaturas = {"lunes": 12, "martes": 14, ..., "domingo": 24}(en °C), crea en una línea un diccionario con los días de más de 20 °C, con la temperatura ya convertida a °F. - 🔴 Reto 4 — Pensamiento computacional: tienes
codigos = {"A": "Alfa", "B": "Bravo", ...}. Con una comprensión, crea el diccionario invertido ({"Alfa": "A", ...}). ¿Qué pasaría si dos claves tuvieran el mismo valor? Pruébalo y explica qué información se pierde.
5. Recorrer un DataFrame de pandas con iterrows
(Fuente: 200 - How to Iterate over a Pandas DataFrame.md)
🎯 Objetivo de aprendizaje
- Diferenciar recorrer las columnas de un DataFrame y recorrer sus filas.
- Usar
iterrows()para acceder a los datos de cada fila.
📖 Explicación conceptual
Partimos de un diccionario que ya conoces:
student_dict = {
"student": ["Angela", "James", "Lily"],
"score": [56, 76, 98],
}Recorrer un diccionario: for (key, value) in student_dict.items(): da las claves (student, score) y sus listas.
Un DataFrame se puede recorrer igual, porque en muchos aspectos se comporta como un diccionario:
import pandas
student_data_frame = pandas.DataFrame(student_dict)
for (key, value) in student_data_frame.items():
print(key) # student, score → ¡los NOMBRES DE LAS COLUMNAS!El curso señala que esto no es muy útil: recorre las columnas, y casi siempre queremos recorrer las filas. Para eso pandas tiene iterrows():
for (index, row) in student_data_frame.iterrows():
print(index) # 0, 1, 2
print(row.student) # Angela, James, Lily
print(row.score) # 56, 76, 98indexes el número de la fila (la primera columna que muestra pandas).rowes una Series de pandas (Día 25), así que puedes leer cada columna con notación de punto:row.student,row.score.
Ejemplo del curso: buscar el puntaje de Angela.
for (index, row) in student_data_frame.iterrows():
if row.student == "Angela":
print(row.score) # 56 (verificado)Recuerda (Día 25): la notación de punto no sirve si el nombre de la columna tiene espacios. En ese caso usa
row["nombre con espacios"].
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: con
student_data_frame, imprime una frase por estudiante:"Lily obtuvo 98". - 🟡 Reto 2: imprime solo los estudiantes con puntaje mayor que el promedio (calcula el promedio con un método de pandas del Día 25).
- 🟠 Reto 3: resuelve el Reto 2 sin
iterrows, filtrando el DataFrame como en el Día 25. ¿Cuál solución te parece más clara? ¿Cuál escribirías si el archivo tuviera un millón de filas? (Ver la nota técnica de la sección 6.) - 🔴 Reto 4: carga tu
mi_semana.csvdel Día 25 y, coniterrows, construye un diccionario{dia: condicion}. Luego busca cómo hacerlo siniterrows.
6. 🚀 Proyecto del día: el deletreador con el alfabeto de la OTAN
(Fuentes: 201 - Introducing the NATO Alphabet Project.md, 202 - Solution & Walkthrough for the NATO Alphabet Project.md)
Problema
Construir un programa de consola que pida una palabra y muestre la lista de palabras del alfabeto fonético de la OTAN que corresponden a cada letra.
Contexto
La anécdota del curso: al deletrear por teléfono, Angela a veces olvida el código y termina inventando cosas como "P de pneumonia" o "M de mnemonic", que empiezan con letras mudas y no sirven de nada. El alfabeto OTAN existe justamente para que nadie confunda una E con una B o una T con una C.
Archivos del proyecto inicial (según la lección 202)
| Archivo | Contenido |
|---|---|
nato_phonetic_alphabet.csv |
Columnas letter y code: cada letra y su palabra clave |
main.py |
Los ejemplos de recorrido de la lección 200 (diccionario y DataFrame) |
Requisitos funcionales
- Paso 1 (el más difícil, según el curso): convertir el CSV en un diccionario con este formato:
{"A": "Alfa", "B": "Bravo", ...}. - Paso 2: pedir una palabra y mostrar la lista de códigos, por ejemplo
THOMAS→['Tango', 'Hotel', 'Oscar', 'Mike', 'Alfa', 'Sierra']. - Aceptar la palabra en mayúsculas o minúsculas.
Restricciones técnicas
- Paso 1 con una comprensión de diccionario y
iterrows(). - Paso 2 con una comprensión de listas.
Planificación
- Entradas: el CSV y la palabra del usuario.
- Procesos: construir el diccionario; convertir la palabra a mayúsculas; buscar cada letra.
- Salida: una lista de palabras clave.
- Pregunta clave: ¿por qué no basta con
data.to_dict()?
Construcción paso a paso
Versión 1 — Leer el CSV y ver por qué to_dict() no sirve.
import pandas
data = pandas.read_csv("nato_phonetic_alphabet.csv")
print(data.to_dict())Resultado verificado con los datos de prueba:
{'letter': {0: 'A', 1: 'B'}, 'code': {0: 'Alfa', 1: 'Bravo'}}to_dict() organiza el diccionario por columnas: las claves son letter y code, y dentro están los índices. Nosotros queremos la letra como clave y el código como valor. Por eso el curso pide construirlo con una comprensión.
Versión 2 — El diccionario fonético (paso 1). Usa el patrón del curso y reemplaza cada palabra clave:
{new_key: new_value for (index, row) in df.iterrows()}🧩 Tu turno: ¿qué va en
new_key? ¿Qué va ennew_value? ¿Cómo se llama el DataFrame? (Consejo del curso: si te atascas, vuelve a los ejemplos demain.py, imprimeindexyrowy observa qué contienen.)
Cuando lo tengas, imprime el diccionario y compáralo con la salida de to_dict().
Versión 3 — Pedir la palabra (paso 2). Las claves del diccionario están en mayúsculas, así que la entrada también debe estarlo:
word = input("Enter a word: ").upper()Versión final — La lista de códigos. Con una comprensión de listas: la list es la palabra, cada item es una letra y el new_item es el valor del diccionario para esa letra (diccionario[letra]).
Solución del curso (en palabras): phonetic_dict = {row.letter: row.code for (index, row) in data.iterrows()} y output_list = [phonetic_dict[letter] for letter in word]. Consúltala solo después de intentarlo.
🛠️ Nota técnica (verificada):
iterrows()es cómodo para aprender, pero lento con tablas grandes. Una alternativa corta que produce el mismo diccionario esdict(zip(data.letter, data.code))(verificado). Ambas son válidas: la del curso practica comprensiones y la alternativa muestra otra herramienta de Python.
Pruebas
| Entrada | Resultado esperado |
|---|---|
angela |
['Alfa', 'November', 'Golf', 'Echo', 'Lima', 'Alfa'] |
THOMAS |
['Tango', 'Hotel', 'Oscar', 'Mike', 'Alfa', 'Sierra'] |
ana maria (con espacio) |
⚠️ ¿Qué pasa? (ver 🧪) |
Muñoz |
⚠️ ¿Qué pasa? (ver 🧪) |
1234 |
⚠️ ¿Qué pasa? (ver 🧪) |
🧪 Prueba y depuración
Ejecuta los tres últimos casos y anota el error. Verificación de esta adaptación:
- Con un espacio:
KeyError: ' '. El espacio no es una clave del diccionario. - Con
Muñoz:KeyError: 'Ñ'. El alfabeto OTAN tiene las 26 letras del inglés; la Ñ no está. Este problema afecta directamente a los nombres en español. - Con números:
KeyError: '1'.
Preguntas para depurar:
- ¿En qué línea exacta se produce el error? ¿Por qué ahí y no en el
input? - ¿Podrías filtrar las letras que no estén en el diccionario con la comprensión condicional de la sección 2? ¿Qué desventaja tiene ocultarle al usuario que parte de su palabra no se deletreó?
- ¿Qué código propondrías para la Ñ? (En el Día 30 volveremos a este proyecto y manejaremos estos errores con excepciones.)
⭐ Extensión del proyecto
- Aceptar frases: mostrar
(espacio)o una línea en blanco entre palabras. - Agregar al CSV los dígitos del 0 al 9 (el alfabeto OTAN también los tiene; investígalos y cita la fuente).
- Mostrar el resultado como un texto listo para leer:
"Alfa - November - Golf - ...". (Pista: el métodojoinde los strings; lo usaremos en el Día 29.)
7. 🌟 Proyecto extra: el codificador Morse de la emisora escolar
Situación
La emisora escolar quiere hacer una sección de "mensajes secretos" en código Morse. Necesitan una herramienta de consola que codifique un mensaje (texto → Morse) y lo decodifique (Morse → texto).
Requisitos
- Datos: construye
morse.csvcon las columnascaracterycodigopara las 26 letras y los 10 dígitos. Busca la tabla en una fuente confiable y cítala en un comentario del programa. - Diccionarios: con comprensiones, crea el diccionario para codificar (
{"A": ".-", ...}) y, a partir de él, el diccionario invertido para decodificar ({".-": "A", ...}). - Codificar: las letras se separan con un espacio y las palabras con
/. Ejemplo:"SOS AYUDA"→"... --- ... / .- -.-- ..- -.. .-". - Decodificar: el proceso inverso. (Pista:
split(" / ")y luegosplit(" ").) - Menú: el usuario elige
c(codificar),d(decodificar) os(salir). - Decisión que debes tomar: ¿qué haces con los caracteres que no están en la tabla (Ñ, tildes, signos)? ¿Los omites, los reemplazas (Ñ → N, Á → A) o avisas al usuario? Justifica tu elección en un comentario.
Restricciones técnicas
- Al menos tres comprensiones (de listas o de diccionarios), una de ellas condicional.
- Nada de
forconappendpara construir listas.
Casos de prueba
| Entrada | Modo | Esperado |
|---|---|---|
sos |
Codificar | ... --- ... |
... --- ... |
Decodificar | SOS |
hola mundo |
Codificar y luego decodificar el resultado | HOLA MUNDO |
Ñandú |
Codificar | Lo que decidiste en el requisito 6, sin que el programa se detenga con un error |
Reflexión
El código Morse y el alfabeto OTAN resuelven el mismo tipo de problema: transmitir información sin ambigüedad por un canal con ruido. ¿Qué otros sistemas conoces que resuelvan ese problema? (Piensa en códigos de barras, códigos QR, lenguaje de señas…)
8. 🧩 Comprueba lo aprendido
Conceptuales
- Escribe el patrón de palabras clave de una comprensión de listas condicional y explica cada parte.
- ¿Qué diferencia hay entre
[x for x in datos]y{x: 0 for x in datos}? - ¿Por qué
data.to_dict()no sirvió para el proyecto de la OTAN?
Análisis de código
palabras = ["sol", "Luna", "mar", "Estrella"]
resultado = [p.lower() for p in palabras if p[0].isupper()]Explica con tus palabras qué hace cada parte. ¿Qué contiene resultado?
Predicción
¿Qué imprime cada línea? Escribe tu respuesta antes de ejecutarla.
print([n * n for n in range(4)])
print({n: n % 2 == 0 for n in range(1, 4)})
print([letra for letra in "banana" if letra != "a"])Depuración
Este código debería crear un diccionario con los estudiantes que reprobaron. Tiene tres errores. Encuéntralos y corrígelos.
notas = {"Ana": 4.2, "Luis": 2.9, "Sofía": 2.5}
reprobados = [nombre: nota for (nombre, nota) in notas.items if nota > 3.0]Modificación
Modifica el proyecto de la OTAN para que, en lugar de una lista, imprima una línea por letra: A → Alfa.
Creación
Con ventas = {"empanadas": 45, "jugos": 12, "arepas": 30, "tintos": 8} (ventas de la tienda escolar en un día), crea en una línea un diccionario con los productos que vendieron más de 10 unidades y su venta aumentada en 10 %, como meta para mañana.
9. 🤖 Programar con apoyo de IA
Las comprensiones son cortas, y eso a veces las hace difíciles de leer. Una IA puede escribir comprensiones muy largas y "elegantes" que ni tú ni tus compañeros entienden.
Actividad: traducir en ambos sentidos.
- Escribe tú una comprensión condicional de los retos de este tutorial.
- Pídele a una IA que la convierta en un bucle
fortradicional y que explique cada línea. - Ejecuta ambas versiones con los mismos datos y comprueba que den exactamente el mismo resultado.
- Ahora al revés: pídele a la IA que convierta en comprensión un bucle que tenga dos condiciones anidadas. ¿El resultado es más fácil o más difícil de leer que el bucle?
- Pregúntale: "¿Cuándo no debería usar una comprensión de listas?". Contrasta su respuesta con la documentación oficial de Python sobre comprensiones (se abre en otra pestaña).
- Escribe en tu cuaderno una regla propia para decidir cuándo usar una comprensión y cuándo un bucle.
10. 🛠️ Correcciones técnicas al material original
| Archivo | Afirmación o comportamiento del curso | Observación | Tratamiento |
|---|---|---|---|
197 |
long_names pide nombres de "5 letras o más" y usa len(name) > 5 |
> 5 excluye los nombres de exactamente 5 letras. Con la lista del curso no se nota porque no hay ninguno (verificado) |
Nota técnica del Tema 2 |
197 |
Se mencionan ejercicios de práctica de comprensiones | No están en la carpeta del curso | Nota inicial; se reemplazan por retos de la adaptación |
197 |
"Esto es único de Python; en otros lenguajes no hay nada comparable" | Es una característica muy representativa de Python, pero otros lenguajes (por ejemplo, Haskell, del cual Python tomó la idea) tienen construcciones similares | Se presenta como "muy propia de Python" en la sección 0 |
202 |
iterrows() para construir el diccionario |
Funciona, pero es lento con tablas grandes; dict(zip(data.letter, data.code)) da el mismo resultado (verificado) |
Nota técnica del proyecto |
202 |
El programa asume que la palabra solo tiene letras del inglés | Espacios, dígitos y la Ñ producen KeyError (verificado) |
🧪 del proyecto; se retoma en el Día 30 |
11. 📋 Matriz de trazabilidad
| Contenido original | Archivo de origen | Concepto desarrollado | Ejercicio original | Reto adicional | Proyecto relacionado |
|---|---|---|---|---|---|
| Objetivos: comprensiones y alfabeto OTAN | 196 |
Sección 0 | — | — | Sección 6 |
| Comprensión de listas, patrón de palabras clave, secuencias | 197 |
Tema 1 | new_numbers, letters_list, range_list |
Retos 1–4 del Tema 1 | Secciones 6 y 7 |
| Comprensión condicional | 197 |
Tema 2 | short_names, long_names |
Retos 1–4 del Tema 2 | Sección 7 |
Reescribir missing_states |
198 |
Tema 3 | Juego de los estados | Reto del Tema 3 | Día 25 |
Comprensión de diccionarios, .items() |
199 |
Tema 4 | students_scores, passed_students |
Retos 1–4 del Tema 4 | Secciones 6 y 7 |
Recorrer DataFrames, iterrows, row.columna |
200 |
Tema 5 | Puntaje de Angela | Retos 1–4 del Tema 5 | Sección 6 |
| Proyecto OTAN: planteamiento | 201 |
Sección 6 | Pasos 1 y 2 | Depuración (espacio, Ñ, números) | Día 30 |
| Proyecto OTAN: solución | 202 |
Sección 6 | Diccionario fonético y lista de salida | Extensiones | Día 30 |
| (No existe en el curso original) | — | — | — | Codificador Morse | Sección 7 |
12. 📦 Evidencias de aprendizaje del Día 26
- Los ejercicios originales resueltos en la consola de Python (captura del panel de variables).
- Tu versión del juego de los estados con
missing_statesen una línea. - El deletreador OTAN funcionando, con la tabla de pruebas completa, incluidos los casos que fallan y tu explicación de por qué fallan.
- El codificador Morse (proyecto extra) con su
morse.csvy la fuente citada. - Cuaderno de errores:
NameErrorpor nombres distintos en la comprensión,SyntaxErrorpor elifmal ubicado,.itemssin paréntesis,to_dict()con el formato equivocado yKeyErrorcon espacios, dígitos y la Ñ.