• python装饰器原理梳理


            python中的装饰器和java的注解在外观上很像。python中,装饰器本质上是一个类或一个带有返回类型为函数的高阶函数。

            装饰器可以扩展一个类或函数的功能。有关装饰器的详细介绍,推荐查看文章“Python装饰器注解

            下面讲讲python中装饰器的本质,我在bilibili上找到一个讲的很好的一个视频,链接是:

    【python】装饰器超详细教学,用尽毕生所学给你解释清楚,以后再也不迷茫了!_哔哩哔哩_bilibili

    1. def dec(f):
    2. pass
    3. @dec
    4. def double(x):
    5. return x *2
    6. #上面double函数上增加注解后,完全等价于下面的写法
    7. double = dec(double)

            可以看到,装饰器本质上是一个返回类型为函数的高阶函数。当在一个普通函数上增加注解,则本质上系统会调用装饰器函数dec,参数为函数对象double,然后装饰器函数返回一个函数对象,并赋值给一个跟函数名同名的对象double。

    例子1: 下面看一个实际的例子

    1. def timeit(f):
    2. def wrapper(x):
    3. start = time.time()
    4. ret = f(x)
    5. print(time.time() - start)
    6. return ret
    7. return wrapper
    8. @timeit
    9. def my_func(x):
    10. time.sleep(1)
    11. if __name__ == '__main__':
    12. my_func(1)

    运行后输出

    1.005021095275879

    编译器运行到下面代码的时候

    1. @timeit
    2. def my_func(x):
    3. time.sleep(1)

    所以其本质是运行了

    my_func = timeit(my_func)

    所以当调用my_func(1)时,实际上是在执行wrapper(1)。

    例子二:注解上还可以增加注解

            看看下面的代码运行结果是什么

    1. import time
    2. def timeit(f):
    3. def wrapper(x):
    4. start = time.time()
    5. ret = f(x)
    6. print(time.time() - start)
    7. return ret
    8. return wrapper
    9. @timeit
    10. @timeit
    11. def my_func(x):
    12. time.sleep(1)
    13. if __name__ == '__main__':
    14. my_func(1)

    运行后结果为:

    1. 1.0050477981567383
    2. 1.0051438808441162

    编译器运行到下面代码时

    1. @timeit
    2. @timeit
    3. def my_func(x):
    4. time.sleep(1)

    实际上执行了my_func=timeit(timeit(my_func))

    例子3: 装饰器有参数

            看看下面代码

    1. import time
    2. def timeit(k):
    3. def inner(f):
    4. def wrapper(x):
    5. start = time.time()
    6. for _ in range(k):
    7. ret = f(x)
    8. print(time.time() - start)
    9. return ret
    10. return wrapper
    11. return inner
    12. @timeit(2)
    13. def my_func(x):
    14. time.sleep(1)
    15. if __name__ == '__main__':
    16. my_func(1)

    其中

    1. @timeit(2)
    2. def my_func(x):
    3. time.sleep(1)

    本质上变成了

    my_func = timeit(2)(my_func)
  • 相关阅读:
    Spring cloud - Hystrix服务限流、熔断及降级
    公司如何防止源代码外泄,保护开发部门代码安全呢?
    apache解决请求无法识别Authorization
    单片机论文参考:4、基于单片机的智能避障小车
    OpenNebula的配置与应用(一)
    无需下载,粘贴视频链接即可实现人声分离~
    HTTP协议和抓包工具Fiddler
    高项 沟通管理论文
    一命通关双指针
    Hive恢复误删数据表
  • 原文地址:https://blog.csdn.net/liuqinhou/article/details/126298423