Python 装饰器整理

是什么:

首先,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指向的地址块了。

下面看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.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值