装饰器
本质就是函数,作用是为其他函数添加附加功能且必须满足以下两点:
1.不修改原函数的代码
2.不改变原函数的调用方式
装饰器=高阶函数+函数嵌套+闭包
高阶函数:满足以下任一条件既是
1.把函数作为参数传入
2.把函数作为返回值
函数嵌套+闭包:在函数中定义函数形成闭包
例子:计算程序运行时间
import time
def timmer(func):
def wrapper():
start_time=time.time()
func()
end_time=time.time()
print('函数运行时间为%s'%(end_time-start_time))
return wrapper
def test():
time.sleep(2)
print('Test,Test,Test')
test=timmer(test)#test得到的其实是timmer函数返回的wrapper的函数地址,所以其实真正运行的函数是wrapper函数
test()
#输出
#Test,Test,Test
函数运行时间为2.0002095699310303
Python里有装饰器的语法糖@,只要在定义函数前加上@timmer就行
import time
def timer(func):
def wrapper():
start_time=time.time()
func()
end_time=time.time()
print('函数运行时间为%s'%(end_time-start_time))
return wrapper
@timer #其实就是在做test=timmer(test),实质在运行wrapper函数
def test():
time.sleep(2)
print('Test,Test,Test')
test()
print('真正运行的是',test.__name__)
#输出
#Test,Test,Test
#函数运行时间为2.0000147819519043
#真正运行的是 wrapper
定义的函数中带参数时
import time
def timer(func):
def wrapper(*args,**kwargs): #因为不知道定义的函数参数的数量,种类,所以用*args,**kwargs接收参数不会出错
start_time=time.time()
res=func(*args,**kwargs) #将参数传给函数,并将返回值赋给res
end_time=time.time()
print('函数运行时间为%s'%(end_time-start_time))
return res #返回结果
return wrapper
@timer
def test(name):
time.sleep(2)
print('Test,Test,Test')
return 'my name is %s'%name
r=test('Alex')
print(r)
#输出
#Test,Test,Test
#函数运行时间为2.000030994415283
#my name is Alex
装饰器中也可以传入参数
import time
def timmer(text='Call'):
def decorator(func):
def wrapper(*args,**kwargs):
print('%s the func %s'%(text,func))
start_time=time.time()
res=func(*args,**kwargs)
end_time=time.time()
print('函数运行时间为%s'%(end_time-start_time))
return res
return wrapper
return decorator
@timmer('Execute')
def test(name):
time.sleep(2)
print('Test,Test,Test')
return 'my name is %s'%name
r=test('Alex')
print(r)
#输出
#Execute the func <function test at 0x000001432E285620>
#Test,Test,Test
#函数运行时间为2.000121831893921
#my name is Alex
写一个简单的验证功能装饰器
user_data=[{'name':'alex','passwd':'123'},
{'name':'alex1','passwd':'123'},
{'name':'alex2','passwd':'123'},
{'name':'alex3','passwd':'123'},
{'name':'alex4','passwd':'123'}]
curren_dict={'user':None,'login':False}
def auth(func):
def wrapper(*args,**kwargs):
r=1
if curren_dict['user'] and curren_dict['login']:
res=func(*args,**kwargs)
return res
else:
while r:
name=input('请输入用户名:').strip()
password=input('请输入密码:').strip()
for data in user_data:
if data['name']==name and data['passwd']==password:
curren_dict['user']=name
curren_dict['login']=True
res=func(*args,**kwargs)
r=0
return res
else:
print('用户名或者密码错误,请重新输入')
return wrapper
@auth
def index(name):
print('欢迎光临%s'%name)
@auth
def home(name):
print('欢迎回家%s'%name)
@auth
def shopping_list(name):
print('%s 的购物清单是[1,2,3]'%name)
index('Alex')
home('Alex')
shopping_list('Alex')