2010-08-26 51 views
1

我寫了一個裝飾,看起來像這樣無爭議裝飾裝修工?

def login_required_message(*args, **kwargs): 
    kwargs.setdefault('message', "You must be logged in to do that.") 
    return _user_passes_test_message(lambda u: u.is_authenticated(), *args, **kwargs) 

但是當我嘗試在最後使用它沒有(),它失敗了,除非我把它改寫這樣的:

def login_required_message(function=None, *args, **kwargs): 
    kwargs.setdefault('message', "You must be logged in to do that.") 
    decorator = _user_passes_test_message(lambda u: u.is_authenticated(), *args, **kwargs) 
    if function: return decorator(function) 
    else: return decorator 

然後()是可選的。那麼,如何將這個「可選」功能封裝到裝飾器中,以便我可以裝飾我的裝飾器以允許沒有參數?

回答

3

我其實最近寫了一個blog post關於這個 - 至少,我認爲它解決你想要做的。對於後人,這裏就是我想出了:

def opt_arguments(func): 
    def meta_wrapper(*args, **kwargs): 
     if len(args) == 1 and callable(args[0]): 
      return func(args[0]) 
     else: 
      def meta_func(inner_func): 
       return func(inner_func, *args, **kwargs) 
      return meta_func 
    return meta_wrapper 

順便說一句,在試圖找出如何做到這一點的過程中,我得出的結論是,這是其中的一件事情是幾乎總是比必要的更復雜;-)

+0

非常好!這就是我正在尋找的!非常感謝! – ramusus 2010-11-01 14:39:31