Ing. Bernardo Prado · DSM3 · UTH 2026-2
Módulo de práctica: Clase con atributo de clase, constructor, métodos y representación __str__. Resuelve cada ejercicio implementando el código en Python 3.
Una videoteca gestiona su catálogo. Cada Pelicula tiene código, título, director y género. El sistema limita a 5 alquileres simultáneos por película. Implementa: hay_disponibilidad(), alquilar(), devolver() y __str__ con operador ternario.
codigo, titulo, director, genero y guarda cada uno con self.x = x. Además inicializa self.alquileres_activos = 0 (contador en cero al crear la película).return con la comparación: return self.alquileres_activos < Pelicula.MAXIMO_ALQUILERES. Si hay menos de 5 alquileres activos → True; si ya se alcanzó el límite → False.if self.hay_disponibilidad():self.alquileres_activos += 1 y return True.if → return False (sin cupo).if self.alquileres_activos > 0: — solo devuelve si hay algo activo.self.alquileres_activos -= 1 y return True.return False (nada que devolver).disp = "Sí" if self.hay_disponibilidad() else "No". Luego return un f-string multilinea con código, título, director, género, alquileres activos/MAXIMO y la variable disp.[V001] Interestelar | Dir: Nolan | Género: Sci-Fi | Alquileres: 1/5 | Disponible: Sí [V002] Parasite | Dir: Bong Joon-ho | Género: Drama | Alquileres: 0/5 | Disponible: Sí [V003] Dune | Dir: Villeneuve | Género: Aventura | Alquileres: 1/5 | Disponible: Sí
# ══════════════════════════════════════════════════════════════════════ # EJERCICIO 01 — Sistema de Videoteca # ══════════════════════════════════════════════════════════════════════ class Pelicula: # Define la clase Pelicula: es el molde para crear objetos película MAXIMO_ALQUILERES = 5 # Atributo de CLASE: límite global de 5 alquileres simultáneos # Al ser de clase, es compartido por TODOS los objetos Pelicula def __init__(self, codigo, titulo, director, genero): # Constructor: Python lo llama automáticamente al hacer Pelicula(...) self.codigo = codigo # Almacena el código identificador (p.ej. "V001") en el objeto self.titulo = titulo # Almacena el título de la película (p.ej. "Interestelar") self.director = director # Almacena el nombre del director (p.ej. "Nolan") self.genero = genero # Almacena el género cinematográfico (p.ej. "Sci-Fi") self.alquileres_activos = 0 # Contador de alquileres en curso; inicia en 0 al crear el objeto def hay_disponibilidad(self): # Método: comprueba si el contador aún no alcanzó el límite return self.alquileres_activos < Pelicula.MAXIMO_ALQUILERES # True si activos < 5 (hay cupo) | False si ya se llegó a 5 def alquilar(self): # Método: registra un nuevo alquiler si existe disponibilidad if self.hay_disponibilidad(): # Reutiliza hay_disponibilidad() para verificar si hay cupo self.alquileres_activos += 1 # Hay cupo: incrementa el contador en 1 registrando el alquiler return True # Retorna True: informa al llamador que el alquiler fue exitoso return False # Sin cupo: retorna False indicando que no se pudo alquilar def devolver(self): # Método: registra la devolución de un ejemplar alquilado if self.alquileres_activos > 0: # Solo procede si hay al menos 1 alquiler activo que devolver self.alquileres_activos -= 1 # Hay activos: decrementa el contador en 1 liberando el alquiler return True # Retorna True: devolución realizada con éxito return False # Sin activos: retorna False, no había nada que devolver def __str__(self): # Método especial: Python lo invoca automáticamente con print(objeto) disp = "Sí" if self.hay_disponibilidad() else "No" # Operador ternario: "Sí" si hay cupo, "No" si el límite fue alcanzado return ( # El paréntesis permite escribir el f-string en múltiples líneas f"[{self.codigo}] {self.titulo} | " # Código entre [ ] y título de la película f"Dir: {self.director} | " # Nombre del director con etiqueta "Dir:" f"Género: {self.genero} | " # Género con etiqueta "Género:" f"Alquileres: {self.alquileres_activos}/{Pelicula.MAXIMO_ALQUILERES} | " # Activos / máximo (p.ej. 1/5) f"Disponible: {disp}" # Disponibilidad evaluada con el ternario ) # Las f-strings contiguas dentro de () se concatenan en una sola cadena # ── Programa principal ────────────────────────────────────────────── p1 = Pelicula("V001", "Interestelar", "Nolan", "Sci-Fi") # Crea objeto p1; __init__ guarda 4 atributos e inicia alquileres_activos=0 p2 = Pelicula("V002", "Parasite", "Bong Joon-ho", "Drama") # Crea objeto p2 con los datos de Parasite; alquileres_activos=0 p3 = Pelicula("V003", "Dune", "Villeneuve", "Aventura") # Crea objeto p3 con los datos de Dune; alquileres_activos=0 p1.alquilar() # alquilar() → hay_disponibilidad()=True → alquileres_activos pasa 0→1 → retorna True p3.alquilar() # alquilar() → hay_disponibilidad()=True → alquileres_activos pasa 0→1 → retorna True # p2 NO se alquila → su alquileres_activos permanece en 0 print(p1) # → "[V001] Interestelar | Dir: Nolan | Género: Sci-Fi | Alquileres: 1/5 | Disponible: Sí" print(p2) # → "[V002] Parasite | Dir: Bong Joon-ho | Género: Drama | Alquileres: 0/5 | Disponible: Sí" print(p3) # → "[V003] Dune | Dir: Villeneuve | Género: Aventura | Alquileres: 1/5 | Disponible: Sí"
Una empresa calcula la nómina de empleados. Cada Empleado tiene ID, nombre, departamento y salario bruto. El sistema aplica un 15% de bono a empleados con salario > 15,000 y descuento fiscal del 15%. Muestra la nómina completa iterando la lista con for.
id_empleado, nombre, departamento, salario_bruto y guarda cada uno. Agrega self.tiene_bono = False — empieza sin bono hasta que aplicar_bono() lo active.neto = self.salario_bruto * (1 - Empleado.DESCUENTO_FISCAL) — aplica el 15% de descuento fiscal.if self.tiene_bono: neto *= (1 + Empleado.BONO_PORCENTAJE) — si aplica bono, incrementa el 15% adicional.return round(neto, 2)if self.salario_bruto > 15000: self.tiene_bono = True. Solo activa la bandera; el cálculo real ocurre en calcular_neto(). No retorna nada.bono_txt = "✓ Bono" if self.tiene_bono else "✗ Sin bono". Luego f-string con ID, nombre, departamento, salario bruto, resultado de calcular_neto() y bono_txt.nomina llamando primero emp.aplicar_bono() y luego print(emp) — en ese orden, porque __str__ usa tiene_bono que debe estar activado antes de imprimir.[E001] Luis Ramos | TI | Bruto: $18000 | Neto: $17595.0 | ✓ Bono [E002] Ana Torres | RRHH | Bruto: $12000 | Neto: $10200.0 | ✗ Sin bono [E003] Carlos Paz | TI | Bruto: $20000 | Neto: $19550.0 | ✓ Bono
# ══════════════════════════════════════════════════════════════════════ # EJERCICIO 02 — Nómina de Empleados # ══════════════════════════════════════════════════════════════════════ class Empleado: # Define la clase Empleado: modela a un trabajador y calcula su nómina BONO_PORCENTAJE = 0.15 # Atributo de CLASE: 15% de bono para quienes superen $15,000 bruto DESCUENTO_FISCAL = 0.15 # Atributo de CLASE: 15% de descuento fiscal aplicado a todos def __init__(self, id_empleado, nombre, departamento, salario_bruto): # Constructor: se ejecuta al hacer Empleado(...) self.id_empleado = id_empleado # Guarda el identificador único del empleado (p.ej. "E001") self.nombre = nombre # Guarda el nombre completo del empleado (p.ej. "Luis Ramos") self.departamento = departamento # Guarda el área de trabajo del empleado (p.ej. "TI" o "RRHH") self.salario_bruto = salario_bruto # Guarda el salario antes de descuentos o bonos (p.ej. 18000) self.tiene_bono = False # Bandera booleana; inicia en False → aplicar_bono() la activa si corresponde def calcular_neto(self): # Método: calcula el salario que el empleado recibirá efectivamente neto = self.salario_bruto * (1 - Empleado.DESCUENTO_FISCAL) # Paso 1: aplica 15% de descuento fiscal al bruto if self.tiene_bono: # Paso 2: verifica si la bandera de bono fue activada neto *= (1 + Empleado.BONO_PORCENTAJE) # Si sí: incrementa el neto en 15% adicional de bono return round(neto, 2) # Retorna el salario neto redondeado a 2 decimales def aplicar_bono(self): # Método: activa la bandera de bono si el salario supera los 15,000 if self.salario_bruto > 15000: # Solo para salarios brutos mayores estrictamente a 15,000 self.tiene_bono = True # Activa la bandera; calcular_neto() la leerá para ajustar el monto def __str__(self): # Método especial: Python lo invoca automáticamente con print(objeto) bono_txt = "✓ Bono" if self.tiene_bono else "✗ Sin bono" # Ternario: texto descriptivo según el estado del bono return ( # El paréntesis permite dividir el f-string en varias líneas f"[{self.id_empleado}] {self.nombre} | " # ID entre [ ] y nombre completo del empleado f"{self.departamento} | " # Departamento al que pertenece el empleado f"Bruto: ${self.salario_bruto} | " # Salario bruto original sin ningún ajuste f"Neto: ${self.calcular_neto()} | " # Llama calcular_neto() en tiempo real → aplica descuento y bono f"{bono_txt}" # Texto del ternario: "✓ Bono" o "✗ Sin bono" ) # Las f-strings contiguas dentro de () se concatenan en una sola cadena # ── Programa principal ────────────────────────────────────────────── nomina = [ # Lista que agrupa los tres objetos Empleado del sistema de nómina Empleado("E001", "Luis Ramos", "TI", 18000), # Salario 18000 > 15000 → aplicar_bono() activará tiene_bono=True Empleado("E002", "Ana Torres", "RRHH", 12000), # Salario 12000 ≤ 15000 → tiene_bono permanece en False Empleado("E003", "Carlos Paz", "TI", 20000), # Salario 20000 > 15000 → aplicar_bono() activará tiene_bono=True ] for emp in nomina: # Itera sobre cada objeto Empleado de la lista nomina emp.aplicar_bono() # PRIMERO: evalúa y activa tiene_bono si el salario supera 15,000 print(emp) # DESPUÉS: llama __str__(); tiene_bono ya está evaluado → salida correcta # Verificación de cálculos: # E001: 18000 × 0.85 = 15300.0 → con bono: 15300 × 1.15 = 17595.0 ✓ # E002: 12000 × 0.85 = 10200.0 → sin bono: neto = 10200.0 ✓ # E003: 20000 × 0.85 = 17000.0 → con bono: 17000 × 1.15 = 19550.0 ✓