Saltar a contenido

Lab guiado: Operaciones con ficheros en Python

Crearemos todos los ficheros .py y .txt en la misma carpeta. Usa rutas relativas en todo el lab ("notas.txt", no rutas absolutas).

Cómo trabajar en parejas

Este lab se realiza en parejas conductor/navegante. Leed las instrucciones antes de empezar.

Roles

Rol Qué hace
Conductor Escribe el código y ejecuta los scripts. Solo el conductor toca el teclado.
Navegante Lee el enunciado en voz alta, propone soluciones, detecta errores y formula las preguntas.

Rotación

  • Cambiad de rol al final de cada paso (0, 1, 2… 8).
  • Al rotar, el navegante ocupa el teclado y el conductor se convierte en navegante.
  • Ambos debéis poder explicar cualquier parte del código al terminar el lab.

Entrega

Carpeta comprimida en forma zip que contenga os ficheros .py de cada paso: paso0.py, paso1.py, … paso8.py, más los de las ampliaciones que hayas completado.


Conceptos base

Antes de escribir código: repasemos los conceptos de los apuntes

¿Qué es un fichero? Una colección de datos guardada de forma persistente en disco. A diferencia de las variables, sobrevive al cierre del programa.

Texto vs binario En este lab trabajamos solo con ficheros de texto (.txt). Los ficheros binarios (imágenes, PDFs...) se abren con modo "b" y se tratan de forma diferente.

Ruta relativa Si el script y el fichero están en la misma carpeta, basta con escribir "notas.txt". Python lo busca en el directorio de trabajo actual.

open(ruta, mode, encoding) La puerta de entrada a cualquier fichero. Devuelve un objeto fichero con métodos para leer o escribir.

with open(...) as f: Garantiza que el fichero se cierra siempre al salir del bloque, aunque ocurra un error. Úsalo siempre.

encoding="utf-8" Obligatorio para que las tildes y la ñ funcionen en cualquier equipo. Si lo omites, el comportamiento depende del sistema operativo.

Paso 0 — Crear el fichero de notas paso0.py

Conceptos

Modo "w": abre para escribir. Si el fichero ya existe, borra su contenido. Si no existe, lo crea. with cierra el fichero automáticamente al salir del bloque.

with open("notas.txt", "w", encoding="utf-8") as f:
    f.write("línea\n")

Objetivo

Crear notas.txt con los datos de cuatro alumnos usando modo "w" y write().

Tarea

Inserta en paso0.py el siguiente programa:

Editor (session: notas-txt) Run
with open("notas.txt", "w", encoding="utf-8") as f:
    f.write("Ana García: 8.5\n")
    f.write("Carlos López: 6.0\n")
    f.write("María Fernández: 9.2\n")
    f.write("Pedro Martín: 4.5\n")

print("Fichero creado.")
Output Clear

Pista

Cada llamada a write() escribe exactamente la cadena que le pasas. Si no añades \n, las líneas quedan pegadas en una sola.

Pregunta:

Si ejecutas el script dos veces seguidas sin modificarlo, ¿el fichero tendrá 8 líneas o 4?

Respuesta

4 líneas. El modo "w" borra el contenido previo cada vez que abre el fichero.

Ejecuta y verifica que notas.txt tiene 4 líneas, una por alumno

TODO

Modifica paso0.py de forma que obtengamos el mismo resultado completando el siguiente código

notas = [
    ("Ana García", 8.5),
    ("Carlos López", 6.0),
    ("María Fernández", 9.2),
    ("Pedro Martín", 4.5),
]

with open("notas.txt", "w", encoding="utf-8") as f:
    # TODO

print("Fichero creado.")

Comprobación

Abre notas.txt con el editor de texto y verifica que tiene 4 líneas, una por alumno.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • A abrir un fichero en modo escritura ("w") para crearlo o sobrescribirlo.
  • A usar with para cerrar el fichero automáticamente y evitar errores.
  • A escribir texto línea a línea con write().
  • A controlar los saltos de línea con \n para que cada registro quede en una línea.
  • A entender que ejecutar de nuevo con "w" no añade contenido: reemplaza el anterior.

