2011-06-19 88 views
1

我試圖找到一種很好的方法來輕鬆註冊Python類中某些命令的處理程序。這些處理程序將被登記爲SomeBaseClass的子類,並且僅在那裏可用。不幸的是,我開始認爲自己正在做的工作超出必要。現在,我已經有了:註冊每個類處理程序

def register_handlers(cls): 
    cls._handlers = {} 
    for method in cls.__dict__.values(): 
     if hasattr(method, "handler_name"): 
      cls._handlers[method.handler_name] = method 
    return cls 

class SomeBaseClass(object): 
    _handlers = None 
    def __init__(self): 
     for h in self._handlers: 
      self._handlers[h] = types.MethodType(self._handlers[h], self, SomeBaseClass) 
    def run_action(self, name, *args): 
     return self._handlers[name](*args) 

def actual_handler_wrapper(f): 
    .... 
    f.handler_name = name 
    .... 

有幾個問題在這裏:

  • 兩個類和它的處理程序必須加以裝飾
  • 子類的第二個層次是不容易得到(_handlers將不得不分配和檢查繼承的各個層面)
  • 結合處理的一類時初始化看來髒兮兮

有什麼方法可以改善嗎?我可能通過將SomeBaseClass更改爲元類來擺脫register_handlers。它還可以在創建課程時綁定處理程序。但這似乎比目前的方法更加複雜。

有沒有更簡單的方法?

編輯:使用範例:

@register_handlers 
class SubClass(SomeBaseClass): 
    @actual_handler_wrapper 
    def handler(self): 
     ... 
+0

你抽象這種模式是什麼樣的?是否稍後編寫'handler = SomeBaseClass._registry [some_name]'的目標是?或者有些不同? –

+0

'@ register_handlers'應該在'SomeBaseClass(object)'類之上嗎?什麼是'cn'? – senderle

+0

'cn'是一個複製和粘貼錯誤。我試圖在'SomeBaseClass'中爲通用調度函數註冊函數,這會將外部請求傳遞給一些'self._handlers [action_name]'。 – viraptor

回答

2

你的得太多問題。如果每個動作一個處理程序,那麼就構成了一個命名約定對於他們來說,是這樣的:

class SomeBaseClass(object): 
    def run_action(self, name, *args): 
     getattr(self, name + '_handler')(*args) 

class SubClass(SomeBaseClass): 
    def foo_handler(self): 
     # called on run_action('foo') 

話又說回來,你可能只是下降的run_action方法完全,但我想這取決於它是如何去被調用,並根據您的個人喜好。

+0

沒錯,這可能是解決問題的更簡單方法。但是,如果我可以簡化「註冊表」方法,我仍然感興趣... – viraptor

+0

@viraptor:使用命名約定和元類將擺脫裝飾器。或者如果你不想使用元類,則將它們減少爲一個類裝飾器。儘管如此,它只是複製了Python已經爲你做的事情,爲什麼呢? –

+0

容易反省,不會意外碰撞類的未來用戶,對一般事物更加明確,能夠進行一個名爲'some we!%d string'的行爲......以及許多其他原因。 – viraptor

相關問題