Python

Python

Tutorial Python: Herencia

Aprende los conceptos clave de herencia, uso de super() y sobreescritura en Python para crear clases flexibles y reutilizables con ejemplos prácticos.

Aprende Python y certifícate

Conceptos básicos

La herencia es uno de los pilares fundamentales de la programación orientada a objetos que permite crear nuevas clases basadas en clases existentes. Este mecanismo facilita la reutilización de código y establece relaciones jerárquicas entre clases.

En Python, la herencia permite que una clase (llamada clase hija o subclase) adquiera los atributos y métodos de otra clase (llamada clase padre o superclase). Esta relación se conoce como relación "es un", donde la clase hija representa una versión especializada de la clase padre.

Sintaxis básica

La sintaxis para crear una clase que hereda de otra es muy sencilla en Python:

class ClasePadre:
    # Atributos y métodos de la clase padre
    pass

class ClaseHija(ClasePadre):
    # Atributos y métodos de la clase hija
    # Más los heredados de la clase padre
    pass

El nombre de la clase padre se coloca entre paréntesis después del nombre de la clase hija. Esto indica a Python que la clase hija debe heredar todas las características de la clase padre.

Ejemplo práctico

Veamos un ejemplo sencillo con una jerarquía de vehículos:

class Vehiculo:
    def __init__(self, marca, modelo, año):
        self.marca = marca
        self.modelo = modelo
        self.año = año
        self.encendido = False
    
    def encender(self):
        self.encendido = True
        return f"{self.marca} {self.modelo} encendido"
    
    def apagar(self):
        self.encendido = False
        return f"{self.marca} {self.modelo} apagado"
    
    def describir(self):
        return f"Vehículo: {self.marca} {self.modelo} del año {self.año}"


class Automovil(Vehiculo):
    def __init__(self, marca, modelo, año, puertas):
        # Inicializamos la parte del padre
        Vehiculo.__init__(self, marca, modelo, año)
        # Añadimos atributos específicos
        self.puertas = puertas
    
    def describir(self):
        return f"Automóvil: {self.marca} {self.modelo} del año {self.año} con {self.puertas} puertas"

En este ejemplo:

  1. Vehiculo es la clase padre que define atributos y comportamientos comunes a todos los vehículos.
  2. Automovil es la clase hija que hereda de Vehiculo y añade características específicas (número de puertas).
  3. La clase hija puede acceder a todos los atributos y métodos de la clase padre.

Podemos crear instancias y usar los métodos heredados:

# Creamos un automóvil
mi_auto = Automovil("Toyota", "Corolla", 2023, 4)

# Usamos métodos heredados
print(mi_auto.encender())  # Toyota Corolla encendido
print(mi_auto.describir())  # Automóvil: Toyota Corolla del año 2023 con 4 puertas

Herencia múltiple

A diferencia de otros lenguajes como Java, Python permite la herencia múltiple, donde una clase puede heredar de varias clases padre:

class ClaseA:
    def metodo_a(self):
        return "Método de ClaseA"

class ClaseB:
    def metodo_b(self):
        return "Método de ClaseB"

class ClaseC(ClaseA, ClaseB):
    def metodo_c(self):
        return "Método de ClaseC"

La clase ClaseC hereda todos los métodos y atributos tanto de ClaseA como de ClaseB. Sin embargo, la herencia múltiple puede introducir complejidad y ambigüedad, por lo que debe usarse con precaución.

Verificación de herencia

Python proporciona funciones útiles para verificar las relaciones de herencia:

  • isinstance(): Comprueba si un objeto es instancia de una clase.
  • issubclass(): Comprueba si una clase es subclase de otra.
mi_auto = Automovil("Toyota", "Corolla", 2023, 4)

# Verificamos instancias
print(isinstance(mi_auto, Automovil))  # True
print(isinstance(mi_auto, Vehiculo))   # True - también es instancia de la clase padre

# Verificamos relaciones de clases
print(issubclass(Automovil, Vehiculo))  # True
print(issubclass(Vehiculo, Automovil))  # False - la relación es unidireccional

