Python中的装饰器装饰器(decorator)可以增强函数的功能。虽然定义起来有点复杂,但是使用起来非常灵活方便。由于函数也是对象,函数对象可以赋值给变量,所以也可以通过变量来调用函数。>>>defnow():...print('2015-3-25')...>>>f=now>>>f()2015-3-25函数对象有一个__name__属性,你可以获取函数名:>>>now.__name__'now'>>>f.__name__'now'假设我们要增强now()函数的功能,比如自动打印函数前后的日志调用,但不想修改now()函数的定义。这种在代码执行期间动态添加功能的方式称为“装饰器”。importfunctoolsdeflog(func):#将原函数的__name__等属性复制到wrapper()函数中@functools.wraps(func)defwrapper(*args,**kw):print('call%s():'%func.__name__)returnfunc(*args,**kw)returnwrapper@logdefnow():print('2015-3-25')执行结果如下:>>>now()callnow():2015-3-25将@log放在now()函数的定义中,相当于执行语句:now=log(now)由于log()是一个装饰器,返回一个函数,所以原来的now()function仍然存在,但是现在同名的now变量指向了新的函数,所以调用now()会执行新的函数,也就是log()函数中返回的wrapper()函数。wrapper()函数的参数定义为(*args,**kw),因此wrapper()函数可以接受任何参数的调用。带参数的装饰器如果装饰器本身需要传入参数,那么就需要写一个返回装饰器的高阶函数,写起来会比较复杂。例如自定义日志的文本:importfunctoolsdeflog(text):defdecorator(func):#将原函数的__name__等属性复制到wrapper()函数中@functools.wraps(func)defwrapper(*args,**kw):print('%s%s():'%(text,func.__name__))returnfunc(*args,**kw)returnwrapperreturndecorator这个3层嵌套的装饰器是用法如下:@log('execute')defnow():print('2015-3-25')执行结果如下:>>>now()executenow():2015-3-25and两层嵌套的装饰器相比较,3层嵌套的效果是这样的:>>>now=log('execute')(now)我们分析一下上面的语句,先执行log('execute'),然后返回装饰器函数,然后调用返回函数,参数是now函数,返回值最后是包装函数。
