2012-10-17 74 views
2

我想提供一個裝飾器,它允許在應用於某個功能時進行可選配置。Python中的可定製裝飾器

一個簡單的實現如下:

import functools 


class Deco(object): 
    config = {'message': 'hello'} 

    def __init__(self, func): 
     self.func = func 
     functools.wraps(func)(self) 

    def __call__(self, *args, **kwargs): 
     print self.config['message'] 
     return self.func(*args, **kwargs) 

    @classmethod 
    def customize(cls, **kwargs): 
     """Return a customized instance of this class. """ 
     return type(cls.__name__, (Deco,), {'config': kwargs}) 


@Deco 
def add(a, b): 
    return a + b 


@Deco.customize(message='bye') 
def sub(a, b): 
    return a - b 


>>> add(1, 2) 
'hello' 
>>> sub(2, 1) 
'bye' 

我想用它來Django的觀點提供了人性化的裝飾。

這種方法沒有錯誤,但是有什麼不好的讓一個類有一個靜態工廠方法實例化它自己的自定義實例,作爲一個裝飾器?

+4

它工作嗎?如果不是,你會得到什麼錯誤? – 2012-10-17 16:34:03

+0

有時它混淆了不應該被混淆的東西...但只要你的罰款那麼你的好我認爲... –

回答

2

您可以在每次使用裝飾器時不創建額外的子類而工作,但是您的代碼沒問題。無需額外的子類的方式可能是沿東西:

class Deco(object): 
    config = {'message': 'hello'} 

    def __init__(self, func=None, **kwargs): 
     if kwargs: 
      self.config = kwargs 
     if func is not None: 
      self._decorate(func) 

    def _decorate(self, func): 
     self.func = func 
     functools.wraps(func)(self) 

    def __call__(self, *args, **kwargs): 
     if not hasattr(self, "func"): 
      self._decorate(func) 
      return self 
     print self.config['message'] 
     return self.func(*args, **kwargs) 

所以,雖然在性能方面會有你的代碼沒有區別(除非你將裝飾至少幾十萬的功能 - 你的代碼中創建一個額外的對象 - 一個類 - 每次使用裝飾器時,除了該類的實例外) - 對人們的影響是檢查你的代碼(要麼使用你的模塊,要麼在你完成之後維護它)。我的意思是「一個動態生成自身子類的裝飾器」可能聽起來太過先進,並且會嚇跑人們。雖然它和我上面的建議一樣簡單,只要你理解Python中的類生成機制就像你一樣。