How to use decorator in observer pattern for Python 2.7

The observer circuit in the very simplified code below works well. I would like to have a decorator @on_eventthat performs registration in a single Observable window.

In the O2 class below this does not work. The problem, of course, is that the on_event decoder is called before the instance is created, and the registration will be associated with an unrelated method event. In some ways, I have to postpone registration until the O2 object is initialized. Maybe it’s not worth saying, but all I want to add to O2 is the decorator, as in the code below.

But surely there must be a solution to this? I googled around, but can't find anything, and tried several approaches.

class Observable(object):
    _instance = None

    @classmethod
    def instance(cls):
        if not cls._instance:
            cls._instance = Observable()
        return cls._instance

    def __init__(self):
        self.obs = []

    def event(self, data):
        for fn in self.obs:
            fn(data)

def on_event(f):
    def wrapper(*args):
        return f(*args)
    Observable.instance().obs.append(f)
    return wrapper

class O(object):

    def __init__(self, name):
        self.name = name
        Observable.instance().obs.append(self.event)

    def event(self, data):
        print self.name + " Event: " + data

class O2(object):

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

    @on_event
    def eventx(self, data):
        print self.name + " Event: " + data

if __name__ == "__main__":
    o1 = O("o1")
    Observable.instance().event("E1")

    o2 = O2("o2")
    Observable.instance().event("E2")
+4
1

, . - , .

/:

class ObservingMeta(type):
    def __call__(cls, *args, **kw):
         instance = super(ObservingMeta, cls).__call__(*args, **kw)
         for attr in vars(cls).values():
             if hasattr(attr, '__observer__'):
                 # register bound method
                 bound = attr.__get__(instance, cls)
                 Observable.instance().obs.append(bound)
         return instance

, cls, ; :

def on_event_method(f):
    f.__observer__ = True
    return f

:

class O2(object):
    __metaclass__ = ObservingMeta

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

    @on_event_method
    def eventx(self, data):
        print self.name + " Event: " + data

, Observable singleton ; O2, bound eventx , , , .

python WeakSet, , , , , .

+5

Source: https://habr.com/ru/post/1546016/


All Articles