Python 的修饰器是一种语法糖(Syntactic Sugar),也就是说:
@decorator@wrapdef func(): pass
是下面语法的一种简写:
def func(): passfunc = decorator(wrap(func))
关于修饰器的两个主要问题:
修饰器用来修饰谁
谁可以作为修饰器
修饰函数
修饰器最常见的用法是修饰新定义的函数,在 0x0d 上下文管理器 中提到上下文管理器主要是为了 更优雅地完成善后工作 ,而修饰器通常用于扩展函数的行为或属性:
def log(func): def wraper(): print("INFO: Starting {}".format(func.__name__)) func() print("INFO: Finishing {}".format(func.__name__)) return wraper@logdef run(): print("Running run...")run()
INFO: Starting runRunning run...INFO: Finishing run
修饰类
除了修饰函数之外,Python 3.0 之后增加了对新定义类的修饰( PEP 3129 ),但是对于类别属性的修改可以通过 Metaclasses 或继承来实现,而新增加的类别修饰器更多是出于 Jython 以及 IronPython 的考虑,但其语法还是很一致的:
from time import sleep, timedef timer(Cls): def wraper(): s = time() obj = Cls() e = time() print("Cost {:.3f}s to init.".format(e - s)) return obj return wraper@timerclass Obj: def __init__(self): print("Hello") sleep(3) print("Obj")o = Obj()
HelloObjCost 3.005s to init.
类作为修饰器
上面两个例子都是以函数作为修饰器,因为函数才可以被调用(callable) decorator(wrap(func)) 。除了函数之外,我们也可以定义可被调用的类,只要添加 __call__ 方法即可:
class HTML(object): """ Baking HTML Tags! """ def __init__(self, tag="p"): print("LOG: Baking Tag !".format(tag)) self.tag = tag def __call__(self, func): return lambda: " {1} ".format(self.tag, func(), self.tag)@HTML("html")@HTML("body")@HTML("div")def body(): return "Hello"print(body())
LOG: Baking Tag !LOG: Baking Tag !LOG: Baking Tag!
Hello
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did111577