Método de resolución de orden (MRO)

Cuando trabajamos con herencia, especialmente herencia múltiple, Python utiliza un algoritmo de resolución de orden para determinar qué método o atributo usar cuando hay nombres duplicados. Podemos ver este orden usando el atributo __mro__ o el método mro():

print(Automovil.__mro__)
# Muestra el orden en que Python busca métodos: primero en Automovil, luego en Vehiculo, y finalmente en object

Herencia y constructores

En nuestro ejemplo anterior, usamos Vehiculo.__init__(self, marca, modelo, año) para llamar al constructor de la clase padre. Sin embargo, Python proporciona una forma más elegante de hacer esto usando super(), que veremos en la siguiente sección.

Ventajas de la herencia

  • Reutilización de código: Evita duplicar código al compartir funcionalidad común.
  • Extensibilidad: Facilita extender la funcionalidad existente sin modificar el código original.
  • Jerarquías naturales: Permite modelar relaciones del mundo real de manera intuitiva.
  • Polimorfismo: Permite tratar objetos de diferentes clases de manera uniforme si comparten una clase base común.

Consideraciones importantes

  • La herencia debe usarse cuando existe una verdadera relación "es un". Por ejemplo, un automóvil es un vehículo.
  • Evita crear jerarquías de herencia demasiado profundas, ya que pueden volverse difíciles de entender y mantener.
  • Prefiere la composición sobre la herencia cuando la relación es más del tipo "tiene un" en lugar de "es un".

La herencia es una herramienta poderosa, pero debe usarse con criterio. En las siguientes secciones, exploraremos cómo usar super() para una gestión más elegante de la herencia y cómo implementar la sobreescritura de métodos para personalizar el comportamiento heredado.

Super()

La función super() es una herramienta fundamental en Python para trabajar con herencia de manera elegante y mantenible. Proporciona una forma de acceder a los métodos y propiedades de la clase padre sin tener que nombrarla explícitamente, lo que hace que el código sea más flexible y menos propenso a errores.

Uso básico de super()

En el contexto de la herencia, super() nos permite llamar a métodos de la clase padre desde la clase hija. Su uso más común es en el método __init__ para asegurar que la inicialización de la clase padre se realice correctamente:

class Vehiculo:
    def __init__(self, marca, modelo, año):
        self.marca = marca
        self.modelo = modelo
        self.año = año
        
class Automovil(Vehiculo):
    def __init__(self, marca, modelo, año, puertas):
        # Llamamos al constructor de la clase padre
        super().__init__(marca, modelo, año)
        # Añadimos atributos específicos
        self.puertas = puertas

En este ejemplo, super().__init__(marca, modelo, año) llama al método __init__ de la clase padre Vehiculo, evitando tener que escribir Vehiculo.__init__(self, marca, modelo, año).

Ventajas de usar super()

El uso de super() ofrece varias ventajas importantes:

  • Desacoplamiento: No necesitamos mencionar explícitamente el nombre de la clase padre, lo que hace el código más mantenible.
  • Compatibilidad con herencia múltiple: Funciona correctamente con el mecanismo de resolución de métodos (MRO) de Python.
  • Adaptabilidad a cambios: Si cambiamos la jerarquía de clases, no necesitamos modificar las llamadas a los métodos de la clase padre.

Super() en métodos regulares

Aunque el uso más común de super() es en el constructor, también podemos utilizarlo para llamar a cualquier método de la clase padre:

class Vehiculo:
    def describir(self):
        return f"Vehículo: {self.marca} {self.modelo} ({self.año})"
        
class Automovil(Vehiculo):
    def describir(self):
        # Obtenemos la descripción básica del vehículo
        descripcion_base = super().describir()
        # Añadimos información específica del automóvil
        return f"{descripcion_base} - {self.puertas} puertas"

En este caso, la clase Automovil extiende el comportamiento del método describir() de la clase Vehiculo, añadiendo información sobre el número de puertas.

Sintaxis de super() en Python 3

