装饰器

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 的文件出现了,里面的内容就是上面的字符串

 

以上是关于装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象学习之八,装饰器

thymeleaf 片段渲染后重新加载 javascript

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码