>>> 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的文本:变量