装饰一个类以监视属性更改 [英] Decorating a class to monitor attribute changes

查看:55
本文介绍了装饰一个类以监视属性更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望有一个在其属性之一发生更改时自动向订户发送通知的类。因此,如果我要编写这段代码:

I want to have classes that automatically send notifications to subscribers whenever one of their attributes change. So if I would write this code:

@ChangeMonitor
class ChangingClass(object):

    def __init__(self, x):
        self.x = x


changer = ChangingClass(5)
print("Going to change x.")
changer.x = 6
print("Going to not change x.")
changer.x = 6
print("End of program")

输出将是:

Going to change x
Old x = 5, new x = 6
Going to not change x.
End of program.

我的问题是如何实现ChangeMonitor装饰器类。在上面的示例中,我假设它将打印一行指示属性更改的行,但是出于有用的目的,它可以向已订阅的对象发送通知。

My question is how to implement the ChangeMonitor decorator class. In the above example I assume it will print a line indicating the changes of an attribute, but for useful purposes it could send notifications to subscribed objects.

推荐答案

您必须添加 __ setattr __()方法

You'd have to add a __setattr__() method:

def ChangeMonitor(cls):
    _sentinel = object()
    old_setattr = getattr(cls, '__setattr__', None)
    def __setattr__(self, name, value):
        old = getattr(self, name, _sentinel)
        if old not is _sentinel and old != value:
            print "Old {0} = {1!r}, new {0} = {2!r}".format(name, old, value)
        if old_setattr:
            old_setattr(self, name, value)
        else:
            # Old-style class
            self.__dict__[name] = value

    cls.__setattr__ = __setattr__

    return cls

这也应该处理现有的 __ setattr __ 钩子。 _sentinel 也用于允许 None 作为旧值。

This should handle existing __setattr__ hooks as well. The _sentinel is used to allow None as the old value too.

Demo:

>>> changer = ChangingClass(5)
>>> changer.x = 6
Old x = 5, new x = 6
>>> changer.x = 6
>>> # nothing printed
...
>>> changer.x = None
Old x = 6, new x = None
>>> changer.x = 6
Old x = None, new x = 6

这篇关于装饰一个类以监视属性更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