装饰器
一、装饰器定义:本质就是函数,功能是为其它函数添加附加功能
原则:
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包
二、高阶函数
高阶函数定义:
1、函数接受的参数是一个函数名
2、函数的返回值是一个函数名
3、满足上述条件任意一个,都称为高阶函数
def foo(): print('您好啊赵师傅') #4、打印 return foo #5、return def test(func): #2、接受foo参数,代入函数体 func() #3、执行foo函数 test(foo) #1、执行test函数,传参foo 执行结果: 您好啊赵师傅
三、在遵循装饰器原则的基础上,修改上述代码,增加计时功能;
ps1:
import time #满足条件1:作用是,可以在不修改源代码的情况下,为被修改函数foo添加新功能 #问题是,修改了foo的调用方式 def foo():
time.sleep(2) print('您好啊赵师傅') def test(func): start_time = time.time() #计算开始时间 func() #执行foo函数 stop_time = time.time() #计算结束时间 print('执行函数所用时间:【%s】'%(stop_time-start_time)) #结束时间减去开始时间为运行时间 test(foo)
执行结果:
您好啊赵师傅
执行函数所用时间:【2.0001139640808105】
ps2:
#满足条件: #1、不修改foo源代码 #2、不修改foo调用方式 #但是多调用一次,不满足业务需求 def foo(): print('您好啊赵师傅') #3、调用函数打印信息 def test(func): start_time = time.time() func() #2、执行传入的foo函数 stop_time = time.time() print('执行函数所用时间:【%s】'%(stop_time-start_time)) #4、打印时间 return func #返回foo函数值 foo=test(foo) #1、执行函数test(foo),并把foo传入函数体/ #6、foo变量接受return的foo()函数的内存地址 foo() #7、得到内存地址,再次执行了一遍foo函数 执行结果: 您好啊赵师傅 执行函数所用时间:【0.0】 您好啊赵师傅
四、函数嵌套、闭包概念
函数嵌套定义:函数内部再定义函数
闭包概念:封装内层的变量值(函数也是变量)
ps1:
def father(name): def son(): print('我的父亲是%s'%name) #3、打印 def grandson(): print('我的爷爷是%s'%name) #5、打印 grandson() #4、调用grandson() son() #2、调用son() father('zk') #1、调用father函数,传参zk给函数体 执行结果: 我的父亲是zk 我的爷爷是zk
五、装饰器基本架子
ps1:基础架子
def timer(func): def wrapper(): func() return wrapper
ps2:加上参数
def timer(func): def wrapper(*args,**kwargs): #接受实际函数所传的参数,给wrapper函数内部调用 func(*args,**kwargs) #将参数 return wrapper
ps3:加上功能
import time def timer(func): def wrapper(*args,**kwargs): start_time=time.time() #可加上具体功能 func(*args,**kwargs) #func为外层变量,在内层可以获取到 stop_time=time.time() print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time)) return wrapper
ps4:加上返回值
import time def timer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) #返回实际执行函数的返回值,用个变量接收到 stop_time=time.time() print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time)) return res #在返回得到的变量的值,这时wrapper的返回值,就是实际执行函数的返回值了 return wrapper
装饰器调用解析:
ps1:
def timer(func): #func————>test def wrapper(): func() #就是在运行test函数 return wrapper #———————————————以上部分是基本架子————————————————————— def test(): print('test执行完毕') res=timer(test) #返回的是wrapper的内存地址 用res接收wrapper的内存地址 res() #执行的是wrapper函数
语法糖@
@timer #@timer就等同于res=timer(test) 后两句
def timer(func): #func————>test
def wrapper():
func() #就是在运行test函数
return wrapper
def test():
print('test执行完毕')
#res=timer(test) #返回的是wrapper的内存地址 用res接收wrapper的内存地址
#res() #执行的是wrapper函数
无参数装饰器实例
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_user={'username':None,'login':False} def auth_deco(func): def wrapper(*args,**kwargs): if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('用户名: ').strip() passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('用户名或者密码错误,重新登录') return wrapper @auth_deco def index(): print('欢迎来到主页面') @auth_deco def home(): print('这里是你家') def shopping_car(): print('查看购物车啊亲') def order(): print('查看订单啊亲') print(user_list) # index() print(user_list) home() 无参装饰器
带参数装饰器实例
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_user={'username':None,'login':False} def auth(auth_type='file'): def auth_deco(func): def wrapper(*args,**kwargs): if auth_type == 'file': if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('用户名: ').strip() passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('用户名或者密码错误,重新登录') elif auth_type == 'ldap': print('ldap___模式') res=func(*args,**kwargs) return res return wrapper return auth_deco #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file') #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数 @auth(auth_type='ldap') def index(): print('欢迎来到主页面') @auth(auth_type='ldap') def home(): print('这里是你家') def shopping_car(): print('查看购物车啊亲') def order(): print('查看订单啊亲') # print(user_list) index() # print(user_list) home() 带参装饰器
自己写的练习题:
user_list=[ {'user':'','passwd':'111111'}, {'user':'','passwd':'111111'} ] operating_dic={'user_name':None,'login_zt':False} def jd_date(my_db='mysql'): def jd_yz(func): def wrapper(*arg,**kwargs): if my_db=='mysql': if operating_dic['user_name'] and operating_dic['login_zt']: print(operating_dic) res=func(*arg,**kwargs) return res else: user=str(input('用户名:')) passwd=str(input('密码:')) for i in user_list: if user==i['user'] and passwd==i['passwd']: operating_dic['user_name']=user operating_dic['login_zt']=True res=func(*arg,**kwargs) return res else: print('用户名密码错误!!!') elif my_db =='sql_server': print('使用sql_server数据库验证') else: print('谁知道你用的是鸟验证') return wrapper return jd_yz @jd_date(my_db='mysql') def index(name): print('欢迎%s来到京东'%(name)) @jd_date(my_db='sql_server') def home(name): print('欢迎%s回家'%(name)) @jd_date(my_db='abc') def order(name): print('%s的订单'%(name)) index('zk') home('zk') order('zk')