发布时间:2018-04-04 00:11:50编辑:admin阅读(4792)
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是1函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
一层装饰器
应用场景最多的就是登录判断
举个例子
默认情况下,登录状态是False。现在有一个需求,需要执行func1执行时,必须要登录才行。
需要增加一个装饰器用来判断
#用户状态(全局变量) login_state = {'username':None,'status':False} #装饰器模板 def first(f): def inner(*args,**kwargs): '''被装饰之前''' ret = f(*args, **kwargs) '''被装饰之后''' return ret return inner #测试函数 def func1(*args,**kwargs): print(args,kwargs) return 666 #执行函数 print(func1())
执行输出:
() {}
666
代码如下:
#用户状态(全局变量) login_state = {'username':None,'status':False} #假设用户名存在文件或者数据库中 info = {'username':'xiao','password':'123'} #失败次数 failures = 1 #最大登录次数 maximum = 3 #装饰器模板 def first(f): def inner(*args,**kwargs): '''被装饰之前''' if login_state['status']: ret = f(*args, **kwargs) else: print('您还未登录,请先登录账户!') #执行登录程序 result = login() #判断结果 if result: print('登录成功') else: print('登录失败') ret = f(*args, **kwargs) #执行被装饰的函数 return ret '''被装饰之后''' return inner #登录判断逻辑 def login(): global failures while failures <= maximum: username = input('请输入用户: ').strip() password = input('请输入密码: ').strip() #判断用户名和密码是否一致 if username == info['username'] and password == info['password']: # 修改全局变量,这里不用global,因为它是可变类型 login_state['username'] = username login_state['status'] = True result = True break else: print('您输入的用户或者密码错误,请重新输入,还有%s次机会' % (maximum - failures)) failures += 1 result = False return result #测试函数 @first def func1(*args,**kwargs): print(args,kwargs) return 666 #执行函数 print(func1())
执行输出:
现在又有一个需求,执行watch_movie函数时,必须是VIP用户才可以。
增加二层装饰器
#!/usr/bin/env python # coding: utf-8 __author__ = 'www.py3study.com' #用户状态(全局变量) login_state = {'username':None,'status':False} #假设用户名存在文件或者数据库中 info = {'username':'xiao','password':'123','level':None} #失败次数 failures = 1 #最大登录次数 maximum = 3 #第一层装饰器,判断登录 def first(f): def inner(*args,**kwargs): '''被装饰之前''' if login_state['status']: ret = f(*args, **kwargs) else: print("\033[41;1m您还未登录,请先登录账户!\033[0m") #执行登录程序 result = login() #判断结果 if result: print('登录成功') else: print("\033[41;1m登录失败!\033[0m") ret = f(*args, **kwargs) #执行被装饰的函数 return ret '''被装饰之后''' return inner #第二层装饰器,判断VIP def second(f): def inner(*args,**kwargs): '''被装饰之前''' #判断电影名后缀是否包含VIP if args[0].endswith('VIP'): if info['level'] == None: return "\033[41;1m该影片只对VIP用户开放!\033[0m" else: ret = f(*args, **kwargs) else: #免费电影 ret = f(*args, **kwargs) return ret '''被装饰之后''' #return ret return inner #登录判断逻辑 def login(): global failures while failures <= maximum: username = input('请输入用户: ').strip() password = input('请输入密码: ').strip() #判断用户名和密码是否一致 if username == info['username'] and password == info['password']: # 修改全局变量,这里不用global,因为它是可变类型 login_state['username'] = username login_state['status'] = True #设置标记 result = True break else: print("\033[41;1m您输入的用户或者密码错误,请重新输入,还有%s次机会!\033[0m" % (maximum - failures)) failures += 1 result = False return result #看电影函数 @first @second def watch_movie(name): if name.strip() == '': return '电影名不能为空' return '正在播放影片 {}'.format(name) #首页 def index(): movie_list = { #序号:电影名 1: '黑暗塔', 2: '环太平洋 VIP', 3: '变形金刚5:最后的骑士 VIP', 4: '退出', } while True: #循环列表 for k, v in movie_list.items(): print('{}\t{}'.format(k, v)) choice_num = input('请选择输入的序号:').strip() if choice_num.isdigit(): choice_num = int(choice_num) #判断数字范围 if 0 < choice_num < len(movie_list): #执行看电影函数 print(watch_movie(movie_list[choice_num])) elif choice_num == len(movie_list): break else: print("\033[41;1m请输入范围内的序号!\033[0m") else: print("\033[41;1m您输入的有非法字符,请重新输入!\033[0m") if __name__ == "__main__": index()
执行输出:
修改全局变量
info = {'username':'xiao','password':'123','level':'VIP'}
再次登录,就可以看VIP电影了
装饰器执行顺序是这样的
上述代码的二层装饰器,都是在被装饰之前操作的
first判断是否登录
second判断用户等级
二层以上装饰器,也都是按照上图的循环来的,多套了几层而已!
上一篇: python 装饰器构造优酷视频登录程序
下一篇: python 面向对象之继承顺序
47675
46116
37002
34563
29164
25824
24656
19794
19339
17832
5639°
6221°
5765°
5818°
6770°
5560°
5558°
6055°
6033°
7366°