20220812-day1601重要的装饰器
作者:互联网
装饰器实质就是一种特殊的函数。要了解装饰器,首先要了解闭包。
#_author: Administrator #_date: 2020/5/25 #闭包 就是满足下面两个条件(条件一、二)的一个函数 def outer(): x = 10 def inner(): #条件一 inner()就是内部函数 print(x) #条件二 x外部环境的一个变量 return inner #将函数名作为了返回值。内部函数inner就是一个闭包 #问题:我们怎么能调用上面的inner函数? # outer()() #调用方式1 # f = outer() #调用方式2 # f() #那除了上面两种方式,还有别的调用方式吗?接下来往下看 # inner() #直接调用inner函数是会报错的NameError: name 'inner' is not defined。报错类似于直接调用函数里的变量一样。局部变量,全局无法调用:如下 # print(x) #NameError: name 'x' is not defined #接下来再想想,下面这种调用方式。可以发现执行f = outer()的时候,outer函数已经执行完了,为什么执行f()函数不会出错呢?其实这就是闭包。 f = outer() #调用方式2 f() #有点难理解吧,直接看闭包定义:如果在一个内部函数里[inner()],对在外部作用域(但不是在全局作用域)的变量[x变量]进行引用,那么内部函数[inner()]就被认为是闭包。 #由上可知,闭包就是符合上面条件的函数。那有什么用呢?闭包函数可以脱离局部环境,可以在外面进行调用,这就是为什么上面的f()是可以执行的。 #上面闭包结束了,接下来看看装饰器 #首先看一个例子:一个公司有一个人写了很多函数,公司的人都可以调用。但有一天boss要求对原函数做出点调整,难道自己直接改原函数吗?岂不是如果改错了,所有的全都错了!!因此需要遵循“开放封闭”原则,即不能修改源代码,但能扩展 import time def foo(): print("foo.....") time.sleep(1) def bar(): print("bar....") time.sleep(3) #假如有很多这样的原函数。但现在要求给每个函数加上每个函数的执行时间,该怎么做呢?可以如下:写个专门记录时间的函数 def show_time(*args): for i in args: start=time.time() i() end=time.time() print("Spend time: %s" %(end-start)) show_time(foo, bar) #但是问题出现了,虽然实现了功能,但致命问题出现了:修改了调用方式(以前调用foo(),现在要调用show_time()),这是很致命的!!! #怎么整呢? def show_time2(f): def in_fun(): start=time.time() f() end=time.time() print("Spend time2: %s" %(end-start)) return in_fun #这里in_fun就是个闭包函数 foo=show_time2(foo) #这样就没有修改原来的调用方式了 foo() #执行的in_fun函数 bar=show_time2(bar) bar() #所以装饰器就出来了:就是给原函数添装新的功能。这里的show_time2()就是一个装饰器 #上面的又出来了:给那个函数加功能,就要给那个函数赋值一次,所以出现了一种改进写法@,如下: @show_time2 #实质就是等于foo_re=show_time2(foo_re) def foo_re(): print("foo_re.....") time.sleep(2) foo_re() #以后想在哪个原函数加上计时功能,只需要在原函数前添加@show_time2就行了 #是不是成就感满满 #当然还有缺点,如果有一万个函数都要加这个功能呢?有没有什么批量添加方法???这里还没法解决,还得继续后面学习。 #装饰器已经学完了,但可以进一步学习一下。先看个需求:假如其中一个原函数有参数呢,该怎么做? #只能真对性再定义个函数。如下: def show_time3(f): def in_fun(x,y): start=time.time() f(x,y) end=time.time() print("Spend time2: %s" %(end-start)) return in_fun @show_time3 def add(a,b): print(a+b) time.sleep(1) add(1,4) #那问题来了,万一各个原函数之间存在不同数目的参数呢??没有讲 #功能函数加参数,就会带动装饰器函数必须加参数。但可不可以单独给装饰器函数加参数呢??当然可以 #需求:对于有些原函数,不仅要打印时间,还要显示日志。看下面: def logger(flag): #再加一层的目的就是要一个参数,用于下面的if判断 def show_time3(f): def in_fun(x,y): start=time.time() f(x,y) end=time.time() print("Time_log spend time2: %s" %(end-start)) if flag == "true": print("日志记录") return in_fun #这里in_fun就是个闭包函数 return show_time3 @logger("true") def fil(a,b): print(a+b) time.sleep(1) fil(1,4) @logger("t") def fil2(a,b): print(a+b) time.sleep(1) fil2(2,3)
标签:函数,show,day1601,20220812,time,print,foo,装饰,def 来源: https://www.cnblogs.com/ly-zy/p/16580925.html