什么是装饰器
装饰器是指装饰的工具(函数),这个函数具有装饰作用.因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能.
注意: 装饰器本身其实是可以任意可调用的对象
被装饰的对象也可以是任意可调用的对象
装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B
装饰器的实现必须遵循两大原则:
- 不改变函数B的调用方式
- 不改变函数B的源代码
装饰器的使用
改变源代码
import time
def index():
start = time.time()
print('welcome to index')
time.sleep(1)
end = time.time()
print(start-end)
index()
welcome to index
-1.0000019073486328
编写重复代码
import time
def index():
print('welcome to index')
time.sleep(1)
def f2():
print('welcome to index')
time.sleep(1)
start = time.time()
index()
end = time.time()
print(start-end)
start = time.time()
f2()
end = time.time()
print(start-end)
welcome to index
-1.0004847049713135
welcome to index
-1.0000324249267578
第一种传参方式:改变调用方法
import time
def index():
print('welcome to index')
time.sleep(1)
def time_count(func):
start = time.time()
func()
end = time.time()
print(start-end)
time_count(index)
welcome to index
-1.0003643035888672
第二种传参方式:包给函数-外包
import time
def index():
print('welcome to index')
time.sleep(1)
def time_count(func):
# func = 最原始的index
def wrapper():
start = time.time()
func()
end = time.time()
print(start-end)
return wrapper
# f = time_count(index)
# f()
index = time_count(index) # index为被装饰函数的内存地址,即index = wrapper
index() # wrapper()
welcome to index
-1.0000269412994385
装饰器语法糖
在被装饰函数正上方,并且是单独一行写上@装饰器名
import time
def deco(func):
def f1(*args, **kwargs):
print('args:',args) # (10,)
print('kwargs:',kwargs)
start = time.time()
# *args = *(10,) 10
res = func(*args, **kwargs) # 真正的index()
end = time.time()
print(end - start)
return res
return f1
@deco # 语法糖(更精简的代码) index = deco(index)
def index(x, a=1):
print('x', x)
print('a', a)
print('hello index')
time.sleep(1)
return 123
#重新创建的index = deco(index真正的index)
index = deco(index) # index = f1
index(10) # f1(1)
args: (10,)
kwargs: {}
args: (10,)
kwargs: {}
x 10
a 1
hello index
1.00038743019104
1.00038743019104
三层装饰器
给双层装饰器加参数
# 判断账号密码来自于哪个地方
def auth(engine):
def login(func):
def inner(*args, **kwargs):
# 登录功能
if engine == 'file':
username = input('usrename:')
pwd = input('pwd:')
if username == 'nick' and pwd == '123':
print('登录成功')
res = func(*args, **kwargs) # shopping()
return res
else:
print('登录失败')
elif engine == 'db':
print('账号密码来自于数据库,非法请求')
return inner
return login
@auth('db')
def shopping():
print('shopping')
# login = auth('db') # login = login
# shopping = login(shopping) # shopping = inner
shopping() # inner()
装饰器模板
双层装饰器
def outter(func):
def inner(*args,**kwargs): #wrapp是未来要运行的函数
#加功能
res=func(*args,**kwargs) #func是被装饰的函数
return res
return inner
@outter
def shopping():
print(shopping)
三层装饰器
def sancneg(engine):
def outter(func):
def inner(*args, **kwargs): #wrapper是未来要运行的函数
# 加功能
print(engine)
res = func(*args, **kwargs) #func是被装饰的函数
return res
return inner
return outter
@sancneg('file')
def shopping():
print(shopping)