装饰器
1.ocp原则(open close protocol)
对已有运行(稳定的)代码,不应该修改它,如果你增加新的功能,添加新的功能代码即可。也就是对修改关闭,对增加扩展开放。
2.装饰器概念(decorator)
装饰器就是一个闭包函数,它能够@闭包名称装饰一个原有的函数,使原有的函数的功能更加强大
3.如何定义装饰器?
(1).定义一个闭包,闭包有一个默认参数,是一个引用,该引用就是需要装饰的函数
(2).一个需要在里面函数里面调用这个引用(函数),在调用之前写的代码就会被装饰在原函数之前,调用之后的代码,会被装饰在原函数之后。
4.一个简单的装饰器原理:可以使用断点调试,追踪下代码的运行流程,发现装饰器的运行原理
def outer(fn): #闭包:函数嵌套函数,并且内层函数使用外层函数的变量
def inner():
print("开始记录日志")
fn() #调用外层函数里的参数,就是调用函数
print("日志记录完毕")
return inner #返回内层函数的地址
@outer #@闭包名称,就是一个装饰器
def login():
#在稳定运行的代码上,不应该修改代码,违背了OCP原则
print("登录账号")
login()
结果如下:
开始记录日志
登录账号
日志记录完毕
一个简单的装饰器的运行原理:
1.调用login()函数时,则会先从@outer这个装饰器开始执行,跳到outer这个外层函数,
并且将login()函数的内存地址传到outer()函数的形参中
2.接下来,outer()函数返回一个值,这个值是inner()函数的地址,
就会把这个返回值返回到login()函数,也就意味着先前调用的login()函数调用的是inner()函数
3.之后,调用了inner()函数,执行里面的代码,随之,将outer()函数的形参拿到的地址,
使用地址加括号的方法去调用login()函数,去完成login()函数里面的代码。
5.装饰器的扩展应用
1.一个没有使用闭包的装饰器的应用
def test(fn): #没有闭包也可以用装饰器但是不合理
print("test")
fn()
@test #代码会从@test这里开始执行,并且闭包里没有返回值的不用去调用函数代码,这样的话也就可以运行
def a():
print("a")
结果如下:
test
a
2.如果被装饰的函数存在参数,要在里面的函数中传递
def outer(fn):
def record(name,password):
print("开始记录日志")
fn(name,password)
print("日志记录完毕")
return record
@outer
def login(name,password):
#在稳定运行的代码上,不应该修改代码,违背了OCP原则
print("{}用户正在使用{}密码登录账号".format(name,password))
print("登录账号成功")
login("haha","123456")
结果如下:
开始记录日志
haha用户组正在使用123456密码登录账号
登陆账号成功
日志记录完毕
3.一个装饰器可以装饰多个函数,那么整体程序里面的这些装饰器从上至下执行
4.一个被装饰的函数,可以被多个装饰器装饰,那么整体程序里面的这个被装饰的函数的多个装饰器从上至下执行
6.装饰器功能
引入日志、函数执行时间统计、执行函数前预备处理、执行函数后清理功能、权限校验等场景、异常的处理、缓存