En Python 3, la sintaxis simplificada de super() (sin argumentos) es suficiente en la mayoría de los casos:

super().__init__(args)  # Python 3

Esta forma abreviada es equivalente a:

super(TipoActual, self).__init__(args)

Donde TipoActual es la clase en la que se está utilizando super() y self es la instancia actual.

Super() en herencia múltiple

Uno de los aspectos más potentes de super() es su comportamiento en escenarios de herencia múltiple. Python utiliza el algoritmo C3 para determinar el orden de resolución de métodos (MRO), y super() respeta este orden:

class Motor:
    def arrancar(self):
        return "Motor arrancado"
        
class Electrico:
    def arrancar(self):
        return "Sistema eléctrico iniciado"
        
class VehiculoElectrico(Vehiculo, Electrico):
    def arrancar(self):
        # Llama al método arrancar del siguiente en el MRO
        return f"{super().arrancar()} - Vehículo listo"

Para entender a qué método llamará super().arrancar(), podemos examinar el MRO:

print(VehiculoElectrico.__mro__)
# (<class '__main__.VehiculoElectrico'>, <class '__main__.Vehiculo'>, 
#  <class '__main__.Electrico'>, <class 'object'>)

En este caso, super().arrancar() llamará al método arrancar() de Vehiculo, ya que es el siguiente en el MRO después de VehiculoElectrico.

Ejemplo práctico completo

Veamos un ejemplo más elaborado que muestra cómo super() facilita la creación de jerarquías de clases mantenibles:

class Animal:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad
    
    def hacer_sonido(self):
        return "Algún sonido animal"
    
    def info(self):
        return f"{self.nombre}, {self.edad} años"

class Perro(Animal):
    def __init__(self, nombre, edad, raza):
        super().__init__(nombre, edad)
        self.raza = raza
    
    def hacer_sonido(self):
        return "Guau guau"
    
    def info(self):
        # Combinamos la información básica con detalles específicos
        info_basica = super().info()
        return f"{info_basica} - Perro {self.raza}"

class PerroGuia(Perro):
    def __init__(self, nombre, edad, raza, persona_asistida):
        super().__init__(nombre, edad, raza)
        self.persona_asistida = persona_asistida
    
    def info(self):
        # Reutilizamos la implementación de la clase padre
        info_perro = super().info()
        return f"{info_perro} - Asiste a {self.persona_asistida}"

Podemos ver cómo cada nivel de la jerarquía extiende el comportamiento del nivel anterior sin duplicar código:

# Creamos instancias
animal = Animal("Criatura", 5)
perro = Perro("Rex", 3, "Pastor Alemán")
perro_guia = PerroGuia("Max", 4, "Labrador", "Ana")

# Mostramos información
print(animal.info())      # Criatura, 5 años
print(perro.info())       # Rex, 3 años - Perro Pastor Alemán
print(perro_guia.info())  # Max, 4 años - Perro Labrador - Asiste a Ana

Consideraciones importantes

  • No uses super() fuera de una clase: La función super() solo funciona dentro de métodos de clase.
  • Coherencia en las firmas de métodos: Asegúrate de que los métodos sobrescritos acepten los mismos parámetros que los métodos de la clase padre, o utiliza parámetros con valores predeterminados o *args y **kwargs para mayor flexibilidad.
  • Orden de inicialización: En herencia múltiple, es crucial entender el MRO para predecir el comportamiento de super().

Patrones comunes con super()

Existen algunos patrones de diseño comunes al utilizar super():

  • Extensión de comportamiento: Llamar al método de la clase padre y luego añadir funcionalidad adicional.
def metodo(self, arg):
    resultado = super().metodo(arg)
    # Añadir comportamiento adicional
    return resultado_modificado
  • Pre-procesamiento: Realizar acciones antes de llamar al método de la clase padre.
def metodo(self, arg):
    # Pre-procesar argumentos
    arg_modificado = transformar(arg)
    return super().metodo(arg_modificado)
  • Delegación condicional: Decidir si llamar o no al método de la clase padre.
