Una clase empaqueta datos y lo que haces con ellos
Una clase te deja definir un tipo de cosa — un usuario, una cuenta bancaria, una configuración, una petición — y todo lo que esa cosa debería poder hacer. La cosa es una instancia de la clase. Las acciones se llaman métodos.
Aquí la clase más simple posible:
Desglosándolo:
class User:inicia una definición de clase. Los nombres de clase usan PascalCase por convención.__init__es el inicializador. Se ejecuta automáticamente cuando creas una nueva instancia. Configura los atributos de la instancia usandoself.whatever = ....greetes un método.selfes cómo un método se refiere a la instancia sobre la que se llamó.User("Rosa", "rosa@example.com")crea una instancia. Python llama a__init__conselfpuesto a la nueva instancia y los otros argumentos pasados a través.user.greet()llama al método. Python pasausercomoselfautomáticamente.
self es solo el primer argumento
self no es una palabra clave. Es el nombre que Python da al primer parámetro de los métodos de instancia — la instancia sobre la que el método está corriendo. Podrías llamarlo como sea; todo el mundo usa self porque todo el mundo lo hace.
Cada método de instancia toma self como su primer parámetro. Así es como un método sabe sobre qué instancia leer o modificar.
Añadir comportamiento
Los métodos pueden leer y mutar el estado:
__repr__ es otro método especial — un gancho de "¿cómo muestro este objeto al imprimirlo?". Definir uno bueno paga dividendos durante la depuración.
Atributos de clase vs atributos de instancia
Los atributos definidos en el cuerpo de la clase (fuera de __init__) se comparten entre todas las instancias. Los atributos asignados a self son por instancia:
Usa atributos de clase para valores genuinamente compartidos — constantes, contadores, configuración. Pon datos específicos de instancia en __init__.
Herencia
Una clase puede heredar de otra, obteniendo sus métodos y atributos gratis y añadiendo o sobrescribiendo según haga falta:
super() te da acceso a la clase padre — comúnmente usada dentro de __init__ para inicializar los atributos del padre antes de añadir los tuyos:
La herencia es útil pero fácil de usar en exceso. Un programador Python novato suele recurrir a la herencia cuando la composición — tener un objeto como atributo — sería más clara. Empieza con una estructura de clase plana e introduce herencia solo cuando tengas una relación real "es-un".
Dataclasses: un valor por defecto más agradable para registros
Cuando principalmente quieres una clase para contener unos atributos con algo de comportamiento de igualdad y representación, @dataclass te ahorra mucho boilerplate:
Compara eso con escribir __init__, __repr__ y __eq__ a mano. Los dataclasses son la primera elección correcta cuando en otro caso escribirías class Thing con nada más que __init__ estableciendo atributos.
Properties: atributos computados
A veces quieres un "atributo" que en realidad se computa. @property hace que eso parezca acceso a atributo:
Usa properties cuando escribirías obj.get_something() — reemplazarlo con una property hace que la API se sienta más natural. No las uses para esconder operaciones caras; un usuario espera que el acceso a atributo sea rápido.
Privado por convención
Python no tiene privado real. Por convención, los atributos con un guion bajo inicial están pensados como privados — se espera que los lectores no los toquen desde fuera de la clase:
class Cache:
def __init__(self):
self._store = {}
def put(self, key, value):
self._store[key] = value
def get(self, key, default=None):
return self._store.get(key, default)
Los nombres con doble guion bajo (__name) disparan name mangling, que añade el nombre de la clase al atributo. Es una herramienta para evitar colisiones en herencia, no una medida de seguridad.
Cuándo no usar una clase
Si todo lo que tienes es un paquete de datos relacionados, un dataclass o un dict plano o una named tuple servirán. Si todo lo que tienes es una función, no necesita una clase que la contenga. Recurre a las clases cuando tengas ambos estado y comportamiento atados juntos — especialmente cuando vayas a tener muchas instancias del mismo tipo.
Un ejemplo final
Un pequeño buffer de log tipo archivo:
Fíjate en __len__ — otro método mágico. Definirlo hace que len(logger) funcione, porque len(x) en realidad es una llamada a x.__len__(). Python tiene docenas de estos ganchos; los cogerás según los necesites.
Siguiente: generadores
Las clases atan datos y comportamiento juntos. El siguiente capítulo mira a un tipo distinto de abstracción — la iteración — empezando con generadores: funciones que producen valores uno a uno, pausando entre ellos. Se emparejan maravillosamente con la sentencia with / los context managers que conocerás justo después.
Preguntas frecuentes
¿Qué es una clase en Python?
Una clase es un plano para crear objetos que agrupan datos (atributos) y comportamiento (métodos) juntos. class User: define una clase User; User(...) crea una instancia. Las clases son la herramienta principal de Python para modelar cosas que tienen estado y comportamiento.
¿Qué significa self en Python?
self es el primer parámetro de cada método de instancia. Cuando llamas a user.greet(), Python pasa la instancia user como self. Dentro del método, self.name accede al atributo name de ese usuario. El nombre self es una convención, no una palabra clave — pero cada Pythonista lo usa.
¿Python es orientado a objetos?
Sí — todo en Python es un objeto, incluidos números, strings y funciones. Puedes hacer programación orientada a objetos cuando encaje, pero Python no te obliga. Muchos programas Python del mundo real usan las clases con moderación, prefiriendo funciones planas y estructuras de datos cuando es posible.