带参数的 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 装饰器类的主要内容,如果未能解决你的问题,请参考以下文章