正如我所理解的那样,有两种方法可以做Python装饰器,既可以使用__call__
类,也可以定义函数作为装饰器.这些方法的优点/缺点是什么?有一种首选方法吗?
例1
class dec1(object):
def __init__(self, f):
self.f = f
def __call__(self):
print "Decorating", self.f.__name__
self.f()
@dec1
def func1():
print "inside func1()"
func1()
# Decorating func1
# inside func1()
Run Code Online (Sandbox Code Playgroud)
例2
def dec2(f):
def new_f():
print "Decorating", f.__name__
f()
return new_f
@dec2
def func2():
print "inside func2()"
func2()
# Decorating func2
# inside func2()
Run Code Online (Sandbox Code Playgroud) 我想构造用作装饰器的类,原则如下:
这是一个Django项目,我正在处理的具体情况现在该方法需要2个装饰器,并显示为普通的python函数:
@AccessCheck
@AutoTemplate
def view(request, item_id) {}
Run Code Online (Sandbox Code Playgroud)
@AutoTemplate更改了函数,以便它不返回HttpResponse,而只返回一个字典以供在上下文中使用.使用RequestContext,并从方法名称和模块推断模板名称.
@AccessCheck根据item_id添加对用户的附加检查.
我猜这只是为了让构造函数正确并复制适当的属性,但这些属性是什么?
以下装饰器不会像我描述的那样工作:
class NullDecl (object):
def __init__ (self, func):
self.func = func
def __call__ (self, * args):
return self.func (*args)
Run Code Online (Sandbox Code Playgroud)
如以下代码所示:
@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));
Run Code Online (Sandbox Code Playgroud)
此外,尝试添加"打印FUNC.名称在NullDecl构造函数,它会为第一个装饰工作,而不是第二个" -正如名字将会丢失.
精致的eduffy的回答有点,而且看起来效果很好:
class NullDecl (object):
def __init__ (self, func):
self.func = func
for n …
Run Code Online (Sandbox Code Playgroud) 考虑这个小例子:
import datetime as dt
class Timed(object):
def __init__(self, f):
self.func = f
def __call__(self, *args, **kwargs):
start = dt.datetime.now()
ret = self.func(*args, **kwargs)
time = dt.datetime.now() - start
ret["time"] = time
return ret
class Test(object):
def __init__(self):
super(Test, self).__init__()
@Timed
def decorated(self, *args, **kwargs):
print(self)
print(args)
print(kwargs)
return dict()
def call_deco(self):
self.decorated("Hello", world="World")
if __name__ == "__main__":
t = Test()
ret = t.call_deco()
Run Code Online (Sandbox Code Playgroud)
打印
Hello
()
{'world': 'World'}
Run Code Online (Sandbox Code Playgroud)
为什么self
参数(应该是Test obj实例)不作为第一个参数传递给装饰函数decorated
?
如果我手动完成,例如:
def call_deco(self):
self.decorated(self, "Hello", …
Run Code Online (Sandbox Code Playgroud)