Prueba manual guiada

  1. Ejecuta el script.
  2. Abre notas.txt con el editor. Cuenta las líneas.
  3. Ejecuta el script de nuevo sin modificarlo.
  4. Vuelve a abrir notas.txt. ¿Cuántas líneas hay ahora?
  5. Confirma con tu pareja la respuesta a la pregunta anterior.

Paso 1 — Leer el fichero completo con read() paso1.py

Conceptos

read() carga todo el contenido del fichero en una única cadena str, incluyendo los saltos de línea \n. El modo de apertura es "r" (lectura, valor por defecto).

Objetivo

Leer el fichero completo y mostrar su contenido, tipo de dato y número de caracteres.

Tarea

Inserta en paso1.py el siguiente programa:

Editor (session: notas-txt) Run
with open("notas.txt", "r", encoding="utf-8") as f:
    contenido = f.read()

print(contenido)
print("---")
print(type(contenido))
print(f"Caracteres totales: {len(contenido)}")
Output Clear

Pista

type() te dice qué tipo de dato ha devuelto read(). len() cuenta los caracteres, incluidos los \n.

Pregunta:

¿Qué tipo de dato devuelve read(): str, list o bytes?

Respuesta

str. read() devuelve una cadena de texto única con todo el contenido del fichero.

Ejecuta el script y verifica la salida en la terminal.

TODO

Edita el fichero paso1.py y agrega el siguiente código de forma que a partir del string ya leído en contenido, sin reabrir el fichero, construye un diccionario {nombre: nota} e imprime solo los alumnos aprobados (nota >= 5).

registro_alumnos = {}
for linea in ______:        # itera sobre las líneas del string
    # TODO: agrega a registro los datos de los alumnos

# TODO: muestra solo los alumnos aprobados recorriendo registro_alumnos

Comprobación

El programa principal muestra las 4 líneas, <class 'str'> y el total de caracteres. El TODO imprime solo los alumnos con nota >= 5.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • read() carga todo el fichero en un str de una sola vez; no hace falta reabrirlo para procesar los datos.
  • El str se puede procesar como cualquier cadena: split, strip, conversiones de tipo, etc.
  • Es adecuado para ficheros pequeños donde se necesita el contenido completo de inmediato.

Paso 2 — Leer por partes: read(n) y readline() paso2.py

Conceptos

  • read(n): lee exactamente n caracteres y mueve el cursor interno. La siguiente llamada continúa desde donde se quedó.
  • readline(): lee hasta el siguiente \n (inclusive). Devuelve "" cuando llega al final del fichero.

Objetivo

Usar read(n) para leer fragmentos y readline() en bucle para recorrer el fichero completo.

Tarea

Inserta en paso2_a.py el siguiente programa:

Parte A — read(n):

1
2
3
4
5
6
with open("notas.txt", "r", encoding="utf-8") as f:
    primeros  = f.read(10)
    siguientes = f.read(10)

print(repr(primeros))
print(repr(siguientes))
Inserta en paso2_b.py el siguiente programa:

Parte B — readline() en bucle:

1
2
3
4
5
6
with open("notas.txt", "r", encoding="utf-8") as f:
    while True:
        linea = f.readline()
        if not linea:
            break
        print(repr(linea))
Pista

repr() muestra los caracteres especiales de forma visible (verás los \n explícitamente). Muy útil para depurar.

🔧 Apoyo — solo si te atascas en la Parte B

Empieza rellenando los huecos de este template:

with open("notas.txt", "r", encoding="utf-8") as f:
    while True:
        linea = f.readline()
        if ______:        # ¿qué condición indica fin de fichero?
            break
        print(______)     # ¿qué variable imprimes?

Pregunta:

En el bucle con readline(), ¿qué valor tiene linea cuando el fichero se ha leído por completo? ¿Por qué el bucle se detiene?

Respuesta

linea vale "" (cadena vacía). not "" es True, por lo que se ejecuta break y el bucle termina.

Ejecuta ambas partes y observa la salida.

TODO

Crea el fichero paso2.py cuyo código sera el de paso2_b.py modificándolo de forma que usando readline() en un bucle, se extraen solo los nombres de los alumnos (la parte antes de ": ") y guárdalos en una lista nombres. No uses readlines() ni for linea in f.

