Pensamiento Computacional · Unidad 4 — Estructuras de datos
Listas
Una lista guarda varios valores en orden, bajo un solo nombre. A diferencia de un string, se puede modificar.
La explicación
Varios valores, un nombre
notas[0] → 7 notas[-1] → 6
len(notas) → 4 notas[1:3] → [4, 9]
Se indexa igual que un string: desde 0, con negativos desde el final, y con rebanadas que no incluyen el límite derecho. Todo lo que aprendiste de strings sirve acá.
Una lista puede mezclar tipos — [1, "hola", True] es válida — aunque en la práctica
casi siempre guardan cosas del mismo tipo.
La diferencia con un string: se puede modificar
"hola"[0] = "H" # esto da error
Las listas son mutables. Eso abre posibilidades y también trae el problema del tema 4.2.
Agregar y sacar
notas.insert(0, 5) inserta en una posición
notas.remove(4) saca la primera aparición del valor 4
notas.pop() saca el último y lo devuelve
notas.pop(0) saca el de la posición 0
remove borra por valor, pop por posición. Con
[10, 20, 30], remove(0) tira error porque no hay ningún 0 en la lista,
mientras que pop(0) saca el 10. Confundirlos es muy común.
Preguntar y contar
sum([1, 2, 3]) → 6
max([4, 9, 2]) → 9
min([4, 9, 2]) → 2
len([4, 9, 2]) → 3
Con sum y len el promedio sale en una línea:
sum(notas) / len(notas).
Armar una lista desde cero
El patrón más usado: empezar vacía y llenarla en un ciclo.
for n in range(1, 5):
cuadrados.append(n * n)
print(cuadrados) # [1, 4, 9, 16]
Es el mismo esquema del acumulador, pero juntando valores en vez de sumarlos. Y con la misma trampa: la lista vacía va afuera del ciclo.
Escribir una función que reciba una lista de notas y devuelva cuántas están aprobadas (7 o más).
El patrón es contar: un contador afuera, y adentro del ciclo se suma 1 cuando se cumple la condición.
cuenta = 0
for n in notas:
if n >= 7:
cuenta = cuenta + 1
return cuenta
Con [7, 4, 9, 6]: el 7 cuenta, el 4 no, el 9 sí, el 6 no. Devuelve 2.
for n in notas y no for i in range(len(notas)).
Como sólo necesitamos los valores y no las posiciones, la primera forma es más corta y
más clara. Reservá la del range para cuando de verdad necesites el índice.
Control: probá con la lista vacía []. Tiene que devolver 0, no tirar error.
El ciclo simplemente no da ninguna vuelta y devuelve el contador como estaba. Las funciones que
reciben listas siempre hay que probarlas con la lista vacía.
Escribir una función que reciba una lista de notas y devuelva una tupla con la cantidad de aprobados (7 o más), el promedio general y el promedio de los aprobados. Tiene que funcionar también con la lista vacía y cuando no hay ningún aprobado.
Los casos borde son la mitad del ejercicio, y conviene listarlos antes de escribir código:
ningún aprobado → hay promedio general pero no de aprobados
todos aprobados → los dos promedios coinciden
La función:
if len(notas) == 0:
return (0, None, None)
aprobados = [n for n in notas if n >= 7]
promedio = sum(notas) / len(notas)
prom_aprob = sum(aprobados) / len(aprobados) if aprobados else None
return (len(aprobados), promedio, prom_aprob)
La primera línea protege de la división por cero, y devuelve None donde no hay número que devolver. Devolver 0 sería mentir: un promedio de 0 significaría que todos sacaron 0, que es otra cosa que no tener alumnos.
La comprensión de lista [n for n in notas if n >= 7] arma la lista de los aprobados en una línea. La versión con ciclo, por si el parcial la pide explícita:
for n in notas:
if n >= 7:
aprobados.append(n)
El if aprobados else None del final es la segunda protección: si la lista de aprobados quedó vacía, len(aprobados) es 0 y la división rompería. En Python una lista vacía se evalúa como falsa, así que if aprobados alcanza.
Las pruebas, una por caso borde:
resumen([]) → (0, None, None)
resumen([2, 3]) → (0, 2.5, None)
resumen([7, 10]) → (2, 8.5, 8.5)
El control a mano del primer caso:
aprobados: 7, 9, 8 → 24/3 = 8.0 ✓
Y un control que vale para cualquier entrada: el promedio de los aprobados tiene que ser mayor o igual que el general, porque los aprobados son los de arriba. Acá 8.0 ≥ 6.0 ✓. Si te diera al revés, hay un error de filtro.
Por qué devolver una tupla y no imprimir tres líneas. Quien llama a la función decide qué hacer con los tres números: mostrarlos, guardarlos, o usarlos en otra cuenta. Una función que imprime obliga a mostrarlos siempre.
Cómo se usa el resultado:
print(cantidad, general, de_aprobados) # 3 6.0 8.0
Dónde se pierde el punto: no contemplar la lista vacía. El programa "anda" con todos los datos de prueba del enunciado y se rompe con el caso que el corrector va a probar primero, que es justo el vacío.
Dónde se cae la mayoría
- Confundir remove (por valor) con pop (por posición).
- Crear la lista vacía adentro del ciclo: se reinicia en cada vuelta.
- Olvidar que las rebanadas no incluyen el límite derecho, igual que en strings.
Hasta acá la explicación. La práctica es la otra mitad: 8 ejercicios de este tema, en cuatro niveles, que no te dicen sólo si está bien al final sino que te corrigen en cada paso y te explican por qué. Y uno para escribir el programa vos, que se prueba ejecutándolo en Python ahí mismo, en el navegador. Además trae una animación que muestra la idea en movimiento.
Practicar Listas →Dónde entra este tema en el parcial
- Primer parcial — Trazar: copiar una lista de listas10 puntos · resuelto paso a paso
- Primer parcial — Completar: armar una lista nueva20 puntos · resuelto paso a paso
Los otros temas de la unidad 4
Estructuras de datos