Saltar al contenido
> 💻 🧠 Código 1001 > 📚 Materiales de Aprendizaje > 🐍 Python > Clases en Python, POO y Administradores de Contexto: Guía Completa

Clases en Python, POO y Administradores de Contexto: Guía Completa

  • por

1. Clases en Python

Las clases son un mecanismo clave de POO. Una clase es un molde para crear objetos con atributos (datos) y métodos (funciones). Los objetos creados desde una clase se llaman instancias. Las clases ayudan a estructurar el código, mejorar su reutilización y simplificar el mantenimiento.

Estructura de una clase

class ClassName:
    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2

    def method(self):
        return f'{self.param1} y {self.param2}'

Puntos clave:

  • __init__: constructor para inicializar atributos del objeto.
  • self: referencia a la instancia actual.
  • Atributos: definidos mediante self, accesibles en todos los métodos.
  • Métodos: operan sobre los datos del objeto.

Creación de objetos

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def description(self):
        return f'{self.year} {self.make} {self.model}'

my_car = Car('Toyota', 'Corolla', 2020)
print(my_car.description())  # Salida: 2020 Toyota Corolla

Tipos de métodos

  1. Métodos de instancia — trabajan sobre objetos (self).
  2. Métodos de clase — trabajan sobre la clase (cls) mediante @classmethod.
  3. Métodos estáticos — independientes de instancia y clase (@staticmethod).

Herencia

class Animal:
    def speak(self):
        return 'Sonido de animal'

class Dog(Animal):
    def speak(self):
        return 'Guau'

Polimorfismo

class Cat(Animal):
    def speak(self):
        return 'Miau'

cat = Cat()
print(cat.speak())  # Salida: Miau
  • El mismo método funciona de manera diferente según el tipo de objeto.

Encapsulación

class Car:
    def __init__(self, make, model):
        self._make = make  # Atributo protegido
        self._model = model

    def get_make(self):
        return self._make

    def set_make(self, make):
        self._make = make

Métodos mágicos y destructor

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

p = Point(3, 4)
print(p)  # Salida: Point(3, 4)

Diagrama ASCII: Herencia y Polimorfismo

       ┌─────────┐
       │ Animal  │
       └─────────┘
       │ speak() │
       └─────────┘
            ▲
    ┌───────┴────────┐
    │                │
┌─────────┐      ┌─────────┐
│  Dog    │      │  Cat    │
└─────────┘      └─────────┘
│ speak() │      │ speak() │
└─────────┘      └─────────┘

2. Administradores de Contexto en Python

Los administradores de contexto permiten asignar y liberar recursos automáticamente, asegurando limpieza incluso ante errores.

Uso de @contextmanager

from contextlib import contextmanager

@contextmanager
def my_context():
    print("Entrando en el contexto")
    try:
        yield "Recurso"
    finally:
        print("Saliendo del contexto")

Uso:

with my_context() as res:
    print("Dentro del contexto:", res)

Captura de stdout/stderr y Tee

Python permite capturar stdout, stderr o ambos, y mostrar y capturar simultáneamente usando el patrón Tee.


3. Ejemplo completo: oop_and_context.py

"""
oop_and_context.py

Ejemplos de clases, principios de POO y administradores de contexto en Python.
Incluye:
- Definición de clases, herencia, polimorfismo, encapsulación
- Métodos de instancia, clase y estáticos
- Métodos mágicos y destructor
- Administradores de contexto con @contextmanager
- Captura de stdout, stderr y combinación de ambos
- Patrón Tee: mostrar y capturar simultáneamente
- Administrador de contexto basado en clase
"""

import sys
import io
from contextlib import contextmanager

# ==========================
# Parte 1: Clases y POO
# ==========================

class Animal:
    """Clase base para animales."""
    def speak(self):
        return 'Sonido de animal'

class Dog(Animal):
    def speak(self):
        return 'Guau'

class Cat(Animal):
    def speak(self):
        return 'Miau'

class Car:
    """Ejemplo de clase con encapsulación."""
    def __init__(self, make, model, year=None):
        self._make = make
        self._model = model
        self.year = year

    def get_make(self):
        return self._make

    def set_make(self, make):
        self._make = make

    def description(self):
        if self.year:
            return f'{self.year} {self._make} {self._model}'
        return f'{self._make} {self._model}'

class Point:
    """Clase con métodos mágicos."""
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

# ==========================
# Parte 2: Administradores de contexto
# ==========================

@contextmanager
def my_context():
    print("Entrando en el contexto")
    try:
        yield "Recurso"
    finally:
        print("Saliendo del contexto")

@contextmanager
def capture_stdout():
    old_stdout = sys.stdout
    sys.stdout = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stdout = old_stdout

@contextmanager
def capture_stderr():
    old_stderr = sys.stderr
    sys.stderr = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stderr = old_stderr

@contextmanager
def capture_output():
    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stdout = sys.stderr = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stdout = old_stdout
        sys.stderr = old_stderr

class Tee(io.StringIO):
    """Salida visible y captura simultánea."""
    def __init__(self, original):
        super().__init__()
        self.original = original

    def write(self, text):
        self.original.write(text)
        super().write(text)

    def flush(self):
        self.original.flush()

@contextmanager
def capture_stdout_tee():
    old_stdout = sys.stdout
    sys.stdout = tee = Tee(old_stdout)
    try:
        yield tee
    finally:
        sys.stdout = old_stdout

# ==========================
# Parte 3: Administrador de contexto basado en clase
# ==========================

class OutputCapture:
    """Administrador de contexto basado en clase para capturar stdout."""
    def __init__(self):
        self._buffer = io.StringIO()
        self._old_stdout = None

    def __enter__(self):
        self._old_stdout = sys.stdout
        sys.stdout = self._buffer
        return self._buffer

    def __exit__(self, exc_type, exc_val, exc_tb):
        sys.stdout = self._old_stdout
        return False  # propaga excepciones

# ==========================
# Parte 4: Demostraciones
# ==========================

def demo_classes():
    print("\n--- Demostración de Clases ---")
    dog = Dog()
    cat = Cat()
    print("Perro dice:", dog.speak())
    print("Gato dice:", cat.speak())

    my_car = Car('Toyota', 'Corolla', 2020)
    print("Descripción del coche:", my_car.description())
    my_car.set_make('Honda')
    print("Marca actualizada:", my_car.get_make())

    point = Point(3, 4)
    print("Punto:", point)

def demo_context_managers():
    print("\n--- Demostración de Administradores de Contexto ---")
    with my_context() as res:
        print("Dentro del contexto:", res)

    with capture_stdout() as out:
        print("stdout capturado")
    print("Contenido:", out.getvalue().strip())

    with capture_stderr() as err:
        print("Esto va a stdout")
        sys.stderr.write("Mensaje de error\n")
    print("Errores:", err.getvalue().strip())

    with capture_output() as out_all:
        print("Stdout dentro de captura combinada")
        sys.stderr.write("Stderr dentro de captura combinada\n")
    print("Salida combinada:", out_all.getvalue().strip())

    with capture_stdout_tee() as tee_out:
        print("Salida visible Y capturada con Tee")
    print("Buffer Tee:", tee_out.getvalue().strip())

    with OutputCapture() as class_capture:
        print("Captura usando administrador basado en clase")
    print

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *