[英]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.