__slots__ и оптимизация памяти
Используйте __slots__, чтобы уменьшить потребление памяти каждым экземпляром.
«__slots__ и оптимизация памяти» — бесплатный урок Python Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.
Накладные расходы стандартного __dict__
По умолчанию каждый экземпляр Python хранит атрибуты в словаре __dict__, что приводит к значительным накладным расходам памяти — обычно 200–400 байт на экземпляр.
import sys
class Point:
def __init__(self, x, y): self.x, self.y = x, y
p = Point(1, 2)
print(sys.getsizeof(p.__dict__)) # ~200 bytesОбъявление __slots__
Определите __slots__ как последовательность имён атрибутов. Python выделяет массив фиксированного размера вместо словаря, экономя память.
class SlottedPoint:
__slots__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
p = SlottedPoint(1, 2)
print(p.x, p.y) # 1 2
# p.z = 3 # AttributeError: no __dict__Экономия памяти
С помощью __slots__ каждый экземпляр обычно занимает на 30–50% меньше памяти по сравнению с экземпляром на основе словаря — это особенно важно при создании миллионов объектов.
import sys
class Reg:
def __init__(self, x, y): self.x, self.y = x, y
class Slotted:
__slots__ = ("x","y")
def __init__(self, x, y): self.x, self.y = x, y
print(sys.getsizeof(Reg(1,2))) # ~56 bytes + ~200 dict
print(sys.getsizeof(Slotted(1,2))) # ~56 bytes (no dict)Нет __dict__ по умолчанию
У класса со слотами нет __dict__, поэтому после создания нельзя добавлять произвольные атрибуты.
class Config:
__slots__ = ("host", "port")
def __init__(self, h, p): self.host, self.port = h, p
c = Config("localhost", 8080)
# c.debug = True # AttributeError
print(hasattr(c, "__dict__")) # FalseСохранение __dict__ с помощью __slots__
Включите "__dict__" в __slots__, чтобы сохранить словарь для каждого экземпляра и при этом заранее объявить часто используемые атрибуты как слоты.
class Hybrid:
__slots__ = ("x", "__dict__")
def __init__(self, x):
self.x = x
h = Hybrid(1)
h.extra = "dynamic" # allowed
print(h.extra)__weakref__ в __slots__
Классы со слотами теряют поддержку слабых ссылок. Добавьте "__weakref__" в __slots__, чтобы снова включить эту возможность.
import weakref
class Node:
__slots__ = ("value", "__weakref__")
def __init__(self, v): self.value = v
n = Node(42)
ref = weakref.ref(n)
print(ref()) # <Node object>Наследование и __slots__
Если родительский класс не использует __slots__, дочерний класс всё равно получает __dict__. Для полной экономии памяти вся иерархия должна определять __slots__.
class Base:
__slots__ = ("x",)
class Child(Base):
__slots__ = ("y",) # no __dict__
class WithoutSlots(Base):
pass # gets __dict__ from objectИзмерение использования памяти
Используйте tracemalloc или pympler, чтобы измерить фактическое использование памяти до и после добавления __slots__.
import tracemalloc
tracemalloc.start()
points = [SlottedPoint(i, i) for i in range(100_000)]
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"Peak: {peak/1024/1024:.1f} MB")__slots__ и сериализация
Объекты со слотами можно сериализовать, если определить __getstate__ и __setstate__, либо использовать стандартный протокол pickle, который автоматически обрабатывает слоты начиная с Python 3.
import pickle
class Point:
__slots__ = ("x", "y")
def __init__(self, x, y): self.x, self.y = x, y
p = Point(3, 4)
data = pickle.dumps(p)
p2 = pickle.loads(data)
print(p2.x, p2.y) # 3 4Классы данных с __slots__ — Python 3.10+
Передайте slots=True декоратору @dataclass, чтобы автоматически сгенерировать __slots__.
from dataclasses import dataclass
@dataclass(slots=True)
class Vector:
x: float
y: float
v = Vector(1.0, 2.0)
print(v.x, v.y) # 1.0 2.0
print(hasattr(v, "__dict__")) # FalseКогда использовать __slots__
Используйте __slots__, если создаёте миллионы экземпляров, ограничены памятью или критична скорость доступа к атрибутам. Не используйте его в классах общего назначения, если гибкость важнее.
# Good candidates:
# - Nodes in a large graph or tree
# - Records in a large dataset
# - High-frequency event objects
# Bad candidates:
# - Configuration objects added to ad-hoc
# - Classes that mix-in dynamic attributesБыстрая проверка
Что произойдёт, если попытаться установить у экземпляра со слотами атрибут, не указанный в __slots__?
Итоги
__slots__ заменяет __dict__ каждого экземпляра массивом фиксированного размера, экономя 30–50% памяти. Включите "__dict__" или "__weakref__", если они нужны. Для полной экономии вся цепочка наследования должна использовать __slots__. В Python 3.10+ используйте @dataclass(slots=True).
Часто задаваемые вопросы
Урок «__slots__ и оптимизация памяти» бесплатный?
Да — полный текст урока «__slots__ и оптимизация памяти» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.
Чему я научусь в уроке «__slots__ и оптимизация памяти»?
Используйте __slots__, чтобы уменьшить потребление памяти каждым экземпляром. Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Python Academy?
Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «__slots__ и оптимизация памяти»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Python Academy?
Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Как создаются классы Python
- Написание пользовательских метаклассов
- Дескрипторы: __get__, __set__, __delete__
- __slots__ и оптимизация памяти