Interfaz de administrador
Parte de la sección Object Oriented Programming del Journey de Python de Coddy — lección 59 de 64.
Desafío
IntermedioEn este desafío, vas a implementar funciones administrativas para un sistema de gestión de bibliotecas.
Tendrás que modificar el archivo library.py para añadir un método get_statistics a la clase Library que devuelva un diccionario con estadísticas clave sobre el estado de la biblioteca. Los detalles de la implementación se encuentran en los comentarios TODO dentro del archivo.
Las estadísticas deben incluir:
- Número total de libros
- Conteo de libros disponibles
- Conteo de libros prestados
- Conteo total de usuarios
- Número de usuarios con libros prestados
Los archivos book.py y user.py contienen clases preimplementadas con las que interactuará tu solución. Aunque puedes revisar estos archivos para entender la estructura del sistema, tu implementación debe centrarse en el archivo library.py.
Pruébalo tú mismo
from book import Book
from user import User
from library import Library
# Manejador de casos de prueba
test_case = input()
if test_case == "empty_library":
library = Library("Empty Library")
stats = library.get_statistics()
print(f"Total Books: {stats['total_books']}")
print(f"Available Books: {stats['available_books']}")
print(f"Borrowed Books: {stats['borrowed_books']}")
print(f"Total Users: {stats['total_users']}")
print(f"Users with Books: {stats['users_with_books']}")
elif test_case == "with_borrowed_books":
library = Library("Community Library")
# Agregar libros y usuarios
library.add_book(Book("The Great Gatsby", "F. Scott Fitzgerald", "123456"))
library.add_book(Book("To Kill a Mockingbird", "Harper Lee", "789012"))
library.add_book(Book("1984", "George Orwell", "345678"))
library.add_user(User("U001", "Alice"))
library.add_user(User("U002", "Bob"))
library.add_user(User("U003", "Charlie"))
# Prestar algunos libros
library.borrow_book("123456", "U001")
library.borrow_book("789012", "U001") # Alice presta 2 libros
library.borrow_book("345678", "U002") # Bob presta 1 libro
stats = library.get_statistics()
print(f"Total Books: {stats['total_books']}")
print(f"Available Books: {stats['available_books']}")
print(f"Borrowed Books: {stats['borrowed_books']}")
print(f"Total Users: {stats['total_users']}")
print(f"Users with Books: {stats['users_with_books']}")
elif test_case == "return_books":
library = Library("Return Test Library")
# Agregar libros y usuarios
library.add_book(Book("Python Programming", "John Smith", "111222"))
library.add_book(Book("Data Structures", "Jane Doe", "333444"))
library.add_user(User("U101", "David"))
library.add_user(User("U102", "Emma"))
# Prestar un libro
library.borrow_book("111222", "U101")
# Get statistics before returning
stats_before = library.get_statistics()
print("Before returning:")
print(f"Total Books: {stats_before['total_books']}")
print(f"Available Books: {stats_before['available_books']}")
print(f"Borrowed Books: {stats_before['borrowed_books']}")
print(f"Users with Books: {stats_before['users_with_books']}")
# Implementación de devolución de libro (estaría en la clase Library)
book = next((book for book in library.books if book.isbn == "111222"), None)
user = next((user for user in library.users if user.user_id == "U101"), None)
if book and user:
book.available = True
book.borrower = None
user.books_borrowed.remove(book)
print("Book returned successfully")
# Get statistics after returning
stats_after = library.get_statistics()
print("\
After returning:")
print(f"Total Books: {stats_after['total_books']}")
print(f"Available Books: {stats_after['available_books']}")
print(f"Borrowed Books: {stats_after['borrowed_books']}")
print(f"Users with Books: {stats_after['users_with_books']}")
elif test_case == "edge_cases":
# Empty library
empty_library = Library("Empty Library")
empty_stats = empty_library.get_statistics()
print("Empty library statistics:")
print(f"Total Books: {empty_stats['total_books']}")
print(f"Available Books: {empty_stats['available_books']}")
print(f"Borrowed Books: {empty_stats['borrowed_books']}")
print(f"Total Users: {empty_stats['total_users']}")
print(f"Users with Books: {empty_stats['users_with_books']}")
# Books but no users
books_only = Library("Books Only")
books_only.add_book(Book("Book 1", "Author 1", "B001"))
books_only.add_book(Book("Book 2", "Author 2", "B002"))
books_stats = books_only.get_statistics()
print("\
Library with books but no users:")
print(f"Total Books: {books_stats['total_books']}")
print(f"Available Books: {books_stats['available_books']}")
print(f"Total Users: {books_stats['total_users']}")
print(f"Users with Books: {books_stats['users_with_books']}")
# Users but no books
users_only = Library("Users Only")
users_only.add_user(User("U201", "User 1"))
users_only.add_user(User("U202", "User 2"))
users_stats = users_only.get_statistics()
print("\
Library with users but no books:")
print(f"Total Books: {users_stats['total_books']}")
print(f"Available Books: {users_stats['available_books']}")
print(f"Total Users: {users_stats['total_users']}")
print(f"Users with Books: {users_stats['users_with_books']}")
# Casos de error
error_library = Library("Error Test")
error_library.add_book(Book("Error Book", "Error Author", "E001"))
error_library.add_user(User("E101", "Error User"))
print("\
Error cases:")
print(f"Borrow non-existent book: {error_library.borrow_book('NONEXISTENT', 'E101')}")
print(f"Borrow with non-existent user: {error_library.borrow_book('E001', 'NONEXISTENT')}")
elif test_case == "large_library":
large_library = Library("Large Library")
# Agregar 100 libros
for i in range(1, 101):
large_library.add_book(Book(f"Book {i}", f"Author {i}", f"ISBN{i:06d}"))
# Agregar 100 usuarios
for i in range(1, 101):
large_library.add_user(User(f"U{i:03d}", f"User {i}"))
# Hacer que 50 usuarios presten libros
for i in range(1, 51):
large_library.borrow_book(f"ISBN{i:06d}", f"U{i:03d}")
# Hacer que algunos usuarios presten varios libros
for i in range(1, 11):
large_library.borrow_book(f"ISBN{i+50:06d}", f"U{i:03d}")
stats = large_library.get_statistics()
print("Large library statistics:")
print(f"Total Books: {stats['total_books']}")
print(f"Available Books: {stats['available_books']}")
print(f"Borrowed Books: {stats['borrowed_books']}")
print(f"Total Users: {stats['total_users']}")
print(f"Users with Books: {stats['users_with_books']}")
# Verificar cálculos
print("\
Verification:")
print(f"Total books should be 100: {stats['total_books'] == 100}")
print(f"Borrowed books should be 60: {stats['borrowed_books'] == 60}")
print(f"Available books should be 40: {stats['available_books'] == 40}")
print(f"Users with books should be 50: {stats['users_with_books'] == 50}")
elif test_case == "statistics_accuracy":
accuracy_library = Library("Accuracy Test")
# Añadir exactamente 10 libros
for i in range(1, 11):
accuracy_library.add_book(Book(f"Book {i}", f"Author {i}", f"A{i:03d}"))
# Añadir exactamente 5 usuarios
for i in range(1, 6):
accuracy_library.add_user(User(f"AU{i}", f"Accuracy User {i}"))
# Aún no se han prestado libros
stats1 = accuracy_library.get_statistics()
print("Initial state:")
print(f"Total Books: {stats1['total_books']} (Expected: 10)")
print(f"Available Books: {stats1['available_books']} (Expected: 10)")
print(f"Borrowed Books: {stats1['borrowed_books']} (Expected: 0)")
print(f"Total Users: {stats1['total_users']} (Expected: 5)")
print(f"Users with Books: {stats1['users_with_books']} (Expected: 0)")
# Hacer que 3 usuarios presten libros
accuracy_library.borrow_book("A001", "AU1")
accuracy_library.borrow_book("A002", "AU1") # El usuario 1 presta 2 libros
accuracy_library.borrow_book("A003", "AU2") # El usuario 2 presta 1 libro
accuracy_library.borrow_book("A004", "AU3") # El usuario 3 presta 1 libro
stats2 = accuracy_library.get_statistics()
print("\
After borrowing:")
print(f"Total Books: {stats2['total_books']} (Expected: 10)")
print(f"Available Books: {stats2['available_books']} (Expected: 6)")
print(f"Borrowed Books: {stats2['borrowed_books']} (Expected: 4)")
print(f"Total Users: {stats2['total_users']} (Expected: 5)")
print(f"Users with Books: {stats2['users_with_books']} (Expected: 3)")Todas las lecciones de Object Oriented Programming
1Fundamentos de la POO
Archivos externosIntroducción a la POOClases vs ObjetosEl parámetro selfMétodosAtributosMétodo constructor (__init__)Resumen - Calculadora simple4Herencia
Herencia básicaLa función super()Sobrescritura de métodosHerencia múltipleOrden de resolución de métodosResumen - Jerarquía de empleados7Métodos especiales
Introducción a los métodos mágicosSobrecarga de operadoresMétodos mágicos de contenedoresRepaso - Lista personalizada10Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy2Decoradores
Introducción a los decoradoresDecorador propertyDecorador de métodos estáticosDecorador de métodos de clase5Polimorfismo
Sobreescritura de métodos revisitadaDuck TypingClases y métodos abstractosDiseño de interfacesResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaMixinsMétodos estáticos y de claseDecoradores de claseGestores de contexto11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Propiedades de clase
Variables de instancia vs de claseDecoradores de propiedadesAtributos privadosResumen - Gestor de cuentas bancarias6Encapsulamiento
Miembros públicos, protegidos y privadosModificadores de accesoOcultamiento de informaciónDecoradores de propiedades avanzadosResumen - Sistema de registros de estudiantes12Proyecto: Gestión de biblioteca
Descripción general del proyectoClases de Libros y UsuariosSistema de préstamosFuncionalidad de búsquedaInterfaz de administradorPruebas e integración