一、什么是装饰器
装饰器本质就是函数,功能是为其他函数附加功能
二、装饰器遵循的原则
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
三、实现装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包
示例1:用函数实现
#统计从1加到100所用的时间 import time def calc(l): start_time = time.time() res = 0 for i in l: time.sleep(0.1) res +=1 stop_time = time.time() print('函数运行时间%s'%(stop_time-start_time)) return res calc(range(100))
运行结果:
函数运行时间10.049538612365723
用装饰器
import time def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print('函数运行时间为%s'%(stop_time-start_time)) return res return wrapper @timmer def calc(l): res = 0 for i in l: time.sleep(0.1) res += 1 return res res = calc(range(100)) print(res)
四、高阶函数
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数
示例1:函数接收的参数是一个函数名
import time def foo(): time.sleep(3) print('helloword') def test(func): print(func) start_time = time.time() func() stop_time =time.time() print('函数运行时间%s'%(stop_time - start_time)) test(foo) >>>>> <function foo at 0x02EBA930> helloword 函数运行时间3.00070858001709
示例二:接收的参数是一个函数名
#多运行了一次,不合格 import time def foo(): time.sleep(3) print('来自foo') def timer(func): start_time=time.time() func() stop_time = time.time() print('函数运行时间是 %s' % (stop_time-start_time)) return func foo=timer(foo) foo()
>>>>>
来自foo
函数运行时间是 3.000398635864258
来自foo
示例三:返回的参数是一个函数名
#没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能 import time def foo(): time.sleep(3) print('来自foo') def timer(func): start_time=time.time() return func stop_time = time.time() print('函数运行时间是 %s' % (stop_time-start_time)) foo=timer(foo) foo()
>>>>>>>
来自foo
结论:高阶函数,满足不了装饰器的功能。
高阶函数总结:
1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能,
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
五、函数的嵌套
1、什么是函数的嵌套?
通过在函数内部def的关键字再声明一个函数即为嵌套
def fathar(name): def son(): print('爸爸是%s'%name) def grandfathar(): name = '还是我自己' print('爷爷是%s'%name) grandfathar() son() fathar('我自己')
>>>>>
爸爸是我自己
爷爷是就是我自己
六、闭包
闭包:在一个作用域里放入定义变量,相当于打了一个包
七、无参装饰器
无参装饰器=高级函数+函数嵌套
1.基本框架
def timer(func): def wrapper(): func() return wrapper
2、基本装饰器(基本框架+参数+功能+返回值+使用装饰器+语法糖@)
import time def timmer(func): #func=test def wrapper(): # print(func) start_time=time.time() func() #就是在运行test() stop_time = time.time() print('运行时间是%s' %(stop_time-start_time)) return wrapper @timmer #test=timmer(test) #在函数名前面加个@ ,这就是语法糖 def test(): time.sleep(3) print('test函数运行完毕') test()
# res=timmer(test) #返回的是wrapper的地址 # res() #执行的是wrapper() # # test=timmer(test) #返回的是wrapper的地址 # test() #执行的是wrapper() # # @timmer 就相当于 test=timmer(test)
3.
import time def timmer(func): #func=test1 def wrapper(*args,**kwargs): #test('linhaifeng',age=18) args=('linhaifeng') kwargs={'age':18} start_time=time.time() res=func(*args,**kwargs) #就是在运行test() func(*('linhaifeng'),**{'age':18}) stop_time = time.time() print('运行时间是%s' %(stop_time-start_time)) return res return wrapper # @timmer #test=timmer(test) def test(name,age): time.sleep(3) print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age)) return '这是test的返回值' @timmer def test1(name,age,gender): time.sleep(1) print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender)) return '这是test的返回值' # res=test('linhaifeng',age=18) #就是在运行wrapper # # print(res) # test1('alex',18,'male') test1('alex',18,'male')
八、装饰器应用案例
写一个模拟京东网站,用户认证登录网站和购物加入购物车功能程序
实现功能:用装饰器给所有函数加上验证功能
def index(): pass def home(): pass def shopping_car() pass def order() pass
实现
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_dic={'username':None,'login':False} def auth(auth_type='filedb'): def auth_func(func): def wrapper(*args,**kwargs): print('认证类型是',auth_type) if auth_type == 'filedb': if current_dic['username'] and current_dic['login']: res = func(*args, **kwargs) return res username=input('用户名:').strip() passwd=input('密码:').strip() for user_dic in user_list: if username == user_dic['name'] and passwd == user_dic['passwd']: current_dic['username']=username current_dic['login']=True res = func(*args, **kwargs) return res else: print('用户名或者密码错误') elif auth_type == 'ldap': print('鬼才特么会玩') res = func(*args, **kwargs) return res else: print('鬼才知道你用的什么认证方式') res = func(*args, **kwargs) return res return wrapper return auth_func @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type --->index=auth_func(index) def index(): print('欢迎来到京东主页') @auth(auth_type='ldap') def home(name): print('欢迎回家%s' %name) # @auth(auth_type='sssssss') def shopping_car(name): print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃')) # print('before-->',current_dic) # index() # print('after--->',current_dic) # home('产品经理') shopping_car('产品经理')
示例2 :给他加上验证功能装饰器(判断用户和密码,跟字典里的用户和密码进行比对)
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_dic={'username':None,'login':False} def auth_func(func): def wrapper(*args,**kwargs): if current_dic['username'] and current_dic['login']: res = func(*args, **kwargs) return res username=input('用户名:').strip() passwd=input('密码:').strip() for user_dic in user_list: if username == user_dic['name'] and passwd == user_dic['passwd']: current_dic['username']=username current_dic['login']=True res = func(*args, **kwargs) return res #返回值 else: print('用户名或者密码错误') return wrapper @auth_func #加证功能,也是装饰器 def index(): print('欢迎来到京东主页') @auth_func def home(name): print('欢迎回家%s' %name) @auth_func def shopping_car(name): print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃')) print('before-->',current_dic) index() print('after--->',current_dic) home('产品经理') shopping_car('产品经理')