簡體   English   中英

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

[英]Python: Move dictionary within a class - with class methods as values - to another file

我有一個處理 TCP 連接的類,當接收到具有給定“ID”的消息時,我需要調用一個特定的函數來處理它。 這些 ID 只是數字,所以我創建了一個 IntEnum 來保存 ID:

class ID(IntEnum):
    # ...
    message_x = 20
    message_y = 21
    # ...

這些 ID 不一定是連續的(即某些 ID 是保留的),我預計最終會有數百甚至數千個 ID。

因為我不想為每個 ID 創建一千個 if - elses,所以我想使用 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__時都會處理整個文件,這遠非理想,因為字典將包含數百個條目。

你甚至嘗試過嗎?

如果將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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM