我想构造用作装饰器的类,原则如下:
应该可以在top off 1函数上堆叠多个这样的类装饰器.
生成的函数名称指针应该与没有装饰器的同一函数无法区分,可以保存它的类型/类.
除非装饰者实际要求,否则对装饰器进行排序不应该是相关的.IE浏览器.独立装饰者可以按任何顺序应用.
这是一个Django项目,我正在处理的具体情况现在该方法需要2个装饰器,并显示为普通的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));
此外,尝试添加"打印FUNC.名称在NullDecl构造函数,它会为第一个装饰工作,而不是第二个" -正如名字将会丢失.
精致的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
eduffy.. 23
一个do-nothing装饰器类看起来像这样:
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)
然后你可以正常应用它:
@NullDecl def myFunc (x,y,z): return (x+y)/z
也许还有一个地方可以将`**kwargs`添加到定义`def __call__(self,*args):`(以及稍后调用`self.func`)? (7认同)
f3lix.. 10
该装饰模块可以帮助你编写签名保留装饰.
而PythonDecoratorLibrary可能会为装修提供有用的例子.
一个do-nothing装饰器类看起来像这样:
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)
然后你可以正常应用它:
@NullDecl def myFunc (x,y,z): return (x+y)/z
该装饰模块可以帮助你编写签名保留装饰.
而PythonDecoratorLibrary可能会为装修提供有用的例子.
要创建一个装饰器来包装函数,使其与原始函数无法区分,请使用functools.wraps
.
例:
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
(我个人的偏好是使用函数创建装饰器,而不是类)
装饰器的顺序如下:
@d1 @d2 def func(): pass # is equivalent to def func(): pass func = d1(d2(func))