Дескриптор протокол (2 части серии)
(Конечно, приходит некоторое допущенное определение)
Согласно официальным документам Python3, это то, что они говорят
В целом, дескриптор представляет собой атрибут объекта с «привязчивым поведением», которого доступен атрибут которого был переопределен методами в протоколе дескриптора. Эти методы __get __ (), __set __ () и __delete __ (). Если какой-либо из этих методов определены для объекта, считается дескриптором.
Теперь кажется довольно ясно, что нам нужен класс, и в этом классе нам нужно определить эти методы, и это. Давайте попробуем
class A: def __get__(self, instance, owner): return instance.__dict__[self.name] def __set__(self, instance, value): print("setting the attribute") instance.__dict__[self.name] = value def __delete__(self, instance): del instance.__dict__[self.name] def __set_name__(self, owner, name): self.name = name
Теперь мы хотим использовать этот дескриптор
class B: a = A() i = B() print(i.a) # KeyError: 'a' i.a = "wysiwyg" # setting the attribute print(i.a) # wysiwyg
(Хорошо, достаточно Chit-Chat, давайте драться, извините, жаль, давайте понять, как мы можем использовать эту концепцию) Так что предположим, что вы хотите подтвердить, прежде чем установить значение или получить значение. Но подождите, есть Getter и Getters, верно? Да, есть, но я поклонник сухого, и я торжественно клянусь, чтобы не повторить, кроме необходимого. Итак, даже если условие одинаковое, вы должны использовать сеттер каждый раз для каждого атрибута.
class CheckString: def __set_name__(self, owner, name): self.name = name def __set__(self, instance, value): if isinstance(value, str): instance.__dict__[self.name] = value else: raise ValueError("Value must be string") class User: name = CheckString() email = CheckString() def __init__(self, name, email): self.name = name self.email = email u = User("Sumit", 1) # ValueError: Value must be string
Теперь, если мы хотим реализовать то же самое с собственностью Как мы бы имели
class User: def __init__(self, name, email): self._name = name self._email = email @property def email(self): return self._email @email.setter def email(self, value): if isinstance(value, str): self._email = value else: raise ValueError("Value must be string") @property def name(self): return self._name @name.setter def name(self, value): if isinstance(value, str): self._name = value else: raise ValueError("Value must be string") ... u.email = 1 # ValueError: Value must be string
В следующем посте мы постараемся декодировать, как ORM (объектно-реляционное отображение) воспользоваться дескрипторами.
Дескриптор протокол (2 части серии)
Оригинал: “https://dev.to/sroy8091/descriptor-protocol-and-how-django-orm-uses-it-23e6”