nombres = []
# TODO: leer del fichero líneas guardando solo nombres de los alumnos en la lista nombres
print(nombres)

Comprobación

  • Parte A: primeros y siguientes muestran fragmentos del texto, no líneas completas.
  • Parte B: se imprimen las 4 líneas con \n visible al final; el bucle termina solo.
  • TODO: nombres es una lista con los 4 nombres sin notas ni \n.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • read(n) mueve un cursor interno; cada llamada lee el siguiente fragmento, no el mismo.
  • readline() permite avanzar manualmente línea a línea; "" indica fin de fichero.
  • La condición de parada del bucle while True con readline() es que devuelva cadena vacía.

Paso 3 — Leer todas las líneas con readlines() paso3.py

Conceptos

readlines() lee todo el fichero de una vez y devuelve una lista donde cada elemento es una línea (con \n incluido). Útil cuando necesitas acceder a líneas por índice.

writelines() escribe de una vez en un fichero una lista donde cada elemento es una línea de texto. No añade saltos de linea: si quieres que cada elemento quede en una linea distinta, cada string de la lista debe terminar en \n.

Objetivo

Leer el fichero con readlines() y mostrar la segunda y la última línea.

Tarea

Inserta en paso3.py el siguiente programa:

Editor (session: notas-txt) Run
with open("notas.txt", "r", encoding="utf-8") as f:
    lineas = f.readlines()

print(f"Total de líneas: {len(lineas)}")
print(f"Segunda línea:   {lineas[1].strip()}")
print(f"Última línea:    {lineas[-1].strip()}")
Output Clear

Pista

.strip() elimina espacios y saltos de línea al principio y al final de la cadena.

Pregunta:

¿Qué contiene lineas[0] exactamente, incluyendo caracteres especiales?

Respuesta

'Ana García: 8.5\n' — la primera línea con el salto de línea incluido.

Ejecuta el script y verifica la salida.

TODO

Añade a paso3.py código siguiente completado de forma que se ordena la lista lineas por nota de mayor a menor y escribe el resultado ordenado en notas_ordenadas.txt. Cada línea debe quedar tal cual (con su \n).

lineas_ordenadas = []
# TODO: obtener líneas ordenadas

with open("notas_ordenadas.txt", "w", encoding="utf-8") as f:
    f.______         # TODO: escribe la lista ordenada de una vez

Comprobación

Se imprime Total de líneas: 4, la segunda y la última sin \n. notas_ordenadas.txt existe con las 4 líneas con el nombre del alumno y su nota ordenadas de mayor a menor nota.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • readlines() devuelve una lista manipulable con todas las herramientas de Python (sorted, slicing, indexado…).
  • Cada elemento incluye el \n
  • writelines() permite escribir una lista de strings de una sola vez.
  • sorted() con key permite ordenar por un criterio extraído de cada string de la lista.

Paso 4 — Iteración directa sobre el fichero paso4.py

Conceptos

Python permite iterar directamente sobre el objeto fichero: for linea in f:. Es la forma más Pythónica: lee línea a línea sin cargar todo en memoria. Es la opción recomendada para recorrer todas las líneas. Cuando leemos línea a línea deberíamos hacerlo siempre de esta forma, no como se hizo en el paso 2 con while (se usó para ver la función readline()).

Objetivo

Iterar sobre el fichero y mostrar cada línea limpia de \n.

Tarea

Inserta en paso4.py el siguiente programa:

1
2
3
4
print("=== Listado de alumnos ===")
with open("notas.txt", "r", encoding="utf-8") as f:
    for linea in f:
        print(linea.strip())
Pista

for linea in f es equivalente a llamar readline() repetidamente hasta obtener "", pero más conciso y eficiente.

Pregunta:

¿En qué se diferencia for linea in f de usar readlines() seguido de for linea in lineas?

Respuesta

Con iteración directa, el fichero se lee línea a línea sin cargar todo en memoria. Con readlines(), todas las líneas se cargan primero en una lista. Para ficheros pequeños el resultado es idéntico; para ficheros grandes, la iteración directa es mucho más eficiente.

