装饰器是一种功能,在原本的代码的运行基础上加上一些功能,比如权限设置,日志记录等等
需求:初创公司有N个业务部门,1个基本平台部门,基础平台负责提供底层的功能,如:数据库操
作,redis调用,监控API等功能。业务部门使用功能时,只需要调用基础平台提供的功能即可。如下:
#基础功能
def f1():
print("f1")
def f2():
print("f2")
def f3():
print("f3")
def f4():
print("f4")
#业务部门A调用平台提供的功能
f1() f2() f3() f4()
#业务部门B调用平台提供的功能
f1() f2() f3() f4()
目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写代码的时候没有关注验证相关的
问题,即:基础平台的提供功能可以被任何人使用。现在需要堆基础平台的而所有功能进行重构,为平
台提供的所有功能添加验证机制,即:执行功能前,先验证
老大把工作交给了lowB,他是这么做的:
跟每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证,这样一来基础
平台就不需要做任何修改了,有充足的时间去干其他的事情了…
老大又把工作交给了lowBB,他是这么做的:
#基础功能
def f1():
#验证1
#验证2
#验证3
print("f1")
def f2():
# 验证1
# 验证2
# 验证3
print("f2")
def f3():
# 验证1
# 验证2
# 验证3
print("f3")
def f4():
# 验证1
# 验证2
# 验证3
print("f4")
#业务部门A调用平台提供的功能
f1() f2() f3() f4()
#业务部门B调用平台提供的功能
f1() f2() f3() f4()
因为修改底层的代码需要很长的时间,过了一个周lowBB被开除了…因为花费的时间太长了,还没有完成工作
老大把工作交给了LowBBB,他是这么做的:
只对基础平台的代码进行了重构,其他业务部门无须做任何修改
#基础功能
def check_login():
# 验证1
# 验证2
# 验证3
pass
def f1():
check_login()
print("f1")
def f2():
check_login()
print("f2")
def f3():
check_login()
print("f3")
def f4():
check_login()
print("f4")
#业务部门A调用平台提供的功能
f1() f2() f3() f4()
#业务部门B调用平台提供的功能
f1() f2() f3() f4()
老大看了lowBBB的实现,最近露出了一丝欣慰的笑,语重心长的和他聊了天:
老大说:
写代码要遵从开放封闭原则(OCP),虽然这个原则是用的面向对象开发,但是也适用于函数式编
程,简单的来说,它规定已经实现的功能代码不允许被修改,但可以扩展,即:
封闭:已经实现的功能代码块
开放:对扩展开发
OCP原则:即开放关闭原则
对已有代码的修改关闭
对已有代码的增加开发
如果将开放封闭原则应用在上述需求中,那么不允许在函数f1,f2,f3,f4的内部进行修改代码,老大给
了lowBBB一个实现方案:
#基础功能
def w1(func):
def inner():
# 验证1
# 验证2
# 验证3
func()
return inner
@w1
def f1():
print("f1")
@w1
def f2():
print("f2")
@w1
def f3():
print("f3")
@w1
def f4():
print("f4")
#业务部门A调用平台提供的功能
f1() f2() f3() f4()
#业务部门B调用平台提供的功能
f1() f2() f3() f4()
对于上述代码,也是仅仅对基础平台的代码进行了修改,就可以实现在其他人调用函数f1,f2,f3,f4之前都进行验证,并且其他业务部门无需做任何操作
def outer(fn):
def record():
print("开始日记记录")
fn()
print("日志记录结束")
return record
@outer
def login():
# with open("log.log","w") as f:
# f.write("xxxxxxxxx")
print("用户开始登录")
print("用户登录成功")
@outer
def reg():
print("用户开始注册")
print("用户注册成功")
login() reg()
什么是装饰器?
就是一个闭包的函数的使用,它能够@闭包函数的名称装饰一个原有的函数,使得原本的函数功能更加完善
如何定义一个装饰器?
1.定义闭包函数,闭包函数有一个默认的参数,引用,引用的就是所要装饰的函数
2.需要在闭包里面的函数调用引用(fn()),在调用之前的代码会被在装饰的函数之前执行,之后的代码在被装饰的函数之后执行
def test(fn):
print("test")
fn()
@test
def a():
print("a")
上面代码没有用闭包
有参数的时候
# def test(fn):
# print("test")
# fn() ###
@test
# def a():
# print("a")
def record(fn):
def inner(username,password):
print("开始日记记录")
fn(username,password)
print("日志记录结束")
return inner
@record
def login(username,password):
print("{}----{}用户开始登录".format(username,password))
print("用户登录成功")
login("张三", "123456")
# def test(fn):
# print("test")
# fn()
### @test
# def a():
# print("a")
def record(fn):
print("装饰器开始工作")
def inner(username,password):
print("开始日记记录")
fn(username,password)
print("日志记录结束")
print("装饰器已经返回")
return inner
@record
def login(username,password):
print("{}----{}用户开始登录".format(username,password))
print("用户登录成功")
login("张三", "123456")