На этом шаге мы рассмотрим использование спецификатора __ slots__.
Ваша программа создает большое количество (миллионы) экземпляров и использует много памяти.
Для классов, которые в основном служат простыми структурами данных, вы часто можете значительно уменьшить потребление памяти экземплярами путем добавления атрибута __slots__ в определение класса. Например:
class Date: __slots__ = ['year', 'month', 'day'] def __init__(self, year, month, day): self.year = year self.month = month self.day = day
Когда вы определяете __slots__, Python использует намного более компактное внутреннее представление экземпляров. Вместо снабжения
каждого экземпляра словарем они создаются на базе небольшого массива фиксированного размера, похожего на кортеж или список. Атрибуты,
перечисленные в спецификаторе __ slots__, внутри отображаются на конкретные индексы в массиве. Побочный эффект использования слотов в том,
что теряется возможность добавления новых атрибутов к экземплярам - у вас будет возможность использовать только атрибуты, перечисленные в
спецификаторе __slots__.
Объем сэкономленной с помощью слотов памяти варьируется в зависимости от количества и типа хранимых атрибутов. Однако в общем случае объем использования памяти сравним с тем, который бы потребовался для сохранения этих данных в кортеже. Чтобы дать вам пищу для размышлений, упомянем, что сохранение одного экземпляра Date без использования слотов потребует 428 байтов на 64-битной версии Python. Если определены слоты, объем падает до 156 байтов. В программах, работающих с большим количеством дат одновременно, это может привести к значительному снижению использования памяти.
Хотя слоты могут показаться возможностью, которая будет полезна всегда, вы должны сопротивляться желанию использовать их повсюду. Очень многие компоненты Python основаны на стандартной реализации на базе словарей. Также нужно отметить, что классы, которые определяют слоты, не поддерживают некоторые возможности - такие как, например, множественное наследование. По большей части вы должны использовать слоты только в классах, которые служат структурами данных в вашей программе (то есть если ваша программа создает миллионы экземпляров какого-то класса).
Часто слоты неправильно воспринимают как инструмент для инкапсуляции, который запрещает пользователям добавлять новые атрибуты к экземплярам. Хотя это действительно является побочным эффектом использования слотов, это не было целью их появления в языке. __slots__ изначально задумывались именно как инструмент для оптимизации.
На следующем шаге мы рассмотрим инкапсуляцию имен в классе.