装饰器
Posted fanggege
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰器相关的知识,希望对你有一定的参考价值。
装饰器是什么
装饰器是让一个函数在执行的过程中它的前后去执行代码,在不改变原函数即原函数的调用的情况下,
为原函数增加一些额外的功能,打印日志,执行时间,登录认证等等。
最简单版的装饰器
在一个函数func1执行时计算它的执行时间,此处就可以定义一个装饰器函数timer,f1 就是要测试的函数作为timer 的参数引入并执行
import time
装饰器函数
def timer(f1): def inner(): start_time = time.time() f1() end_time = time.time() print(‘此函数的执行效率%s‘ %(end_time-start_time)) return inner
def func1():
print(‘晚上回去吃烧烤....‘)
time.sleep(0.3)
装饰被测试的函数
func1 = timer(func1) # func1 = inner
或
@timer #此方式相当于执行 func1 = timer(func1)
def func1():
print(‘晚上回去吃烧烤....‘)
time.sleep(0.3)
执行函数
func1() # inner()
被装饰的函数带参数
def timer(f1): # f1 = func1 def inner(*args,**kwargs): # 参数通过inner引入到f1 start_time = time.time() f1(*args,**kwargs) # func1() end_time = time.time() print(‘此函数的执行效率%s‘ %(end_time-start_time)) return inner @timer # func1 = timer(func1) inner def func1(a,b): print(a,b) print(‘这是被测试函数func1....‘) time.sleep(0.3) func1(111,222) # inner(111,222)
接收函数的返回值
def wrapper(f1): def inner(*args,**kwargs): ‘‘‘执行函数之前的操作‘‘‘ ret = f1(*args,**kwargs) #通过把函数的返回值赋值给ret,最后返回即可 ‘‘‘执行函数之后的操作‘‘‘ return ret return f1
@wrapper
def fun1(a,b):
return a,b #由于func1中通过return 返回值,想要获取结果必须在inner 中赋值给ret,把值传递到最外层执行者必须return ret
fun1(1,2)
注意事项
当一个函数被装饰器装饰后打印它的函数名,此时函数名已经发生了变化
#上面的示例中已经被装饰过的函数func1再打印它的函数名字时,名字变成了装饰器的名字inner
print(func1.__name__)
#output inner
#解决
from functools import wraps #引入wraps
def timer(f1):
@wraps(f1) #通过wraps装饰inner来解决此问题
def inner(*args,**kwargs):
start_time = time.time()
f1(*args,**kwargs)
end_time = time.time()
print(‘此函数的执行效率%s‘ %(end_time-start_time))
return inner
@timer # func1 = timer(func1) inner
def func1(a,b):
print(a,b)
print(‘这是被测试函数func1....‘)
time.sleep(0.3)
print(fun1.__name__)
#output fun1
使用场景
授权登陆/认证
from functools import wraps def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): #如果未进行认证或者认证失败那么重新认证 authenticate() return f(*args, **kwargs) #认证通过后才真正执行操作 return decorated
日志功能
from functools import wraps def logit(func): @wraps(func) def with_logging(*args, **kwargs): print(func.__name__ + " was called") #执行函数func打印日志 return func(*args, **kwargs) return with_logging @logit def addition_func(x): """Do some math.""" return x + x result = addition_func(4) # Output: addition_func was called
在函数中嵌入装饰器
通过在装饰器外层的函数传递参数给装饰器
from functools import wraps def logit(logfile=‘out.log‘): #指定日志记录的文件参数传递给装饰器 def logging_decorator(func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + " was called" print(log_string) # 打开logfile,并写入内容 with open(logfile, ‘a‘) as opened_file: # 现在将日志打到指定的logfile opened_file.write(log_string + ‘\n‘) return func(*args, **kwargs) return wrapped_function return logging_decorator #外层函数执行后,最后返回的是装饰器函数 @logit() #执行logit()得到的是装饰器函数logging_decorator,所以相当于@logging_decorator
def myfunc1():
pass
myfunc1()
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
@logit(logfile=‘func2.log‘)
def myfunc2():
pass
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串
以上是关于装饰器的主要内容,如果未能解决你的问题,请参考以下文章