def metodo(self, arg):
    if condicion:
        return super().metodo(arg)
    else:
        return resultado_alternativo

La función super() es una herramienta esencial para implementar herencia de manera limpia y mantenible en Python, permitiendo crear jerarquías de clases flexibles y robustas sin duplicar código.

Sobreescritura

La sobreescritura de métodos es una técnica fundamental en la programación orientada a objetos que permite a una clase hija proporcionar una implementación específica de un método ya definido en su clase padre. Este mecanismo es esencial para implementar el polimorfismo y personalizar el comportamiento heredado.

En Python, sobreescribir un método es tan simple como definir en la clase hija un método con el mismo nombre que existe en la clase padre. Cuando se llama a este método en una instancia de la clase hija, se ejecutará la versión de la clase hija en lugar de la versión de la clase padre.

Implementación básica

Para sobreescribir un método, simplemente definimos un método con el mismo nombre en la clase hija:

class Animal:
    def hablar(self):
        return "El animal hace un sonido"

class Gato(Animal):
    def hablar(self):
        return "Miau"

En este ejemplo, la clase Gato sobreescribe el método hablar() de la clase Animal. Cuando llamamos a este método en una instancia de Gato, obtendremos "Miau" en lugar del mensaje genérico.

mi_animal = Animal()
mi_gato = Gato()

print(mi_animal.hablar())  # El animal hace un sonido
print(mi_gato.hablar())    # Miau

Cuándo sobreescribir métodos

La sobreescritura es apropiada en varios escenarios:

  • Cuando la implementación de la clase padre es demasiado genérica y necesitamos una versión más específica
  • Cuando queremos modificar completamente el comportamiento heredado
  • Cuando necesitamos adaptar un método para que funcione con atributos específicos de la clase hija

Sobreescritura del método init

Un caso común de sobreescritura es el del constructor __init__. Cuando una clase hija necesita inicializar atributos adicionales, debe sobreescribir el constructor de la clase padre:

class Vehiculo:
    def __init__(self, marca, modelo):
        self.marca = marca
        self.modelo = modelo
        self.en_marcha = False
    
    def arrancar(self):
        self.en_marcha = True
        return f"{self.marca} {self.modelo} arrancado"

class Motocicleta(Vehiculo):
    def __init__(self, marca, modelo, cilindrada):
        super().__init__(marca, modelo)
        self.cilindrada = cilindrada
    
    def arrancar(self):
        return f"{super().arrancar()} - {self.cilindrada}cc rugiendo"

En este ejemplo, Motocicleta sobreescribe tanto el método __init__ como el método arrancar. Observa cómo utilizamos super() para mantener la funcionalidad base y luego la extendemos.

Sobreescritura completa vs. extensión

Existen dos enfoques principales para sobreescribir métodos:

  • Sobreescritura completa: Reemplazar totalmente la implementación del padre
class Pez(Animal):
    def hablar(self):
        return "Glub glub"  # Implementación completamente nueva
  • Extensión del comportamiento: Utilizar la implementación del padre y añadir funcionalidad
class Perro(Animal):
    def hablar(self):
        sonido_base = super().hablar()
        return f"{sonido_base}, específicamente: Guau"

La elección entre estos enfoques depende de si necesitamos preservar parte del comportamiento original o reemplazarlo por completo.

Sobreescritura de métodos especiales

Python tiene métodos especiales (también llamados métodos dunder o mágicos) que podemos sobreescribir para personalizar el comportamiento de nuestras clases:

class Punto:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __str__(self):
        return f"({self.x}, {self.y})"
    
class Punto3D(Punto):
    def __init__(self, x, y, z):
        super().__init__(x, y)
        self.z = z
    
    def __str__(self):
        return f"({self.x}, {self.y}, {self.z})"

En este ejemplo, Punto3D sobreescribe tanto __init__ como __str__ para adaptarlos a su naturaleza tridimensional.

Ejemplo práctico: Sistema de formas geométricas

Veamos un ejemplo más completo que muestra cómo la sobreescritura permite implementar comportamientos específicos en una jerarquía de clases:

