一、OCP原则
OCP(open close protocol)开放关闭原则:对已有运行(稳定的)代码,不应该修改它。如果你增加新的功能,添加新的功能代码即可。
- 封闭:已实现的功能代码块
- 关闭对已有代码的修改
- 开放:对拓展开发
- 开放对已有代码的功能增加
-
原有功能
def login(): print("用户开始登录") #功能模块 print("用户登录成功") def reg(): print("注册用户") #功能模块 print("完成注册") login() reg() """ 结果: 用户开始登录 用户登录成功 注册用户 完成注册 """
-
在1的条件下,两个函数的功能正常运行。但是现在需求对这两个函数功能增加日志功能。如果直接在 def login() 代码块中直接添加日志功能,会违反OCP原则。
-
利用装饰器
def log(fn): def record(): print("开始记录日志") fn() #功能模块 print("日志记录结束") return record @log def login(): print("用户开始登录") #功能模块 print("用户登录成功") def reg(): print("注册用户") #功能模块 print("完成注册") login() #reg() """ 结果: 开始记录日志 用户开始登录 用户登录成功 日志记录结束 """
二、装饰器
2.1 什么是装饰器
装饰器就是一个闭包函数,他能够使用 @闭包名称 装饰一个原有的函数,使得原有函数的功能更加强大
2.2 如何定义装饰器
-
定义一个闭包函数,闭包有一个默认的参数,是一个引用。该引用就是需要装饰的函数
def log(fn): #闭包函数有参数fn,fn就是被装饰的函数。此处fn就是函数login def record(): print("开始记录日志") fn() #调用login函数 #功能模块 print("日志记录结束") return record @log def login(): print("用户开始登录") #功能模块 print("用户登录成功")
-
在闭包的内部函数中调用引用(函数)。在调用之前写的代码就会装饰在原函数之前,调动之后写的代码就会装饰在原函数之后。
2.3 参数问题
def record(fn):
# 如果装饰的函数存在了参数,请在闭包里面的函数中传递
def inner(name, password):
print("开始记录日志")
fn(name, password)
print("日志记录结束")
return inner
@record
def login(name, password):
print("{} --{} 用户要开始登录了".format(name, password))
print("登录成功率")
login("王", "123456")
"""
结果:
开始记录日志
王 --123456 用户要开始登录了
登录成功率
日志记录结束
"""
2.4 装饰器原理
def record(fn):
print("装饰器开始工作了")
# 如果装饰的函数存在了参数,请在闭包里面的函数中传递
def inner(name, password):
print("开始记录日志")
fn(name, password)
print("日志记录结束")
print("装饰器返回了")
return inner
@record #@符号有自动执行的功能,所以这是执行的第一行代码,下一行进入record函数
def login(name, password):
print("{} --{} 用户要开始登录了".format(name, password))
print("登录成功率")
login("王", "123456")
"""
结果:
装饰器开始工作了 #@符号的作用,自动执行record函数
装饰器返回了
开始记录日志 #执行login("王",“123456”)语句。调用login函数,此时login指向inner
王 --123456 用户要开始登录了
登录成功率
日志记录结束
"""