2012-10-17 39 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中的类生成机制就像你一样。