闭包: 能够访问其他函数内部变量的函数就叫做闭包,弱数据类型的语言特有的现象
闭包最大的特点就是将局部变量全局化,但导致了局部变量无法及时释放,常驻内存,内存的占有比较高,只是此时局部变量作用域比较小,代码整合时可以防止变量覆盖
闭包优化了变量,原来需要类对象完成的工作,闭包也可以完成
#这是一个闭包:inner函数能够访问outer函数内部变量a
#引用传递是将函数内存地址赋给变量,函数调用是将函数返回值赋给变量
def outer():
a = 10
print("这是外部函数")
def inner():
print(a)
print("这是内部函数")
return inner
#outer函数返回的是一个函数,所以此时a指向inner函数
a = outer() #函数调用是将函数返回值(return inner)赋给变量
#print(a) #<function outer.<locals>.inner at 0x000001918F667598>
#调用a函数,相当于调用inner函数
a()
#outer()() #此时也可以调用inner函数
装饰器:就是在运行原来功能基础上,加上一些其它功能
装饰器功能:引入日志、函数执行时间统计、执行函数前预备处理、执行函数后清理功能、权限校验、异常处理、缓存
OCP原则(open close protocol):写代码要遵循开放封闭原则
设计模式的出现:golf提出了23种设计模式—装饰者设计模式
#闭包函数中的参数fn就是我们要装饰的对象,只需要加@logining就可以使用闭包函数logining()对原来的login()与reg()函数进行装饰
def logining(fn):
def inner():
print("正在加入日志")
fn()
print("日志已经加入")
return inner #此处返回inner函数,并且@logining已经将login函数替换为inner函数,下面调用login函数时返回的是inner函数
@logining #执行@logining时logining函数中的fn就是login函数
def login():
print("登录")
@logining
def reg():
print("注册")
login()
reg()
1、被装饰的函数无参数
#装饰器没有打破OCP原则,而是将需要加入的功能正常的添加进去,可用于重构代码
#装饰器可以装饰多个函数
#被装饰函数无参数
def logining(fn):
def inner():
print("开始记录日志……")
fn()
print("日志记录完成……")
return inner
def check(fn):
def inner():
print("开始数据校验……")
fn()
return inner
@logining
@check
def login():
print("登录")
if __name__ == '__main__':
login()
运行结果:
开始记录日志……
开始数据校验……
登录
日志记录完成……
2、被装饰的函数存在参数,则参数在装饰器内部的函数中传递
#被装饰函数有参数
def logining(fn):
#如果被装饰的函数存在参数,则参数在装饰器内部的函数中传递
def inner(username,password,*arg,**kwarg):
print("开始记录日志……")
fn(username,password,*arg,**kwarg)
print("日志记录完成……")
return inner
def check(fn):
def inner(username,password,*arg,**kwarg):
print("开始数据校验……")
fn(username,password,*arg,**kwarg)
return inner
@logining
@check
def login(username,password,*arg,**kwarg):
print(username + "使用密码登录,密码是" + password)
print("登录")
if __name__ == '__main__':
UserName = "zhang"
PassWord = "123"
login(UserName,PassWord)
3、被装饰的函数存在返回值,则需要在内部函数调用原函数时返回
#如果被装饰的函数存在返回值,则需要在内部函数调用原函数时返回
def logining(fn):
#如果被装饰的函数存在参数,则参数在装饰器内部的函数中传递
def inner(username,password,*arg,**kwarg):
print("开始记录日志……")
f = fn(username,password,*arg,**kwarg)
print("日志记录完成……")
return f
return inner
def check(fn):
def inner(username,password,*arg,**kwarg):
print("开始数据校验……")
return fn(username,password,*arg,**kwarg)
return inner
@logining
@check
def login(username,password,*arg,**kwarg):
print(username + "使用密码登录,密码是" + password)
print("登录")
return True
if __name__ == '__main__':
UserName = "zhang"
PassWord = "123"
login(UserName,PassWord)
偏函数:
#偏函数的使用
from functools import partial
def print_msg(msg,type = 1):
if type == 1:
for x in msg:
print(x)
elif type == 2:
for k,v in msg.items():
print(k,v)
elif type == 3:
for x in msg:
print(x)
print_msg("you are dog?") #type不写默认为1
print_msg({"k1":25,"k2":100,"k3":150},type = 2)
print_msg([1,2,3,4,5,6],type = 3)
#此时print_dict函数就是print_msg函数,但是print_dict的type值已经固定为2
print_dict = partial(print_msg,type = 2)
print_dict({"k1":25,"k2":100,"k3":150}) #等价于print_msg({"k1":25,"k2":100,"k3":150},type = 2)
print(print_dict) #functools.partial(<function print_msg at 0x000002093A991E18>, type=2)