Decorator classes in Python
我想构建一些类作为装饰器使用,它们的原则是完整的:
这是针对一个Django项目的,我现在正在研究的具体情况是,该方法需要2个修饰器,并且要显示为一个普通的python函数:
1 2 3 | @AccessCheck @AutoTemplate def view(request, item_id) {} |
@autotemplate更改了函数,因此它不返回httpresponse,而只返回一个字典用于上下文。使用了RequestContext,并从方法名和模块推断模板名。
@accesscheck根据项目_id添加对用户的附加检查。
我猜这只是为了让构造函数正确并复制适当的属性,但是这些属性是什么?
下面的装饰器不能像我描述的那样工作:
1 2 3 4 5 | class NullDecl (object): def __init__ (self, func): self.func = func def __call__ (self, * args): return self.func (*args) |
号
如以下代码所示:
1 2 3 4 5 6 7 8 9 10 11 | @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",它将为第一个修饰器工作,但不会丢失第二个as名称。
Eduffy的回答有点精练,而且似乎效果很好:
1 2 3 4 5 6 7 8 9 10 | 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 |
。
Do Nothing Decorator类如下所示:
1 2 3 4 5 6 7 8 | class NullDecl (object): def __init__ (self, func): self.func = func for name in set(dir(func)) - set(dir(self)): setattr(self, name, getattr(func, name)) def __call__ (self, *args): return self.func (*args) |
然后您可以正常应用它:
1 2 3 | @NullDecl def myFunc (x,y,z): return (x+y)/z |
号
decorator模块帮助您编写保留签名的decorator。
而pythondecoratorlibrary可能为装饰师提供有用的例子。
要创建一个包装函数使其与原始函数不可区分的装饰器,请使用
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | def mydecorator(func): @functools.wraps(func): def _mydecorator(*args, **kwargs): do_something() try: return func(*args, **kwargs) finally: clean_up() return _mydecorator # ... and with parameters def mydecorator(param1, param2): def _mydecorator(func): @functools.wraps(func) def __mydecorator(*args, **kwargs): do_something(param1, param2) try: return func(*args, **kwargs) finally: clean_up() return __mydecorator return _mydecorator |
(我个人的偏好是使用函数而不是类创建装饰器)
装饰师的订购如下:
1 2 3 4 5 6 7 8 9 10 | @d1 @d2 def func(): pass # is equivalent to def func(): pass func = d1(d2(func)) |
。