Ejecuta el script y verifica la salida.

TODO

Modifica paso4.py de forma que en una sola pasada sobre el fichero (sin listas intermedias), calcula simultáneamente el número de alumnos, la suma de notas, los aprobados y los suspensos. Imprime el resumen al final.

aprobados  = 0
suspensos  = 0
suma_notas = 0.0
num_notas  = 0

with open("notas.txt", "r", encoding="utf-8") as f:
    for linea in f:
        print(linea.strip())
        # TODO: obtener aprobados, suspensos, suma_notas, num_notas
        # Ayúdate de strip().split(": ") para parsear líneas de la forma clave: valor

print(f"Número de alumnos: {num_notas} | Aprobados: {aprobados} | Suspensos: {suspensos}")
print(f"Media: {______:.2f}")

Comprobación

Se imprimen las 4 líneas sin \n. El TODO muestra el recuento y la media correctos.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • La iteración directa sobre el fichero permite procesar línea a línea sin cargar todo en memoria.
  • Es posible acumular varios resultados en una sola pasada usando variables contadoras.
  • El patrón strip().split(": ") es la forma estándar de parsear líneas con formato clave: valor.

Paso 5 — Añadir notas con modo "a" paso5.py

Conceptos

Modo "a" (append): escribe al final del fichero sin borrar lo que había. Si el fichero no existe, lo crea. Diferencia clave: "w" destruye el contenido previo, "a" lo conserva.

Objetivo

Añadir dos alumnos nuevos al fichero sin borrar los cuatro existentes.

Tarea

Inserta en paso5.py el siguiente programa:

1
2
3
4
5
with open("notas.txt", "a", encoding="utf-8") as f:
    f.write("Laura Sánchez: 7.8\n")
    f.write("Tomás Díaz: 4.3\n")

print("Alumnos añadidos.")

Tras añadir, verifica el resultado leyendo el fichero completo:

with open("notas.txt", "r", encoding="utf-8") as f:
    print(f.read())
Pista

Ejecuta el script de añadir varias veces y observa cómo crece el fichero. Eso confirma que "a" no borra.

Pregunta:

Si ejecutas el script de añadir tres veces seguidas, ¿cuántas líneas tendrá el fichero?

Respuesta

4 + 2×3 = 10 líneas. Cada ejecución añade 2 líneas al final sin borrar las anteriores.

Ejecuta el script una vez (partiendo de notas.txt con 4 líneas) y verifica la salida.

TODO

Tras el append, reabre notas.txt en modo "r" y verifica que el número de líneas es exactamente el esperado. Imprime "OK" si es correcto o "ERROR: N líneas encontradas" si no.

LINEAS_ESPERADAS = 6

with open("notas.txt", "r", encoding="utf-8") as f:
    lineas = ______

if ______:
    print("OK")
else:
    print(f"ERROR: {______} líneas encontradas")

Comprobación

El fichero tiene 6 líneas tras la primera ejecución; el TODO imprime OK. Si ejecutas el script de nuevo sin restaurar el fichero, el TODO imprimirá ERROR.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • El modo "a" acumula contenido en cada ejecución; es importante verificar el estado real del fichero tras cada operación.
  • Reabrir en "r" inmediatamente después de "a" permite comprobar el resultado sin inspeccionar el fichero manualmente.
  • "w" y "a" son de intención opuesta: uno destruye el contenido previo, el otro lo preserva.

Prueba manual guiada

  1. Ejecuta paso0.py para restaurar notas.txt a 4 líneas.
  2. Ejecuta paso5.py una vez → verifica que imprime OK.
  3. Ejecuta paso5.py de nuevo → ¿qué imprime ahora? ¿Por qué?

Paso 6 — Escritura con writelines() y print(..., file=f) paso6.py

Conceptos

  • Como ya hemos visto, writelines(lista): escribe los elementos de una lista uno tras otro, sin añadir \n automáticamente.
  • print(valor, file=f): escribe en el fichero igual que en pantalla, y sí añade \n automáticamente al final.

Objetivo

Crear notas_nuevas.txt usando primero writelines() y luego print(..., file=f).

