Слоти - це шлях:
Пітонічний спосіб полягає у використанні слотів замість того, щоб пограти з __setter__
. Незважаючи на те, що це може вирішити проблему, це не сприяє покращенню продуктивності. Атрибути об'єктів зберігаються у словнику " __dict__
", ось чому ви можете динамічно додавати атрибути до об'єктів класів, які ми створили на сьогодні. Використовувати словник для зберігання атрибутів дуже зручно, але це може означати втрату місця для об’єктів, які мають лише невелику кількість змінних екземпляра.
Слоти - це приємний спосіб обійти цю проблему споживання простору. Замість того, щоб мати динамічний дикт, що дозволяє динамічно додавати атрибути до об’єктів, слоти надають статичну структуру, яка забороняє додавання після створення екземпляра.
Коли ми розробляємо клас, ми можемо використовувати слоти, щоб запобігти динамічному створенню атрибутів. Щоб визначити слоти, вам потрібно визначити список з назвою __slots__
. Список повинен містити всі атрибути, які ви хочете використовувати. Ми демонструємо це в наступному класі, в якому список слотів містить лише ім'я атрибута "val".
class S(object):
__slots__ = ['val']
def __init__(self, v):
self.val = v
x = S(42)
print(x.val)
x.new = "not possible"
=> Не вдається створити атрибут "new":
42
Traceback (most recent call last):
File "slots_ex.py", line 12, in <module>
x.new = "not possible"
AttributeError: 'S' object has no attribute 'new'
Примітка:
- З мовою Python 3.3 перевага в оптимізації споживання місця вже не така вражаюча. У Python 3.3 Словники спільного використання ключів використовуються для зберігання об’єктів. Атрибути примірників можуть спільно використовувати частину свого внутрішнього сховища між собою, тобто частину, яка зберігає ключі та відповідні їм хеші. Це допомагає зменшити споживання пам'яті програмами, які створюють багато екземплярів невбудованих типів. Але все-таки це шлях, щоб уникнути динамічно створених атрибутів.
- Використання слотів також постачається за власну вартість. Це порушить серіалізацію (наприклад, соління). Це також порушить багаторазове успадкування. Клас не може успадкувати більше ніж одного класу, який або визначає слоти, або має макет екземпляра, визначений у коді С (наприклад, список, кортеж або int).
__setattr__
але це, мабуть, було б хакі.