Vetsin February 2016

Decorators to register functions before being called

I would like to decorate bar and baz to register them with Container and collect the callback in Foo. Is this possible given python decorators?

class Foo(object):
    results = []
    def __init__(self, app):
        self.app = app
        self.registerAll()

    def registerAll(self):
        self.results.append(self.app.myRegister(self.baz))
        self.results.append(self.app.myRegister(self.bar))

    def baz(self):
        print("baz")

    def bar(self):
        print("bar")

class Container(object):
    funcs = []

    def start(self):
        self.f = Foo(self)

    def myRegister(self, f):
        self.funcs.append(f)
        print("myRegister")
        def callback(res):
            print('cb')
        return callback

x = Container()
x.start()

Answers


martineau February 2016

Your question looks suspiciously like an XY Problem, since it's very unclear what you ultimately hope to accomplish by registering the functions (which are actually class methods). (Also see What is the XY problem?) Nevertheless, here's one way to do what you want — assuming I understand what you have so far in your question.

I made Container.myRegister() a classmethod since it only references an attribute of the class it is in. I also defined the Container class before the Foo class so the former could be referenced by the decorator. In addition I removed the registerAll() method, since it's no longer needed (however that means the class attribute results is now not referenced anywhere, so maybe it should be removed, too...).

class Container(object):
    funcs = []

    def start(self):
        self.f = Foo(self)

    @classmethod
    def myRegister(cls, f):
        cls.funcs.append(f)
        print("myRegister")
        def callback(res):
            print('cb')
        return callback

def decorate(cls):
    def decorator(method):
        cls.myRegister(method)
        return method
    return decorator

class Foo(object):
    results = []

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

    @decorate(Container)
    def baz(self):
        print("baz")

    @decorate(Container)
    def bar(self):
        print("bar")

x = Container()
x.start()

Post Status

Asked in February 2016
Viewed 2,280 times
Voted 10
Answered 1 times

Search




Leave an answer