Как украсить недвижимость в Python - PullRequest
0 голосов
/ 28 января 2019

Я пытаюсь добавить дополнительный декоратор для магического метода (__get__) в классе дескриптора.

Я могу сделать это, когда использую @property, но не когда использую класс дескриптора.

Я проверяю диапазон, потому что мой набор объектов регистрируется на шине, и некоторые регистры могут принимать только определенный диапазон значений:

import functools

def check_range(min, max):
    def decorator(f):
        @functools.wraps(f)
        def wrap(self, value):
            if value not in range(min, max+1):
               return
           return f(self, value)
        return wrap
    return decorator

Это работает:

class Foo:
   def __init__(self):
      self.device.init_smth('my_object')

   @property
   def my_object(self):
      return self.device.get_value('my_object')

   @my_object.setter
   @check_range(0,1)
   def my_object(self, value):
       self.device.set_value('my_object', value)

a = Foo()
print(a.my_object)
a.my_object = 1
print(a.my_object)
a.myobject = -1

Ив этом примере все работает одинаково, но check_range не вызывается:

class Register:
    def __init__(self, name, device):
        self.name = name
        device.init_smth(name)

    def __get__(self, instance, owner):
        return instance.device.get_value(self.name)

    @check_range(0,1)
    def __set__(self, instance, value):
        instance.device.set_value(self.name, value)

class Foo:
   def __init__(self):
      self.my_object = Register('my_object', self.device)

a = Foo()
print(a.my_object)
a.my_object = 1
print(a.my_object)
a.myobject = -1

1 Ответ

0 голосов
/ 28 января 2019

Я могу ошибаться, но, скорее всего, ваш дескриптор вообще не вызывается, декоратор не проблема.Дескрипторы предназначены для использования как

class Foo2:
    my_object = Register('my_object', 'init_value')

- вы определяете его как атрибут класса.И python выполнит все механизмы с __get__ / __set__ / __del__, если ваш атрибут класса поддерживает его (т.е. это дескриптор).

Именно поэтому в дескрипторных методах есть аргумент "instance"- вы определяете дескриптор как переменную класса, но метод __set__ будет получать фактический экземпляр вашего класса, поэтому вы можете управлять данными для каждого экземпляра, например, device

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...