0Pricing
Python Academy · Урок

__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 — локальная установка не требуется.

Все уроки этого курса

  1. Как создаются классы Python
  2. Написание пользовательских метаклассов
  3. Дескрипторы: __get__, __set__, __delete__
  4. __slots__ и оптимизация памяти
← Назад к Python Academy