python装饰器

我每一次接触到一个新概念的时候,脑袋中立马浮现的是:为什么要用这个东西?现有的东西不能代替吗?带着这样的疑问,开始装饰器的学习吧。
为什么要用这个东西?
为了在不动函数调用接口(也就是你开始的时候是怎么调用这个函数的就怎么调用)的同时给函数附加上一些功能。

#STEP1:一个简单的函数

import time
def summ():
	time.sleep(2)

STEP1:增加功能

现在我想给函数增加一个功能:计算函数执行时间

import time

def summ():
    time.sleep(2)
start_time=time.time()#time.time()是一个时间戳,计算从1970年到现在总共有多少秒
summ()
end_time=time.time()#执行完summ()后的时间戳
print(end_time-start_time)#两者相减,就是运算耗费时间
>>2.0003156661987305

STEP2:功能的简化:使用无参函数

我们在外部共增加了3行函数来对时间进行运算,这样是最开始的做法,但是有一个很麻烦的问题就是,我们每验算一个函数的运算时间,就要把这三行代码复制过去,太恶心,有没有什么办法呢,有,把这三行做成一个函数来进行调用,代码如下:

import time

def summ(a,b):
    time.sleep(2)

def calculate_time():
    start_time = time.time()
    summ()
    end_time=time.time()
    print(end_time-start_time)
calculate_time()

>>2.000300168991089

STEP3:函数的复用:把整体当作一个参数传入

通过把这个计时步骤写成一个函数,我们只需要调用就可以了,再进一步,如果我其他的函数也想调用呢?很简单,把summ()当成一个参数传递进去就好了。代码完善后如下:

import time

def summ():
    time.sleep(2)

def calculate_time(f):
    start_time = time.time()
    f()
    end_time=time.time()
    print(end_time-start_time)
calculate_time(summ)

>>2.0006697177886963

STEP4:为什么要用装饰器

这么做,我虽然能够很便捷地查询函数运行时间,但还是改变了调用接口。我想要的是我输入summ()的时候,自动打印出来一个运行时间,而不是我要专门去输入一个calculate_time(summ()),总之,还不够简洁,就像我们玩游戏,本来我们用W|A|S|D四个方向键用得好好的,你内部写了个程序,说,为了使得每次移动的时候,玩家知道自己移动的位置坐标,我们给四个方向指令增加了一个功能,这个功能可以让玩家在游戏中看到自己的坐标数字,但是,大家在按住WASD键盘的时候还要按住一个L(location)键盘激发这个功能,你说,大家会用你这个功能吗?老板娘会骂人吗?大家想要的功能是,我按住WASD任意一个键的时候,位置坐标你就给我显示出来得了,别整这么麻烦。

于是装饰器横空出世,目的就是为了,不改变指令的情况下增加一些功能。就像装修的时候我们不打掉一个承重墙,但是贴了一些装饰性的壁纸。

STEP5:装饰器的前身

import time

def summ():
    time.sleep(2)

def calculate_time(f):
    def inner():
        start_time = time.time()
        f()
        end_time=time.time()
        print(end_time-start_time)
    return inner

summ=calculate_time(summ)
summ()
>>2.000295639038086

STEP6:装饰器出来了

这时候,我们只从calculate_time()把summ作为f传进去,并返回一个inner的值(inner会实现打印时间的功能),最后把这个值赋值给summ.
但每次都要summ=calclulate(summ)太麻烦,何况这个summ函数也会换成其他函数,于是我们用一个语法糖来代替这个写法,放在装饰器函数(此时的装饰器就是calculate_time这个函数)的下面。成果如下:

import time

def calculate_time(f):
    def inner():
        start_time = time.time()
        f()
        end_time=time.time()
        print(end_time-start_time)
    return inner

@calculate_time#语法糖,等价于上面的summ=calculate_time(summ)
def summ():#此时的这个函数也可以更换为其他函数。
    time.sleep(2)
summ()
>>2.000237226486206

上面的是无参数调用,且没有返回值,下面给出一个有参数和返回值的案例

import time

def calculate_time(f):
    def inner(*args,**kwargs):#这里添加两个参数
        start_time = time.time()
        ret=f(*args,**kwargs)#同样加载上面的参数
        end_time=time.time()
        print(end_time-start_time)
        return ret#设置一个返回值,这个返回值就是要装饰函数的返回值,本例是add(),返回a+b
    return inner

@calculate_time
def add(a,b):
    time.sleep(2)
    return a+b
print(add(3,4))#把时间和函数返回值打印出来

>>2.000807523727417
>>7
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值