python之装饰器
一、开放封闭原则
1. 是什么?
开放原则
软件面试时不可能将所有功能都设计好,当前未来一两年的你需要的功能上线,定期更新迭代,对于软件之前写的源代码一般不会修改,对函数里面的代码以及函数的调用方式。在源码不改变的情况下,增加一些额外的功能。
封闭原则
不要改变源码
python中装饰器: 完美的诠释了开放封闭原则
2. 装饰器的用途
装饰器就是一个函数: 装饰器本身就是一个函数,他要装饰一个函数在不改变原函数的源码以及调用方式的前提下,给其增加一个额外的功能。
登录认证,打印日志
二、初识装饰器
装饰器格式:
def test_time(x):
def inner():
start_time = time.time()
x()
end_time = time.time()
print(end_time-start_time)
return inner
@test_time # index = test_time(index)
def index():
time.sleep(2)
print('欢迎访问博客园首页')
index()
例题:
# 1. 写一个代码测试怼怼哥写的函数的执行效率。
def index():
time.sleep(2)
print('欢迎访问博客园首页')
print(time.time())
start_time = time.time()
index()
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
# 2. 主管让你测试小邓,李大象,重复代码太多
def func1():
time.sleep(2)
print('欢迎访问日记首页')
def func2():
time.sleep(1)
print('欢迎访问评论首页')
start_time = time.time()
func1()
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
start_time = time.time()
func2()
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
# 3. 整合到函数中
def func1():
time.sleep(2)
print('欢迎访问日记首页')
def func2():
time.sleep(1)
print('欢迎访问评论首页')
def test_time(x):
start_time = time.time()
x()
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
test_time(func1)
test_time(func2)
# 4. 怼怼哥这个函数在实际项目中被500执行,主管要求:在被执行此函数时,
同时要测试一下被执行函数的效率。
def index():
time.sleep(2)
print('欢迎访问博客园首页')
# index()
def test_time(x):
start_time = time.time()
x()
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
test_time(index)
版本4的问题: 开放原则满足了,封闭原则:不改变原函数的源码,以及调用方式。
违反了封闭原则:改变了函数的调用方式。
# 版本5: 不能改变原函数的调用方式(闭包):
def index():
time.sleep(2)
print('欢迎访问博客园首页')
# index()
# def func1():
# time.sleep(2)
# print('欢迎访问日记首页')
def test_time(x): # x = index
def inner():
start_time = time.time()
x()
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
return inner
index = test_time(index)
index()
# 版本6:被装饰函数有返回值
def test_time(x): # x = index
def inner():
start_time = time.time()
ret = x()
# print(F'ret: {ret}')
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
return ret
return inner
@test_time # index = test_time(index)
def index():
time.sleep(0.5)
print('欢迎访问博客园首页')
return True
print(index()) # inner()
你应该是让True返回给index()这样才完美了,但是现在index是inner,所以你要是完全不改变原函数的使用,
你print(index()) ---> True
# 版本7: 被装饰函数带参数,无论加不加装饰器,你的实参'太白金星'应该传给形参n,。
但版本6不能实现传参,index('太白金星') == inner('太白金星')
def test_time(x): # x = index
def inner(*args,**kwargs):
# 函数的定义:* ** 聚合。
# args = ('苹果')
#args = (1, 3)
start_time = time.time()
ret = x(*args,**kwargs)
# 函数的执行:* ** 打散。
# ret = x(*('苹果')) ==x('苹果',)
# ret = x(*(1, 3)) ==x(1,3)
# print(F'ret: {ret}')
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
return ret
return inner
# @test_time # index = test_time(index)
def index(n):
time.sleep(0.5)
print(f'欢迎{n}访问博客园首页')
return True
# @test_time # index = test_time(index)
def func2(a,b):
time.sleep(0.5)
print(f'最终结果:{a+b}')
return a + b
print(index('苹果')) # inner('苹果')
print(func2(1,3)) # == inner(1,3)
def warpper(f):
def inner(*args,**kwargs):
'''被装饰函数之前的操作'''
# print(666)
ret = f(*args,**kwargs)
'''被装饰函数之后的操作'''
# print('执行完毕了')
return ret
return inner
@warpper
def func():
print(111)
#
func()
func()
func()
func()
func()
装饰器的应用:在不改变原函数的源码以及调用方式前提下,为其增加额外的功能。
登陆认证,打印日志等。
三、被装饰函数带返回值
带返回值是什么?
def test_time(x):
def inner():
start_time = time.time()
ret = x() # 我是新加的参数
end_time = time.time()
print(end_time-start_time)
return ret # 我是新加的参数
return inner
@test_time
def func1():
time.sleep(0.5)
print('欢迎登录博客园首页')
return True
print(func1())
带返回值的目的?
就是为满足开放封闭原则,使函数更完美
四、被装饰函数带参数
是什么?
函数在不加装饰器的情况下也是要能执行的,加装饰器要不改变原函数的代码
index('太白金星') == inner('太白金星')
def test_time(x): # x = index
def inner(*args,**kwargs):
# 函数的定义:* ** 聚合。
# args = ('苹果')
#args = (1, 3)
start_time = time.time()
ret = x(*args,**kwargs)
# 函数的执行:* ** 打散。
# ret = x(*('苹果')) ==x('苹果',)
# ret = x(*(1, 3)) ==x(1,3)
# print(F'ret: {ret}')
end_time = time.time()
print(f'此函数的执行效率{end_time-start_time}')
return ret
return inner
# @test_time # index = test_time(index)
def index(n):
time.sleep(0.5)
print(f'欢迎{n}访问博客园首页')
return True
# @test_time # index = test_time(index)
def func2(a,b):
time.sleep(0.5)
print(f'最终结果:{a+b}')
return a + b
print(index('苹果')) # inner('苹果')
print(func2(1,3)) # == inner(1,3)
怎么用?
五、标准版装饰器
是什么?
# 五行
def warpper(f): #定一个一个外层函数
def inner(*args,**wkargs): #定一个内层函数,支持传入参数,在定义时*起聚合的作用,在执行的时候**起打散的作用
ret = f(*args,**wkargs)
return ret
return inner