1. 最简单的装饰器模型.
装饰器其实就是对函数进行的一次包装,渲染函数用的,例如下面这个最简单的例子:
def say_hi(fn): def improve(): print("Welcome from decorator: ") fn() return improve @say_hi def hi(): print("hi there in hi function") hi()
在Python中,一个函数可以作为参数传递给另一个函数,因此,可否这么考虑,我们把一个函数传递给另一个函数之后,
在这个被传递的函数的外部补充一些操作(装饰),而后,把这个额外添加了补充装饰的函数得新吐回来。使用装饰器时,
就相当于把装饰器符号下面定义的函数作为参数传递给前面的装饰器对应的函数作为参数。
2. 可接受函数传参数的装饰器
1 def timeit(fn): 2 def warp(*args, **kwargs): 3 print('----start------') 4 fn(*args, **kwargs) 5 print('----stop--------') 6 return warp 7 8 9 @timeit 10 def hi(*args, **kwargs): 11 for i in args: 12 print('* {0}'.format(i)) 13 for k, v in kwargs.items(): 14 print('k/v: {0} ---> {1}'.format(k, v)) 15 16 17 18 hi('a', 'b', 'c', name='topic', email='topic@outlook.com')
# 这样一看似乎很难理解,下面拆分一下进行理解:
# hi()函数执行的时候,
# 1. 首先第一步会调用timeit函数,timeit(hi) 此时hi函数作为参数传入了timeit函数,
# 即 tmp = timeit(hi), 可以使用type(tmp)看下返回值是function,即warp函数
#
# 2. 执行warp函数: 首先会打印start,随后执行1步骤中传入的函数,最后再打印stop
#
# 至此,函数执行完毕.
# PS : *args 和 **args是作为函数的 可变位置参数和可变关键字参数.
# warp 函数中的fn(*args, **args) 称为解包.
# 装饰器等同于这样调用: timeit(hi)('a', 'b', 'c', name='topic', email='topic@outlook.com')
第二版: (添加传入函数的返回值)
def timeit(fn): def warp(*args, **kwargs): print('----start------') ret=fn(*args, **kwargs) print('----stop--------') return ret return warp #@timeit def hi(*args, **kwargs): for i in args: print('* {0}'.format(i)) for k, v in kwargs.items(): print('k/v: {0} ---> {1}'.format(k, v)) @timeit def add(x, y): return x + y a=add(5, 6) print(a)