如何在Python中装饰属性

时间:2019-01-28 09:59:00

标签: python properties decorator descriptor

我正在尝试在描述符类中为魔术方法(__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 :(得分:1)

我可能是错的,但很可能根本没有调用您的描述符,装饰器不是问题。描述符应该像

一样使用
class Foo2:
    my_object = Register('my_object', 'init_value')

-您正在像类属性一样定义它。如果您的类属性支持python(即它是描述符),则python将使用__get__ / __set__ / __del__执行所有机制。

这就是为什么描述符方法中有一个“实例”参数的原因-您将描述符定义为类变量,但是__set__方法将接收您的类的实际实例,因此您可以管理每个实例的数据,就像您的device