__slots__
— это специальный атрибут класса в Python, который позволяет явно объявлять фиксированный набор атрибутов экземпляра, заменяя динамический словарь __dict__
на статический массив дескрипторов.
При обычном создании класса Python использует словарь __dict__
для хранения атрибутов экземпляра, что дает гибкость, но требует памяти. __slots__
оптимизирует это:
class RegularClass:
pass
class SlotsClass:
__slots__ = ['x', 'y']
# Сравнение
regular = RegularClass()
slotted = SlotsClass()
regular.new_attr = 10 # Разрешено
slotted.new_attr = 10 # AttributeError: 'SlotsClass' object has no attribute 'new_attr'
Экономия памяти (основное преимущество)
__dict__
, который потребляет больше памяти__slots__
заменяет словарь на фиксированный массив, экономя 40-50% памятиУскорение доступа к атрибутам
Защита от опечаток в именах атрибутов
AttributeError
Полезен для массовых объектов
Невозможность динамического добавления атрибутов
instance.new_attr = value
Проблемы с наследованием
__slots__
, а потомок нет — __dict__
все равно создается__slots__
, они объединяютсяНесовместимость с некоторыми инструментами
__dict__
pickle
требует __getstate__
/__setstate__
Сложности с weakref
'__weakref__'
в __slots__
при необходимостиimport sys
class Regular:
def __init__(self, x, y):
self.x = x
self.y = y
class Slotted:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
regular = Regular(1, 2)
slotted = Slotted(1, 2)
print(sys.getsizeof(regular) # Например, 56 (зависит от Python и системы)
print(sys.getsizeof(slotted)) # Например, 48 (экономия памяти)
Можно комбинировать с __dict__
для частичной гибкости:
class Mixed:
__slots__ = ['x', 'y', '__dict__']
def __init__(self, x, y):
self.x = x
self.y = y
m = Mixed(1, 2)
m.x = 10 # Слот
m.z = 30 # __dict__
__slots__
— это оптимизация памяти и производительности__slots__
— мощный инструмент оптимизации, но как любая оптимизация, должен применяться обдуманно и только там, где это действительно необходимо.