class Forma:
    def __init__(self, color="negro"):
        self.color = color
    
    def area(self):
        # Método base que será sobreescrito
        return 0
    
    def describir(self):
        return f"Forma de color {self.color} con área {self.area()} unidades cuadradas"

class Circulo(Forma):
    def __init__(self, radio, color="rojo"):
        super().__init__(color)
        self.radio = radio
    
    def area(self):
        import math
        return math.pi * self.radio ** 2
    
    def describir(self):
        return f"Círculo {self.color} de radio {self.radio} con área {self.area():.2f} unidades cuadradas"

class Rectangulo(Forma):
    def __init__(self, ancho, alto, color="azul"):
        super().__init__(color)
        self.ancho = ancho
        self.alto = alto
    
    def area(self):
        return self.ancho * self.alto

Podemos usar estas clases de la siguiente manera:

# Creamos instancias
forma = Forma()
circulo = Circulo(5)
rectangulo = Rectangulo(4, 6, "verde")

# Mostramos descripciones
print(forma.describir())      # Forma de color negro con área 0 unidades cuadradas
print(circulo.describir())    # Círculo rojo de radio 5 con área 78.54 unidades cuadradas
print(rectangulo.describir()) # Forma de color verde con área 24 unidades cuadradas

Observa que Rectangulo sobreescribe area() pero utiliza la implementación de describir() de la clase Forma. Esto demuestra que no es necesario sobreescribir todos los métodos, solo aquellos que necesitan un comportamiento específico.

Polimorfismo a través de la sobreescritura

La sobreescritura es la base del polimorfismo, que permite tratar objetos de diferentes clases de manera uniforme si comparten una clase base común:

def imprimir_area(forma):
    print(f"El área es: {forma.area()}")

# Podemos pasar cualquier objeto que herede de Forma
imprimir_area(circulo)      # El área es: 78.53981633974483
imprimir_area(rectangulo)   # El área es: 24

La función imprimir_area() funciona con cualquier objeto que tenga un método area(), independientemente de su implementación específica.

Buenas prácticas para la sobreescritura

  • Mantén la firma del método: Los parámetros del método sobreescrito deben ser compatibles con los del método original.
  • Respeta el contrato: El método sobreescrito debe cumplir con el mismo propósito general que el método original.
  • Documenta los cambios: Si el comportamiento cambia significativamente, documéntalo claramente.
  • Usa super() cuando sea apropiado: Si necesitas extender el comportamiento en lugar de reemplazarlo completamente.
class Ave(Animal):
    def hablar(self):
        # Documentamos el cambio de comportamiento
        """Produce el sonido característico del ave."""
        return "Pío pío"

Sobreescritura vs. sobrecarga

Es importante distinguir entre sobreescritura (override) y sobrecarga (overload):

  • La sobreescritura implica redefinir un método en una clase hija manteniendo la misma firma.
  • La sobrecarga implica definir múltiples versiones de un método con diferentes parámetros.

Python no admite sobrecarga de métodos de la misma manera que otros lenguajes como Java o C++. En Python, si defines múltiples métodos con el mismo nombre, el último definido sobrescribirá a los anteriores.

Sin embargo, podemos simular la sobrecarga utilizando parámetros opcionales o *args y **kwargs:

class Calculadora:
    def sumar(self, *args):
        return sum(args)

Esta implementación permite llamar a sumar() con cualquier número de argumentos.

Sobreescritura de propiedades

También podemos sobreescribir propiedades en las clases hijas:

class Empleado:
    def __init__(self, nombre, salario_base):
        self.nombre = nombre
        self._salario_base = salario_base
    
    @property
    def salario(self):
        return self._salario_base

class Gerente(Empleado):
    def __init__(self, nombre, salario_base, bonus):
        super().__init__(nombre, salario_base)
        self.bonus = bonus
    
    @property
    def salario(self):
        # Sobreescribimos la propiedad para incluir el bonus
        return self._salario_base + self.bonus

En este ejemplo, la propiedad salario se sobreescribe en la clase Gerente para incluir el bonus en el cálculo.

