1.什么是装饰器

让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
装饰器装饰一个函数,带一个或者多个参数的函数,带返回值的函数

2.装饰器的形成过程

  1. def func1():
  2. print('in func1')
  3. def timer(func):
  4. def inner():
  5. start = time.time() # time.time() 1970年后经过的浮点秒数
  6. func()
  7. print(time.time() - start)
  8. return inner
  9. func1 = timer(func1)
  10. func1()

@ 语法糖

  1. def timer(func): #func1
  2. def inner():
  3. start = time.time()
  4. time.sleep(2)
  5. func()
  6. print(time.time()-start)
  7. return inner
  8. @timer # func1 = timer(func1)
  9. def func1():
  10. print('in func1')
  11. ###就是每次还得传个值这样就比较麻烦 #inner
  12. func1() #>>>inner()

3.

3.1带一个参数的装饰器函数

  1. import time
  2. def timer(func):
  3. def inner(a):
  4. start = time.time()
  5. func(a)
  6. print(time.time() - start)
  7. return inner
  8. @timer
  9. def func1(a):
  10. time.sleep(1)
  11. print(a)
  12. func1('hello world')

3.2装饰一个带各种参数的函数

  1. import time
  2. def timer(func):
  3. def inner(*args,**kwargs):
  4. start = time.time()
  5. func(args,kwargs)
  6. print(time.time() - start)
  7. return inner
  8. @timer
  9. def func1(*args,**kwargs):
  10. print(args,kwargs)
  11. func1('hello world','abc',123,432)

3.3装饰带返回值的函数

  1. def timer(func):
  2. def inner():
  3. start = time.time()
  4. time.sleep(0.5)
  5. ret = func()
  6. print(time.time() - start)
  7. return ret
  8. return inner
  9. @timer #==> func1 = timer(func1)
  10. def func1():
  11. print('in func1')
  12. return '我是返回值'
  13. ret = func1()
  14. print(ret)

3.4查看函数的相关信息,在加上装饰器后就失效了

  1. def index():
  2. '''这是一条注释信息'''
  3. print('from index')
  4. print(index.__doc__) # 查看函数注释
  5. print(index.__name__) # 查看函数字符串名称
  6. 但是此处如果我想看一个被装饰器装饰的函数的字符串函数名就会显示的是inner的名字
  7. print(func1.__name__)

3.5导入wraps装饰器

  1. from functools import wraps
  2. def deco(func):
  3. @wraps(func)
  4. def wrapper(*args,**kwargs):
  5. return func(*args,**kwargs)
  6. return wrapper
  7. @deco
  8. def index():
  9. '''这是一条注释信息'''
  10. print('from index')
  11. print(index.__doc__) # 查看函数注释
  12. print(index.__name__) # 查看函数名称

4.开放封闭原则

对扩展时开放的,对修改是封闭的 封版之后不允许修改了
软件实体应该是可扩展但是不可修改的。

  • 对于扩展是开放的
  • 对于修改是封闭的

装饰器完美的遵循了这个开放封闭原则

5.装饰器的固定结构

  1. from functools import wraps
  2. def timer(func):
  3. @wraps(func)
  4. def inner (*args,**kwargs) #被装饰函数里面肯定会传的参数
  5. '''执行函数之前要做的'''
  6. re = func(*args,**kwargs) #使我们被装饰函数
  7. '''执行函数之后要做的'''
  8. return re
  9. return inner
  10. # 下面是加上wraps的固定结构
  11. from functools import wraps
  12. def timer(func):
  13. @wraps(func)
  14. def wrapper(*args,**kwargs)
  15. return func(*args,**kwargs)
  16. return wrapper

6.带参数的装饰器

加上一个outer函数,可以携带一个flag的值,然后控制装饰器是否生效

  1. def outer(flag):
  2. def timer(func):
  3. def inner(*args,**kwargs):
  4. if flag:
  5. print('函数开始执行')
  6. re = func(*args,**kwargs)
  7. print('函数执行完毕')
  8. else:
  9. re = func(*args, **kwargs)
  10. return re
  11. return inner
  12. return timer
  13. #@timeer #timer =outer(true)
  14. @outer(True)
  15. def func():
  16. print('test'/)
  17. func()

7.多个装饰器装饰一个函数

  1. def wrapper1(func):
  2. def inner1():
  3. print('第一个装饰器,在程序运行之前')
  4. func()
  5. print('第一个装饰器,在程序运行之后')
  6. return inner1
  7. def wrapper2(func):
  8. def inner2():
  9. print('第二个装饰器,在程序运行之前')
  10. func()
  11. print('第二个装饰器,在程序运行之后')
  12. return inner2
  13. @wrapper1
  14. @wrapper2
  15. def f():
  16. print('Hello')
  17. f()