Tarea

Parte A — writelines():

Inserta en paso6_a.py el siguiente programa:

1
2
3
4
5
6
7
8
alumnos = [
    "Elena Torres: 9.0\n",
    "Marco Ruiz: 6.5\n",
    "Sara Vega: 8.2\n",
]

with open("notas_nuevas.txt", "w", encoding="utf-8") as f:
    f.writelines(alumnos)

Parte B — print(..., file=f):

Inserta en paso6_b.py el siguiente programa:

1
2
3
4
5
6
7
8
9
datos = [
    ("Elena Torres", 9.0),
    ("Marco Ruiz", 6.5),
    ("Sara Vega", 8.2),
]

with open("notas_nuevas.txt", "w", encoding="utf-8") as f:
    for nombre, nota in datos:
        print(f"{nombre}: {nota}", file=f)
Pista

En la Parte A, si olvidas los \n dentro de los strings de la lista, todas las líneas quedarán pegadas en una sola.

Pregunta:

¿Cuál es la diferencia principal entre writelines() y print(..., file=f) respecto al salto de línea?

Respuesta

writelines() no añade \n automáticamente — tienes que incluirlo en los strings de la lista. print(..., file=f) sí añade \n al final de cada llamada, igual que hace en pantalla.

Ejecuta ambas partes y abre notas_nuevas.txt después de ejecutar cada una para verificar que el resultado es idéntico.

TODO

Genera paso6_.py de forma que en lugar de la lista de la Parte A, generamos la lista a partir de un diccionario datos_dict. El resultado en notas_nuevas.txt debe ser idéntico.

datos_dict = {
    "Elena Torres": 9.0,
    "Marco Ruiz":   6.5,
    "Sara Vega":    8.2,
}

# TODO: pasa datos en datos_dict a una lista

with open("notas_nuevas.txt", "w", encoding="utf-8") as f:
    f.writelines(______) # TODO: usa writelines para escribir la lista obtenida anteiormente

Comprobación

notas_nuevas.txt tiene 3 líneas bien separadas en ambos casos y en el TODO.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • writelines() escribe cada elemento de un iterable sin separadores; el \n debe estar en los propios strings.
  • print(..., file=f) añade \n automáticamente al final, igual que en pantalla; más cómodo para formato variable.
  • Las comprensiones de lista permiten generar la lista para writelines() de forma concisa a partir de otras estructuras.

Reto de restricciones pasos 5 y 6

Una vez completado el paso anterior:

Restricción

Reescribe los scripts finales de los pasos 5 y 6 usando exclusivamente print(..., file=f) para toda escritura.


Paso 7 — Modo "x": creación exclusiva paso7.py

Conceptos

Modo "x": crea un fichero nuevo. Si el fichero ya existe, falla con un error. Es la opción más segura cuando no quieres sobrescribir datos existentes por accidente.

Objetivo

Observar el comportamiento de "x" al crear un fichero nuevo y al intentar crearlo de nuevo.

Tarea

Inserta en paso7.py el siguiente programa:

Primera ejecución — crea el fichero:

1
2
3
with open("registro.txt", "x", encoding="utf-8") as f:
    f.write("Primer registro\n")
print("Fichero creado con modo 'x'.")

Segunda ejecución — ejecuta exactamente el mismo código de nuevo y observa qué ocurre.

Pista

El segundo intento fallará. Lee el mensaje de error en la terminal. ¿Qué tipo de error es? No hace falta gestionarlo con try/except; solo obsérvalo.

Pregunta:

¿En qué situación real usarías "x" en lugar de "w"?

Respuesta

Cuando quieres asegurarte de no sobrescribir un fichero que ya contiene datos importantes. Por ejemplo, al generar ficheros de exportación con nombre único por fecha/hora.

TODO

Modifica paso7.py para que pida al usuario el nombre del fichero por teclado, lo cree con modo "x" y escriba en él el nombre y la cantidad de caracteres que tiene ese nombre. Ejecuta dos veces con el mismo nombre y observa qué ocurre.

nombre_fichero = input("Nombre del fichero a crear (sin extensión): ") + ".txt"