La sobreescritura de métodos es una técnica poderosa que permite adaptar y especializar el comportamiento heredado, facilitando la creación de jerarquías de clases flexibles y expresivas que modelan con precisión los dominios del problema.

Aprende Python online

Otras lecciones de Python

Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Python

Python

Introducción

Instalación Y Creación De Proyecto

Python

Introducción

Tema 2: Tipos De Datos, Variables Y Operadores

Python

Introducción

Instalación De Python

Python

Introducción

Tipos De Datos

Python

Sintaxis

Variables

Python

Sintaxis

Operadores

Python

Sintaxis

Estructuras De Control

Python

Sintaxis

Funciones

Python

Sintaxis

Estructuras Control Iterativo

Python

Sintaxis

Estructuras Control Condicional

Python

Sintaxis

Testing Con Pytest

Python

Sintaxis

Listas

Python

Estructuras De Datos

Tuplas

Python

Estructuras De Datos

Diccionarios

Python

Estructuras De Datos

Conjuntos

Python

Estructuras De Datos

Comprehensions

Python

Estructuras De Datos

Clases Y Objetos

Python

Programación Orientada A Objetos

Excepciones

Python

Programación Orientada A Objetos

Encapsulación

Python

Programación Orientada A Objetos

Herencia

Python

Programación Orientada A Objetos

Polimorfismo

Python

Programación Orientada A Objetos

Mixins Y Herencia Múltiple

Python

Programación Orientada A Objetos

Métodos Especiales (Dunder Methods)

Python

Programación Orientada A Objetos

Composición De Clases

Python

Programación Orientada A Objetos

Funciones Lambda

Python

Programación Funcional

Aplicación Parcial

Python

Programación Funcional

Entrada Y Salida, Manejo De Archivos

Python

Programación Funcional

Decoradores

Python

Programación Funcional

Generadores

Python

Programación Funcional

Paradigma Funcional

Python

Programación Funcional

Composición De Funciones

Python

Programación Funcional

Funciones Orden Superior Map Y Filter

Python

Programación Funcional

Funciones Auxiliares

Python

Programación Funcional

Reducción Y Acumulación

Python

Programación Funcional

Archivos Comprimidos

Python

Entrada Y Salida Io

Entrada Y Salida Avanzada

Python

Entrada Y Salida Io

Archivos Temporales

Python

Entrada Y Salida Io

Contexto With

Python

Entrada Y Salida Io

Módulo Csv

Python

Biblioteca Estándar

Módulo Json

Python

Biblioteca Estándar

Módulo Datetime

Python

Biblioteca Estándar

Módulo Math

Python

Biblioteca Estándar

Módulo Os

Python

Biblioteca Estándar

Módulo Re

Python

Biblioteca Estándar

Módulo Random

Python

Biblioteca Estándar

Módulo Time

Python

Biblioteca Estándar

Módulo Collections

Python

Biblioteca Estándar

Módulo Sys

Python

Biblioteca Estándar

Módulo Statistics

Python

Biblioteca Estándar

Módulo Pickle

Python

Biblioteca Estándar

Módulo Pathlib

Python

Biblioteca Estándar

Importar Módulos Y Paquetes

Python

Paquetes Y Módulos

Crear Módulos Y Paquetes

Python

Paquetes Y Módulos

Entornos Virtuales (Virtualenv, Venv)

Python

Entorno Y Dependencias

Gestión De Dependencias (Pip, Requirements.txt)

Python

Entorno Y Dependencias

Python-dotenv Y Variables De Entorno

Python

Entorno Y Dependencias

Acceso A Datos Con Mysql, Pymongo Y Pandas

Python

Acceso A Bases De Datos

Acceso A Mongodb Con Pymongo

Python

Acceso A Bases De Datos

Acceso A Mysql Con Mysql Connector

Python

Acceso A Bases De Datos

Novedades Python 3.13

Python

Características Modernas

Operador Walrus

Python

Características Modernas

Pattern Matching

Python

Características Modernas

