如何在装饰器中创建Python描述符的示例?

gzszwxb4  于 2023-05-16  发布在  Python
关注(0)|答案(1)|浏览(321)

我正在尝试编写一个Python程序,在该程序中捕获属性的更新,以便稍后更新所有更改的GUI或进行其他处理。现在,我正在使用一个实现描述符协议的类的示例来捕获观察到的属性中的所有更改,这工作得很好。
我想要改变/改进的是将ObservedAccess的示例,如下面TestObserving类中所示,移动到装饰器中,类似于这样:@observableclass(some_int,some_string)class TestObserving
并在装饰器中创建所需的ObservedAccess示例。
谢谢你的任何信息或想法,保罗。

# dummy observer method
def changed(instance, private_name):
    print(f'instence: {instance}, attribute: {private_name} changed')

class ObservedAccess:
    def __set_name__(self, owner, name):
        self.public_name = name
        self.private_name = '_' + name

    def __get__(self, obj, object_type=None):
        value = getattr(obj, self.private_name)
        return value

    def __set__(self, obj, value):
        setattr(obj, self.private_name, value)
        # let observers know the instance has changed
        changed(obj, self.private_name)

class TestObserving:
    some_string = ObservedAccess()
    some_int = ObservedAccess()

    def __init__(self):
        self.some_string = "Today is a demo day"
        self.some_int = 5

if __name__ == '__main__':
    t = TestObserving()

我甚至不知道如何从装饰者开始做到这一点。我想我的绊脚石是如何将示例的“名称”传递给装饰器函数,除非我将它们作为真字符串传递,这看起来很尴尬。

lvmkulzt

lvmkulzt1#

这是你需要的吗

def changed(instance, private_name):
    print(f'instence: {instance}, attribute: {private_name} changed')

class ObservedAccess:
    def __set_name__(self, owner, name):
        self.public_name = name
        self.private_name = '_' + name

    def __get__(self, obj, object_type=None):
        value = getattr(obj, self.private_name)
        return value

    def __set__(self, obj, value):
        setattr(obj, self.private_name, value)
        # let observers know the instance has changed
        changed(obj, self.private_name)

class observableclass:
    def __init__(self, some_string, some_int):
        self.some_string = some_string
        self.some_int = some_int
        
    def __call__(self, obj):
        def new(cls):
            instance = object.__new__(cls)
            instance.some_string = self.some_string
            instance.some_int = self.some_int
            return instance
        obj.__new__ = new
        return obj
  
@observableclass(some_string='abc', some_int=123)
class TestObserving:
    some_string = ObservedAccess()
    some_int = ObservedAccess()

    # def __init__(self):
    #     self.some_string = "Today is a demo day"
    #     self.some_int = 5

if __name__ == '__main__':
    t = TestObserving()

相关问题