装饰器
1. 什么叫装饰器
装饰器本质就是函数,为其他函数添加附加功能
原则:
1>.不修改被修饰函数的源代码
2>.不改变修饰函数的调用方式
2. 装饰器的知识储备:
装饰器 = 高阶函数 + 函数嵌套 + 函数闭包
3. 高阶函数
高阶函数定义:
1)函数接收的参数是一个函数名
2)函数的返回值是一个函数名
3)满足上述条件中的任意一个,都可称之为高阶函数
def mvp(func): #高阶函数1,接收的参数是一个函数名
res = func()
return res
def dpoy(): #高阶函数2,函数的返回值是一个函数名
print('mvp和dpoy都属于lebron')
return fmvp
def fmvp():
print('当然fmvp也属于lebron')
高阶函数(把函数当做参数传给高阶函数)的应用1:计算函数运行的时间
import time def timmer(func): start_time = time.time() func() stop_time = time.time() print('函数的运行时间为%s' %(stop_time - start_time)) def test(): time.sleep(2) print('来自函数test') timmer(test)
#总结:我们确实为函数test增加了test运行时间的功能,但是test原来的执行方式是test(),现在我们需要调用高阶函数timmer(test),改变了函数的调用方式
高阶函数(函数的返回值是一个函数名)的应用2:
import time
def timmer(func):
start_time = time.time()
func()
stop_time = time.time()
print('函数的运行时间为%s' %(stop_time - start_time))
return func
def test():
time.sleep(2)
print('来自函数test')
test = timmer(test)
test()
#总结:我们为函数test增加了test运行时间的功能,也没有改变test函数的执行方式和源代码,但是这种方法使得test函数运行了两次,相当于没有为foo增加任何新功能
高阶函数总结
1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能,
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
4. 函数嵌套
def father(name1):
print('爸爸是%s' %name1)
def son(name2):
print('儿子是%s' %name2)
def grandson(name3):
print('孙子是%s' %name3)
grandson('bose')
son('xueba')
father('sword')
5. 闭包
闭包:在一个作用域里放入定义变量,相当于打了一个包。其实就是对作用域的一种说法,在函数嵌套中,因为作用域的不同,内一层的变量不能在外一层使用,就相当于给内一层的变量封包
def father(name):
print('爸爸是%s' %name)
def son():
name = 'xueba'
print('儿子是%s' %name)
def grandson():
name = 'bose'
print('孙子是%s' %name)
grandson()
son()
father('sword')
6. 无参装饰器
无参装饰器=高级函数+函数嵌套
基本框架
def timmer(func):
def wrapper():
res = func()
return wrapper
加上参数
def timmer(func):
def wrapper(*args, **kwargs):
func(*args, **kwargs)
return wrapper
加上功能
import time
def timmer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
func()
stop_time = time.time()
print('函数%s,运行时间%s' %(func, stop_time - start_time)
return wrapper
加上返回值
import time
8
de3f timmer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func()
stop_time = time.time()
print('函数%s,运行时间%s' %(func, stop_time - start_time)
return res
return wrapper
使用装饰器
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
def test():
time.sleep(2)
print('来自函数test')
test = timmer(test)
test()
语法糖@
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 #相当于test = timmer(test)
def test():
time.sleep(2)
print('来自函数test')
# test = timmer(test)
test()
7. 装饰器应用示例
user_list = [
{'name': 'chen', 'passwd': '123'},
{'name': 'lebron', 'passwd': '123'},
{'name': 'druant', 'passwd': '123'},
{'name': 'curry', 'passwd': '123'}
]
user_dic = {'name': None, 'login': False}
def passwd(func):
def wrapper(*args, **kwargs):
if user_dic['name'] and user_dic['login']:
res = func(*args, **kwargs)
return res
name = input('用户名:')
password = input('密码:')
for index, user_id in enumerate(user_list):
if name == user_id['name'] and password == user_id['passwd']:
user_dic['name'] = name
user_dic['login'] = True
res = func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
return wrapper
@passwd
def home():
print('欢迎登陆')
@passwd
def ordr():
print('所有订单')
@passwd
def shopcar():
print('购物车')
home()
user_list = [
{'name': 'chen', 'passwd': '123'},
{'name': 'lebron', 'passwd': '123'},
{'name': 'druant', 'passwd': '123'},
{'name': 'curry', 'passwd': '123'}
]
user_dic = {'name': None, 'login': False}
def passwd(passwd_tpye = 'file'):
def passwd_deo(func):
def wrapper(*args, **kwargs):
if passwd_tpye == 'file':
if user_dic['name'] and user_dic['login']:
res = func(*args, **kwargs)
return res
name = input('用户名:')
password = input('密码:')
for index, user_id in enumerate(user_list):
if name == user_id['name'] and password == user_id['passwd']:
user_dic['name'] = name
user_dic['login'] = True
res = func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
elif passwd_tpye == 'ldap':
print('下次再处理')
res = func(*args, **kwargs)
return res
return wrapper
return passwd_deo
@passwd(passwd_tpye = 'file')
def home():
print('欢迎登陆')
@passwd(passwd_tpye = 'ldap')
def ordr():
print('所有订单')
@passwd(passwd_tpye = 'file')
def shopcar():
print('购物车')
home()
ordr()
#passwd(passwd_type='file')就是在运行一个函数,然后返回passwd_deco,所以@passwd(passwd_type='file')
就相当于@passwd_deco,只不过现在,我们的passwd_deco作为一个闭包的应用,外层的包passwd给它留了一个passwd_type='file'参数