装饰器
1.装饰器的概念:
1)装饰器的组成:
装饰器 = 高阶函数+嵌套函数+语法糖
2)装饰器的原理:
装饰器实际上就是为了给程序增添功能。(大前提:不修改被装饰的函数的源代码和调用方式)
2.高阶函数:
高阶函数的形式有两种:
1)把一个函数名当作实参传给另外一个函数(“实参高阶函数”)
2)返回值中包含函数名(“返回值高阶函数”)
示例:
import time def func(): time.sleep(1) print('ceshi') def call_func(func): start = time.time() func() stop = time.time() print(stop-start) func = call_func(func) print(func)
3.函数嵌套:在一个函数中再次创建一个函数
例:
def test(): print('这是第一层函数输出') def secend_test(): print('这是第二层函数输出') secend_test() print(test()) 错误示例: def first(): print('aaa') def second(): print('bbb') first() second() #这是调用不是嵌套
4.装饰器的简单应用:
import time def timer(func): def run_time(): start = time.time() func() stop = time.time() print('函数运行时间为:',start-stop) return run_time @timer def test(): a = 0 time.sleep(1) for i in range(10000): a += i print(a) test()
5.装饰器为什么需要两层嵌套?
def test(func): #1 def test1(): #2 func() #3 print('22:48') return test1 #4 @test #5 def date(): #6 print('2018.12.17') date()
上面是一个简单的装饰器,它分为两层,
外层a#1 定义装饰器的名称,参数为被装饰的函数a,#4 return装饰后的函数,即内层函数b;
内层b#2引入函数date的参数,并进行修饰.
当程序运行到#4时,装饰器test开始执行,此时外层a相当于一个函数,运行函数时发现return,开始运行内层#2,此时a已经指向了b,此后再调用a,就会调用b
双层装饰器的意义:
一是两层结构可以传递被装饰的函数a的参数
二是不改变函数原来的结构,因为装饰器本身就是一个函数,他与其他函数有相同的执行顺序
6.装饰器添加返回值案例:
def test(func): def test1(): res = func() print('22:48') return res return test1 @test def date(): print('2018.12.17') return 'aaa' print(date())
7.函数带有参数的案例:
def test(func): def wrapper(*args,**kwargs): print('garbage') res = func(*args,**kwargs) return res return wrapper @test def garbage(recycled,unrecoverable): print(recycled) print(unrecoverable) return 'Everyone in this room is rubbish' print(garbage('paper','plastic'))
7.解压数列:
l = [1,254,6465753523,45,24,52,3] a,*b,c=l #注:a代表第一个元素,b代表中间的元素,c代表最后一个元素 print(a) print(c) print(b)
8.给函数添加认证功能:
在进入网购页面中,有的页面是需要你登录才能够正常的显示,下面的示例中,购物车和订单函数模拟为相关页面,需要登录才能进行相关操作
login_status = False def validation(func): def wrapper(*args, **kwargs): global login_status if login_status == True: res = func(*args, **kwargs) return res else: username = input('用户名:').strip() passwd = input('密码:').strip() if username == 'Jiang' and passwd == 'Feng': #global login_status login_status = True res = func(*args, **kwargs) return res else: print('你输入的用户名或密码错误!') return wrapper def index(): print('this is index') @validation def shopping_car(): print('this is shopping_car') @validation def order(name): print('this is order') index() shopping_car() order('Jiang_Feng') -------升级版 user_list = [ {'name':'aaa','passwd':'aaa'}, {'name':'bbb','passwd':'bbb'}, {'name':'ccc','passwd':'ccc'} ] login_status = {'username':None,'status':False} def validation(func): def wrapper(*args, **kwargs): if login_status['status'] == True: res = func(*args, **kwargs) return res else: username = input('用户名:').strip() passwd = input('密码:').strip() for user_log in user_list: if user_log['name'] == username and user_log['passwd'] == passwd: login_status['status'] = True res = func(*args, **kwargs) return res else: print('你输入的用户名或密码错误!') return wrapper def index(): print('this is index') @validation def shopping_car(): print('this is shopping_car') @validation def order(name): print('this is %s order'%name) index() shopping_car() order('Jiang_Feng')
9.装饰器带有参数案例:登录时的认证选择
def auth(authentication = 'HTTP Digest'): #默认的认证方式 def validation(func): def wrapper(*args, **kwargs): if authentication == 'HTTP Digest': pass elif authentication == 'HTTP Basic': pass return wrapper return validation() @auth(authentication = 'HTTP Basic') #选择的认证方式 def order(name): print('this is order') order()