2.20. De primera clase

Una clase agrupa datos y las funciones que actúan sobre esos datos bajo un único nombre. Recurrir a una merece la pena cuando varias piezas de estado van juntas y la mayoría de las funciones de un script reciben ese mismo conjunto de valores como argumentos.

2.20.1. La palabra clave class

La palabra clave es class. El cuerpo contiene un método __init__ que se ejecuta cada vez que se crea una nueva instancia:

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

p = Point(3, 4)
print(p.x, p.y)

Salida:

3 4

Point es la clase; p es una instancia de ella. Los paréntesis en la llamada Point(3, 4) invocan a __init__, que asigna los argumentos a atributos de la nueva instancia. self es el nombre convencional para la instancia; self.x establece un atributo que el resto de los métodos de la instancia leerán.

2.20.2. Cuándo usar una clase

Recurre a una clase cuando se cumplan estas condiciones al mismo tiempo:

  • Un puñado de valores relacionados viajan juntos por todas partes (la x y la y de un punto; el valor, la unidad y la marca de tiempo de una lectura de un sensor).

  • Varias funciones reciben ese mismo conjunto de valores y operan sobre ellos.

  • Resulta útil mantener vivos más de uno de estos paquetes a la vez, distintos entre sí.

Si los datos son puntuales, un dict o una tuple corriente suele bastar. Si solo necesitas un único paquete de constantes, las variables a nivel de módulo están bien. Las clases no son el contenedor por defecto: se ganan su lugar cuando el estado y el comportamiento quieren permanecer unidos.

2.20.3. Qué hace __init__

__init__ es simplemente un método normal. Cualquier cosa asignada a self dentro de él se convierte en un atributo de la nueva instancia:

class Sensor:
    def __init__(self, name, unit):
        self.name = name
        self.unit = unit
        self.readings = []

temp = Sensor("temperature", "C")
print(temp.name, temp.unit, temp.readings)

Salida:

temperature C []

readings se inicializa como una lista vacía: cada nueva instancia obtiene su propia lista, no una compartida. Cualquier cosa que no se asigne a self es local a __init__ y desaparece cuando este retorna.