__slots__ = "Hello", "World"

__slots__ = "Hello", "World"

KarmanovichDev

__slots__ является атрибутом класса и используется для:

  1. Ускорения доступа к атрибутам
  2. Уменьшение размера создаваемого объекта
  3. Ограничение возможных атрибутов объекта

Разберём, как использовать __slots__:

В атрибут __slots__ передаётся коллекция строк либо единичная строка. Эти строки и будут являться именами возможных атрибутов объекта.

Пока ничем не отличается от привычного нам создания объекта, за исключением самого атрибута класса __slots__. Давайте вернёмся к трём пунктам из начала статьи и убедимся в преимуществах данного подхода при создании объектов.

  1. При тестировании на разных версиях python я обнаружил, что в более новых версиях разница в скорости минимальна, на уровне погрешности, однако в более старых версиях эта разница доходила до 20%+. Вот некоторые из моих замеров:
В более старой версии python(3.8) разница была 15%-20% от запуска к запуску. В более новой версии python(3.12), её практически нет.

Во всяком случае в рамках моего ПК можно сказать, что преимущества в скорости на элементарных примерах и последних версиях python нет. Всё же если у вас не самые свежие версии, вы всё ещё можете получить неплохой прирост в скорости, если подобные операции с объектами в вашем проекте многочисленны.

2. Как же обстоят дела с кол-вом потребляемой памяти? Отлично!

Да, от версии к версии некоторые объекты меняют свой размер, но это не мешает оценить картину в целом.

Почему же так происходит, и где мы экономим память? Проведём чуть более подробный анализ, из чего состоят эти объекты:

Заметили какая большая разница при малом кол-ве атрибутов? Это всё страшный магический словарь! 😄
8 всё ещё не равно 32, но это сильно сократило разницу в размере объектов.

Что же такое эти __dict__ и __weakref__?

  • __weakref__, если коротко, это нужно для работы механизма слабых ссылок. В python всё работает на ссылочной системе. В переменных лежат, не объекты, а лишь ссылки на них. В функцию, передавая свою переменную, вы так же передаёте лишь ссылку на реальный объект, лежащий где-то в оперативной памяти. Объект живёт в памяти, пока на него есть, хотя бы одна ссылка. Как только кол-во ссылок на объект равно нулю, в ближайшее время придёт сборщик мусора и удалит его из памяти. Есть модуль weakref, который позволяет создавать слабые ссылки на объекты, и через эти ссылки использовать объект точно так же, как обычно. Такие ссылки не видны сборщику мусора, поэтому как только кол-во обычных ссылок будет равно нулю, сборщик удалит объект, а все слабые ссылки перестанут работать.
  • __dict__ Вот кто занимает большинство памяти! Что это такое? Это просто словарь, а весят они достаточно много. Зачем он нужен? В нём хранятся все атрибуты экземпляра класса, причём их можно менять динамически уже после инстанцирования объекта.

3. Ну хотя бы с ограничениями по атрибутам ситуация неизменна от версии к версии😄

Это защитит нас от установки некорректных/лишних атрибутов. Без использования __slots__ это можно сделать без проблем.

Это базовая статья про __slots__. Возможно, в будущем я дополню её материалом, но как показывает практика, это не самый часто используемый инструмент в python.

Что не было затронуто:

  1. Наследование __slots__
  2. Когда использовать слот не выйдет/следует - например, вы не сможете использовать cached_property, так как ему требуется __dict__ для работы.

Report Page