Las clases y objetos son fundamentales en la programación orientada a objetos (OOP) en Python. Una clase es un plano o plantilla para crear objetos, mientras que un objeto es una instancia de una clase.

class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def saludar(self):
        print(f"Hola, soy {self.nombre} y tengo {self.edad} años.")

Creación de Objetos:

# Crear objetos de la clase Persona
persona1 = Persona("Juan", 25)
persona2 = Persona("Ana", 30)

# Acceder a atributos
print(persona1.nombre)  # Resultado: Juan

# Llamar a métodos
persona2.saludar()  # Resultado: Hola, soy Ana y tengo 30 años.

Herencia:

La herencia es un concepto clave en la programación orientada a objetos que permite a una clase heredar atributos y métodos de otra clase. La clase que hereda se llama clase hija, y la clase de la que se hereda se llama clase padre o superclase. La herencia facilita la reutilización de código y la creación de una jerarquía de clases.

class Estudiante(Persona):
    def __init__(self, nombre, edad, carrera):
        super().__init__(nombre, edad)
        self.carrera = carrera

    def estudiar(self):
        print(f"Soy {self.nombre} y estudio {self.carrera}.")

# Crear objeto de la clase Estudiante
estudiante1 = Estudiante("Carlos", 22, "Ingeniería")
estudiante1.saludar()   # Resultado: Hola, soy Carlos y tengo 22 años.
estudiante1.estudiar()  # Resultado: Soy Carlos y estudio Ingeniería.
class Animal:
    def __init__(self, nombre):
        self.nombre = nombre

    def hacer_sonido(self):
        pass  # Método que puede ser implementado por clases hijas

class Perro(Animal):
    def hacer_sonido(self):
        return "Woof"

class Gato(Animal):
    def hacer_sonido(self):
        return "Meow"

super(): Referencia a la clase padre.

Encapsulamiento:

El encapsulamiento es un principio de la programación orientada a objetos que consiste en ocultar los detalles internos de una clase y restringir el acceso directo a algunos de sus componentes. En Python, podemos lograr el encapsulamiento marcando un atributo como privado mediante el uso de doble guion bajo (__).

class Coche:
    def __init__(self, marca, modelo):
        self.__marca = marca  # Atributo privado
        self.__modelo = modelo

    def obtener_marca(self):
        return self.__marca

    def cambiar_marca(self, nueva_marca):
        self.__marca = nueva_marca

# Crear objeto de la clase Coche
coche1 = Coche("Toyota", "Corolla")
print(coche1.obtener_marca())  # Resultado: Toyota

coche1.__marca = "Honda"  # No cambia el atributo privado
coche1.cambiar_marca("Honda")
print(coche1.obtener_marca())  # Resultado: Honda

__atributo: Atributo privado.

class CuentaBancaria:
    def __init__(self, saldo_inicial):
        self.__saldo = saldo_inicial

    def obtener_saldo(self):
        return self.__saldo

    def realizar_retiro(self, cantidad):
        if cantidad > 0 and cantidad <= self.__saldo:
            self.__saldo -= cantidad
            return True
        else:
            return False

Abstracción:

La abstracción es otro principio clave de la programación orientada a objetos que implica simplificar y modelar objetos del mundo real en el código. Proporciona una representación esencial y oculta los detalles innecesarios. En Python, la abstracción se logra mediante la creación de clases y la definición de métodos que encapsulan la funcionalidad compleja.

from abc import ABC, abstractmethod

# Definición de la clase abstracta Vehiculo
class Vehiculo(ABC):
    def __init__(self, marca, modelo):
        self.marca = marca
        self.modelo = modelo

    @abstractmethod
    def arrancar(self):
        pass

    @abstractmethod
    def detener(self):
        pass

# Implementación de una clase concreta: Coche
class Coche(Vehiculo):
    def arrancar(self):
        print(f"{self.marca} {self.modelo} arrancando el motor.")

    def detener(self):
        print(f"{self.marca} {self.modelo} deteniendo el motor.")

# Implementación de una clase concreta: Moto
class Moto(Vehiculo):
    def arrancar(self):
        print(f"{self.marca} {self.modelo} encendiendo el motor.")

    def detener(self):
        print(f"{self.marca} {self.modelo} apagando el motor.")

# Uso de las clases
coche = Coche("Toyota", "Corolla")
moto = Moto("Honda", "CBR")

coche.arrancar()  # Resultado: Toyota Corolla arrancando el motor.
coche.detener()   # Resultado: Toyota Corolla deteniendo el motor.

moto.arrancar()   # Resultado: Honda CBR encendiendo el motor.
moto.detener()    # Resultado: Honda CBR apagando el motor.

abc — Abstract Base Classes