1.装饰器定义
把一个函数当作参数,返回一个替代版的函数
本质上就是一个返回函数的函数
作用:在不改变原函数的基础上,给函数增加功能
2.装饰器的功能
案例一:
装饰器的使用
案例二:
使用装饰器给函数增添新的功,在已经写好的函数上添加新内容
案例三:
装饰器传入参数
案例四:
装饰器设置可变参数
案例五:
装饰器可以设置关键字参数
3. 装饰器的实际应用
案例一:
装饰器实现一个函数计时器
import time 时间模块(import time)
import functools 用于高阶函数:指那些作用于函数或者返回其它函数的函数,通常只要是可以被当做函数调用的对象就是这个模块的目标
def timetest(fun):
"""这是一个装饰器"""
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print('运行时间:是%.6f' % (end_time - start_time))
return res 返回值
return wrapper
@timetest
def fun_list(n):
"""这是一个fun_list函数"""
return [2 *i for i in range(n)] 列表生成式
@timetest
def fun_map(n):
"""这是一个fun_map函数"""
return list(map(lambda x:x*2,range(n))) 匿名函数
print(fun_list(1000))
print(fun_map(1000)
案例二:
创建装饰器, 要求如下:
1.创建add_log装饰器, 被装饰的函数打印日志信息;
2.日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回 值结果:xxx
import time
import functools
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print('[%s]函数名:%s运行时间:%.6f,运行返回值结果:%d'
% (time.ctime(), fun.__name__, end_time - start_time, res))
return res
return wrapper
@add_log
def add(x,y):
time.sleep(1) #time.sleep()函数推迟调用线程的运行,可通过参数secs指秒数,表示进程挂起的时间语法格式:time.sleep(t)
return x + y
add(1,5)
案例三:
编写装饰器required_types, 条件如下:
- 当装饰器为@required_types(int,float)确保函数接收到的每一>个参数都是int或者float类型;
- 当装饰器为@required_types(list)确保函数接收到的每一个参数 都是list类型;
- 当装饰器为@required_types(str,int)确保函数接收到的每一个>参数都是str或者int类型;
- 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类型
sinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
isinstance() 与 type() 区别:
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 isinstance()。
isinstance(object, classinfo)
import functools
def required_types(*kind): #最外面定义一个装饰器 *kind表示接受多个元素
def required(fun): #里面的装饰器
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(i,kind): #sinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()
print('TypeError:参数必须为%s,%s类型' %kind)
exit()
else:
res = fun(*args,**kwargs)
return res
return wrapper
return required
@required_types(float,float) #调用最外层函数float浮点型,表示有小数点的数值整型
def add(x,y):
return x+y
print(add(1.2,2.3))
print(add(1,3.5))
4. 多个装饰器执行顺序
先调用那个装饰器,那个就先运行
def decorator_a(fun): #第一个装饰器
def inner_a(*args,**kwargs):
print('get in inner_a')
return fun(*args,**kwargs)
return inner_a
def decortor_b(fun): #第二个装饰器
def inner_b(*args,**kwargs):
print('get in inner_b')
return fun(*args,**kwargs)
return inner_b
@decorator_a #先调用那个装饰器,那个就先运行
@decortor_b
def f(x):
print('get in f')
return x*3
f(1)
@decortor_b
@decorator_a
def f(x):
print('get in f')
return x*3
f(1)