- 装饰器本质
装饰器本质就是一个修饰其他函数的函数,为其他函数添加附加功能
- 装饰器要把握的2个原则
1.不修改被修饰函数的源代码
2.不修改被修饰函数的调用方式
- 装饰器的实现
装饰器 = 高阶函数+函数嵌套+闭包
满足下面任何一个条件都是高阶函数:
(1)函数接收的参数是一盒函数名
(2)函数的返回值是一个函数名
函数嵌套:父函数里面还有子函数
闭包:作用域的一种体现,一层套一层(一层一个函数),给最外层传一个参数,可以一直渗透到最里层
- 只用高阶函数例子:给函数加上统计运行时间的功能
# 方式一:修改了调用方式
import time
def foo():
print("你好")
def test(func):
start_time = time.time()
print(func)
func()
stop_time = time.time()
print("函数%s的运行时间为%s;但是函数调用方式从foo()变成了test(foo)" % (func.__name__, stop_time-start_time))
test(foo)
# 方式二:虽然没有修改调用方式,但是foo1函数被调用了两次func
import time
def foo1():
print("你好")
def test1(func):
start_time = time.time()
print(func)
func()
stop_time = time.time()
print("函数%s的运行时间为%s;但是函数调用方式从foo()变成了test(foo)" % (func.__name__, stop_time-start_time))
return func
foo1 = test1(foo1)
foo1()
- 高阶函数+函数嵌套实现基本的装饰器架子
# 装饰器架子
def func():
pass
def timmer(func):
def wrapper():
# 函数执行前操作
func()
# 函数执行后操作
return wrapper
func = timmer(func)
func()
- 高阶函数+函数嵌套实现基本的装饰器:给函数加上统计运行时间的功能
import time
def func():
print("in func")
time.sleep(2)
def timmer(func):
def wrapper():
start_time = time.time()
func()
stop_time = time.time()
print("函数%s的运行时间为%s;但是函数调用方式从foo()变成了test(foo)" % (func.__name__, stop_time-start_time))
return wrapper
func = timmer(func) # 这一句等价于在func定义上面加上@time
func()
- 装饰器优化:带参数和返回值的装饰器
'''
func = timmer(func)
func(1,2,3)
func=timmer(func)的返回值是wrapper函数,给func加参数等价于给wrapper加参数
所以func(*args, **kwargs) => wrapper(*args, **kwargs)
func的返回值要在wrapper中接收一下,再return回去
'''
def timmer(func):
# 函数嵌套
def wrapper(*args, **kwargs):
start_time = time.time()
print(func)
res = func(*args, **kwargs) # 参数+返回值
stop_time = time.time()
print("%s函数运行时间为%s" % (func.__name__, stop_time-start_time))
return res
return wrapper # 高阶函数
def func(*args, **kwargs):
time.sleep(1)
print(args, kwargs)
print("in func")
func = timmer(func)
res = func(1,2,3)
print(res)
- 修改成@的方式
def timmer(func):
# 函数嵌套
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
duration = stop_time-start_time
print("%s函数运行时间为%s" % (func.__name__, duration))
return res
return wrapper # 高阶函数
@timmer # 等价于 func = timmer(func)
def func(*args, **kwargs):
time.sleep(1)
print("in func")
print(args, kwargs)
return (args, kwargs)
print(func(1, 2, 3))
- 带参数的装饰器–实现认证类型选择
def auth(auth_type="file_auth"):
def dec_auth(func):
def wrapper(*args, **kwargs):
# 验证功能
print("你输入的认证类型是%s" % auth_type)
username = input("用户名:").strip()
passwd = input("密码:").strip()
if username == "root" and passwd == "123":
res = func(*args, **kwargs)
return res
else:
print("用户名密码错误")
return wrapper
return dec_auth
# 下面的过程分以下步骤
# (1) auth(auth_type="db_auth")=>dec_auth
# (2)@auth(auth_type="db_auth") ==》 car = auth(auth_type="db_auth")=dec_auth(car)
@auth(auth_type="db_auth")
def car(name):
print("欢迎来到%s的购物车"%name)
car("ybp")