Menu

Clases en Python: __init__, self, métodos, herencia y dataclasses

Una introducción para principiantes a las clases de Python — definirlas, crear instancias, el método __init__, herencia y cuándo usar dataclasses en su lugar.

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:

main.py
Output
Click Run to see the output here.

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 usando self.whatever = ....
  • greet es un método. self es 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__ con self puesto a la nueva instancia y los otros argumentos pasados a través.
  • user.greet() llama al método. Python pasa user como self automá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:

main.py
Output
Click Run to see the output here.

__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:

main.py
Output
Click Run to see the output here.

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:

main.py
Output
Click Run to see the output here.

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:

main.py
Output
Click Run to see the output here.

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:

main.py
Output
Click Run to see the output here.

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:

main.py
Output
Click Run to see the output here.

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:

main.py
Output
Click Run to see the output here.

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.

Aprende a programar con Coddy

COMENZAR