Ответ
Метод __set__(self, instance, value)
является частью протокола data descriptor (дескриптора данных) в Python. Он перехватывает операцию присваивания значения атрибуту, позволяя выполнить валидацию, преобразование типов или другую логику перед сохранением.
Он вызывается автоматически, когда происходит попытка присвоить значение атрибуту, управляемому дескриптором.
Параметры:
self
: экземпляр самого дескриптора.instance
: экземпляр класса, в котором находится атрибут (например,MyClass()
).value
: присваиваемое значение.
Пример: Дескриптор для неотрицательных чисел
Чтобы дескриптор знал имя атрибута, с которым он работает, используется метод __set_name__
(Python 3.6+).
class NonNegative:
def __set_name__(self, owner, name):
# Сохраняем имя атрибута, например, 'price' или 'quantity'
self.private_name = '_' + name
def __get__(self, instance, owner):
# Возвращаем значение из приватного атрибута экземпляра
return getattr(instance, self.private_name)
def __set__(self, instance, value):
# Логика валидации перед присваиванием
if value < 0:
raise ValueError(f"Значение не может быть отрицательным.")
# Сохраняем значение в приватный атрибут экземпляра
setattr(instance, self.private_name, value)
class Product:
price = NonNegative()
quantity = NonNegative()
def __init__(self, price, quantity):
self.price = price
self.quantity = quantity
# Использование
item = Product(100, 5)
print(f"Цена: {item.price}, Количество: {item.quantity}") # Цена: 100, Количество: 5
item.price = 200 # OK
# Эта строка вызовет ValueError
try:
item.quantity = -1
except ValueError as e:
print(e)
Ключевые моменты:
- Data Descriptor: Наличие метода
__set__
(или__delete__
) делает дескриптор дескриптором данных, который имеет более высокий приоритет, чем атрибуты в словаре экземпляра (__dict__
). - Валидация: Это основной сценарий использования
__set__
— проверка данных на соответствие определенным правилам. - Инкапсуляция: Позволяет скрыть внутреннюю логику хранения данных за простым интерфейсом атрибута.