装饰器和元数据

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装饰内部包裹函数,可以制定将函数的某些属性,更新到包裹函数上面;

你可能感兴趣的:(装饰器和元数据)