我想提供一个装饰器,允许在应用于函数时进行可选配置。
一个简单的实现如下:
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 View 提供用户友好的装饰器。
这种方法可以正常工作,不会出现错误,但是作为装饰器,允许类拥有静态工厂方法来实例化其自身的自定义实例有什么不好吗?
最佳答案
您可以在每次使用装饰器时无需创建额外的子类,但您的代码很好。没有额外子类的方式可能是这样的:
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 中的类生成机制。
关于python - Python 中的可定制装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12939012/