一.闭包函数
1.闭函数:被封闭起来的函数==>定义在函数内部的函数,特点是只能在函数内调用
2.包函数:该函数引用了一个名字,该名字来自于E这一层
总结:闭包函数指的是定义在函数内部的函数引用了一个来自于外层函数作用域中的名字
#例如wrapper函数
# def outter():
# x = 100
# def wrapper():
# print(x)
3.闭包函数升级:结合函数对象
# def outter():
# x = 100
# def wrapper():
# print(x)
# return wrapper # 千万不要加括号
#
# f = outter()
#
# print(f)
#
# def foo():
# x = 666
# f()
#
# foo()
4.为函数体传参的两种解决方案
方案一:直接以参数的形式传入
# def wrapper(x):
# print(x)
#
# wrapper(100)
方案二:闭包函数方式
# def outter(x):
# # x = 100
# def wrapper():
# print(x)
# return wrapper # 千万不要加括号
#
# f = outter(100)
# f()
二.装饰器
1.什么是装饰器
’装饰’代指为被装饰对象添加新的功能
’器’代指器具/工具
但实现装饰器必须遵循的原则是:开放封闭原则
开放指的是对拓展新功能是开放的,封闭指的则是对修改源代码以及调用方式是封闭的
#综上装饰器指的是我们要创建一个工具,该工具可以在遵循原则1和2的前提下还能为被装饰对象添加新功能
原则1、不修改被装饰对象源代码
原则2、不修改被装饰对象调用方式
2.为什么要用装饰器
软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃,而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。
3.用法
**装饰器的推导**
# 被装饰者:给被装饰者添加新功能
# import time
#
# def index():
# print('from index')
# time.sleep(3)
#
# index()
# 方案一:改变被装饰者的源代码
# import time
#
# def index():
# start = time.time()
# print('from index')
# time.sleep(1)
# end = time.time()
# print('run time is %s' %(end - start))
#
# index()
# # 方案二:装饰器的功能需要重复编写,代码冗余
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
#
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
#
# # 方案三:解决方案二的代码冗余问题,但是存在问题-》装饰器的功能写死了,只能装饰index函数
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# def wrapper():
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
#
# wrapper()
# wrapper()
# # 方案四:装饰器的功能写活
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# def outter(func):
# # func = index
# def wrapper():
# start = time.time()
# func()
# end = time.time()
# print('run time is %s' %(end - start))
# return wrapper
#
# index = outter(index) # index = wrapper的内存地址
# # print(index)
# index()
# 方案五:装饰器的功能写活
import time
def index():
print('from index')
time.sleep(1)
def home(name):
print('welcome %s to home page' % name)
time.sleep(0.5)
return 123
def outter(func):
# func = 最原始那个home的内存地址
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs) # 最原始那个home的内存地址()
end = time.time()
print('run time is %s' % (end - start))
return res
return wrapper
home = outter(home) # home = wrapper的内存地址
index = outter(index) # home = wrapper的内存地址
res = home('egon')
print(res)
# res = index()
# print(res)
**装饰器语法糖**(简化)
import time
def outter(func):
# func = 最原始那个home的内存地址
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs) # 最原始那个home的内存地址()
end = time.time()
print('run time is %s' % (end - start))
return res
return wrapper
@outter # index = outter(index)
def index():
print('from index')
time.sleep(1)
@outter # home = outter(home)
def home(name):
print('welcome %s to home page' % name)
time.sleep(0.5)
return 123
res = home('lzl')
print(res)
**多个装饰器叠加**
# 装饰器模板
# def deco(func):
# def wrapper(*args,**kwargs):
# res = func(*args,**kwargs)
# return res
# return wrapper
# 统计时间的装饰器
# import time
#
# def timmer(func):
# def wrapper(*args,**kwargs):
# start = time.time()
# res = func(*args,**kwargs)
# stop = time.time()
# print(stop - start)
# return res
# return wrapper
# 认证功能装饰器
# def auth(func):
# def wrapper(*args,**kwargs):
# inp_user = input('Username: ').strip()
# inp_pwd = input('Password: ').strip()
# if inp_user == 'egon' and inp_pwd == '123':
# res = func(*args,**kwargs)
# return res
# else:
# print('登录失败')
# return wrapper
#
# @auth # index = auth(index)
# def index():
# print('from index')
#
# index()
"""
def deco1(func1): # func1 = wrapper2的内存地址
def wrapper1(*args,**kwargs):
print('===>wrapper1')
res1 = func1(*args,**kwargs)
print('=====>end wrapper1')
return res1
return wrapper1
def deco2(func2): # func2 = wrapper3的内存地址
def wrapper2(*args,**kwargs):
print('===>wrapper2')
res2 = func2(*args,**kwargs)
print('=====>end wrapper2')
return res2
return wrapper2
def deco3(func3): # func3 = 最原始那个index的内存地址
def wrapper3(*args,**kwargs):
print('===>wrapper3')
res3 = func3(*args,**kwargs)
print('=====>end wrapper3')
return res3
return wrapper3
# index = wrapper1的内存地址
@deco1 # deco1(wrapper2的内存地址) ---> wrapper1的内存地址
@deco2 # deco2(wrapper3的内存地址) ---> wrapper2的内存地址
@deco3 # deco3(最原始那个index的内存地址) ---> wrapper3的内存地址
def index():
print('=======>index')
index()
"""
# print(index)
import time
def timmer(func):
def wrapper1(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print(stop - start)
return res
return wrapper1
def auth(func):
def wrapper2(*args,**kwargs):
inp_user = input('Username: ').strip()
inp_pwd = input('Password: ').strip()
if inp_user == 'egon' and inp_pwd == '123':
res = func(*args,**kwargs)
return res
else:
print('登录失败')
return wrapper2
@auth
@timmer
def index():
print('====>index')
time.sleep(3)
index()
有参装饰器:
def outter2(mode,yyy):
# mode = 'mysql'
def outter(func): # func = index
def wrapper(*args ,**kwargs):
print(yyy)
inp_user = input('Username: ').strip()
inp_pwd = input('Password: ').strip()
if mode == 'file':
if inp_user == "egon" and inp_pwd == "123":
res = func(*args ,**kwargs)
return res
else:
print('login failed')
elif mode == 'mysql':
print("基于mysql数据库的认证")
elif mode == 'ldap':
print("基于ldap数据库的认证")
else:
print('未知的认证来源')
return wrapper
return outter
@outter2('mysql',111) # @outter # index = outter(index) # index = wrapper
def index():
print('from index')
@outter2('ldap',222)
def home(name):
print('hello %s' %name)
###functools模块下提供一个装饰器wraps专门用来保留原函数属性####
4.总结
1、无参装饰器模板
# def outter(func):
# def wrapper(*args,**kwargs):
# res = func(*args,**kwargs)
# return res
# return wrapper
#
# @outter
# def index():
# pass
2、有参装饰器模板
def outter2(xxx):
def outter(func):
def wrapper(*args,**kwargs):
xxx
res = func(*args,**kwargs)
return res
return wrapper
return outter
@outter2(xxx=111)
def index():
pass