Python 装饰器整理

系统 1512 0

是什么:

首先,Python装饰器的作用是:让被装饰的函数在不需要 任何 变化的情况下,增加额外的功能。

为什么:

为什么要用装饰器呢,直接增加功能不就行了?

因为有的程序已经上线或已经被使用,那么就不能大批量的修改源代码,于是就产生了装饰器。

怎么装饰:

预备知识:函数名和函数的区别,即带括号和不带括号的区别

1.test1表示的是函数的内存 地址。 可以理解为一个指向某块内存的标签。

2.test1()就是调用对在test1这个地址的内容,即函数。

3.再通俗的比喻,test1是存折,test1()才是你的钱。

看个半成品代码:

            
               import time

 def timer(func):
     def deco():  
         start = time.time()
         func()
         stop = time.time()
         print(stop-start)
     return deco

 test = timer(test)   #1

 def test():
     time.sleep(2)
     print("test is running!")   

 test()               #2
            
          

先执行#1,test这个函数名传给timer的func,此时,func就指向了test指向的地址块了。

Python 装饰器整理_第1张图片

下面看timer()这个函数的结构:大盒子timer()里,有一个中盒子deco(),中盒子里有一个小盒子func(),小盒子是通过传参传入的。

接着看,大盒子的返回值是一个函数名,即大盒子返回的是中盒子的地址,此时timer()执行完了,带着返回值回到#1。

此时,test这个函数名,被赋值了中盒子deco的地址,也就是说,test指向了deco()这个函数的地址。

来捋一捋 ,刚才的中盒子deco()中嵌入了小盒子func(),也就是说,传入的小盒子包在了中盒子deco()中。

经过这个过程,test()函数指向了deco()函数,【原本的功能包在了里边,反过来说,test()的功能被扩展了。】

 

好,继续刚才的代码,#1执行结束后,执行#2,test()函数就找指向的位置,就找到了中盒子deco()的位置。

最后输出什么呢?:NameError: name 'test' is not defined。

因为test的定义下载了下边,执行#1的时候就找不到他的定义。因此把test()的定义挪到#1上边就行了。

(这么看来,两个也不是完全等价)

就会输出:

            
              test is running!
2.000791072845459

            
          

成品代码:

1、我们见到的装饰器装什么样子呢?

            
               import time

 def timer(func):
     def deco():  
         start = time.time()
         func()
         stop = time.time()
         print(stop-start)
     return deco

 @timer                

 def test():
     time.sleep(2)
     print("test is running!")   

 test()               #2
            
          

把test = timer(test)替换成@timer   放在def test():的上边。

2、如果test()本身有参数怎么写?依葫芦画瓢吧。改动在#3、#4、#5.

            
               import time

 def timer(func):
     def deco(*args, **kwargs):  #3
         start = time.time()
         func(*args, **kwargs)   #4
         stop = time.time()
         print(stop-start)
     return deco

 @timer  
 def test(parameter):           #5
     time.sleep(2)
     print("test is running!")   

 test()               
            
          

3、装饰器带参数

            
              import time

def timer(p):                           #7
    def middl(func):                    #8
        def deco(*args, **kwargs): 
            if p == 'ss':
                start = time.time()
                res = func(*args, **kwargs)
                stop = time.time()
                print(stop-start)
            return res 
        return deco                     #8
    return middl                        #7

@timer('ss')
def test(): #8
    time.sleep(2)
    print("test is running!")   
test() 
            
          

就在timer()和deco()中间在套一层middl()。

此时@timer(’ss')相当于:test = timer('ss')(test ) 

注意!这里timer后面跟了两个括号。 这是什么意思? 
其实很简单,先执行timer(‘ss’),返回结果为middl    即 #7 处标注。 
再执行middl(test),得到的返回结果为deco              即 #8 处标注。
 

参考1:https://blog.csdn.net/weixin_39541558/article/details/79972104

参考2:https://blog.csdn.net/buster_zr/article/details/81104551

The end.


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论