繁体   English   中英

如何在类级别正确使用装饰器?

[英]How to use a decorator in class level correctly?

我有一条消息总线,并且一个类为消息总线预订了许多方法,例如:

class BookingService(object):
    def start(self):
        self.msg_bus.login(self.user, self.password)
        self.msg_bus.subscribe('/broadcast/aliveResponse', self.handleAliveResponse)
        self.msg_bus.subscribe('/broadcast/musicInfoUpdated', self.handleMusicInfo)
        self.msg_bus.subscribe('/broadcast/radioOnline', self.handleRadioOnline)
        self.msg_bus.subscribe('/broadcast/radioOffline', self.handleRadioOffline)
        self.msg_bus.subscribe('/broadcast/online', self.handleBroadcastOnline)
        self.msg_bus.subscribe('/proxy/aliveResponse', self.handleEvent)
        self.msg_bus.subscribe('/proxy/online', self.handleProxyOnline)
        self.msg_bus.subscribe('/proxy/radioReady', self.handleEvent)
        self.msg_bus.subscribe('/proxy/radioUpdate', self.handleEvent)
        self.msg_bus.subscribe('/proxy/radioClosed', self.handleEvent)
        self.msg_bus.subscribe('/message_bus/detached', self.handleDetached)
        self.msg_bus.run()

它可以工作,但是很难理解每种方法的消息路径是什么,我想要的是使用装饰器通过方法订阅消息总线,看起来像这样

class BookingService(object):

    @subscribe('/broadcast/aliveResponse')
    @subscribe('/broadcast/onLine')
    def handleEvent(self, dest, data):
        print dest, data

    @subscribe('/proxy/aliveResponse')
    def handleAnotherEvent(self, dest, data):
        print dest, data

但是这里要解决一些困难,首先,msg_bus属性属于实例,即属于self。 我无法在课堂上获得self.msg_bus。 为了解决这个问题,我可以这样写:

class BookingService(object):

    subscribations = []
    def subscribe(dest):
        """Decorator for subscribing function to destination

        """
        def callee(func):
            subscribations.append((dest, func))
            return func
        return callee

    def subscribe_all(self):
        for dest, func in self.subscribations:
            self.msg_bus.subscribe(dest, func)

    @subscribe('/broadcast/aliveResponse')
    def handleEvent(self, dest, data):
        print dest, data

    def start(self):
        self.subscribe_all()

我尝试将预订收集到BookingService.subscribations中,然后在subscribe_all中将它们添加到msg_bus中,但这是问题所在。 我有一个错误

subscribations.append((dest, func))
NameError: global name 'subscribations' is not defined

看来,订阅不在订阅功能的范围内,如何解决这个问题?

而不是将其放入实例的列表中,而是将其放入函数或类的列表中。

class BookingService(object):

    def subscribe(dest):
        """Decorator for subscribing function to destination

        """
        def callee(func):
            if not hasattr(func, 'subscriptions'):
                func.subscriptions = []
            func.subscriptions.append((dest, func))
            return func
        return callee

    def subscribe_all(self):
        for classmember in dir(self):
            for dest, func in getattr(getattr(self, classmember), 'subscriptions', []):
                self.msg_bus.subscribe(dest, func)

    @subscribe('/broadcast/aliveResponse')
    def handleEvent(self, dest, data):
        print dest, data

    def start(self):
        self.subscribe_all()

但是,您可能仍然遇到方法未绑定的问题; 注意“自我”的含义。

您可能还想将“ subscribe”移到类定义之外,或将其重命名为“ _subscribe”或使其被称为self.subscribe() (目前, self.subscribe()可以正常工作,但并不符合您的期望)

您可以在类主体中定义预订,这使它成为类属性。 但是,在使用它时,会将其用作全局变量。 您必须从方法中获取它,但是由于这是在创建类之前发生的,因此您不能这样做。

您可以将其设置为函数的属性,也可以具有一个全局字典,其中包含函数和目标之间的映射。 在这两种情况下,您都必须通过subscribe_all方法中的类中的所有函数来查看它们是否具有预订。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM