Ответ
Протокол дескрипторов в Python — это механизм, позволяющий объекту (дескриптору) управлять доступом к атрибутам другого объекта (владельца). Дескриптор должен реализовать один или несколько из следующих методов:
__get__(self, instance, owner): для получения значения атрибута.__set__(self, instance, value): для установки значения атрибута.__delete__(self, instance): для удаления атрибута.
Дескрипторы работают только тогда, когда они являются атрибутами класса, а не экземпляра.
Пример: дескриптор для валидации положительных чисел
class PositiveNumber:
def __set_name__(self, owner, name):
# Сохраняем имя атрибута, к которому привязан дескриптор
self.private_name = '_' + name
def __get__(self, instance, owner):
return getattr(instance, self.private_name)
def __set__(self, instance, value):
if not isinstance(value, (int, float)) or value <= 0:
raise ValueError(f"Значение должно быть положительным числом, а не {value}")
setattr(instance, self.private_name, value)
class Product:
price = PositiveNumber()
quantity = PositiveNumber()
def __init__(self, price, quantity):
self.price = price
self.quantity = quantity
# Использование
book = Product(150, 10)
print(book.price) # 150
try:
book.price = -50 # Вызовет ValueError
except ValueError as e:
print(e)
Типы дескрипторов:
- Data Descriptor: реализует
__set__или__delete__. Имеет приоритет над словарем экземпляра (__dict__). - Non-Data Descriptor: реализует только
__get__. Имеет меньший приоритет.
Этот протокол является основой для многих возможностей Python, включая @property, @staticmethod, @classmethod и работу слотов (__slots__).