我想构建可用作装饰器的类,并保持以下原则不变:
- 应该可以将多个这样的类装饰器叠加在一个函数上。
- 结果函数名指针应与没有装饰器的相同函数无法区分,除了可能是其类型/类别不同。
- 装饰器的顺序不应该有影响,除非特定的装饰器强制规定。也就是说,独立的装饰器可以以任何顺序应用。
这是为一个Django项目,我现在正在处理的具体情况是该方法需要两个装饰器,并且看起来像普通的Python函数:
@AccessCheck
@AutoTemplate
def view(request, item_id) {}
@AutoTemplate将函数更改为仅返回一个字典以在上下文中使用,而不是返回HttpResponse。使用RequestContext,并从方法名称和模块推断模板名称。
@AccessCheck基于item_id对用户进行额外检查。
我猜只是为了正确获取构造函数并复制适当的属性,但这些属性是哪些?
以下装饰器无法按我所述工作:
class NullDecl (object):
def __init__ (self, func):
self.func = func
def __call__ (self, * args):
return self.func (*args)
如下代码所示:
@NullDecl
@NullDecl
def decorated():
pass
def pure():
pass
# results in set(['func_closure', 'func_dict', '__get__', 'func_name',
# 'func_defaults', '__name__', 'func_code', 'func_doc', 'func_globals'])
print set(dir(pure)) - set(dir(decorated));
此外,尝试在NullDecl构造函数中添加“print func.name”,它将适用于第一个装饰器,但不适用于第二个 - 因为名称会丢失。对eduffy的答案进行了改进,看起来效果相当不错:
class NullDecl (object):
def __init__ (self, func):
self.func = func
for n in set(dir(func)) - set(dir(self)):
setattr(self, n, getattr(func, n))
def __call__ (self, * args):
return self.func (*args)
def __repr__(self):
return self.func