1. 装饰器开篇_time模块
范例1:
time.sleep():让程序在执行到这个位置的时候停一会儿
import time
time.sleep(5)
print("哇咔咔")
执行结果:
# 先停5秒
哇咔咔
范例2:
time.time():获取当前时间(从1970年到现在的总秒数)
import time
print(time.time())
执行结果:
1539995896.847099
范例3:
统计代码执行的时间
import time
def func():
start = time.time()
print("世界大同")
time.sleep(0.01)
end = time.time()
print(end-start)
func()
执行结果
世界大同
0.010123491287231445
范例4.1:
将范例3函数内的时间与打印分开,各自独立成一个函数
import time
def timer(f): # 计算函数执行的时间
start = time.time()
f()
end = time.time()
print(end-start)
def func():
time.sleep(0.01)
print("世界大同")
timer(func)
执行结果
世界大同
0.010216474533081055
范例4.2:
同范例4.1,容易理解的方式
import time
def func():
time.sleep(0.01)
print("世界大同")
def timer():
start = time.time()
func()
end = time.time()
print(end-start)
timer()
执行结果:
世界大同
0.010337352752685547
范例5:
进一步优化范例4
import time
def func(): # 第一步
time.sleep(0.01) # 第十步
print("世界大同") # 第十一步
def timer(f): # 第二步:f为func的内存地址 # 装饰器函数
def inner(): # 第四步
start = time.time() # 第八步
f() # 第九步 # 被装饰的函数
end = time.time() # 第十二步
print(end-start) # 第十三步
return inner # 第五步
func = timer(func) # 第三步:等号右边 # 第六步:等号左边
func() # 第七步:执行inner()
执行结果
世界大同
0.01023554801940918
1.1 装饰器的作用
装饰器的作用 —— 不想修改函数的调用方式 但是还想在原来的函数前后添加功能
timmer
就是一个装饰器函数,只是对一个函数有一些装饰作用。
2 语法糖
import time
def timer(f): # 装饰器函数
def inner():
start = time.time()
f() # 被装饰的函数
end = time.time()
print(end-start)
return inner
@timer # 语法糖 @装饰器函数名
def func(): # 被装饰的函数
time.sleep(0.01)
print("世界大同")
#func = timer(func) # 被语法糖代替
func()
执行结果
世界大同
0.010994911193847656
3 取得被装饰函数的返回值
import time
def timer(f): # 装饰器函数
def inner():
start = time.time()
ret = f() # 被装饰的函数
end = time.time()
print(end-start)
return ret
return inner
@timer # 语法糖
def func():
time.sleep(0.01)
print("世界大同")
return "新年好"
#func = timer(func) # 被语法糖代替
ret = func()
print(ret)
执行结果
世界大同
0.010995149612426758
新年好
4 装饰带一个参数函数的装饰器
范例:
import time
def timer(f): # 装饰器函数
def inner(a):
start = time.time()
ret = f(a) # 被装饰的函数
end = time.time()
print(end-start)
return ret
return inner
@timer # 语法糖
def func(a):
time.sleep(0.01)
print("世界大同",a)
return "新年好"
#func = timer(func) # 被语法糖代替
ret = func(1)
print(ret)
执行结果
世界大同 1
0.010066032409667969
新年好
5 装饰带万能参数函数的装饰器
范例:
import time
def timer(f): # 装饰器函数
def inner(*args,**kwargs):
start = time.time()
ret = f(*args,**kwargs) # 被装饰的函数
end = time.time()
print(end-start)
return ret
return inner
@timer # 语法糖
def func(a,b):
time.sleep(0.01)
print("世界大同",a,b)
return "新年好"
@timer # 语法糖
def func1(a):
time.sleep(0.01)
print("世界大同",a)
return "新年好"
#func = timer(func) # 被语法糖代替
ret = func(1,2)
ret = func(1,b = 2)
print(ret)
执行结果
世界大同 1 2
0.010993003845214844
世界大同 1 2
0.010015010833740234
新年好
6 装饰器的固定格式
详解:
def wrapper(f): #装饰器函数,f是被装饰的函数
def inner(*args,**kwargs):
'''在被装饰函数之前要做的事'''
ret = f(*args,**kwargs) #被装饰的函数
'''在被装饰函数之后要做的事'''
return ret
return inner
@wrapper #语法糖 @装饰器函数名
def func(a,b): #被装饰的函数
time.sleep(0.01)
print('老板好同事好大家好',a,b)
return '新年好'
粗解:
def wrapper(func): #qqxing
def inner(*args,**kwargs):
ret = func(*args,**kwargs) #被装饰的函数
return ret
return inner
@wrapper #qqxing = wrapper(qqxing)
def qqxing():
print(123)
ret = qqxing() #inner
复习时的例子:
def wrapper(func): # 第一步
def inner(*args,**kwargs): # 第三步
print('在被装饰的函数执行之前做的事') # 第七步
ret = func(*args,**kwargs)# 第八步 等号右边:holiday(*(3),**{}) # 第十一步:等号左边,接收了第十步的返回值
print('在被装饰的函数执行之后做的事') # 第十二步
return ret # 第十三步
return inner # 第四步
@wrapper #holiday = wrapper(holiday) # 第二步:执行等号右边 # 第五步:等号左边,此时的holiday就等于inner
def holiday(day):
print('全体放假%s天'%day) # 第九步
return '好开心' # 第十步
ret = holiday(3) # 第六步:等号右边 inner(3) # 第十四步,接收第十三步的返回值
print(ret) # 第十五步
执行结果:
在被装饰的函数执行之前做的事
全体放假3天
好开心
在被装饰的函数执行之后做的事
另一个说明:
def outer(*args): # 接收 聚合
print(args)
print(*args) # 调用 打散
def inner(*args): # 接收 聚合
print('inner : ',args)
inner(*args) # 调用 打散
outer(1,2,3,4) #==outer(*[1,2,3,4]) #==outer(*(1,2,3,4))
7 查看函数信息的方法
7.1 查看字符串格式的函数名
范例:_name_
def wahaha():
print("哇咔咔")
print(wahaha.__name__)
执行结果
wahaha
7.2 查看函数内的注释文档
范例:_doc_
def wahaha():
"""
一个打印哇哈哈的函数
:return:
"""
print("哇咔咔")
print(wahaha.__doc__)
执行结果
一个打印哇哈哈的函数
:return:
7.3 装饰器:wraps
@wraps
接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
范例1:未使用@wraps
#from functools import wraps
def wrapper(func): #func = holiday
#@wraps(func)
def inner(*args,**kwargs):
print('在被装饰的函数执行之前做的事')
ret = func(*args,**kwargs)
print('在被装饰的函数执行之后做的事')
return ret
return inner
@wrapper #holiday = wrapper(holiday)
def holiday(day):
'''这是一个放假通知'''
print('全体放假%s天'%day)
return '好开心'
print(holiday.__name__)
执行结果
inner
范例2:使用@wraps
from functools import wraps
def wrapper(func): #func = holiday
@wraps(func) # 加在最内层函数正上方
def inner(*args,**kwargs):
print('在被装饰的函数执行之前做的事')
ret = func(*args,**kwargs)
print('在被装饰的函数执行之后做的事')
return ret
return inner
@wrapper #holiday = wrapper(holiday)
def holiday(day):
'''这是一个放假通知'''
print('全体放假%s天'%day)
return '好开心'
print(holiday.__name__)
print(holiday.__doc__)
ret = holiday(3) #inner
print(ret)
执行结果
holiday
这是一个放假通知
在被装饰的函数执行之前做的事
全体放假3天
在被装饰的函数执行之后做的事
好开心
8 带参数的装饰器(三层函数)
范例1.1:给装饰器一个控制开关(开)
import time
FLAGE = True
def timmer_out(flag):
def timmer(func):
def inner(*args,**kwargs):
if flag:
start = time.time()
ret = func(*args,**kwargs)
end = time.time()
print(end-start)
return ret
else:
ret = func(*args, **kwargs)
return ret
return inner
return timmer
# 第二种理解 timmer = timmer_out(FLAGE)
@timmer_out(FLAGE) # 第一种理解 timmer_out(FLAG) == timmer @timmer == wahaha = timmer(wahaha)
def wahaha():
time.sleep(0.1)
print('wahahahahahaha')
@timmer_out(FLAGE)
def erguotou():
time.sleep(0.1)
print('erguotoutoutou')
wahaha()
erguotou()
执行结果:
wahahahahahaha
0.10094094276428223
erguotoutoutou
0.10099601745605469
范例1.2:给装饰器一个控制开关(关)
# 关
import time
FLAGE = False
def timmer_out(flag):
def timmer(func):
def inner(*args,**kwargs):
if flag:
start = time.time()
ret = func(*args,**kwargs)
end = time.time()
print(end-start)
return ret
else:
ret = func(*args, **kwargs)
return ret
return inner
return timmer
# timmer = timmer_out(FLAGE)
@timmer_out(FLAGE)
def wahaha():
time.sleep(0.1)
print('wahahahahahaha')
@timmer_out(FLAGE)
def erguotou():
time.sleep(0.1)
print('erguotoutoutou')
wahaha()
erguotou()
执行结果:
wahahahahahaha
erguotoutoutou
9 多个装饰器装饰一个函数
双层装饰器可用于:
1.1 记录用户的登录情况
1.2 计算这个函数的执行时间
范例1.1:双层装饰器1
def wrapper1(func): # 第一步 # 第三之后 func -> f
def inner1(): # 第四步
print('wrapper1 ,before func') # 第十五步 # 第二执行
func() # 第十六步 f()
print('wrapper1 ,after func') # 第十八步 # 第四执行
return inner1 # 第五步
def wrapper2(func): # 第二步 # 第七步之后 func --> inner1
def inner2(): # 第八步
print('wrapper2 ,before func') # 第十三步 # 第一执行
func() # 第十四步 inner1()
print('wrapper2 ,after func') # 第十九部 # 第五执行
return inner2 # 第九步
@wrapper2 # 第七步 f = wrapper2(f) wrapper(inner1) # 第十步 f = wrapper2(f) wrapper(inner1) = inner2
@wrapper1 # 第三步 f = wrapper1(f) # 第六步 f = wrapper1(f) = inner1
def f():
print('in f') # 第十七步 # 第三执行
f() # 第十一步 执行了inner2()
执行结果
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
范例1.2:双层装饰器2
def wrapper1(func):
def inner1():
print('wrapper1 ,before func') # 第一执行
func()
print('wrapper1 ,after func') # 第五执行
return inner1
def wrapper2(func):
def inner2():
print('wrapper2 ,before func') # 第二执行
func()
print('wrapper2 ,after func') # 第四执行
return inner2
@wrapper1
@wrapper2
def f():
print('in f') # 第三执行
f()
执行结果:
wrapper1 ,before func
wrapper2 ,before func
in f
wrapper2 ,after func
wrapper1 ,after func
范例2:三层装饰器
def wrapper1(func):
def inner1():
print('wrapper1 ,before func')
ret = func()
print('wrapper1 ,after func')
return ret
return inner1
def wrapper2(func):
def inner2():
print('wrapper2 ,before func')
ret = func()
print('wrapper2 ,after func')
return ret
return inner2
def wrapper3(func):
def inner3():
print('wrapper3 ,before func')
ret = func()
print('wrapper3 ,after func')
return ret
return inner3
@wrapper3
@wrapper2
@wrapper1 # f = wra
def f():
print('in f')
return '哈哈哈'
print(f())
执行结果
wrapper3 ,before func
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
wrapper3 ,after func
哈哈哈