一、何为装饰器?
由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。装饰器是可调用的对象,其参数是另一个函数(被装饰的函数)。装饰器可能会处理被装饰的函数,然后把它返回,或者将其替换成另一个函数或可调用对象。
二、装饰器例子
一个装饰器的例子:
def deco(func):
def inner(*args, **kw):
print('running inner()')
return func(*args, **kw)
return inner
@deco
def target():
print('running target()')
上述代码就相当于:
def target():
print('running target()')
target = deco(target())
两种写法的结果一样,最终结果都是decorate(target)返回的函数,而不是原来的函数target。
装饰器的特点:一是能把被装饰的函数替换成其他函数,二是在加载模块是立即执行
结果:
>>> target
<function deco.<locals>.inner at 0x112138510>
>>> target()
running inner()
running target()
当你看见过flask的路由,你会发现语法糖中会写路由地址(@app.route(‘/login’, methods=[‘GET’,’POST’])),以及其他参数信息。
所以我们想修改以上程序内容,使它能处理或接受的信息更加丰富,如果装饰器(上例的deco)本身需要传入参数,那就需要编写一个返回装饰器(上例的deco)的高阶函数,写出来会更复杂。
def log(text):
def deco(func):
def inner(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return inner
return deco
@log('execute')
def target():
print('running target()')
这样我们就可以从语法糖接受并输出text的数据,这个数据不会影响被装饰的函数。
来看看输出
>>> target
<function log.<locals>.deco.<locals>.inner at 0x1121386a8>
>>> target()
execute target():
running target()