装饰器
装饰器
定义
在不改变函数的源码和调用方式的情况下,给函数加功能
装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B
- 不改变函数B的调用方式
- 不改变函数B的源代码
分类
双层装饰器
例如,函数world是一个完整的功能函数,想要给world函数增加一个程序运行时长的功能,但不改变world函数的源码和调用方式,如何实现呢?
这样,我们就可以用到装饰器了:
import time
def time_world(func): # func是真正的world
"""装饰函数"""
def add():
# 增加功能部分
t1 = time.time() # func() == world()
func()
t2 = time.time()
print(t2 - t1)
return add
def world():
"""被装饰函数"""
print('hello world!')
time.sleep(1)
world = time_world(time)
world() # 调用方式不变world(),实际是调用add()
"""
用语法糖来调用更简单
@time_world
def world():
"""被装饰函数"""
print('hello world!')
time.sleep(1)
world()
"""
三层装饰器
三层装饰器就是给双层装饰器加参数
例如,给shopping函数增加登录功能,并且传入登录方式变量,如果登录方式是file,则登录成功,如果是db,则登录非法。
因为涉及到传值,双层装饰器显然实现较为困难,因此,引入三层装饰器:
def three(gen):
def login(func):
def inner(*args,**kwargs): # 接收shopping传的所有值
if gen == 'file':
name = input('name:')
pwd = input('password:')
# 假定name,pwd固定
if name == 'wzh' and pwd == '123':
print('success!')
res = func(*args,**kwargs)
return res
else:
print('default')
elif gen == 'db':
print('登录非法!')
return inner
return login
@three('file')
def shopping():
print('shopping!')
shopping()
双层语法糖
执行顺序相关
# 双层语法糖
def outer1(func):
def inner(*args,**kwargs): # 接收index里的参数
"""功能模块"""
print('----------------')
res = func(*args,**kwargs)
print('----------------')
return res # 返回index里的参数
return inner
def outer2(func):
def inner(*args,**kwargs): # 接收index里的参数
"""功能模块"""
print('****************')
res = func(*args,**kwargs)
print('****************')
return res # 返回index里的参数
return inner
@outer1
@outer2
def f():
print('success')
f()
"""
----------------
****************
ssss
****************
----------------
"""
装饰器模板(重要)
# 双层装饰器
def two(func):
def two_inner(*args,**kwargs):
"""功能模块"""
res = func(*args,**kwargs)
return res
return inner
@two
def f():
pass
f()
# 三层装饰器
def three(value):
def two(func):
def innere(*args,**kwargs):
"""功能模块"""
print(value)
res = func(*args,**kwargs)
return res
return inner
return two
@three('shabi')
def f():
pass
f()