Consolida lo aprendido para construir un sistema de préstamos en Python claro y robusto. Aquí se integran identificación de usuarios por cédula, verificación de disponibilidad de libros, validación del límite de préstamos y registro del préstamo, con mensajes de confirmación o error precisos. Además, se retoma el reto previo: crear una excepción específica de libro no disponible y otras que apoyan el flujo de la aplicación.
¿Cómo se estructura el sistema de préstamos con Python y excepciones?
El proyecto organiza una clase Biblioteca con dos colecciones: una lista de usuarios y una lista de libros. Se reutiliza la lista declarada en main asignándola a biblioteca.usuarios y lo mismo con los libros usando biblioteca.libros. Se limpian ejemplos que ya no se usan y se eliminan flags redundantes como disponible = True en clases que ya lo heredan, facilitando la lectura del código.
Flujo de requerimientos del sistema:
Identificar al usuario por cédula.
Solicitar el libro deseado.
Verificar disponibilidad del libro.
Validar límite de préstamos permitido.
Registrar el préstamo.
Mostrar confirmación o error adecuado.
Excepción revisada del reto anterior:
Libro no disponible: error específico dentro de exceptions para claridad al prestar.
¿Qué pasos de código habilitan búsqueda, entrada y manejo de errores?
El primer paso clave es crear un método para localizar usuarios por cédula y responder con una excepción clara si no existe.
¿Cómo buscar un usuario por cédula con manejo de error?
Método en la clase biblioteca: buscar_usuario(cedula) recorre con for la lista self.usuarios y compara usuario.cedula.
Si lo encuentra, retorna el objeto usuario.
Si no, hace raise de UsuarioNoEncontrado con un mensaje útil: “El usuario con la cédula X no fue encontrado.”
# exceptions.pyclassUsuarioNoEncontrado(Exception):pass# biblioteca.pyfrom exceptions import UsuarioNoEncontrado
classBiblioteca:def__init__(self): self.usuarios =[] self.libros =[]defbuscar_usuario(self, cedula:str):for usuario in self.usuarios:if usuario.cedula == cedula:return usuario
raise UsuarioNoEncontrado(f"El usuario con la cédula {cedula} no fue encontrado.")
Claves técnicas mencionadas: for, raise, excepción UsuarioNoEncontrado, retorno del usuario válido.
¿Cómo capturar la cédula y validar con try-except?
Se pide la cédula con input cuidando el formato del prompt: "Digite el número de cédula: ".
Se usa try-except (mencionado como “try catch”) para capturar UsuarioNoEncontrado y evitar que el programa termine abruptamente.
Se imprime el usuario solo si fue encontrado, moviendo el print al lugar correcto para no mostrar datos inexistentes.
# main.pyfrom exceptions import UsuarioNoEncontrado
from biblioteca import Biblioteca
biblioteca = Biblioteca()# Asignar datos iniciales creados previamente# biblioteca.usuarios = [...]# biblioteca.libros = [...]print("Bienvenido a Platzi Biblioteca.")print("Libros disponibles:")for titulo in biblioteca.libros_disponibles():print(f" - {titulo}")print()cedula =input("Digite el número de cédula: ")try: usuario = biblioteca.buscar_usuario(cedula)print(f"Cédula: {usuario.cedula}, Nombre: {usuario.nombre}")except UsuarioNoEncontrado:print("El usuario que estás buscando no existe.")
Palabras clave aplicadas: input, print, try-except, UsuarioNoEncontrado, formato de prompt claro y validación de usuario.
¿Cómo mejorar la experiencia mostrando libros disponibles?
Se agrega un título: “Libros disponibles”.
Se invoca el método biblioteca.libros_disponibles() que retorna títulos y se imprime con un guion y sangría para legibilidad.
Se eliminan libros marcados como no disponibles cuando ya no aportan al ejemplo.
Consejo práctico:
Mantener el listado de libros e usuarios centralizado en biblioteca.libros y biblioteca.usuarios evita duplicidades y confusiones.
¿Qué habilidades y conceptos clave refuerzas al implementarlo?
Este desarrollo potencia buenas prácticas de organización de código y control de errores, esenciales en aplicaciones de gestión.
Manejo de excepciones personalizadas: UsuarioNoEncontrado y libro no disponible para mensajes claros.
Búsqueda lineal en colecciones: comparación usuario.cedula == cedula con for.
Interacción con usuario: uso de input y print con formatos legibles.
Modularidad: separación en módulos main, biblioteca y exceptions.
Legibilidad: eliminar flags redundantes (como disponible = True cuando ya se hereda) y ejemplos obsoletos.
UX básica en terminal: listado de libros disponibles antes de solicitar cédula.
Preparación para el siguiente paso: crear un módulo de libros de ejemplo para pruebas de búsqueda y préstamo.
Como reto final, crea un módulo nuevo que genere datos de libros de ejemplo y así podrás buscarlos y pedirlos prestados en el siguiente paso.
¿Tienes dudas o una variante de implementación? Comparte en comentarios cómo organizaste tus módulos, nombres de excepciones y mejoras al flujo de préstamo.
El buscar_usuario no debería lanzar una excepción cuando en usuario no se encuentra, ya que para el contexto, esto no es un error, es uno de los dos posibles resultados.
Depende, puede que en tu lógica de negocio el usuario que recibas deba exisitir, y en vez de retornar un None, puedes capturar la excepción para "crear un nuevo usuario".
return f"El libro {titulo} ha sido agregado a la biblioteca."
Me gusta, sigue practicando
¿Cuál es la mejor forma de buscar usuarios?
La forma más eficiente y escalable de buscar usuarios no es iterar sobre una lista con un ciclo for, sino utilizar diccionarios en Python. Cuando usas una lista, el programa tiene que revisar cada elemento uno por uno (lo que se conoce como complejidad O(n)). Si tienes un millón de usuarios y el que buscas está al final, tomará mucho tiempo.
Si transformas tu estructura de datos para que la colección de usuarios sea un diccionario donde la llave es la cédula y el valor es el objeto del usuario, la búsqueda se vuelve instantánea (O(1)). Solo tendrías que hacer usuario = usuarios.get(cedula). Si el resultado es None, lanzas tu excepción. Esta técnica, conocida como hashing, es el estándar en la industria para búsquedas rápidas por identificador único, ahorrando recursos de procesamiento y haciendo que tu código sea mucho más limpio.
🧑💻💻📚
datos_ejemplo.py
"""
Módulo para generar datos de ejemplo de libros de la biblioteca.
Este módulo contiene una colección de libros preconfigurados para
facilitar las pruebas y demostraciones del sistema.
"""from libros import LibroFisico, LibroDigital
defobtener_libros_ejemplo():"""
Retorna una lista de libros de ejemplo para la biblioteca.
Returns:
list: Lista de instancias de Libro (físicos y digitales)
""" libros =[# Libros Físicos LibroFisico("100 Años de Soledad","Gabriel García Márquez","9781644734728", disponible=True), LibroFisico("El Principito","Antoine de Saint-Exupéry","9781644731234728", disponible=True), LibroFisico("Cien años de soledad","Gabriel García Márquez","9789588882529", disponible=True), LibroFisico("Don Quijote de la Mancha","Miguel de Cervantes","9788424127749", disponible=False), LibroFisico("La Metamorfosis","Franz Kafka","9788497935074", disponible=True),# Libros Digitales LibroDigital("Python para Principiantes","Mark Lutz","9781449355739", disponible=True), LibroDigital("Clean Code","Robert C. Martin","9780132350884", disponible=True), LibroDigital("Design Patterns","Gang of Four","9780201633610", disponible=False), LibroFisico("El Quijote","Miguel de Cervantes","9788420462165", disponible=True), LibroFisico("Orgullo y Prejuicio","Jane Austen","9788498383980", disponible=True),]return libros
defobtener_usuarios_ejemplo():"""
Retorna una lista de usuarios de ejemplo para la biblioteca.
Returns:
list: Lista de instancias de Usuario (Estudiantes y Profesores)
"""from usuarios import Estudiante, Profesor
usuarios =[ Estudiante("Luis","1123123123","Sistemas"), Estudiante("Jose","56789","Salud"), Estudiante("María","9876543210","Ingeniería"), Estudiante("Carlos","1111111111","Administración"), Profesor("Felipe","123123123"), Profesor("Ana","987654321"),]return usuarios
"""
# Proyecto Biblioteca
Proyecto de catálogo de libros
Este proyecto define una clase Libro para representar libros en un catálogo.
Cada libro tiene un título, autor, ISBN y disponibilidad.
Se crean instancias de libros y se almacenan en una lista que representa el catálogo.
"""from biblioteca import Biblioteca
from usuarios import Estudiante
from exceptions import UsuarioNoEncontrado
from datos_ejemplo import obtener_libros_ejemplo, obtener_usuarios_ejemplo
biblioteca = Biblioteca("Biblioteca Perfecta")# Cargar usuarios y libros de ejemplobiblioteca.usuarios = obtener_usuarios_ejemplo()biblioteca.libros = obtener_libros_ejemplo()# Imprimir el catálogo de libros disponiblesprint("\n")print("Bienvenido a Biblioteca Perfecta.")print("\n")print("Libros disponibles:")print("\n")for titulo in biblioteca.libros_disponibles():print(f" - {titulo}")print()# Buscar un usuario por cédulacedula =input("Digite el número de cédula: ")try: usuario = biblioteca.buscar_usuario(cedula)print(f"\nCédula: {usuario.cedula}, Nombre: {usuario.nombre}")# Permitir que el usuario solicite un libroprint("\nLibros disponibles para prestar:")for libro in biblioteca.libros:if libro.disponible:print(f" - {libro.titulo}") titulo_libro =input("\n¿Qué libro deseas pedir prestado? ")# Buscar el libro y hacer el préstamofor libro in biblioteca.libros:if libro.titulo.lower()== titulo_libro.lower()and libro.disponible: resultado = usuario.solicitar_libro(libro.titulo)print(resultado)print(libro.prestar())breakelse:print(f"El libro '{titulo_libro}' no está disponible.")except UsuarioNoEncontrado:print(f"El usuario con cédula {cedula} que estás buscando no existe.")