zoukankan      html  css  js  c++  java
  • 装饰器

    装饰器是什么

    装饰器是让一个函数在执行的过程中它的前后去执行代码,在不改变原函数即原函数的调用的情况下,

    为原函数增加一些额外的功能,打印日志,执行时间,登录认证等等。

    最简单版的装饰器

    在一个函数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 + '
    ')
                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 的文件出现了,里面的内容就是上面的字符串
  • 相关阅读:
    ASP.NET上传文件的三种基本方法
    实例分析 equals 和 ==
    如何保证Web Service的安全
    Winform动态显示图片,数据流方式
    C# 文件保存到数据库中或者从数据库中读取文件
    简说Session
    NotifyIcon的简单使用
    c# Invoke和BeginInvoke 区别
    DataGridView 的 CurrentCellDirtyStateChanged事件用法
    十种发送邮件的方式
  • 原文地址:https://www.cnblogs.com/fanggege/p/10963487.html
Copyright © 2011-2022 走看看