装饰器这玩意挺有用, 当时感觉各种绕, 现在终于绕明白了, 俺滴个大爷, 还是要慢慢思考才能买明白各种的真谛, 没事就来绕一绕
- def outer(func):
- def inner():
- print("认证成功")
- result=func()
- print("登录成功")
- return result
- return inner
- @outer
- def OA():
- print("OA 接口")
这里面需要注意的是:
@outer 和 @outer()有区别, 没有括号时, outer 函数依然会被执行, 这和传统的用括号才能调用函数不同, 需要特别注意!
是 OA 这个函数名 (而不是 OA() 这样被调用后)当做参数传递给装饰函数 outer, 也就是: func = OA,@outer 等于 outer(OA), 实际上传递了 OA 的函数体, 而不是执行 OA 后的返回值.
outer 函数 return 的是 inner 这个函数名, 而不是 inner()这样被调用后的返回值.
1. 程序开始执行 outer 函数内部的内容, 一开始它又碰到了一个函数, inner 函数定义块被程序观察到后不会立刻执行, 而是读入内存中.
2. 再往下, 碰到 return inner, 返回值是个函数名, 并且这个函数名会被赋值给 OA 这个被装饰的函数, 也就是 OA = inner, 此时 OA 函数被新的函数 inner 覆盖了 (实际上是 OA 这个函数名更改成指向 inner 这个函数名指向的函数体内存地址, OA 不再指向它原来的函数体的内存地址), 再往后调用 OA 的时候将执行 inner 函数内的代码, 而不是先前的函数体. 那么先前的函数体去哪了? 还记得我们将 OA 当做参数传递给 func 这个形参么? func 这个变量保存了老的函数在内存中的地址, 通过它就可以执行 老的函数体, 你能在 inner 函数里看到 result = func() 这句代码, 它就是这么做的!
3. 接下来, 还没有结束, 依然通过 OA()的方式调用 OA 函数时, 执行的就不再是老的 OA 函数的代码, 而是 inner 函数的代码. 在本例中, 它首先会打印个 "认证成功" 的提示, 然后, 它会执行 func 函数并将返回值赋值个变量 result, 这个 func 函数就是老的 OA 函数; 接着, 它又打印了 "登陆成功" 的提示; 最后返回 result 这个变量. 我们可以用 r = OA()的方式接受 result 的值.
4. 仅仅是添加了一个装饰函数, 就实现了我们的需求, 在函数调用前先认证, 调用后写入日志, 这就是装饰器的最大作用.
来源: https://www.cnblogs.com/python2687806834/p/9897641.html