好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

PyTips0x0f

项目地址: https://git.io/pytips

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

查看更多关于PyTips0x0f的详细内容...

  阅读:34次