ProgramaciónDesarrollador Backend Python

¿Qué son __slots__ en las clases de Python, para qué se necesitan y cuáles son sus limitaciones?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

__slots__ es un atributo especial de la clase que limita el conjunto de atributos permitidos en la instancia, ahorrando memoria y acelerando el acceso a los atributos. El uso de __slots__ es especialmente relevante para un gran número de objetos similares.

Historia de la cuestión:

La aparición de __slots__ está relacionada con el hecho de que, por defecto, cada instancia de un objeto Python tiene un diccionario de atributos (__dict__), lo que es conveniente pero costoso en términos de memoria. Para un millón de objetos con un conjunto pequeño de campos, surge una sobrecarga significativa.

Problema:

Las instancias de una clase normal pueden expandirse dinámicamente, lo que es conveniente, pero ineficiente. La aplicación de __slots__ limita la adición dinámica de nuevos atributos, elimina el diccionario de atributos de la instancia, ahorra memoria y acelera el acceso.

Solución:

Describa la lista de campos permitidos en el atributo __slots__:

class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2) p.z = 3 # AttributeError: 'Point' object has no attribute 'z'

Características clave:

  • Ahorra memoria al no tener dict y weakref por defecto.
  • Define un conjunto estricto de campos permitidos.
  • Permite acelerar el acceso a los atributos gracias a los slots preasignados (no requiere búsqueda en dict).

Preguntas trampa.

¿Se puede crear una instancia de una clase con slots y luego agregar un atributo que no está en la lista?

No. Al intentar agregar un atributo que no está en la lista de slots, se lanzará un AttributeError. Esto impone restricciones a la expandibilidad del objeto.

¿Se puede heredar de una clase con slots y agregar nuevos campos?

Sí, pero cada heredero debe declarar sus propios slots. En este caso, los slots parentales y actuales se combinan. Sin embargo, si no se declara slots en el heredero, ¡el descendiente nuevamente tendrá dict!

¿Funciona slots para tipos inmutables?

Sí, pero se deben implementar medidas adicionales para hacer que el objeto con slots sea inmutable (por ejemplo, mediante property sin setter).

Errores típicos y anti-patrones

  • No declarar slots en la clase hija, rompiendo la eficiencia de memoria.
  • Esperar que slots funcione en presencia de herencia múltiple: pueden ocurrir conflictos y errores.
  • Intentar serializar objetos con slots utilizando métodos estándar a veces puede ser difícil (por ejemplo, pickle requiere dict).

Ejemplo de la vida real

Caso negativo

Clase normal para un punto:

class Point: def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]

Ventajas:

  • Flexible: se pueden agregar cualquier atributo.
  • Claro para principiantes.

Desventajas:

  • El administrador de tareas muestra un consumo de memoria notablemente elevado (hasta +20-30%).

Caso positivo

Clase similar, pero con slots:

class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]

Ventajas:

  • Hasta 30% de ahorro de memoria en millones de objetos.
  • Acceso más rápido a los campos.

Desventajas:

  • Los objetos se vuelven inflexibles: no se pueden agregar nuevos atributos sobre la marcha.