美文网首页
装饰器和元数据

装饰器和元数据

作者: overad | 来源:发表于2018-03-14 00:10 被阅读0次

    1.装饰器:

    装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

    正常的斐波拉函数:

    def fibonacci(n):
        if n <= 1:
            return 1
        return  fibonacci(n - 1) + fibonacci(n - 2)
    

    在求解的时候会存在大量的重复计算过程;f(8) = f(7)+f(6),f(7) = f(6)+f(5)这里的f(6)存在一次重复计算,一次类推,在每个大于2的计算过程中都存在重复计算从而导致函数的开销很大,影响函数的效率;
    我们在解决这个的问题的时候可以使用缓存:

    def fibonacci(n,cache = None):
        if cache is None:
            cache = {}
        if n in cache:
            return cache[n]
    
        if n <= 1:
            return 1
        cache[n] = fibonacci(n - 1,cache) + fibonacci(n - 2,cache)
        return cache[n]
    
    if __name__ == '__main__':
        print(fibonacci(40))
    

    这样定义了一个缓存,每次计算完毕都放到缓存字典中,每次计算先判断是否在缓存中,这样可以消除上面的重复计算的过程;但是在大量的这类问题面前,每个函数都要消除缓存的话,推荐装饰器

    def memo(func):
        cache = {}
        def wrap(*args):
            if args not in cache:
                cache[args] = func(*args)
            return cache[args]
        return wrap
    
    #装饰器的语法糖
    @memo
    def fibonacci(n):
        if n <= 1:
            return 1
        return  fibonacci(n - 1) + fibonacci(n - 2)
    
    if __name__ == '__main__':
        print(fibonacci(50))
    
    

    2.如何为被装饰的函数保存元数据

    在函数对象中保存着一些函数的元数据:

    函数 描述
    f.____name__ 函数的名字
    f.____doc__ 函数的文档字符串
    f.____module__ 函数所属模块名
    f.____dict__ 属性字典
    f.____defaults__ 默认参数元组

    问题:我们在使用装饰器后,在使用上面这些属性访问时,看到的是内部包裹函数的元数据没原来函数的元数据丢丢失掉了,应该如何解决?

    解决方案:使用标准库functools中的装饰器wraps装饰内部包裹函数,可以制定将函数的某些属性,更新到包裹函数上面;

    相关文章

      网友评论

          本文标题:装饰器和元数据

          本文链接:https://www.haomeiwen.com/subject/sbcxqftx.html