python-装饰器
装饰器:
装饰器是一个闭包,把一个函数当作参数传递给另一个函数,返回一个替代版的函数(即返回值为函数对象)
本质上就是一个返回函数的函数
“在不改变原函数的基础上 给函数增加功能”
装饰器工作场景:插入日志、性能测试、事务处理等等。
函数被装饰器装饰过后,此函数的属性均已发生变化,如名称变为装饰器的名称。
python3支持用@符号直接将装饰器应用到函数
@装饰器函数名 ##语法糖
无参数的装饰器
被装饰的函数不带参数
编写装饰器,先定义装饰器名字,在定义装饰器的功能,最后返回该功能的函数名
import functools
@functools.wraps(func)
eg:
def my_decorator(func):
def inner():
print("**********")
print("要添加的功能代码")
func()
return inner
# script1()函数调用装饰器的第一种方法
def script1():
print("测试")
runScript1 = my_decorator(script1) # 运行script()函数的同时添加有my_decorator()函数的功能
runScript1()
# script1()函数调用装饰器的第二种方法:
使用@,简单明了
@my_decorator
def script1():
print("测试")
script1()
被装饰的函数带参数
可变参数args和关键字参数*kwargs添加函数通用的装饰器
def timeit(func):
#@functools.wraps(fun)
def wrapper(*args,**kwargs):# 接收可变参数和关键字参数
"""这是一个装饰器timeit"""
# 在函数执行之前
start_time = time.time()
# 执行函数
res = fun(*args,**kwargs)
# 在函数执行之后
stop_time = time.time()
print('运行时间为:%.6f' %(stop_time-start_time))
return res
return wrapper
有参数的装饰器
def log(kind):
def add_log(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs)
end_time = time.time()
print('<%s> [%s] 函数名:%s,运行时间:%.6f,运行返回值的结果'':%d' %(kind,time.ctime(),func.__name__,end_time-start_time,res))
return res
return wrapper
return add_log
@log('local2')
def add(x,y):
time.sleep(1)
return x+y
add(1,10)
##此处的参数也可以是个列表
多个装饰器装饰函数时
一般情况下,在函数中可以使用一个装饰器,但是有时也会有两个或两个以上的装饰器。多个装饰器装饰的顺序是从里到外(就近原则),而调用的顺序是从外到里(就远原则)。
eg:
def decorator_a(fun):
print('a')
def inner_a(*args,**kwargs):
print('Get in inner_a')
fun(*args,**kwargs)
return inner_a
def decorator_b(fun):
print('b')
def inner_b(*args,**kwargs):
print('Get in inner_b')
fun(*args,**kwargs)
return inner_b
@decorator_a
@decorator_b
def f(x):
print('Gat in f')
f(1)
结果:
b
a
Get in inner_a
Get in inner_b
Gat in f