python装饰器函数怎么使用,有哪些知识点
Admin 2022-11-01 群英技术资讯 375 次浏览
这篇文章我们来了解“python装饰器函数怎么使用,有哪些知识点”的内容,小编通过实际的案例向大家展示了操作过程,简单易懂,有需要的朋友可以参考了解看看,那么接下来就跟随小编的思路来往下学习吧,希望对大家学习或工作能有帮助。
假如我写了一个函数 f
def f(): print('hello')
之后我想知道这段函数执行所要的时间,这好办,我只要将代码改为如下就行
import time def f(): start = time.time() #获取程序执行开始的时间 print('hello') end = time.time() #获取程序执行结束的时间 print(end - start) #得出函数f执行所要时间 f()
但之后我有写了无数个函数f2,f3……fn,我想知道每个函数执行所需要的时间,那么如果都像上面一样改,岂不是很闹心?还是不行,因为这样实在是太麻烦了。那怎么办呢?于是灵机一动,写了一个timer函数。。。
import time def timer(func): start = time.time() func() print(time.time() - start) def f(): print('hello') def f2(): print('xorld') timer(f) timer(f2)
这样看起来是不是简单多啦?不管我们写了多少个函数都可以调用这个计时函数来计算函数的执行时间
但是如果我只想用原来的方式f1(),f2(),fn()调用了这个函数,函数在原本执行输出的结果不变的前提下还可以增加计算时间的功能,而不是调用timer(f),timer(f2)才能计算时间,这该怎么办呢?
看了下面的装饰器函数你就会知道如何解决这个问题
以下就是解决上面问题的代码的简单版:
import time def f(): print('hello') def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner f = timer(f) f()
还是这句话我只想用原来的方式f1(),f2(),fn()调用了这个函数,函数在原本执行输出的结果不变的前提下还可以增加计算时间的功能,但我还是要在函数 f 执行前写 f = timer(f)在这一串代码,是不是觉得碍眼?python的开发者也觉得碍眼,所以python的开发者就为我们提供了一句语法糖来解决这个问题!
用@timmer代替f = timer(f),这就是一句语法糖。
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer #==> 写着这句话就相当于执行了f = timer(f) def f(): print('hello') f()
1、本质
装饰器的本质就是一个闭包函数
2、功能
在不修改原函数及其调用方式的情况下对原函数功能进行扩展
刚才我们写的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?
import time def timer(func): def inner(a): start = time.time() func(a) print(time.time() - start) return inner @timer def f(a): print(a) f('hello')
其实装饰带参的函数并不是什么难事,但假如你有两个函数,需要传递的参数不一样呢,比如 函数func1有两个参数func1(a ,b),函数func 2只有一个参数func2(a), 且它们都想用这个装饰器装饰,做到计算函数执行时间?这怎么办呢?那就用下面代码。
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func1 = timer(func1) def func1(a,b): print('in func1') @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func1('aaaaaa','bbbbbb') print(func2('aaaaaa')) 输出结果: in func1 0.0 in func2 and get a:aaaaaa 0.0 fun2 over
现在参数的问题已经完美的解决了,可是如果你的函数是有返回值的呢?用上面的代码你就拿不到返回值了那究竟要如何解决这个问题呢?那就看下面的代码吧!
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func2('aaaaaa') print(func2('aaaaaa')) 输出结果: in func2 and get a:aaaaaa 0.0 in func2 and get a:aaaaaa 0.0 fun2 over
有些时候,我们也会用到多个装饰器装饰同一个函数的情况。
ef wrapper1(func): #func ----- f def inner1(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner1 def wrapper2(func): def inner2(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner2 @wrapper2 #f = wrapper2(f) ----->> wrapper2(inner1) == inner2 @wrapper1 #f = wrapper1(f) = inner def f(): print('in f') f() #===>>inner2 #多个装饰器装饰同一个函数 输出结果: wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper2 ,after func
上面那个装饰器已经非常beautiful了,但是还有一个问题,如果我给代码中无数个函数都加了@timer这个语法糖,如果之后我又不想用它了那岂不是又要每个去将它注释,没日没夜忙活3天?岂不是特别麻烦,为了使装饰器不用时能够更好的回收而不是一个一个去注释或者删除 我们引入带参数的装饰器概念
''' 为了使装饰器不用时能够更好的回收而不是一个一个去注释或者删除 我们引入带参数的装饰器概念 ''' import time '''FLAGE的目的是用它控制装饰器的开关, 那么当我们不用的时候就不要一个一个去注释只需将True改为False就行''' FLAGE = True def timmer_out(flag): def timmer(func): def inner(*args,**kwargs): if flag: start = time.time() ret = func(*args,**kwargs) end = time.time() print(end - start) return ret else: ret = func(*args, **kwargs) return ret return inner return timmer @timmer_out(FLAGE) #timmer_out(FLAGE) # 也相当于执行 timmer_out(FLAGE)--->>返回timmer———————>>@timmer(wahaha = timmer(wahaha)) def wahaha(): time.sleep(0.1) #不休息的话函数执行的太快难以计算时间 print('wahahahahahaha') wahaha() @timmer_out(FLAGE) def erguotou(): time.sleep(0.1) #不休息的话函数执行的太快难以计算时间 print('erguotoutoutou') erguotou() 输出结果: wahahahahahaha 0.10152268409729004 erguotoutoutou 0.10795140266418457
''' print(wahaha.__name__) #查看字符串格式的函数名 print(wahaha.__doc__) #查看一个函数的注释 ''' #下面用__name__查看holiday的函数名 from functools import wraps def wrapper(func): @wraps(func) #加在最内层函数正上方 def inner(*args,**kwargs): print('在被装饰的函数执行之前做的事') ret = func(*args,**kwargs) print('在被装饰的函数执行之后做的事') return ret return inner @wrapper #holiday = wrapper(holiday) def holiday(day): ''' 这是一个放假通知 :param day: :return: ''' print('全体放假%s天'%day) return '好开心' print(holiday.__name__) print(holiday.__doc__) ''' 结果是inner和None 但我们想要的是打印holiday的字符串格式的函数名和函数的注释这时该怎么办? 解决方法就是 from functools import wraps 使用语法是@wraps(被装饰的函数名) ''' 输出结果: holiday 这是一个放假通知 :param day: :return:
1、开放封闭原则
1.对原函数的功能扩展是开放的
为什么要对功能扩展开放呢?
对于任何一个程序来说,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许后来扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能在其他地方已经被导入使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经正在使用该函数的代码。
装饰器就完美遵循了这个开放封闭原则。这就是学装饰器的初衷
1、装饰器的固定格式(模板)
#格式一 def timer(func): def inner(*args,**kwargs): '''执行函数之前要做的''' re = func(*args,**kwargs) '''执行函数之后要做的''' return re return inner #格式二 from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper
到此,关于“python装饰器函数怎么使用,有哪些知识点”的学习就结束了,希望能够解决大家的疑惑,另外大家动手实践也很重要,对大家加深理解和学习很有帮助。如果想要学习更多的相关知识,欢迎关注群英网络,小编每天都会给大家分享实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
我们在学习Python语言时会遇到各种各样的字符串方法处理,下面这篇文章主要给大家介绍了关于Python基础篇之字符串的最全常用操作方法的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
用Python来编写脚本简化日常的运维工作是Python的一个重要用途。在Linux下,有许多系统命令可以让我们时刻监控系统运行的状态,如ps,top,free等等。要获取这些系统信息,Python可以通过subprocess模块调用并获取结果。但这样做显得很麻烦,尤其是要写很多解析代码。
本篇文章给大家详细分析了Python的优点和缺点以及相关的优势劣势分析,对此有兴趣的朋友学习下。
本文主要介绍了TensorFlow训练网络两种方式,一种是基于tensor(array),另外一种是迭代器,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这篇文章主要介绍了Python机器学习之Kmeans基础算法,文中有非常详细的代码示例,对正在学习python的小伙伴们有非常好的帮助,需要的朋友可以参考下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008