数据设计程序-装饰者模式
问题: 我们生活在海量的数据库中,如何高效梳理和归纳我们接触到的数据?
解决办法: 通过数据设计一个可靠的设计, 既有输入、又有过程的函数、最后获得响应目的的数据
案例: 装饰者模式的运用
1. 思路及想法
- 执行某个函数f,插入某段代码g,不影响函数f,但是显示出代码g的结果 函数f指的就是foo和bar等(在我们数据设计程序世界里面,函数是最小单元)
def foo():
print('foo.....')
time.sleep(2)
print(f"end-start: {end-start}")
foo()
def bar():
print('bar .....')
time.sleep(1)
print(f"end-start: {end-start}")
bar()
我们希望添加的插入代码块g如下,即增加计时器或者其他logger切面功能
start=time.time()
print('foo.....')
time.sleep(2)
end=time.time()
print(f"end-start: {end-start}")
start=time.time()
print('bar .....')
time.sleep(1)
end=time.time()
print(f"end-start: {end-start}")
2. 初始解决方案
我们出发点认为所有函数是first class对象,这样就可以把函数当做变量来对象。
有了这个出发点,咱们就可以设计我们的解决方案
- 新建一个showTime函数,函数f作为变量
- 调用showTime函数,把函数f传入作为输入变量,得到我们想要的结果.
## <2022-01-16 22:13>测试通过
def showTime(f):
start=time.time()
f()
end=time.time()
print(f"end-start: {end-start}")
def fooUpdate():
print('fooUpdate.....')
time.sleep(2)
def barUpdate():
print('barupdate.....')
time.sleep(1)
showTime(fooUpdate)
showTime(barUpdate)
存在问题:你改变了之前很多业务员的代码习惯,必须调用showTime了(不满足我们初始的思路)
3. 解决showTime的缺点
## <2022-01-16 22:12> 测试通过
def foo():
print("fooo ......")
time.sleep(1)
def showTime(f):
def inner():
start= time.time()
f()
end= time.time()
print(f"end-start: {end-start}")
return inner
foo =showTime(foo)
foo()
上面基本解决了我们的想法,但是写法不太友好,python引入了注解写法,更为简洁,如下所示: 即_注解等效于调用了一次外部程序。
## <2022-01-16 22:12> 测试通过
def showTime(f):
def inner():
start= time.time()
f()
end= time.time()
print(f"end-start: {end-start}")
return inner
@showTime ## 等价于foo=showTime(foo)
def foo():
print("fooo ......")
time.sleep(1)
# foo =showTime(foo) ## 等价于@showTime
foo()
但是上面解决的仅仅是无参函数,如果我们的函数f有很多参数? 即add1
def add1(*a, **b):
sums=0
for i in a:
sums=sums+i
print(sums)
time.sleep(1)
print(f"a= {a} , b={b}")
add1(1,2,3,4,hf=3,hfd=4)
4. 多参数解决方案改进
- 通过引入一个wrapper函数,考虑args和kwargs来解决多常数问题
def showtime(func):
def wrapper(*args,**kwargs):
start=time.time()
func(*args,**kwargs)
end=time.time()
print(f"end-start is {end-start}")
if flag==2:
print("已将上述操作操作录入文件")
return wrapper
return showtime
## <2022-01-16 22:12> 测试通过
## 多参数解决方法
def showtime1(func):
def wrapper(*args,**kwargs):
start=time.time()
func(*args,**kwargs)
end=time.time()
print(f"end-start is {end-start}")
return wrapper
@showtime1
def add(*a,**b):
time.sleep(1)
sum=0
for i in a:
sum+=i
print(f"sum of {a} is equal to {sum}")
add(1,2,3,5,6)
上面还有个缺陷,如果我的showtime1有参数? 即比如@showtime1(authtype=‘local’) 我的日志可能是网络记录、本地记录或者其他方式,该如何解决?
5. 日志参数解决方法
-
思路: 再增加一层函数,考虑参数authtype,并返回showtime函数
## <2022-01-16 22:15> 测试通过 import time def logger(flag=1): def showtime(func): def wrapper(*args,**kwargs): start=time.time() func(*args,**kwargs) end=time.time() print(f"end-start is {end-start}") if flag==2: print("已将上述操作操作录入文件") return wrapper return showtime @logger(flag=2) def add(*a,**b): time.sleep(1) sum=0 for i in a: sum+=i print(f"sum of {a} is equal to {sum}") add(1,2,3,4)
至此,我们完成了一种完美的添加时间的日志记录功能,支持初始函数的多参数功能,支持日志记录的参数类型指定,三层函数嵌套实现装饰者模式。
6. 案例1 网站登录功能(无多参数功能)
user="yzl"
passwd='123'
loginStatus=False
def login1(authtype):
if loginStatus == False:
def wrapper(f):
print(f"authtype is {authtype}")
if authtype=="jingdong":
username = input("input your Username:")
password = input("input your Password:")
if( username == user and password == passwd):
print("welcome to Jd")
login_Status=True
elif authtype=="weixin":
username = input("input your Username:")
password = input("input your Password:")
if( username == user and password == passwd):
print("welcome to Jd")
login_Status=True
else:
print("无效")
return wrapper
else:
pass
@login1(authtype="jingdong")
def home():
print("欢迎来到主界面")
@login1(authtype="weixin")
def finance():
print("欢迎来到经融界面") ## 登录完了 就应该具备记录登录状态功能,不需要重复输入,也就是单点登录功能
@login1(authtype="weixin")
def manager():
print("欢迎来到管理界面") ## 登录完了 就应该具备记录登录状态功能,不需要重复输入,也就是单点登录功能
Related