python 基础 07 装饰器
2020-04-15 本文已影响0人
a王义山a
python 基础 07
1. 装饰器
#装饰器:在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。
#开放封闭原则:
#开放:对代码的扩展是开放的
#封闭:对源码的修改是封闭的
#装饰器:完全遵守开放封闭原则
#装饰器就是一个函数,他的功能就是为另一个函数添加新的功能,但是不能改变
#那个函数的调用方式
#装饰器的本质就是闭包
#版本一:写一些代码测试 index 函数的执行效率
#但是,如果想要测试另一个函数,就得再写一个一遍,不好
def index():
'''省略一堆代码''' #模拟网路延迟
time.sleep(2)
print('欢迎登陆博客园')
def dairy():
time.sleep(2)
print('欢迎来到b站')
import time
print(time.time()) #这一刻的格林威治时间
start_time=time.time()
index()
end_time = time.time()
print(end_time-start_time) #这个就测出了函数执行的时间
start_time=time.time()
dairy()
end_time = time.time()
print(end_time-start_time) #这个就测出了函数执行的时间
#版本二:利用函数解决代码重复使用问题
#这个版本的问题:这么写,确实没改变源码,而且给 原函数增加了新功能,
#但是我们改变了原函数的调用方式
def timmer(f):
start_time = time.time()
f()
end_time = time.time()
print(f'测试函数执行效率:{end_time - start_time}')
timmer(index)
#版本三:不能改变原函数的调用方式
def timmer2(f): # 这个函数就是装饰器了,但是不是终极形态
def inner():
start_time = time.time()
f() #index()
end_time = time.time()
print(f'测试函数执行效率:{end_time - start_time}')
return inner
# ret = timmer2(index) #inner
# ret() #inner()
index = timmer2(index) #inner
index() #inner() 这就按照原来的方式调用了原函数,而且为其增加了执行效率功能
#版本四:装饰器,python做优化,叫做语法糖
import time
def timmer2(f): #装饰器函数一定要写在被装饰函数前边
def inner():
start_time = time.time()
f() #index()
end_time = time.time()
print(f'测试函数执行效率:{end_time - start_time}')
return inner
@timmer2 #在被装饰函数前边,写个这个,就可为下边函数增加功能了
def index():
'''省略一堆代码''' #模拟网路延迟
time.sleep(0.6)
print('欢迎登陆博客园')
index()
def dairy(): #这个函数定义的时候没有在前边写装饰器的语法糖,所以没有附加功能
time.sleep(0.6)
print('欢迎来到b站')
dairy()
#版本六:被装饰函数带返回值.装饰器不应该改变原函数的返回值
import time
def timmer2(f): #装饰器函数一定要写在被装饰函数前边
def inner():
start_time = time.time()
print(f'真正的index()返回值位置:{f()}') #index()
end_time = time.time()
print(f'测试函数执行效率:{end_time - start_time}')
return inner
@timmer2 #在被装饰函数前边,写个这个,就可为下边函数增加功能了
def index():
'''省略一堆代码''' #模拟网路延迟
time.sleep(0.6)
print('欢迎登陆博客园')
return 666
ret=index()
#这里,index()实际上就是 timmer2装饰器里的inner()
#当真正的 index() 函数有返回值的时候,这个返回值其实
#没有被返回给 ret ,而是停留在 inner() 函数里边的 f()上
#所以要想把 index() 函数的返回值正经赋给 ret,还得在装饰器里
#加上一步返回值步骤
#上一步给 ret 的赋值,实际上是赋值的 inner()的返回值,但是
#inner()没有返回值。所以就啥都没有赋值
print(ret) #None ,赋值没成功,所以这里打印就是none
#版本七:解决装饰器会改变被装饰函数返回值的问题
import time
def timmer2(f): #装饰器函数一定要写在被装饰函数前边
def inner():
start_time = time.time()
r = f() #index()
end_time = time.time()
print(f'测试函数执行效率:{end_time - start_time}')
return r
return inner
@timmer2 #在被装饰函数前边,写个这个,就可为下边函数增加功能了
def index():
'''省略一堆代码''' #模拟网路延迟
time.sleep(0.6)
print('欢迎登陆博客园')
return 666
ret=index()
print(ret)
#版本八:当被装饰函数有参数
import time
def timmer2(f): #装饰器函数一定要写在被装饰函数前边
def inner(*args,**kwargs):
#函数定义时,*args,**kwargs,将参数聚合
start_time = time.time()
r = f(*args,**kwargs) #index()
#函数调用h时,*args,**kwargs,将参数打散
end_time = time.time()
print(f'测试函数执行效率:{end_time - start_time}')
return r
return inner
@timmer2 #在被装饰函数前边,写个这个,就可为下边函数增加功能了
def index(name):
'''省略一堆代码''' #模拟网路延迟
time.sleep(0.6)
print(f'欢迎{name}登陆博客园')
return 666
ret=index('fallen')
print(ret)
@timmer2
def dairy(name,age):
time.sleep(0.5)
print(f'欢迎{age}岁{name}来到b站')
dairy('fallen',18)
'''
********************
重要
********************
'''
#标准的装饰器函数定义
def wrapper(f):
def inner(*args,**kwargs):
'''
在这里添加额外的功能
执行被装饰函数之前的操作
'''
ret = f(*args,**kwargs)
'''
在这里添加额外的功能
执行被装饰函数之后的操作
'''
return ret
return inner