2016-09-26 2 views
3

Я где-то читал о том, что вы можете иметь дескриптор с __set__ и без __get__.Как работает дескриптор с __set__, но без __get__?

Как это работает?

Учитывается ли он как дескриптор данных? Это дескриптор без данных?

Вот пример кода:

class Desc: 
    def __init__(self, name): 
     self.name = name 
    def __set__(self, inst, value): 
     inst.__dict__[self.name] = value 
     print("set", self.name) 

class Test: 
    attr = Desc("attr") 

>>>myinst = Test() 
>>> myinst.attr = 1234 
set attr 
>>> myinst.attr 
1234 
>>> myinst.attr = 5678 
set attr 
>>> myinst.attr 
5678 

ответ

5

Дескриптор вы в приведенном примере является дескриптором данных.

После установки атрибута, как и любой другой дескриптор данных, он занимает самый высокий приоритет и называется так:

type(myinst).__dict__["attr"].__set__(myinst, 1234) 

Это, в свою очередь, добавляет attr в словарь экземпляра согласно вашему методу __set__.

После доступа к атрибутам, дескриптор проверяется имеющий метод __get__, но терпит неудачу, в результате чего для поиска будет перенаправлен словарю экземпляра следующим образом:

myinst.__dict__["attr"] 

Если он не найден в словаре экземпляра , сам дескриптор возвращается.

Такое поведение вскоре задокументированы в data model так:

Если он не определяет __get__(), а затем получить доступ к атрибуту будет возвращать сам объект дескриптора, если нет значение в словаре экземпляра в объекта ,

Обычные способы использования включают в себя предотвращение использования в дескрипторах словарей {instance: value} и эффективных значений кеширования.


В Python 3.6, __set_name__ был добавлен в протокол дескриптора, таким образом, устраняя необходимость в указании имени внутри дескриптора. Таким образом, ваш дескриптор может быть записан следующим образом:

class Desc: 
    def __set_name__(self, owner, name): 
     self.name = name 
    def __set__(self, inst, value): 
     inst.__dict__[self.name] = value 
     print("set", self.name) 

class Test: 
    attr = Desc() 
+0

Что касается поведения документированного в модели данных, есть более полное описание в Реймонд [как] (https://docs.python.org/2/ howto/descriptor.html). – wim

+0

@wim На самом деле, причина, по которой я поднял этот вопрос поначалу, состоит в том, что там не документировано. Ничто не учитывает дескриптор данных без '__get__'. Подумал, как это работает. Я добавлю это к pydocs, я думаю. – Bharel