Создаем портфолио за 1 месяц
К концу месяца: 4 классных проекта в вашем портфолио! Стоимость: 100$. Подробности...
⊗pyOpAaSa 109 of 174 menu
◀ ▶

Запись атрибутов через __setattr__ в ООП в Python

Метод __setattr__ вызывается при каждой попытке записать атрибут через точку - и в новое имя, и в уже существующее, и в приватное. В качестве параметров он принимает имя атрибута и значение, которое ему пытаются присвоить.

Давайте посмотрим на практическом примере. Пусть у нас дан вот такой класс Test:

class Test: pass

Давайте сделаем в этом классе метод __setattr__, который будет выводить имя атрибута, к которому произошло обращение, и значение, которое этому атрибуту пытаются установить:

class Test: def __setattr__(self, name, value): print(name, value)

Проверим работу нашего класса:

test = Test() test.prop = 'value' # __setattr__ выведет 'prop value'

Давайте теперь будем устанавливать значение атрибуту, имя которого пришло в параметре name:

class Test: def __setattr__(self, name, value): super().__setattr__(name, value) # устанавливаем значение

Теперь мы сможем записывать данные снаружи, в том числе в новые имена:

test = Test() test.prop1 = 1 # запишем 1 test.prop2 = 2 # запишем 2

Давайте попробуем записать данные в несуществующий атрибут - это будет работать:

test = Test() test.prop3 = 3 # запишем 3 print(test.prop3) # выведет 3

Пусть мы не хотим разрешать записывать в несуществующие атрибуты. И, вообще, хотим разрешить запись только в атрибуты prop1 и prop2.

Это легко сделать - достаточно в методе __setattr__ добавить соответствующее условие:

class Test: def __setattr__(self, name, value): # Напишем условие: if name == 'prop1' or name == 'prop2': super().__setattr__(name, value) def __getattr__(self, name): return super().__getattribute__(name)

Если таких атрибутов будет много, то не очень удобно перечислять их все в условии.

Давайте запишем разрешенные для записи атрибуты в список и будем проверять наличие атрибута в этом списке с помощью оператора in:

class Test: def __setattr__(self, name, value): properties = ['prop1', 'prop2'] # разрешенные атрибуты if name in properties: super().__setattr__(name, value) def __getattr__(self, name): return super().__getattribute__(name)

На самом деле, конечно же, не стоит разрешать всем подряд записывать в приватные атрибуты, иначе пропадает суть этих приватных атрибутов (проще сделать их публичными и все).

Поэтому метод __setattr__ следует применять только тогда, когда в этом действительно есть необходимость.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить