2

我想提供一个装饰器,允许在应用于函数时进行可选配置。

一个简单的实现如下:

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

1 回答 1

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)

So, while performance wise there would be no difference to your code (unless you would be decorating at least hundreds of thousands of functions - your code create an extra object - a class - for each time the decorator is used, besides the instance of that class) - there is an impact on people would review your code (either to use your modules, or to maintain it after you are done). I mean "a decorator that dynamically generates subclasses of itself" may sound too advanced and scare people away. Although it is as simple as my suggestion above once one understands the mechanisms of class generation in Python as you had.

于 2012-10-17T20:15:03.750 回答