Ответ
Протокол дескрипторов в 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__
).