• Python学习基础笔记十九——装饰器


    装饰器的形成过程:

    1. import time
    2. def func1():
    3. print('in func1')
    4. start = time.time()
    5. func1()
    6. end = time.time()
    7. print(end - start)

    再进一步:

    1. import time
    2. def timer(f): # 计算函数执行时间,将函数名作为参数
    3. start = time.time()
    4. f() # 执行函数
    5. end = time.time()
    6. print(end - start)
    7. def func():
    8. print("Hello world!")
    9. timer(func)

    第二次进化:

    1. import time
    2. def func():
    3. print("Hello world!")
    4. def timer(f): # 装饰器
    5. def inner(): # 闭包
    6. start = time.time()
    7. f() # 被装饰器函数
    8. end = time.time()
    9. print(end - start)
    10. return inner
    11. func = timer(func)
    12. func()

    说明程序的运行过程:

    第一步:def func():  func函数声明

    第二步:def timer(func)  timer函数声明

    第三步:func = timer(func)  先运行timer函数,传递func函数名(内存地址)

    第四步:def inner():开始运行timer函数内部代码,声明inner函数

    第五步:return inner: 返回inner内存地址

    第六步:func = timer(func):  将timer的返回值(inner内存地址)传给func变量(实际也是内存地址,跟func函数的内存地址是一样的

    第七步:func() 开始执行func(),实际上执行的就是inner函数,因为将inner内存地址赋值给了func变量的内存地址。

    第八步:start = time.time(), 开始到inner函数内部开始执行,从这步开始,获得当前系统时间赋值给start变量。

    第九步:f(), 开始执行f函数,该f,就是上一层timer函数传递进来的参数func。

    第十步:print("Hello world!")然后执行func函数内部代码,执行完毕,即退出func函数。

    第十一步:end = time.time(), 获得当前系统时间,赋值给end变量。

    第十二步:print(end - start), 然后获得两个时间时间差,并打印,到这一步,inner函数执行完毕,退出inner。

    第十三步:到func()调用函数的下一行。

    装饰器的作用:

    不想修改函数的调用方式,但是还想在原来的函数的前后添加新功能,timer是一个装饰器函数,只是对一个函数有一些装饰作用。

    从上面的代码可见,timer是装饰器函数,f() 是被装饰的函数。

    进一步变化:

    1. import time
    2. def timer(f):
    3. def inner():
    4. start = time.time()
    5. f()
    6. end = time.time()
    7. print(end - start)
    8. return inner
    9. @timer # 装饰器函数名
    10. def func(): # 被装饰的函数名
    11. print("Hello world!")
    12. # func = timer(func)
    13. func()

    注意其中的@timer的位置。

    再进一步,注意其中对返回值的处理:

    1. import time
    2. def timer(f):
    3. def inner():
    4. start = time.time()
    5. ret = f()
    6. end = time.time()
    7. print(end - start)
    8. return ret
    9. return inner
    10. @timer # 装饰器函数名
    11. def func(): # 被装饰的函数名
    12. print("Hello world!")
    13. return '新年好'
    14. # func = timer(func)
    15. ret = func()
    16. print(ret)

    如果func有返回值,看看装饰器函数timer中是怎么处理的,然后调用的时候也要注意下这个返回值。

    再进一步:

    1. import time
    2. def timer(f):
    3. def inner(a):
    4. start = time.time()
    5. ret = f(a)
    6. end = time.time()
    7. print(end - start)
    8. return ret
    9. return inner
    10. @timer # 装饰器函数名
    11. def func(a): # 被装饰的函数名
    12. print("Hello world!", a)
    13. return '新年好'
    14. # func = timer(func)
    15. ret = func(1)
    16. print(ret)

    装饰带参数函数的装饰器。有了对带参数的处理。

    进一步变化, 万能参数:

    1. import time
    2. def timer(f):
    3. def inner(*args, **kwargs):
    4. start = time.time()
    5. ret = f(*args, **kwargs)
    6. end = time.time()
    7. print(end - start)
    8. return ret
    9. return inner
    10. @timer # 装饰器函数名
    11. def func(a): # 被装饰的函数名
    12. print("Hello world!", a)
    13. return '新年好'
    14. @timer # 装饰器函数名
    15. def func(a, b): # 被装饰的函数名
    16. print("Hello world!", a, b)
    17. return '新年好'
    18. # func = timer(func)
    19. ret = func(1)
    20. print(ret)

    最后,我们再将装饰器简化:

    1. def wrapper(f): # 装饰器wrapper
    2. def inner(*args, **kwargs):
    3. '''在装饰前要做的事情'''
    4. ret = f(*args, **kwargs) # 被装饰的函数
    5. '''在装饰后要做的事情'''
    6. return ret
    7. return inner
    8. @wrapper # 装饰器函数名
    9. def func(a, b): # 被装饰的函数

    这个就是一个装饰器固定模式。

    原则:开放封闭原则:

    开放:对扩展是开放的。

    封闭:对修改是封闭的。

    目的是维护代码的稳定性,那么这个就是装饰器存在的意义。

  • 相关阅读:
    LC 200, 721,684 并查集解法
    【第十章】认识与学习BASH
    关于“网络安全”五点须知!
    【C语言】【排序算法】----- 归并排序
    Python如何调用ixchariot进行吞吐量测试
    流體小球加載動畫
    Python 多进程模块 multiprocessing - 简单使用
    【附源码】计算机毕业设计JAVA校园讲座管理
    2022年最新安徽建筑施工信号工(建筑特种作业)考试真题题库及答案
    《低代码指南》——国内首个向量数据库标准亮相,腾讯云联合50家企业共同编制
  • 原文地址:https://blog.csdn.net/chang_chunhua/article/details/128168171