簡體   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