with open(______, ______, encoding="utf-8") as f:
    f.write(f"Fichero: {______}\n")
    f.write(f"Longitud del nombre: {______} caracteres\n")
    # TODO: añade también una línea con la fecha y la hora actual

print(f"'{nombre_fichero}' creado correctamente.")

Comprobación

  • Primera ejecución: registro.txt se crea y contiene Primer registro.
  • Segunda ejecución: el programa termina con un error FileExistsError visible en la terminal.
  • TODO: el fichero con el nombre introducido se crea y contiene el nombre y su longitud.

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • El modo "x" falla con FileExistsError si el fichero ya existe; es el mecanismo de protección sin necesidad de comprobaciones previas.
  • A diferencia de "w", "x" garantiza que nunca se sobreescribe un fichero existente de forma accidental.
  • El nombre del fichero puede ser dinámico (variable, entrada de usuario) sin cambiar la lógica de apertura.

Paso 8 — Informe final paso8.py

Conceptos

Integramos todo lo aprendido: leer con iteración directa, procesar datos línea a línea y escribir el resultado en un nuevo fichero con print(..., file=f).

Objetivo

Leer notas.txt, calcular la media de las notas y generar informe.txt con el listado completo y la media del grupo.

Tarea

Inserta en paso8.py el siguiente programa:

alumnos = []

with open("notas.txt", "r", encoding="utf-8") as f:
    for linea in f:
        partes = linea.strip().split(": ")
        nombre = partes[0]
        nota = float(partes[1])
        alumnos.append((nombre, nota))

media = sum(nota for _, nota in alumnos) / len(alumnos)

with open("informe.txt", "w", encoding="utf-8") as f:
    print("=== Informe de notas ===", file=f)
    for nombre, nota in alumnos:
        estado = "APROBADO" if nota >= 5 else "SUSPENDIDO"
        print(f"  {nombre}: {nota:.1f}{estado}", file=f)
    print(f"\nMedia del grupo: {media:.2f}", file=f)

print("Informe generado en informe.txt.")

Pregunta:

¿Qué hace linea.strip().split(": ") sobre la cadena "Ana García: 8.5\n"?

Respuesta

Primero strip() elimina el \n del final, dejando "Ana García: 8.5". Luego split(": ") divide en la lista ["Ana García", "8.5"].

Ejecuta el script y abre informe.txt para verificar su contenido.

TODO

Añade al informe ya generado (usando modo "a" para no borrarlo) tres líneas adicionales al final: el alumno con la nota más alta, el de nota más baja y el total de aprobados.

Comprobación

informe.txt Debería quedar de la forma:

=== Informe de notas ===
Ana García: 8.5 — APROBADO
Carlos López: 6.0 — APROBADO
María Fernández: 9.2 — APROBADO
Pedro Martín: 4.5 — SUSPENDIDO

Media del grupo: 7.05
Mejor nota:   María Fernández (9.2)
Peor nota:    Pedro Martín (4.5)
Aprobados:    4 de 4

Reflexión

¿Qué hemos aprendido en este paso?

Respuestas
  • Lectura y escritura pueden combinarse en un mismo script usando bloques with separados o consecutivos.
  • El modo "a" permite añadir datos a un fichero ya existente sin perder su contenido previo.

🔄 Kata de refactor — Paso 8

Una vez que el informe funciona, refactoriza el código:

Kata 1

Reescribe la lectura de notas.txt usando readlines() en lugar de iteración directa. ¿Cambia el resultado?

Kata 2

Reescribe la escritura del informe usando write() en lugar de print(..., file=f). ¿Qué tienes que cambiar?

Kata 3 — avanzado

Reescribe el script de forma que lectura y escritura ocurran dentro de un único bloque with, usando la sintaxis de múltiples ficheros:

with open("notas.txt", "r", encoding="utf-8") as entrada, \
     open("informe.txt", "w", encoding="utf-8") as salida:
    ...


Comprobaciónlist de entrega

Al finalizar el lab, marca lo que has conseguido:

He creado notas.txt con modo "w" y write().

He leído el fichero con al menos tres métodos distintos (read(), readline(), iteración directa).

He añadido líneas con modo "a" sin borrar el contenido previo.

He usado writelines() con los \n correctamente en los elementos.

He usado print(..., file=f) para escribir en un fichero.

He probado el modo "x" y entiendo cuándo usarlo.

He generado el fichero informe.txt con el script integrador.


Activides de ampliación

Si has completado todos los pasos, continúa aquí. Cada ampliación se escribe en un fichero propio: ampliacion_a.py, ampliacion_b.py, etc. (salvo la F, que usa gestor.py).


Ampliación A — Encapsular en funciones (tras Paso 0 y Paso 5) ampliacion_a.py

Reescribe las operaciones básicas como funciones reutilizables:

def crear_fichero(ruta, lineas):
    """Crea el fichero en ruta y escribe la lista de strings lineas."""
    # tu código aquí

def registrar_nota(ruta, nombre, nota):
    """Añade una línea 'nombre: nota' al fichero sin borrar el contenido."""
    # tu código aquí

def leer_fichero(ruta):
    """Devuelve el contenido completo del fichero como string."""
    # tu código aquí

Verifica que las tres funciones producen el mismo resultado que el código original de los Pasos 0 y 5.


Ampliación B — Comprensiones de lista (tras Paso 3) ampliacion_b.py

A partir de readlines(), obtén en una sola línea de código:

  1. Lista con solo los nombres (sin notas ni \n):
    nombres = [_______ for linea in lineas]
    
  2. Lista con solo las notas como float:
    notas = [_______ for linea in lineas]
    
  3. La media directamente desde esa lista:
    media = sum(notas) / len(notas)
    

Ampliación C — Construir un diccionario (tras Paso 4) ampliacion_c.py

Usa la iteración directa para construir un diccionario {nombre: nota}:

1
2
3
4
5
6
7
8
registro = {}

with open("notas.txt", "r", encoding="utf-8") as f:
    for linea in f:
        # tu código aquí

print(registro)
# {'Ana García': 8.5, 'Carlos López': 6.0, ...}

Una vez construido, imprime solo los alumnos con nota >= 5 usando una comprensión de diccionario.


Ampliación D — Leer en bloques (tras Paso 2) ampliacion_d.py

Usa read(n) en un bucle para leer el fichero en bloques de 8 caracteres:

1
2
3
4
5
6
with open("notas.txt", "r", encoding="utf-8") as f:
    while True:
        bloque = f.read(8)
        if not bloque:
            break
        print(repr(bloque))

Responde: ¿cuántos bloques tiene el fichero? ¿Coincide exactamente con len(contenido) / 8? ¿Por qué puede no ser exacto?


Ampliación E — Clase RegistroNotas (tras Paso 8) ampliacion_e.py

Encapsula todas las operaciones del lab en una clase:

class RegistroNotas:
    def __init__(self, ruta):
        self.ruta = ruta

    def crear(self, alumnos):
        """Recibe una lista de tuplas (nombre, nota) y crea el fichero."""
        # tu código aquí

    def añadir(self, nombre, nota):
        """Añade un alumno al fichero sin borrar los anteriores."""
        # tu código aquí

    def leer_todos(self):
        """Devuelve una lista de tuplas (nombre, nota)."""
        # tu código aquí

    def generar_informe(self, ruta_informe):
        """Escribe el informe con estado y media en ruta_informe."""
        # tu código aquí

Prueba con:

1
2
3
4
registro = RegistroNotas("notas.txt")
registro.crear([("Ana García", 8.5), ("Carlos López", 6.0)])
registro.añadir("María Fernández", 9.2)
registro.generar_informe("informe_clase.txt")

Ampliación F — Reto final

Sin plantilla. Sin pistas.

Escribe un script gestor.py que muestre un menú en bucle:

1. Añadir alumno
2. Mostrar todos
3. Generar informe
4. Salir

Requisitos:

  • Los datos se guardan en alumnos.txt con modo "a".
  • La opción 2 lee e imprime con iteración directa.
  • La opción 3 escribe informe.txt con print(..., file=f).
  • Sin try/except ni pathlib.
  • Toda la lógica de ficheros en métodos de una clase.