带参数的 Python 装饰器类

Posted

技术标签:

【中文标题】带参数的 Python 装饰器类【英文标题】:Python Decorator class with arguments 【发布时间】:2014-03-24 10:18:22 【问题描述】:

我有一个简单的 Python 类,我想用它来为我正在编写的程序添加命名钩子。我尝试运行以下代码并得到以下输出。


代码:

hooks = 

class hook(object):
    def __init__(self, f, hook):
        if hook not in hooks:
            hooks[hook] = []

        hooks[hook].append("module": f.__module__, "func": f)
        self.f = f

    def __call__(self, *args):
        f(*args)

@hook("test")
def testHook():
    print "hi"

输出:

Traceback (most recent call last):                       
  File "<stdin>", line 1, in <module>                    
TypeError: __init__() takes exactly 3 arguments (2 given)

我该如何解决这个问题?我正在使用 Python 2.7

【问题讨论】:

【参考方案1】:

你的装饰器语法:

@hook("test")
def testHook():
    # ...

翻译为:

def testHook():
    # ...

testHook = hook("test")(testHook)

所以它只给出了 一个 参数。您需要重组您的代码以将您的类装饰器生成为hook()返回值

以下方法可行:

def hook(hookname):
    class HookDecorator(object):
        def __init__(self, f):
            if hookname not in hooks:
                hooks[hookname] = []

            hooks[hook].append("module": f.__module__, "func": f)
            self.f = f

        def __call__(self, *args):
            return self.f(*args)

    return HookDecorator

其中__call__ 使用self.f,而不是全局f,并返回任何产生的修饰函数。我假设hooks 是某处的全局字典。

然而,把它变成一个类没有什么意义;你使用很少的状态。您也可以在这里使用包装器 function

from functools import wraps

def hook(hookname):
    def decorator(f):
        if hookname not in hooks:
            hooks[hookname] = []

        hooks[hookname].append("module": f.__module__, "func": f)

        @wraps(f)
        def wrapper(*args):
            return f(*args)

        return wrapper

    return decorator

【讨论】:

我明白了。非常感谢! :)

以上是关于带参数的 Python 装饰器类的主要内容,如果未能解决你的问题,请参考以下文章

python_如何定义带参数的装饰器?

装饰器、装饰器类与类装饰器(三)

python装饰器详解,多层装饰器,及带参数的装饰器。

Python装饰器实现带参数和不带参数

python基础 带参数以及返回值的函数装饰器

用于制作 python 装饰器类的精益接口