Conceptos básicos de OOP
10 ejemplos para empezar con Python orientado a objetos: 7 básicos y 3 intermedios.
Prerrequisitos
- Python 3.14.0 y Conceptos básicos de Python.
Ejemplos básicos
1. Definir una clase y __init__
Inicializa el estado de la instancia en el constructor.
class Greeter:
def __init__(self, prefix: str) -> None:
self.prefix = prefix
def greet(self, name: str) -> str:
return f"{self.prefix}, {name}!"
g = Greeter("Hello")
print(g.greet("Ada"))__init__configura nuevas instancias; no es un constructor verdadero en el sentido de C++.selfes la convención para la referencia de la instancia.- Los métodos son funciones enlazadas a instancias.
Relacionado: Métodos Dunder / Mágicos - métodos especiales
2. Atributos de instancia vs. de clase
Los atributos de clase se comparten; los atributos de instancia son por objeto.
class Counter:
total = 0
def __init__(self) -> None:
Counter.total += 1
self.value = 0- Modificar
Counter.totalafecta a todas las instancias a menos que se sombreé en la instancia. - Los atributos de instancia establecidos en
__init__son independientes por objeto. - Evita atributos de clase mutables (
list,dict) como trampas de estado compartido.
Relacionado: Métodos de clase vs. de instancia vs. estáticos -
@classmethod
3. Herencia simple
Reutiliza el comportamiento mediante la subclasificación.
class Animal:
def speak(self) -> str:
return "..."
class Dog(Animal):
def speak(self) -> str:
return "woof"- Las subclases sobrescriben métodos definiendo el mismo nombre.
super()llama a la implementación del padre; es crucial en cadenas de__init__.- Prefiere la composición cuando la relación no es "es-un".
Relacionado: Herencia y MRO - herencia múltiple
4. dataclass para registros
Reduce el código repetitivo para clases que contienen datos.
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
p = Point(3, 4)
print(p.x, p.y)- Genera automáticamente
__init__,__repr__y comparaciones cuando se configura. - Añade
frozen=Truepara objetos de valor inmutables. - Usa
field(default_factory=list)para valores predeterminados mutables.
Relacionado: Dataclasses -
fieldypost_init
5. Propiedades para encapsulación
Expone atributos con getters/setters sin cambiar los puntos de llamada.
class Account:
def __init__(self, balance: float) -> None:
self._balance = balance
@property
def balance(self) -> float:
return self._balance- El guion bajo inicial (
_) indica internamente por convención; no es privacidad forzada. @propertypuede añadir validación en el setter más adelante.- Mantiene la API pública similar a un atributo mientras permite lógica.
Relacionado: Propiedades y Descriptores - descriptores
6. __repr__ para depuración
Representación legible del objeto en logs y REPL.
class User:
def __init__(self, user_id: int, name: str) -> None:
self.user_id = user_id
self.name = name
def __repr__(self) -> str:
return f"User({self.user_id__repr__debe ser idealmente inequívoco y fácil de reconstruir.__str__es para visualización humana;printusa__str__y recurre a__repr__si no está.- Las
dataclassesgeneran automáticamente un__repr__útil.
Relacionado: Métodos Dunder / Mágicos -
reprvsstr
7. Enum para constantes con nombre
Reemplaza cadenas mágicas con enumeraciones tipadas.
from enum import StrEnum
class Role(StrEnum):
ADMIN = "admin"
DEV = "dev"
def authorize(role: Role) -> bool:
return role == Role.ADMIN- Los miembros de
StrEnumse comparan limpiamente con cadenas en contextos JSON. - Los Enums son singletons; la identidad es estable para comparaciones.
matchexhaustivo sobre miembros de enum detecta casos faltantes.
Relacionado: Enums -
IntEnumy flags
Ejemplos intermedios
8. Composición sobre herencia
Delega el comportamiento a objetos auxiliares.
class EmailSender:
def send(self, to: str, body: str) -> None:
print(f"to={to} body={body}")
class Notifier:
def __init__(self, sender: EmailSender) ->
Notifiertiene unEmailSenderen lugar de extenderlo.- Pruebas más fáciles con un remitente falso inyectado.
- Intercambia implementaciones sin una explosión de subclases.
Relacionado: Mejores prácticas de Python Orientado a Objetos - reglas de diseño
9. Interfaz abstracta con abc
Impone métodos que las subclases deben implementar.
from abc import ABC, abstractmethod
class Repository(ABC):
@abstractmethod
def get(self, item_id: int) -> dict: ...
class InMemoryRepo(Repository):
def get(self, item_id: int) ->
- No se puede instanciar una ABC hasta que se implementen los métodos abstractos.
- Documenta puntos de extensión para plugins y pruebas.
Protocolofrece una alternativa estructural; consulta la sección de type hints.
Relacionado: Clases Base Abstractas -
collections.abc
10. __slots__ para memoria
Restringe atributos y reduce la sobrecarga del diccionario por instancia.
class Coord:
__slots__ = ("x", "y")
def __init__(self, x: int, y: int) -> None:
self.x = x
self.y = y- Las instancias no pueden obtener atributos nuevos arbitrarios.
- Significativo al crear millones de objetos pequeños.
- Incompatible con algunos patrones de herencia múltiple; úsalo con prudencia.
Relacionado: Inmutabilidad y Hashabilidad - puntos hasheables
Versiones de Stack: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ y uv 0.6+.