如何在 Python 中装饰 属性

How to decorate property in Python

我正在尝试为描述符 class 中的魔术方法 (__get__) 添加额外的装饰器。

我可以在使用@属性 时执行此操作,但在使用描述符class 时则不行。

我检查范围是因为我的对象集在总线上注册,一些寄存器只能取特定范围的值:

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

我可能错了,但很可能你的描述符根本没有被调用,装饰器不是问题。描述符意味着像

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

— 您将其定义为 class 属性。 python 将使用 __get__/__set__/__del__ 执行所有机器,如果您的 class 属性支持它(即它是描述符)。

这就是描述符方法中有一个 "instance" 参数的原因——您将描述符定义为 class 变量,但是 __set__ 方法将接收您的 class,因此您可以管理每个实例的数据,例如您的 device