Instalación Beautiful Soup

Python

Web Scraping

Sintaxis General De Beautiful Soup

Python

Web Scraping

Tipos De Selectores

Python

Web Scraping

Web Scraping De Html

Python

Web Scraping

Web Scraping Para Ciencia De Datos

Python

Web Scraping

Autenticación Y Acceso A Recursos Protegidos

Python

Web Scraping

Combinación De Selenium Con Beautiful Soup

Python

Web Scraping

Accede GRATIS a Python y certifícate

Ejercicios de programación de Python

Evalúa tus conocimientos de esta lección Herencia con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Módulo math

Python
Puzzle

Reto herencia

Python
Código

Excepciones

Python
Test

Introducción a Python

Python
Test

Reto variables

Python
Código

Funciones Python

Python
Puzzle

Reto funciones

Python
Código

Módulo datetime

Python
Test

Reto acumulación

Python
Código

Reto estructuras condicionales

Python
Código

Polimorfismo

Python
Test

Módulo os

Python
Test

Reto métodos dunder

Python
Código

Diccionarios

Python
Puzzle

Reto clases y objetos

Python
Código

Reto operadores

Python
Código

Operadores

Python
Test

Estructuras de control

Python
Puzzle

Funciones lambda

Python
Test

Reto diccionarios

Python
Código

Reto función lambda

Python
Código

Encapsulación

Python
Puzzle

Reto coleciones

Python
Proyecto

Reto funciones auxiliares

Python
Código

Crear módulos y paquetes

Python
Puzzle

Módulo datetime

Python
Puzzle

Excepciones

Python
Puzzle

Operadores

Python
Puzzle

Diccionarios

Python
Test

Reto map, filter

Python
Código

Reto tuplas

Python
Código

Proyecto gestor de tareas CRUD

Python
Proyecto

Tuplas

Python
Puzzle

Variables

Python
Puzzle

Tipos de datos

Python
Puzzle

Conjuntos

Python
Test

Reto mixins

Python
Código

Módulo csv

Python
Test

Módulo json

Python
Test

Herencia

Python
Test

Análisis de datos de ventas con Pandas

Python
Proyecto

Reto fechas y tiempo

Python
Proyecto

Reto estructuras de iteración

Python
Código

Funciones

Python
Test

Reto comprehensions

Python
Código

Variables

Python
Test

Reto serialización

Python
Proyecto

Módulo csv

Python
Puzzle

Reto polimorfismo

Python
Código

Polimorfismo

Python
Puzzle

Clases y objetos

Python
Código

Reto encapsulación

Python
Código

Estructuras de control

Python
Test

Importar módulos y paquetes

Python
Test

Módulo math

Python
Test

Funciones lambda

Python
Puzzle

Reto excepciones

Python
Código

Listas

Python
Puzzle

Reto archivos

Python
Proyecto

Encapsulación

Python
Test

Reto conjuntos

Python
Código

Clases y objetos

Python
Test

Instalación de Python y creación de proyecto

Python
Test

Reto listas

Python
Código

Tipos de datos

Python
Test

Crear módulos y paquetes

Python
Test

Tuplas

Python
Test

Herencia

Python
Puzzle

Reto acceso a sistema

Python
Proyecto

Proyecto sintaxis calculadora

Python
Proyecto

Importar módulos y paquetes

Python
Puzzle

Clases y objetos

Python
Puzzle

Módulo os

Python
Puzzle

Listas

Python
Test

Conjuntos

Python
Puzzle

Reto tipos de datos

Python
Código

Reto matemáticas

Python
Proyecto

Módulo json

Python
Puzzle

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender el concepto de herencia y su sintaxis básica en Python.
  • Aprender a utilizar super() para llamar a métodos de la clase padre de forma elegante.
  • Entender cómo sobreescribir métodos para personalizar el comportamiento heredado.
  • Conocer la herencia múltiple y el método de resolución de orden (MRO) en Python.
  • Aplicar buenas prácticas en el uso de herencia, super() y sobreescritura para diseñar código mantenible.