Flask接口签名sign原理与实例代码浅析
274
2022-08-25
python--装饰器(python装饰器的作用和功能)
前戏
装饰器:定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
原则:
不能修改被装饰的函数的源代码不能修改被装饰的函数的调用方式
实现装饰器知识储备
1.函数即'变量'
2.高阶函数
把一个函数当做实参传递给另外一个参数(在不修改被装饰函数源代码的情况下为其添加功能)返回值中包含函数名(不修改函数的调用方式)
无参数的装饰器
下面有一个函数,如果我们想统计一下函数执行的时间,使用装饰器怎么实现呢
import timedef test1(): time.sleep(2) print('in the test1')
如果不使用装饰器我们可以在之前前加一个时间,执行后加一个时间就可以了,如下
import timedef test1(): start_time = time.time() time.sleep(2) print('in the test1') print(time.time()-start_time)test1()
但是这样的话,我们修改了源代码,如果这个函数有好多地方调用了,有些地方不希望要其他的功能,有些地方需要,难道我们需要重新写一个函数吗?在把调用到的地方都修改一下?如果你这样的话,明天就可以去财务领工资了。。。那来看看怎么使用装饰器来实现
1 import time 2 3 4 def timmer(func): 5 def warpper(): 6 start_time = time.time() 7 func() # run test1 8 stop_time = time.time() 9 print('the func time is %s' % (stop_time - start_time))10 11 return warpper12 13 14 @timmer # test1=timmer(test1)语法糖,给哪个函数加装饰器,就在哪个函数前加上 @ 装饰名15 def test1():16 time.sleep(2)17 print('in the test1')18 19 test1() # 运行warpper()
代码解释:
函数从上往下执行,执行到14行的时候,14行的代码等价于test1=timmer(test1)。就回去执行timmer函数,所以timmer里的func就是test1。执行完返回了warpper,所以test1=warpper,然后执行19行,因为test1=warpper,所以19行相当于warpper(),执行了waepper函数,而func为test1,func()就是调用了test1()这个函数。
这样我们就实现了一个装饰器,在不修改源代码和调用方式的情况下给函数增加了新的功能。
带参数的装饰器
上面的test1函数没有参数,如果test1需要一个参数,还这样写的话就会报错
import timedef timmer(func): def warpper(): start_time = time.time() func() # run test1 stop_time = time.time() print('the func time is %s' % (stop_time - start_time)) return warpper@timmer def test1(m1): time.sleep(2) print('in the test1')test1('2')
结果:
TypeError: warpper() takes 0 positional arguments but 1 was given
报错信息告诉了我们warpper需要一个参数,那我们去修改一下
import timedef timmer(func): def warpper(arg): start_time = time.time() func(arg) # run test1 stop_time = time.time() print('the func time is %s' % (stop_time - start_time)) return warpper@timmerdef test1(m1): time.sleep(2) print('in the test1')test1('2')
我们给warpper传了一个参数arg,因为func(test1)是需要一个参数的,那如果test1需要多个参数怎么办呢,我们可以用可变参数*args,**kwargs来实现动态的传参
import timedef timmer(func): def warpper(*args, **kwargs): start_time = time.time() func(*args, **kwargs) # run test1 stop_time = time.time() print('the func time is %s' % (stop_time - start_time)) return warpper@timmerdef test1(m): time.sleep(2) print('in the test1')test1('12')
这样不管test1有没有参数,有几个参数都能满足需求
有返回值的装饰器
还是上面的代码,假如test1里有返回值,如下
1 import time 2 3 4 def timmer(func): 5 def warpper(*args, **kwargs): 6 start_time = time.time() 7 func(*args, **kwargs) # run test1 8 stop_time = time.time() 9 print('the func time is %s' % (stop_time - start_time))10 11 return warpper12 13 14 @timmer15 def test1():16 time.sleep(2)17 print('in the test1')18 return 66619 20 # test1()21 print(test1())
结果:
in the test1the func time is 2.0003857612609863None
我们可以看到,结果返回了一个None,因为warpper函数的时候,在执行到func(*args, **kwargs)的时候,执行了test1函数,虽然是执行了,但是return返回的值没有接收,那我们可以定义一个变量接收一下,然后再return给调用者
1 import time 2 3 4 def timmer(func): 5 def warpper(*args, **kwargs): 6 start_time = time.time() 7 res = func(*args, **kwargs) # run test1 8 stop_time = time.time() 9 print('the func time is %s' % (stop_time - start_time))10 return res11 12 return warpper13 14 15 @timmer16 def test1():17 time.sleep(2)18 print('in the test1')19 return 66620 21 # test1('12')22 print(test1())
这样的话,我们也实现了一个带返回值的装饰器,如果test1没有返回值,则返回的是None,在看个栗子,加深下理解
def auth(func): def timer(*args, **kwargs): print('加的新功能start。。。') res = func(*args, **kwargs) # 将返回值得结果赋给res print('加的新功能end。。。') return res # 执行返回值的结果,没有不执行 return timer@auth # test2=auth(test2)def test2(*args, **kwargs): print('in the test2...') return '我是返回值'print(test2('zou', 'IT', '24'))
结果:
加的新功能start。。。in the test2...加的新功能end。。。我是返回值
实战
1 user, passwd = 'zou', '123' 2 3 def auth(func): 4 def timmer(*args, **kwargs): 5 username = input('输入用户名:') 6 password = input('输入密码:') 7 if username == user and password == passwd: 8 print('加的新功能') 9 res = func(*args, **kwargs) # 如果不将结果赋给res就没有返回值10 return res11 else:12 exit('密码错误')13 return timmer14 15 def test1():16 print('in the test1')17 18 19 @auth20 def test2(name, job):21 print('name:%s' % name)22 print('job:%s' % job)23 24 25 @auth26 def test3():27 print('in the test3')28 return 'end'29 30 31 test1()32 test2('zou', 'IT')33 print(test3())
大家可以自己在脑海里想一下,是怎么运行的,为什么这么运行?最后运行的结果是什么?
结果:
in the test1输入用户名:zou输入密码:123加的新功能name:zoujob:IT输入用户名:zou输入密码:123加的新功能in the test3end
点我偷看
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~