如何将带参数的方法传递给装饰器?

2 投票
2 回答
1039 浏览
提问于 2025-04-18 00:14

有没有办法把带参数的方法传递给装饰器的 __init__ 方法呢?

下面是一个简单的装饰器和使用示例:

class Decorator(object):
    def __init__(self, *args):
        print args

    def __call__(self, func): # yep the method still have to be callable
        return func

@Decorator
def foo():
    pass

一个没有参数的装饰器会把方法作为参数传递。

$ python foo.py
(<function foo at 0x7fefd7ac1b90>,)

当我给装饰器添加参数时:

@Decorator(1, 2, 3)
def foo():
    pass

结果是:

$ python test.py 
(1, 2, 3)

如你所见,传递的参数中现在缺少了这个方法。

2 个回答

2

这里有一个不需要内部类的替代方案:

class decorator(object):
    def __init__(self, *args):
        # This creates the decorator
        self.args = args

    def __call__(self, func):
        # This applies the decorator
        self.func = func
        return self.call

    def call(self, *moreargs):
        # And this happens when the original function is called
        print self.args, self.func, moreargs
        return self.func()

@decorator(1, 2, 3)
def foo():
    pass

我还使用过 functools.partial(self.method, func) 来做装饰器。这在某些情况下很有用。

4

当我们给一个装饰器传递参数时,我们需要先创建一个额外的函数,这个函数用来接收这些参数,然后再返回真正的装饰器。

def decorator_creator(*args):
    class Decorator(object):
        def __init__(self, func):
            print args
            print func
            self.func = func
        def __call__(self):
            return self.func()
    return Decorator

@decorator_creator(1, 2, 3)
def foo():
    pass

输出结果:

(1, 2, 3)
<function foo at 0x0000000002EB9EB8>

撰写回答