DMarlon Studio

Lección 9 · 9 de 20

Herencia y super() · Python

Reutilice y especialice clases en Python con herencia: subclases, super(), sobrescritura de métodos, isinstance y el MRO, con una nómina.

Python · Herencia y super() en DMarlon Studio: el código del ejemplo y su salida en la terminal

class Manager(Employee) crea una subclase: un Manager es un Employee y hereda todo lo que este tiene (name, salary, describe()…) sin volver a escribirlo.

El __init__ de Manager necesita un dato más, bonus. En lugar de copiar el código del padre, llama a `super().__init__(name, salary)` para que Employee prepare su parte y luego añade la suya. Intern no define __init__, así que usa el del padre tal cual.

Las dos subclases sobrescriben monthly_pay(): un método con el mismo nombre sustituye al heredado. Manager reaprovecha el cálculo del padre con super().monthly_pay() y suma la prima; Intern devuelve una beca fija.

Lo potente es el polimorfismo: describe() está escrito una sola vez en Employee, pero self.monthly_pay() llama en cada caso al método de la clase real del objeto, y type(self).__name__ escribe esa clase. El bucle trata igual a todos y cada uno responde a su manera.

isinstance(staff[1], Employee) es True porque un jefe también es empleado, e issubclass compara clases. Manager.__mro__ es el orden de resolución de métodos: la lista de clases donde Python busca cada método, de la más concreta a object.

Código · main.py

class Employee:    def __init__(self, name, salary):        self.name = name        self.salary = salary    def monthly_pay(self):        return self.salary / 12    def describe(self):        return f"{self.name:<6} {type(self).__name__:<9} {self.monthly_pay():>8.2f}"class Manager(Employee):              # Manager is an Employee    def __init__(self, name, salary, bonus):        super().__init__(name, salary)    # let the parent set its part        self.bonus = bonus    def monthly_pay(self):            # override: same name, new behaviour        return super().monthly_pay() + self.bonus / 12class Intern(Employee):    def monthly_pay(self):        return 800.0                  # fixed grantstaff = [Employee("Lucia", 30000), Manager("Pablo", 48000, 6000),         Intern("Iker", 0)]for person in staff:                  # the same call, the right method    print(person.describe())print("Payroll:", round(sum(p.monthly_pay() for p in staff), 2))print("Pablo is an Employee:", isinstance(staff[1], Employee))print("Manager subclass of Employee:", issubclass(Manager, Employee))print("Method order:", [c.__name__ for c in Manager.__mro__])

Salida · python3 main.py

Lucia  Employee   2500.00
Pablo  Manager    4500.00
Iker   Intern      800.00
Payroll: 7800.0
Pablo is an Employee: True
Manager subclass of Employee: True
Method order: ['Manager', 'Employee', 'object']

Para recordar

  • class Hija(Padre) hereda atributos y métodos.
  • super() llama a la versión del padre.
  • Un método con el mismo nombre sobrescribe al heredado.
  • isinstance acepta también las subclases.
  • El MRO dice en qué orden se buscan los métodos.

Ejercicio

Cree una subclase Contractor que cobre por horas (hours * rate) y añada un contratista a staff para que aparezca en la nómina.