如何理解python中的装饰器, 这篇文章就够了!

1. python中的函数

  • 理解裝飾器之前先要理解閉包, python中閉包的出現是因爲函數在python中也是一個對象, 也可以被引用, 然後調用, 比如
def log():
    print('我是一些log信息')


if __name__ == '__main__':
    print(type(log))
    log_func = log
    log_func()
  • 執行結果如下
<class 'function'>
我是一些log信息
  • 可以看到log函數是一個對象, 可以被賦值給log_func, log_func可以像函數一樣被執行

2. python中的闭包

  • 理解了python也是一個函數, 我們看看閉包, 閉包就是函數裏面返回了一個函數, 第二層嵌套函數還可以引用第一層函數的局部變量, 相當於嵌套函数引用了这个变量,将这个局部变量封闭在了嵌套函数中, 這樣的結構叫做閉包, 比如
def log():
    log_info = '我是一些log信息'

    def wrapper():
        print(log_info)
        print('我是函數wrapper實現的功能')
        

    return wrapper


if __name__ == '__main__':
    f = log()()
  • 函数log()执行结果是一个wrapper函数对象, log()后面再加一个()调用就是wapper函数, 返回打印结果如下:
我是一些log信息
我是函數wrapper實現的功能

3. python中的装饰器

  • 理解了闭包, 我们看看装饰器, 装饰器可以看成一个"自动"帮我们执行的闭包, 它的作用是能帮我们的函数或者类在不改变原有功能代码的前提下额外增加一些功能
import functools


def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('name参数是: {}'.format(*args))
        print('我在函数%s()被调用前做了一些事情' % func.__name__)
        print('调用函数 %s():' % func.__name__)
        return func(*args, **kwargs)

    return wrapper


@log
def get_user_info(name):
    print('函数{}的执行结果是: 获取到用户{}的信息'.format(get_user_info.__name__, name))


if __name__ == '__main__':
    get_user_info('XiaoMing')

  • 执行结果如下:
name参数是: XiaoMing
我在函数get_user_info()被调用前做了一些事情
调用函数 get_user_info():
函数get_user_info的执行结果是: 获取到用户XiaoMing的信息
  • log函数是一个闭包, 传入的参数是一个函数, 并且函数的参数被一层层嵌套函数传递下去
  • @语法帮我们做的事情就是"自动"执行这个闭包函数到最后一层, 也就是到wrapper函数这一层, 相当于是
    get_user_info = log(get_user_info('XiaoMing'))()
  • 当我们调用get_user_info函数时候, 我们并不是调用我们写的函数, 而是log闭包函数里面的wrapper函数, 然后wrapper的返回结果会真正调用我们写的get_user_info函数
  • @functools.wraps(func)这段代码的意思就是将原函数get_user_info的元信息(docstring、name、参数列表)拷贝到装饰器里面的wrapper函数中
  • 这样@log这个装饰器就帮我们实现了在不改变原有代码的基础上额外增加了get_user_info这个函数的功能
我在想我要不要写一句励志的话......
原文地址:https://www.cnblogs.com/iread9527/p/12549205.html