亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Python:將類中的字典(以類方法作為值)移動到另一個文件

Python:將類中的字典(以類方法作為值)移動到另一個文件

小怪獸愛吃肉 2023-07-18 15:34:57
我有一個處理 TCP 連接的類,當接收到具有給定“ID”的消息時,我需要調用特定的函數來處理它。這些 ID 只是數字,因此我創建了一個 IntEnum 來保存這些 ID:class ID(IntEnum):    # ...    message_x = 20    message_y = 21    # ...這些 ID 不一定是連續的(即保留一些 ID),我預計最終會有數百甚至數千個 ID。因為我不想為每個 ID 創建一千個 if - else,所以我考慮使用 ID 作為字典中的鍵,該字典包含對處理每條消息的函數的引用:class ComManager:    def __init__(self):        # Init socket, message queues, threads for sending/receiving etc...        self.rcv_functions = {#...                              ID.message_x: ComManager._rcv_message_x,                               ID.message_y: ComManager._rcv_message_y,                              #...                              }        # Launch _rcv_thread here    def _rcv_thread(self):        message_id = self.rcv_message_id() # receive message ID from socket        message_id = ID(message_id) # Change from type "int" to type "ID"        self._rcv_functions[message_id](self) # Call appropriate method according to the dictionary, thus avoiding a massive if/else here or "switch case"-like workarounds    def _rcv_message_x(self):        # Handle reception and processing of message x here    def _rcv_message_y(self):        # Handle reception and processing of message y here我一直在嘗試將“_rcv_functions”放入自己的文件中,因為每條消息都有一個函數已經很煩人了:# import ID and ComManager classes from their respetive files_rcv_functions = {    # ...    ID.message_x:  ComManager._rcv_message_x,    ID.message_y:  ComManager._rcv_message_y,    # ...}然后,在 ComManager 中:class ComManager:    def __init__(self):        # Init socket, message queues, threads for sending/receiving etc...        from x import _rcv_functions這顯然會導致循環依賴。我一直在尋找這個問題的解決方案,有些人建議使用類型提示,但在這種情況下我無法讓它發揮作用。我還看到一些答案建議對每個字典值使用類似的東西__import__('module_name').ComManager.class_method,但我讀到這會嚴重影響性能,因為每次我調用時都會處理整個文件__import__,這遠非理想,因為字典將包含數百個條目。
查看完整描述

1 回答

?
萬千封印

TA貢獻1891條經驗 獲得超3個贊

你嘗試過嗎?


如果您將import語句放在上面所示的方法中__init__,則不會出現“循環依賴”:在第一次導入另一個模塊時,定義 ComManager 的調用者模塊已經運行,并且該類已定義并準備好在第二個模塊中導入。


除此之外,您可以將處理方法放在 mixin 類中,而不是放在處理程序ComManager本身的主體中。


因此,在另一個模塊中,您將擁有:



...

class ID(IntEnum):

    ...


class HandlersMixin:

    def _rcv_message_x(self, msg):

        ...

    ...


mapping = {

  ID.message_x = HandlerMixn._rcv_message_x,  

}


請注意,通過這種方式,映射映射了未綁定的方法:它們是普通函數,需要“HandlerMixin”實例作為其第一個參數


在你的第一個模塊上:


from other_module import ID, mapping, HandlerMixin


class ComManager(HandlerMixin):

    def _rcv_thread(self):

        message_id = self.rcv_message_id() # receive message ID from socket

        message_id = ID(message_id) # Change from type "int" to type "ID"

        mapping[message_id](self)  

        # Passing "self" explictly will make the methods work the same

        # as f they were called from this instance as `self.method_name`,

        # and since they are methods on this class through inheritance

        # they can use any other methods or attributes on this instance


查看完整回答
反對 回復 2023-07-18
  • 1 回答
  • 0 關注
  • 129 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號