Domina la herencia en Python con un ejemplo claro y útil: un sistema de usuarios que evita duplicar código entre estudiantes y profesores. Aprenderás a usar la clase base, la herencia simple, el método constructor, la sobrescritura de métodos y una validación práctica de límite de libros. Todo con mensajes de retorno consistentes y listas para registrar préstamos.
¿Qué resuelve la herencia simple en Python?
La herencia simple permite que una clase hija copie funcionalidades y atributos de una clase padre. Aquí, Usuario es la base que comparten Estudiante y Profesor, lo que evita reescribir atributos comunes como nombre y cédula y métodos como solicitar libro.
Reduce duplicación de código y errores.
Centraliza atributos y comportamientos comunes.
Facilita extender con nuevos atributos específicos.
Mantiene mensajes de retorno consistentes.
¿Cómo se implementan usuario, estudiante y profesor con super?
Partimos del archivo usuarios.py y definimos la clase base con los atributos comunes. Las clases hijas heredan colocando el nombre de la clase padre entre paréntesis. El uso de super en el constructor (init) llama al init de la clase padre sin nombrarla directamente, evitando confusiones y acoplamientos innecesarios.
¿Cómo definir atributos comunes y lista de libros prestados?
En Usuario centralizamos nombre, cédula y una lista compartida para registrar préstamos. Así resolvemos el posible bug de duplicar la lista en hijas.
classUsuario:def__init__(self, nombre, cedula): self.nombre = nombre
self.cedula = cedula
self.libros_prestados =[]defsolicitar_libro(self, titulo):returnf"Solicitud de libro '{titulo}' realizada."
¿Cómo agregar carrera y límite de libros al estudiante?
Estudiante hereda de Usuario, añade la carrera y define un límite de libros de 3 por defecto.
classEstudiante(Usuario):def__init__(self, nombre, cedula, carrera):super().__init__(nombre, cedula) self.carrera = carrera
self.limite_libros =3
¿Qué cambia en el profesor y por qué límite es None?
Profesor también hereda de Usuario, pero su límite no aplica: se usa None para indicar que no hay restricción.
¿Cómo funciona solicitar libro y la sobrescritura con validación?
Definimos un método base que retorna un mensaje simple y lo sobrescribimos en las clases hijas. En Estudiante, se valida con len de la lista si aún puede prestar; si sí, se agrega con append y se retorna un mensaje de préstamo autorizado. Si alcanzó el límite, retorna un texto de límite alcanzado. En Profesor, no hay validación: se agrega y se confirma el préstamo.
classUsuario:# ... (mismo __init__)defsolicitar_libro(self, titulo):returnf"Solicitud de libro '{titulo}' realizada."classEstudiante(Usuario):# ... (mismo __init__)defsolicitar_libro(self, titulo):iflen(self.libros_prestados)< self.limite_libros: self.libros_prestados.append(titulo)returnf"Préstamo del libro '{titulo}' autorizado."else:returnf"No puedes prestar más libros. Límite alcanzado: {self.limite_libros}."classProfesor(Usuario):# ... (mismo __init__)defsolicitar_libro(self, titulo): self.libros_prestados.append(titulo)returnf"Préstamo del libro '{titulo}' autorizado."
Usuario retorna confirmación simple de solicitud.
Estudiante sobrescribe para validar el límite antes de agregar.
Profesor sobrescribe para agregar sin límite.
Mensajes consistentes facilitan pruebas con print y lectura en terminal.
¿Cómo probar la lógica con instancias y print?
Creamos un estudiante y un profesor, luego pedimos cuatro libros para comprobar límites y mensajes.
¿Te gustaría extender la funcionalidad? Crea y comenta un método para que un estudiante pueda devolver un libro y que la lista quede actualizada. ¿Cómo gestionarías el caso en que intente devolver un libro que no tiene?.
def devolver_libro(self, titulo):if titulo in self.libros_prestados: self.libros_prestados.remove(titulo) self.limite_libros-=1return f"el libro {titulo} ha sido devuelto exitosamente, su limite de libros ahora es de {self.limite_libros}, sus libros prestados son {self.libros_prestados}"else:return f"este libro {titulo} no esta en su lista de libros prestados, devolucion rechazada"
Muy buena implementación
🧠HERENCIA SIMPLE EN PYTHON
🎯 Objetivo General
Aprender cómo la herencia simple permite reutilizar código en Python.
📚 Ejemplo práctico: un sistema de usuarios (Estudiante y Profesor) que heredan de una clase base llamada Usuario.
🧩 Concepto Clave
🔹 La herencia simple permite que una clase hija copie atributos y métodos de una clase padre.
👉 En este caso:
Usuario ➜ Clase base
Estudiante y Profesor ➜ Clases hijas
💡 ¿Por qué usar herencia?
✨ Beneficios principales:
🚫 Elimina código duplicado
🧭 Centraliza atributos y comportamientos comunes
🔧 Facilita extender con funciones nuevas
📏 Mantiene mensajes y respuestas consistentes
⚙️ Estructura General del Ejemplo
📁 Archivo:
📜 Estrategia: usar super() para acceder al constructor del padre sin mencionarlo directamente.
🧱 Diagrama Conceptual:
Usuario
├── Estudiante
└── Profesor
👤 Clase Base: Usuario
🧩 Contiene los atributos y métodos comunes a todos los usuarios.
class Usuario:
def __init__(self, nombre, cedula):
self.nombre = nombre
self.cedula = cedula
self.libros_prestados = []
def solicitar_libro(self, titulo):
return f"Solicitud de libro '{titulo}' realizada."
🧠 Qué hace:
Guarda nombre y cédula.
Lleva el registro de libros prestados.
Define el método básico de solicitud.
🎓 Clase Hija: Estudiante
👨🎓 Añade el atributo carrera y un límite de 3 libros.
class Estudiante(Usuario):
def __init__(self, nombre, cedula, carrera):
super().__init__(nombre, cedula)
self.carrera = carrera
self.limite_libros = 3
📌 Diferencia clave:
El estudiante solo puede prestar 3 libros.
🧑🏫 Clase Hija: Profesor
👩🏫 Hereda de Usuario, pero sin límite de libros.
class Profesor(Usuario):
def __init__(self, nombre, cedula):
super().__init__(nombre, cedula)
self.limite_libros = None
📌 Diferencia clave:
El profesor puede prestar todos los libros que desee.
🔁 Sobrescritura del Método solicitar_libro
Cada clase redefine (sobrescribe) el método según sus reglas:
🧱 Usuario
Mensaje genérico de solicitud.
def solicitar_libro(self, titulo):
return f"Solicitud de libro '{titulo}' realizada."
🎓 Estudiante
Controla el número de préstamos.
def solicitar_libro(self, titulo):
if len(self.libros_prestados) < self.limite_libros:
self.libros_prestados.append(titulo)
return f"Préstamo del libro '{titulo}' autorizado."
else:
return f"No puedes prestar más libros. Límite alcanzado: {self.limite_libros}."
🔍 Validación incluida:
✔️ Si hay espacio disponible → agrega el libro
❌ Si ya alcanzó el límite → muestra mensaje de advertencia
🧑🏫 Profesor
No valida el límite.
def solicitar_libro(self, titulo):
self.libros_prestados.append(titulo)
return f"Préstamo del libro '{titulo}' autorizado."
📘 Resultado: Todos los préstamos son aprobados.
Suelo tomar las clases en el celular y trabajar en laptop, pero ahora me aparecen preguntas sorpresa a media clase que debo responder bien sí o sí. Si no me reinicia la clase. Si quiero volver al tiempo donde quedaba en la clase ya no puedo moverlo, debo presionar adelantar cada 15 segundos y cuando llego a esa parte nuevamente me sale el cuestionario, aunque ya lo haya respondido bien 😅
No tiene que ver con la clase, va perfecta de echo, pero ojalá resuelvan pronto eso, o si es posible me ayuden con ese detalle
Te recomiendo que les escribas a así te lee el equipo adecuado para solucionar tu problema!
Personalmente no me gustan esas ventanas emergentes porque me "rompen el ritmo" de la clase, pero veo el lado positivo de que Platzi busca que reafirmemos lo aprendido
classUsuario: #Método constructor
def __init__(self, nombre, cedula): self.nombre= nombre
self.cedula= cedula
self.libros_prestamos=[] def solicitar_prestamo(self, titulo):return f"solicitud de préstamo de {titulo} realizada"#Clase hija HEREDA de la clase Usuario(herencia)classEstudiante(Usuario): #Método constructor
def __init__(self, nombre, cedula, carrera):super().__init__(nombre, cedula) self.carrera= carrera
self.limite_prestamos=3 def solicitar_prestamo(self, titulo):iflen(self.libros_prestamos)< self.limite_prestamos: self.libros_prestamos.append(titulo)return f"préstamo del libro *{titulo}, realizado"return f"no se puede realizar el préstamo del libro *{titulo}, porque se ha alcanzado el límite de préstamos: {self.limite_prestamos}" def devolver_prestamo(self, titulo):if titulo in self.libros_prestamos: self.libros_prestamos.remove(titulo)return f"devolución del libro *{titulo}, realizada. Libros pendientes: {len(self.libros_prestamos)}, titulos: {self.libros_prestamos}"return f"no se puede realizar la devolución del libro *{titulo}, porque no se ha prestado"classProfesor(Usuario): #Método constructor
def __init__(self, nombre, cedula):super().__init__(nombre, cedula) self.limite_prestamos=None def solicitar_prestamo(self, titulo): self.libros_prestamos.append(titulo)return f"préstamo del libro *{titulo}, realizado"estudiante =Estudiante("Juan","1234567890","Ingeniería")profesor =Profesor("Pedro","1234567890")print(estudiante.solicitar_prestamo("El principito"))print(estudiante.solicitar_prestamo("1984"))print(estudiante.solicitar_prestamo("El quijote"))print(estudiante.solicitar_prestamo("La biblia"))print(profesor.solicitar_prestamo("El principito"))print(profesor.solicitar_prestamo("1984"))print(profesor.solicitar_prestamo("El quijote"))print(profesor.solicitar_prestamo("La biblia"))print(estudiante.devolver_prestamo("El principito"))print(estudiante.devolver_prestamo("1984"))
defdevolver_libro(self, titulo):ifnot titulo in self.libros_prestados:returnf"El libro '{titulo}' no ha sido prestado al usuario {self.nombre}" self.libros_prestados.remove(titulo)returnf"Libro '{titulo}' ha sido devuelto."
classUsuario: def __init__(self, nombre, cedula): self.nombre= nombre
self.cedula= cedula
self.libros_prestados=[] def solicitar_libro(self, titulo):return f"Solicitud de libro '{titulo}' realizada" def devolver_libro(self, titulo):if titulo in self.libros_prestados: self.libros_prestados.remove(titulo)return f"Libro {titulo} devuelto con exito"else:return f"{titulo} no se encuentra la lista de libros prestados"classEstudiante(Usuario): def __init__(self, nombre, cedula, carrera):super().__init__(nombre, cedula) self.carrera= carrera
self.limite_libros=3 def solicitar_libro(self, titulo):iflen(self.libros_prestados)< self.limite_libros: self.libros_prestados.append(titulo)return f"Prestamo de libro: {titulo} autorizado"else:return( f"No puedes prestar más libros, Limite alcanzado: {self.limite_libros}")classProfesor(Usuario): def __init__(self, nombre, cedula, departamento):super().__init__(nombre, cedula) self.departamento= departamento
self.limite_libros=None def solicitar_libro(self, titulo): self.libros_prestados.append(titulo)return f"Prestamo de libro: {titulo} autorizado"estudiante =Estudiante("Luis","54376","De relevos")profesor =Profesor("Manuel","65486","Programacion")print(estudiante.solicitar_libro("Python Basico"))print(estudiante.solicitar_libro("Python Intermedio"))print(estudiante.solicitar_libro("Python Avanzado"))print(estudiante.solicitar_libro("Python / Django"))print(profesor.solicitar_libro("Python Basico"))print(profesor.solicitar_libro("Python Intermedio"))print(profesor.solicitar_libro("Python Avanzado"))print(profesor.solicitar_libro("Python / Django"))print(estudiante.devolver_libro("Python Basico"))print(estudiante.devolver_libro("Python Intermedio"))print(estudiante.devolver_libro("Python Avanzado"))print(estudiante.devolver_libro("Python / Django"))print(profesor.devolver_libro("Python Basico"))print(profesor.devolver_libro("Python Intermedio"))print(profesor.devolver_libro("Python Avanzado"))print(profesor.devolver_libro("Python / Django"))
Mi método para devolver el libro:
🧑💻💻📚👍
def devolver_libro(self, titulo):if titulo in self.libros_prestados: self.libros_prestados.remove(titulo)return"Libro devuelto con éxito."return f"El libro {titulo} no lo has solicitado."
defreturn_book(self, title:str)->str:if title in self.lend_books: self.lend_books.remove(title)returnf"Libro {title} devuelto exitosamente."else:returnf"Libro '{title}' no fue prestado al usuario."
agregue tambien una funcion que muestre los libros prestados
classUsuarios:def__init__(self,nombre, cedula): self.nombre = nombre
self.cedula = cedula
self.libros_prestados =[]defsolicitud_libro(self, titulo):returnf"\nla solicitud del libro {titulo} realizada"defmostrar_prestados(self): encabezado =f"Libros prestados a {self.nombre}: "ifnot self.libros_prestados:return encabezado +"No tenés libros prestados."return encabezado +", ".join(self.libros_prestados)defdevolver_libro(self, titulo):for libro in self.libros_prestados:if titulo.lower()== libro.lower(): self.libros_prestados.remove(libro)returnf"\n'{titulo}' se ha devuelto con exito"returnf"\nlibro no devuelto, {titulo} no se ha encontrado"classEstudiante(Usuarios):def__init__(self, nombre, cedula,carrera):super().__init__(nombre, cedula) self.carrera = carrera
self.limite_libros =3defsolicitud_libro(self, titulo):if self.limite_libros >len(self.libros_prestados): self.libros_prestados.append(titulo)return(f"\nla solicitud del libro '{titulo}' realizada")else:return(f"\nse ha alcanzado el limite de libros prestados ({self.limite_libros}) porfavor devuelva alguno ante de solicitar uno nuevo")classProfesor(Usuarios):def__init__(self, nombre, cedula):super().__init__(nombre, cedula) self.limite_libros =Nonedefsolicitud_libro(self, titulo): self.libros_prestados.append(titulo)return(f"\nla solicitud del libro '{titulo}' realizada")estudiante = Estudiante("carlos",1231233,"ing. informatica")profesor = Profesor("ricardo",123142124)print("\nejemplo estudiante")print(estudiante.solicitud_libro("python lv 1"))print(estudiante.solicitud_libro("python lv 2"))print(estudiante.solicitud_libro("python lv 3"))print(estudiante.solicitud_libro("python lv 4"))print(estudiante.mostrar_prestados())print(estudiante.devolver_libro("python lv 1"))print(estudiante.solicitud_libro("python lv 4"))print(estudiante.mostrar_prestados())print("\nejemplo profesor")print(profesor.solicitud_libro("python lv 1"))print(profesor.solicitud_libro("python lv 2"))print(profesor.solicitud_libro("python lv 3"))print(profesor.solicitud_libro("python lv 4"))print(profesor.mostrar_prestados())print(profesor.devolver_libro("python lv 1"))print(profesor.mostrar_prestados())
Comparto mi reto (codigo completo):
classUsuario:def__init__(self, nombre, cedula): self.nombre = nombre
self.cedula = cedula
self.libros_prestados =[]defsolicitar_libro(self, titulo):returnf"La solicitud del libro '{titulo}' realizada"classEstudiante(Usuario):def__init__(self, nombre, cedula, carrera):super().__init__(nombre, cedula) self.carrera = carrera
self.limite_libros =3defsolicitar_libro(self, titulo):iflen(self.libros_prestados)< self.limite_libros: self.libros_prestados.append(titulo)returnf"Prestamo del libro '{titulo} autorizado"else:return(f"No puedes prestar mas libros, Limite alcanzado: {self.limite_libros}")defdevolver_libro(self, titulo): self.libros_prestados.remove(titulo)returnf"Devolucion del libro '{titulo}' exitosa"classProfesor(Usuario):def__init__(self, nombre, cedula, departamento):super().__init__(nombre, cedula) self.departamento = departamento
self.limite_libros =Nonedefsolicitar_libro(self, titulo): self.libros_prestados.append(titulo)returnf"Prestamo del libro '{titulo}' autorizado"estudiante = Estudiante("Luis","1223131313","Sistemas")profesor = Profesor("Felipe","21315364651","Ciencias")print(estudiante.solicitar_libro("Python Basico"))print(estudiante.solicitar_libro("Python Intermedio"))print(estudiante.solicitar_libro("Python Avanzado"))print(estudiante.devolver_libro("Python Avanzado"))print(estudiante.solicitar_libro("Python / Django"))print("\n")print(profesor.solicitar_libro("Python Basico"))print(profesor.solicitar_libro("Python Intermedio"))print(profesor.solicitar_libro("Python Avanzado"))print(profesor.solicitar_libro("Python / Django"))
Les comparto mi código con el reto
"""_Partimos del archivo usuarios.py y definimos la clase base con los
atributos comunes. Las clases hijas heredan colocando el nombre de la
clase padre entre paréntesis.
El uso de super en el constructor (init) llama al init de la clase padre
sin nombrarla directamente, evitando confusiones y acoplamientos innecesarios.
"""classUsuario:def__init__(self, nombre, cedula): self.nombre = nombre
self.cedula = cedula
self.libros_prestados =[]# Se inicializa la lista de libros prestados para cada estudiante, lo que permite llevar un registro de los libros que cada estudiante tiene prestados.# Se pone aquí la lista porque ambos usuarios están usando la lista de libros prestados, por lo que es un atributo común que se puede definir en la clase padre Usuario para evitar duplicación de código en las clases hijas Estudiante y Profesor.defsolicitar_libro(self, titulo):# Permite agregar dentro de una lista de libros prestados el título del libro solicitado por el usuario, lo que permite llevar un registro de los libros que cada usuario tiene prestados.returnf"Solicitud de libro '{titulo}' realizada."classEstudiante(Usuario):# Se hereda en el paréntesis para que herede los atributos de la clase padre.def__init__(self, nombre, cedula, carrera):super().__init__(nombre, cedula)# Super permite llamar al constructor de la clase padre para inicializar los atributos heredados sin tener que nombrar directamente la clase padre, lo que hace que el código sea más flexible y menos acoplado.# __init__ es el constructor de la clase, es decir, el método que se ejecuta al crear una instancia de la clase. Por ejemplo, cuando se crea un objeto de la clase Estudiante, se llama automáticamente al método __init__ para inicializar los atributos del objeto. self.carrera = carrera # Atributo específico de la clase Estudiante, que no es heredado de la clase Usuario. Se debe agregar en el constructor de la clase Estudiante para que se inicialice correctamente al crear una instancia de Estudiante. self.limite_libros =3# Se establece un límite de libros para los estudiantes, lo que significa que un estudiante no puede tener más de 3 libros prestados al mismo tiempo. Este atributo es específico de la clase Estudiante y no se hereda de la clase Usuario, por lo que se debe agregar en el constructor de la clase Estudiante para que se inicialice correctamente al crear una instancia de Estudiante.defsolicitar_libro(self, titulo):# Copiamos el método solicitar_libro para agregar la lógica de límite de libros prestados para los estudiantes, ya que el comportamiento de solicitar un libro es diferente para los estudiantes en comparación con los profesores, por lo que se debe sobreescribir el método solicitar_libro en la clase Estudiante para implementar esta lógica específica.iflen(self.libros_prestados)< self.limite_libros:# len permite obtener la cantidad de libros prestados actualmente por el estudiante, y se compara con el límite establecido para determinar si se puede autorizar el préstamo del libro solicitado. self.libros_prestados.append(titulo)returnf"Préstamo del libro '{titulo}' autorizado."else:return(f"No puedes prestar más libros. Límite alcanzado: {self.limite_libros}.")defdevolver_libro(self, titulo):# Permite a un estudiante devolver un libro y actualiza la lista de libros prestados. Gestiona el caso en que el estudiante intente devolver un libro que no tiene.if titulo in self.libros_prestados:# Verifica si el libro solicitado está en la lista de libros prestados del estudiante. self.libros_prestados.remove(titulo)# Si el libro está en la lista, lo elimina usando el método remove().returnf"Devolución del libro '{titulo}' registrada. Total de libros: {len(self.libros_prestados)}."else:# Si el libro no está en la lista de libros prestados, se retorna un mensaje de error.returnf"No tienes el libro '{titulo}' prestado."classProfesor(Usuario):# Al agregar la clase Profesor como hija de Usuario, se heredan los atributos y métodos de la clase padre como nombre y cedula.def__init__(self, nombre, cedula):# El método constructor se ejecuta automáticamente al crear una instancia de la clase Profesor.super().__init__(nombre, cedula) self.limite_libros =None# No hay límite de libros para los profesores, por lo que se establece como None. Este atributo es específico de la clase Profesor y no se hereda de la clase Usuario, por lo que se debe agregar en el constructor de la clase Profesor para que se inicialice correctamente al crear una instancia de Profesor.# Esta es una herencia simple, ya que solo hay una clase padre (Usuario) y dos clases hijas (Estudiante y Profesor). No debemos sobreescribir el método solicitar_libro en las clases hijas, ya que el comportamiento de solicitar un libro es el mismo tanto para estudiantes como para profesores, por lo que se puede utilizar el método heredado de la clase Usuario sin necesidad de modificarlo.# Tampoco debemos volver a escribir las líneas de nombre y cedula en las clases hijas, ya que estos atributos son heredados de la clase Usuario y se inicializan correctamente al llamar al constructor de la clase padre con super().__init__(nombre, cedula). Esto evita la duplicación de código y mantiene una estructura más limpia y mantenible.defsolicitar_libro(self, titulo): self.libros_prestados.append(titulo)returnf"Préstamo del libro '{titulo}' autorizado."defdevolver_libro(self, titulo):# Permite a un profesor devolver un libro y actualiza la lista de libros prestados.if titulo in self.libros_prestados: self.libros_prestados.remove(titulo)returnf"Devolución del libro '{titulo}' registrada. Total de libros: {len(self.libros_prestados)}."else:returnf"No tienes el libro '{titulo}' prestado."# Hacemos las pruebas creando instancias de Estudiante y Profesor, y solicitando libros para cada uno, lo que permite verificar que la lógica de límite de libros prestados para los estudiantes se implementa correctamente, mientras que los profesores pueden solicitar libros sin restricciones.# Instanciar objetos: retorna una variable que representa un objeto de la clase, lo que permite crear múltiples objetos con diferentes atributos y comportamientos basados en la misma clase. Por ejemplo, al crear una instancia de Estudiante, se puede asignar un nombre, cédula y carrera específicos para ese estudiante, lo que permite tener múltiples estudiantes con diferentes características en el sistema. De manera similar, al crear una instancia de Profesor, se puede asignar un nombre y cédula específicos para ese profesor, lo que permite tener múltiples profesores con diferentes características en el sistema. Esto es fundamental para la programación orientada a objetos, ya que permite modelar entidades del mundo real de manera más flexible y organizada.estudiante = Estudiante("Luis","123456","Ingeniería")# Las variables empiezan con minúscula por convención, y en mayúscula para las clases, así podemos crear instancias de las clases.profesor = Profesor("Ana","987654")# Pruebas de préstamoprint("=== PRUEBAS DE PRÉSTAMO ===")print("\n")print(estudiante.solicitar_libro("Python básico"))print(estudiante.solicitar_libro("Python intermedio"))print(estudiante.solicitar_libro("Python avanzado"))print(estudiante.solicitar_libro("Python Django"))# Debe indicar límite alcanzado: 3print("\n")# Salto de línea para separar las pruebas de estudiante y profesorprint(profesor.solicitar_libro("Python básico"))print(profesor.solicitar_libro("Python intermedio"))print(profesor.solicitar_libro("Python avanzado"))print(profesor.solicitar_libro("Python Django"))# Todos autorizados# Pruebas de devolución de librosprint("\n=== PRUEBAS DE DEVOLUCIÓN ===")print(f"Libros prestados del estudiante antes: {estudiante.libros_prestados}")print(estudiante.devolver_libro("Python básico"))# Debe devolver exitosamenteprint(f"Libros prestados del estudiante después: {estudiante.libros_prestados}")print("\nIntentando devolver un libro que no tiene...")print(estudiante.devolver_libro("Python Django"))# Debe indicar que no tiene este libroprint("\n")print(f"Libros prestados del profesor antes: {profesor.libros_prestados}")print(profesor.devolver_libro("Python intermedio"))# Debe devolver exitosamenteprint(f"Libros prestados del profesor después: {profesor.libros_prestados}")print("\nIntentando devolver un libro que no tiene...")print(profesor.devolver_libro("Harry Potter"))# Debe indicar que no tiene este libro
Siguiendo lo aprendido en clase para evitar la duplicación de código y como Tanto Estudiante como Profesor tienen un método devolver_libroidéntico entonces lodefinimos una sola vez enUsuario, y dejar que ambos lo hereden:
defdevolver_libro(self, titulo):if titulo in self.libros_prestados: self.libros_prestados.remove(titulo)returnf"{self.nombre} ha devuelto el libro: {titulo}"else:returnf"{self.nombre} no tiene el libro: {titulo} prestado."
Hola Samuel, si el método de las clases hijas realiza exactamente la misma funcionalidad que el método definido en la clase padre, volver a declararlo en cada hija es redundante. En esos casos, lo ideal es definirlo solo en la clase padre y permitir que las hijas lo hereden directamente. De todas formas, puedo estar equivocado o haber interpretado mal tu ejemplo.
classUsuario: def __init__(self, nombre, cedula): self.nombre= nombre
self.cedula= cedula
self.libros_prestados=[] def solicitar_libro(self, titulo):return f"Ha solicitado el libro '{titulo}'."classEstudiante(Usuario): def __init__(self, nombre, cedula, carrera):super().__init__(nombre, cedula) self.carrera= carrera
self.limite_libros=3 def solicitar_libro(self, titulo):iflen(self.libros_prestados)< self.limite_libros: self.libros_prestados.append(titulo)return f"✓ Estudiante {self.nombre} ha solicitado el libro '{titulo}'. ({len(self.libros_prestados)}/{self.limite_libros})"else:return f"❌ Estudiante {self.nombre} ha alcanzado el límite de libros prestados." def devolver_libro(self, titulo):if titulo in self.libros_prestados: self.libros_prestados.remove(titulo)return f"✓ Estudiante {self.nombre} ha devuelto '{titulo}'. ({len(self.libros_prestados)}/{self.limite_libros})"else:return f"❌ Estudiante {self.nombre} no tiene prestado '{titulo}'."classProfesor(Usuario): def __init__(self, nombre, cedula, departamento):super().__init__(nombre, cedula) self.departamento= departamento
def solicitar_libro(self, titulo): self.libros_prestados.append(titulo)return f"✓ Profesor {self.nombre} ha solicitado el libro '{titulo}'. (Total: {len(self.libros_prestados)})"
classUser:def__init__(self, name, identification): self.__name = name
self.__identification = identification
self.books =[] self.books_limit =0defadd_book(self, book_title):returnf"book {book_title} added \n"defremove_book(self, book_title):if book_title in self.__books: self.books.remove(book_title)deffetch_books(self):print(f"The user: {self.__name} currently has the following books on loan \n")for i, book inenumerate(self.books,1):print(f"{i}. {book}\n")classStudent(User):def__init__(self, name, identification, carrer:str):super().__init__(name, identification) self.carrer = carrer
self.books_limit =3defadd_book(self, book_title):iflen(self.books)< self.books_limit: self.books.append(book_title)returnsuper().add_book(book_title)else:returnf"You exceeded the max loans limit: {self.books_limit}\n"classTeacher(User):def__init__(self, name, identification):super().__init__(name, identification) self.books_limit =Nonedefadd_book(self, book_title): self.books.append(book_title)returnsuper().add_book(book_title)
Dejo el reto y un dato curioso:
def devolver_libro(self, titulo):if titulo in self.libros_prestados: self.libros_prestados.remove(titulo)return f'Has devuelto el libro {titulo}'else:if self.libros_prestados:return'El titulo no esta en la lista de libros prestados'else:return'No tienes libros por retornar'
Esa fue mi version sencilla, ahora, comparto una cosita que estaba viendo con Gemini que me hizo enamorarme un poquito más de este lenguaje de programación,
De acuerdo al Zen de Python: EAFP (Easier to Ask for Forgiveness than Permission)
una solución alternativa sería, usar un try except y cuando nos de error, entonces usaremos el error para determinar qué sucede y seguir adelante:
Solución de Gemini
def devolver_libro_EAFP(self, titulo):try: # 1.Intenta remover el libro.Si tiene éxito, hemos terminado.self.libros_prestados.remove(titulo)return f'Has devuelto el libro {titulo}' except ValueError: # 2.Si self.libros_prestados.remove(titulo) falló, # es porque el libro no existe en la lista.if not self.libros_prestados: # 2a.Si falla Y la lista está vacía, este es el mensaje más preciso.return'No tienes libros por retornar'else: # 2b.Si falla Y la lista NO está vacía, el libro no está en la lista.return'El titulo no esta en la lista de libros prestados'
Dejo esto por acá porque me sorprendió un poco que tan arraigado puede estar la personalidad de un lenguaje de programación en lo que hacemos, también se me hizo gracioso este enfoque de, deja que el programa explote un poquito y usamos el error para seguir adelante y determinar lo siguiente. Entonces, adelante y a darse de cara con los errores 😂 y los usamos para seguir adelante, como la vida misma!
Sí pero... hay que tener cuidado. no se debem anidaar try excepts porque causa confusiones.
#una forma menos efectiva pero funcional
def devolve_libro(self, titulo):for libro in self.libros_prestados:if(titulo == libro): self.libros_prestados.remove(libro)return f"Devolucion del libro {titulo} realizada"return f"No tienes prestado el libro {titulo}"
Intenta aprender cuánto espacio y tiempo toma la función que tú estás escribiendo versus una más óptima
¿Cuál es el punto de poner límite al profesor si ese límite no existe ni lo incluimos de ninguna manera en la lógica?
La idea que tenía ahí era dejar explicito que el profesor no tiene limites. Si por ejemplo en la clase padre ponen un limite el profesor no asumiría ese limite puesto que tiene definido que NO tendrá limites.
Apliqué lo del atributo privado haha
classUser: def __init__(self, name, registration_number): self.name= name
self.registration_number= registration_number
self.__checked_out_books=[] def get_checked_out_books(self):return self.__checked_out_books def set_checked_out_books(self, books): self.__checked_out_books= books
def check_out_book(self, book_title): self.__checked_out_books.append(book_title)return f"{book_title} has been checked out" def check_in_book(self, book_title):if book_title in self.__checked_out_books: self.__checked_out_books.remove(book_title)return f"{book_title} has been checked in"else:return f"Didn't find {book_title} in the books list"classStudent(User): def __init__(self, name, registration_number, major):super().__init__(name, registration_number) self.major= major
self.checked_out_books_limit=3 def check_out_book(self, book_title):iflen(self.get_checked_out_books())< self.checked_out_books_limit:returnsuper().check_out_book(book_title)else:return f"Limit exceeded for checking out books. {book_title} couldn't be borrowed"classProfessor(User): pass
student =Student("Fran","110011","CS")professor =Professor("Erick","111011")print(student.check_out_book("The Life of a Showgirl"))print(student.check_out_book("The Tortured Poets Department"))print(student.check_out_book("Midnights"))print(student.check_out_book("Evermore"))print("------------"*10)print(professor.check_out_book("The Life of a Showgirl"))print(professor.check_out_book("The Tortured Poets Department"))print(professor.check_out_book("Midnights"))print(professor.check_out_book("Evermore"))
classUsuario:def__init__(self, nombre, dni): self.nombre = nombre
self.dni = dni
self.libros_Prestados =[]defdevolver(self, titulo):if titulo in self.libros_Prestados: self.libros_Prestados.remove(titulo)returnf"El libro {titulo} ha sido devuelto exitosamente"else:returnf"No puedes devolver un libro que no tienes"classEstudiante(Usuario):def__init__(self,nombre,dni,carrera):super().__init__(nombre,dni) self.carrera = carrera
self.limite_Libros =3defprestamo(self, titulo):iflen(self.libros_Prestados)< self.limite_Libros : self.libros_Prestados.append(titulo)returnf"El libro {titulo} ha sido prestado exitosamente"else:returnf"El libro {titulo} no puede ser prestado ya que superaste tu limite de prestamos."classProfesor(Usuario):def__init__(self,nombre,dni):super().__init__(nombre,dni) self.limite_Libros =Nonedefprestamo(self,titulo): self.libros_Prestados.append(titulo)returnf"el libro {titulo} ha sido prestado exitosamente."