十六.装饰器

装饰器

因为函数也是一个对象,并且函数对象能够被赋值给变量,因此,经过变量也能调用该函数。
 
>>> def now():
...     print '2013-12-25'
...
>>> f = now
>>> f()
2013-12-25

函数对象有一个__name__属性,能够拿到函数的名字:app

>>> now.__name__
'now'
>>> f.__name__
'now'

如今,假设咱们要加强now()函数的功能,好比,在函数调用先后自动打印日志,但又不但愿修改now()函数的定义,这种在代码运行期间动态增长功能的方式,称之为“装饰器”(Decorator)。函数

本质上,decorator就是一个返回函数的高阶函数。因此,咱们要定义一个能打印日志的decorator,能够定义以下:spa

def log(func):
    def wrapper(*args, **kw):
        print 'call %s():' % func.__name__
        return func(*args, **kw)
    return wrapper

观察上面的log,由于它是一个decorator,因此接受一个函数做为参数,并返回一个函数。咱们要借助Python的@语法,把decorator置于函数的定义处:日志

@log
def now():
    print '2013-12-25'

调用now()函数,不只会运行now()函数自己,还会在运行now()函数前打印一行日志:code

>>> now()
call now():
2013-12-25

@log放到now()函数的定义处,至关于执行了语句:对象

now = log(now)

因为log()是一个decorator,返回一个函数,因此,原来的now()函数仍然存在,只是如今同名的now变量指向了新的函数,因而调用now()将执行新函数,即在log()函数中返回的wrapper()函数。blog

wrapper()函数的参数定义是(*args, **kw),所以,wrapper()函数能够接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。class

若是decorator自己须要传入参数,那就须要编写一个返回decorator的高阶函数,写出来会更复杂。好比,要自定义log的文本:变量

相关文章
相关标签/搜索