美文网首页
python装饰器

python装饰器

作者: 大墩子丶 | 来源:发表于2018-05-20 19:38 被阅读0次

简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
一般而言,我们要想拓展原来函数代码,最直接的办法就是侵入代码里面修改,例如:

1. import time
2. def func():
3.     print("hello")
4.     time.sleep(1)
5.     print("world")

这是我们最原始的的一个函数,然后我们试图记录下这个函数执行的总时间,那最简单的做法就是:

1. #原始侵入,篡改原函数
2. import time
3. def func():
4.     startTime = time.time()
5. 
6.     print("hello")
7.     time.sleep(1)
8.     print("world")
9.     endTime = time.time()
10. 
11.     msecs = (endTime - startTime)*1000
12.     print("time is %d ms" %msecs)

但是如果你的Boss在公司里面和你说:这段代码是我们公司的核心代码,你不能直接去改我们的核心代码。”那该怎么办呢,我们仿照装饰器先自己试着写一下:

1. #避免直接侵入原函数修改,但是生效需要再次执行函数
2. import time
3. 
4. def deco(func):
5.     startTime = time.time()
6.     func()
7.     endTime = time.time()
8.     msecs = (endTime - startTime)*1000
9.     print("time is %d ms" %msecs)
10. 
11. 
12. def func():
13.     print("hello")
14.     time.sleep(1)
15.     print("world")
16. 
17. if __name__ == '__main__':
18.     f = func
19.     deco(f)#只有把func()或者f()作为参数执行,新加入功能才会生效
20.     print("f.__name__ is",f.__name__)#f的name就是func()
21.     print()
22.     #func()

这里我们定义了一个函数deco,它的参数是一个函数,然后给这个函数嵌入了计时功能。然后你可以拍着胸脯对老板说,看吧,不用动你原来的代码,我照样拓展了它的函数功能。
然后你的老板有对你说:我们公司核心代码区域有一千万个func()函数,从func01()到func1kw(),按你的方案,想要拓展这一千万个函数功能,就是要执行一千万次deco()函数,这可不行呀,我心疼我的机器。”
好了,你终于受够你老板了,准备辞职了,然后你无意间听到了装饰器这个神器,突然发现能满足你闫博士的要求了。
我们先实现一个最简陋的装饰器,不使用任何语法糖和高级语法,看看装饰器最原始的面貌:

1. #既不需要侵入,也不需要函数重复执行
2. import time
3. 
4. def deco(func):
5.     def wrapper():
6.         startTime = time.time()
7.         func()
8.         endTime = time.time()
9.         msecs = (endTime - startTime)*1000
10.        print("time is %d ms" %msecs)
11.    return wrapper
12.
13. 
14. @deco
15. def func():
16.     print("hello")
17.     time.sleep(1)
18.     print("world")
19. 
20. if __name__ == '__main__':
21.     f = func #这里f被赋值为func,执行f()就是执行func()
22.     f()

这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数func()前面加上@deco,func()函数就相当于被注入了计时功能,现在只要调用func(),它就已经变身为“新的功能更多”的函数了。
所以这里装饰器就像一个注入符号:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。

1. #带有参数的装饰器
2. import time
3. 
4. def deco(func):
5.     def wrapper(a,b):
6.         startTime = time.time()
7.         func(a,b)
8.         endTime = time.time()
9.         msecs = (endTime - startTime)*1000
10.        print("time is %d ms" %msecs)
11.     return wrapper
12. 
13. 
14. @deco
15. def func(a,b):
16.     print("hello,here is a func for add :")
17.     time.sleep(1)
18.     print("result is %d" %(a+b))
19. 
20. if __name__ == '__main__':
21.     f = func
22.     f(3,4)
23.     #func()

然后你满足了Boss的要求后,Boss又说:我让你拓展的函数好多可是有参数的呀,有的参数还是个数不定的那种,你的装饰器搞的定不?”然后你嘿嘿一笑,深藏功与名!

1. #带有不定参数的装饰器
2. import time
3. 
4. def deco(func):
5.     def wrapper(*args, **kwargs):
6.         startTime = time.time()
7.         func(*args, **kwargs)
8.         endTime = time.time()
9.         msecs = (endTime - startTime)*1000
10.        print("time is %d ms" %msecs)
11.    return wrapper
12. 
13. 
14. @deco
15. def func(a,b):
16.     print("hello,here is a func for add :")
17.     time.sleep(1)
18.     print("result is %d" %(a+b))
19. 
20. @deco
21. def func2(a,b,c):
22.     print("hello,here is a func for add :")
23.     time.sleep(1)
24.     print("result is %d" %(a+b+c))
25. 
26. 
27. if __name__ == '__main__':
28.     f = func
29.     func2(3,4,5)
30.     f(3,4)
31.     #func()

最后,你的老板说:可以的,我这里一个函数需要加入很多功能,一个装饰器怕是搞不定,装饰器能支持多个嘛,最后你就把这段代码丢给了他:

#多个装饰器

import time

def deco01(func):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
        print("deco01 end here")
    return wrapper

def deco02(func):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        func(*args, **kwargs)

        print("deco02 end here")
    return wrapper

@deco01
@deco02
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))



if __name__ == '__main__':
    f = func
    f(3,4)
    #func()

'''
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here
'''

多个装饰器执行的顺序就是从第一个装饰器开始,执行到最后一个装饰器,再执行函数本身。

相关文章

  • 装饰器模式

    介绍 在python装饰器学习 这篇文章中,介绍了python 中的装饰器,python内置了对装饰器的支持。面向...

  • python中的装饰器

    python装饰器详解 Python装饰器学习(九步入门) 装饰器(decorator) 就是一个包装机(wrap...

  • [译] Python装饰器Part II:装饰器参数

    这是Python装饰器讲解的第二部分,上一篇:Python装饰器Part I:装饰器简介 回顾:不带参数的装饰器 ...

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • Python进阶——面向对象

    1. Python中的@property   @property是python自带的装饰器,装饰器(decorat...

  • Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方

    Python 装饰器简介装饰器(Decorator)是 Python 非常实用的一个语法糖功能。装饰器本质是一种返...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

  • 2019-05-26python装饰器到底是什么?

    装饰器例子 参考语法 装饰器是什么?个人理解,装饰器,是python中一种写法的定义。他仍然符合python的基本...

  • 2018-07-18

    Python装饰器 装饰,顾名思义,是用来打扮什么东西的。Python装饰...

网友评论

      本文标题:python装饰器

      本文链接:https://www.haomeiwen.com/subject/dbitjftx.html