python编写装饰器_我也来写一下python装饰器

有借用,但原文出处已经找不到了,根据笔记分享一下解释器的基础。

下面的代码表示,等待两秒钟,输出‘test is running'。

现在要求增加统计程序运行时间的功能。

等待两秒钟,输出‘test is running',现要求增加统计程序运行时间的功能。

import time

def test():

time.sleep(2)

print('test is running!')

test()

学习先问为什么,有什么用,学基础的时候有时不理解为什么简单的事情要搞那么复杂,而对应的实际应用时,往往“这个复杂方法有很多优点和简化了很多事情”。学基础时用简单的例子,只是为了讲明知识点,而不要去关注例子实现的什么功能,这个功能当然是个‘屁’了。

那么,装饰器的实际应用场景:程序已上线或已使用,但需要增加新功能,修改原函数不合理也不科学(这里真的包含了很多背景声音),就要求:

(1)不能修改原功能函数的代码。例子中的功能是非常简单的,要实现当然是直接修改,但现实中一个功能的实现是非常复杂的代码,直接修改是不合理不科学的。

(2)不能修改原函数的调用方式。在符合第一条的情况下,调用时仍然是用test(),即老方法能实现新功能。现实中后面程序在反复用test(),就是要完全不动老代码的基础上,增加一个’装饰器‘更新整个程序。

(3)上述说的老方法是表面上的,这就是装饰器介入的作用。

好,以下开始改造,用试错的方法解释装饰器的实现过程和原理。

满足条件(1)可以增加代码如下:

def deco(func):

start=time.time()

func()

stop=time.time()

print(stop-start)

deco(test)

#把老代码里的test函数作为参数传递给新函数

#(因为是增加新功能,老功能还是要的,所以新代码里肯定要引用老代码的功能,就采取了这种方法)

看上去新功能就实现了,但可以看到调用方式变为了deco(test),即违背了条件(2),以前程序里可能反复调用了test(),都要改成deco(test),不科学。

同时满足条件(2),再改:

思路:产生一个新函数,重新赋值给test,test=某函数,那么后面反复调用的test()就被实质上改过来了,实现功能。

#试一下:

test=deco(test) #计算右边的,是一个两行字符串,赋值给test根本不是一个函数。

test() #因此跳错误码

再试一下:

增加:return func

然后:

test=deco(test)

test()

代码正常运行,但因为return func的缩进和其他代码是同级的,所以deco(test)这步已经把新功能给实现了,又返回了一次test(),结果重复。

把下面完整的代码去试一下,出现了两次test is running ,不合格。

import time

def test():

time.sleep(2)

print('test is running!')

def deco(func):

start=time.time()

func()

stop=time.time()

print(stop-start)

return func

test=deco(test)

test()

思路没有错,上述这里return一个函数的思考过程也是对的,只是返回的方式不对,应当使用’嵌套函数‘。

def timer(func):

def deco():

start=time.time()

func()

stop=time.time()

print(stop-start)

return deco

#把deco()嵌套在timer(func)里,返回一个deco()函数的函数名deco;

#调用timer(func)时,deco()里面的过程代码类似于没有执行的,

#被打包成了一个函数,执行的只是return了这个函数的函数名。

test=timer(test)

#右边代码返回的是一个deco()的函数名deco,deco()打包了作为被参数传入的原test()里的功能,

#同时增加了新功能。

test()

#符合(2)要求,没有改变调用方法,但实质上这句调用的已经是deco()了。

#顶格代码是不能调用经过了二次缩进的嵌套函数的,

#但这里用了deco()用了return,成了闭包函数,就可以被调用了。

至此,本质上是修改了调用函数,但在表面上并未修改调用方式,而且实现了附加功能,需求实现。

真正的装饰器:语法糖

在原test()的上一行加上@timer,删除test=timer(test).

而且要把新增的函数写在原函数的上面

最后代码

import time

def timer(func):

print(func.__name__) #看看打印出来的是什么

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=timer(test)这句不用了,注释掉

test()

过程比较啰嗦,但每一步都看下来后,装饰 器的原理就知道了,涉及到有参数的时候,再另外理解了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值