Как украсить недвижимость в Python
Я пытаюсь добавить дополнительный декоратор для магического метода (__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 ответ
Я могу ошибаться, но, скорее всего, ваш дескриптор вообще не вызывается, декоратор не проблема. Дескрипторы предназначены для использования как
class Foo2:
my_object = Register('my_object', 'init_value')
- вы определяете это как атрибут класса. И Python выполнит все машины с __get__
/__set__
/__del__
если ваш атрибут класса поддерживает это (т.е. это дескриптор).
Вот почему в дескрипторных методах есть аргумент "экземпляр" - вы определяете дескриптор как переменную класса, но т.е. __set__
Метод получит фактический экземпляр вашего класса, так что вы можете управлять данными для каждого экземпляра, такими как ваш device