【问题标题】:How to decorate property in Python如何在 Python 中装饰属性
【发布时间】:2019-06-21 07:18:46
【问题描述】:

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

【问题讨论】:

    标签: python properties decorator descriptor


    【解决方案1】:

    我可能是错的,但很可能你的描述符根本没有被调用,装饰器不是问题。旨在像这样使用的描述符

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

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

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

    【讨论】:

    • 是的,你是对的。我以为它正在调用 get/set 但实际上它返回了我稍后设置的 my_object 变量(a.my_object = 1)。谢谢!
    猜你喜欢
    • 2016-03-17
    • 2018-07-06
    • 1970-01-01
    • 2012-07-15
    • 2022-11-09
    • 2019-12-26
    • 2017-01-06
    • 2021-12-15
    • 2013-05-11
    相关资源
    最近更新 更多