2011-01-30 29 views
5

我試圖在Python中實現一個「子命令」系統作爲可繼承的類。我的預期使用情況是這樣的:在類中定義一個裝飾器,這在類定義中也是可用的

from command import Command 
import sys 

class MyCommand(Command): 
    @Command.subcommand 
    def foo(self): 
     print "this can be run as a subcommand" 

    def bar(self): 
     print "but this is a plain method and isn't exposed to the CLI" 

MyCommand()(*sys.argv) 

# at the command line, the user runs "mycommand.py foo" 

我實現Command.subcommand作爲一個靜態方法,直到我試圖子命令添加到父類,這讓我TypeError: 'staticmethod' object is not callable一切正常。現在回想起來,很明顯,this將無法​​正常工作:

class Command(object): 
    @staticmethod 
    def subcommand(method): 
     method.is_subcommand = True 

     return method 

    @subcommand 
    def common(self): 
     print "this subcommand is available to all child classes" 

到目前爲止我發現的唯一的選擇是聲明父類的外部subcommand裝飾,那麼類定義完成後注入它。

def subcommand(method): 
    method.is_subcommand = True 

    return method 

class Command(object): 
    @subcommand 
    def common(self): 
     print "this subcommand is available to all child classes" 

Command.subcommand = staticmethod(subcommand) 
del subcommand 

但是,作爲在裝飾器添加之前從未使用Python的人,這對我來說感覺非常笨重。有沒有更好的方法來實現這個目標?

+0

那麼,第一個問題是爲什麼你實現一個裝飾器作爲一個類的方法,除非該類用於一堆裝飾器。如果這就是它的原因,爲什麼你裝飾裝飾「普通」?感覺很笨重,可能是因爲你的課堂設計有點奇怪...... :) – 2011-01-30 21:43:52

+0

你希望這個裝飾者能爲你完成什麼? Python已經知道子命令是什麼,因爲它知道哪些類是其他子類的子類。 – 2011-01-30 21:56:35

回答

5

這個問題有兩種解決方案,我可以想到。最簡單的就是使它成爲一個靜態方法後,你使用它的父類進行:

class Command(object): 
    def subcommand(method): # Regular function in class definition scope. 
     method.is_subcommand = True 

     return method 

    @subcommand 
    def common(self): 
     print "this subcommand is available to all child classes" 

    subcommand = staticmethod(subcommand) 
    # Now a static method. Can no longer be called during class definition phase. 

這有點脆弱,因爲你做之後,你不能使用它的父類一個靜態方法。更強大的方式做,這是添加一箇中間類:

class Command(object): 
    @staticmethod 
    def subcommand(method): 
     method.is_subcommand = True 

     return method 

class CommandBase(Command): 

    @Command.subcommand 
    def common(self): 
     print "this subcommand is available to all child classes" 

現在,您可以繼承所有的類從CommandBase而不是Command