装饰器:用来拓展原函数的功能,在不改变原函数的情况下,给函数增加新的功能。
特点:装饰器的返回值是一个函数,是内嵌函数的函数。
它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。
import time
def deco(f):
def wrapper():
start_time = time.time()
f()
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" %execution_time )
return wrapper
@deco #装饰器,相当于 f=deco(f)
def f():
print("hello")
time.sleep(1)
print("world")
f()
#输出结果:
hello
world
time is 1000 ms
deco是一个装饰器,它的参数是一个函数,返回值也是一个函数。其中作为参数的函数f()在内嵌函数wrapper()内部执行。
内嵌函数wrapper()可以有固定参数和不固定参数。
例如:def wrapper(a,b)中a,b为固定参数;
def wrapper(*args, **kwargs)为无固定参数,在f2()中指定具体参数。
PS:*args 用来将参数打包成tuple给函数体调用;
**kwargs 用来将参数打包成dict给函数体调用
import time
def deco(f):
def wrapper(*args, **kwargs):
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execution_time= (end_time - start_time)*1000
print("time is %d ms" %execution_time)
return wrapper
@deco
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b))
@deco
def f2(a,b,c):
print("be on")
time.sleep(1)
print("result is %d" %(a+b+c))
f2(3,4,5)
f(3,4)
可以使用多个装饰器,装饰同一个函数。
比如定义两个装饰器deco1,deco2,然后@语法糖声明顺序为@deco1,@deco2,但是装饰器的调用顺序是相反的,即 “f = deco1(deco2(f))”。
import time
def deco1(f):
def wrapper(*args, **kwargs):
print("this is deco01")
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" % execution_time)
print("deco1 end here")
return wrapper
def deco2(f):
def wrapper(*args, **kwargs):
print("this is deco02")
f(*args, **kwargs)
print("deco2 end here")
return wrapper
@deco1
@deco2
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b))
f(3,4)
#输出结果:
this is deco01
this is deco02
be on
result is 7
deco2 end here
time is 1000 ms
deco1 end here