写在前面🐸
- python的装饰器是一种
语法糖
,是在不改变原有代码的前提下进行 追加新功能,如:登陆鉴权… - 装饰器由闭包实现
闭包🧅
- 闭包三要素
- 1.函数嵌套, 即外部函数嵌套一个内部函数;
- 2.外部函数返回内部函数引用;
- 3.内部函数使用外部函数的变量或者形参
- 闭包范例
def out(func): variable = 'This is out variable' def inner(): print(variable) func() return inner
函数装饰器🧅
- 1 简单装饰器
import functools def out(func): @functools.wraps(func) def inner(*args, **kwargs): return func(*args, **kwargs) return inner @out def func(*args, **kwargs): pass return
- 2 带参数的装饰器
== 常见如 FastApi Flask 等定义接口的方式便是采用这种带参数的装饰器来规定请求方式的==import functools def Out(*args, **kwargs): def out(func): @functools.wraps(func) def inner(*args, **kwargs): return func() return inner return out # 常见的 如 FastApi Flask 等定义接口的方式便是采用这种带参数的装饰器来规定请求方式的 @Out('post') def func(): pass
- 3 函数装饰器应用实例
我们定义一个登录和鉴权装饰器来装饰api# 1.定义登录认证装饰器 import functools def authenticated(func): @functools.wraps(func) def inner1(*args, **kwargs): print('登录认证代码') res = func(*args, **kwargs) print('登录认证后执行') return res return inner1 # 2.定义鉴权装饰器 def accesstoken(func): @functools.wraps(func) def inner2(*args, **kwargs): print('鉴权代码') res = func(*args, **kwargs) print('鉴权后执行') return res return inner2 @authenticated @accesstoken def api(): print('api逻辑') return api()
类装饰器🐚
类装饰器比之函数装饰器更好理解
- 1 简单装饰器
class Decorator(): def __init__(self, func): self._func = func def __call__(self, *args, **kwargs): return self._func(*args, **kwargs) @Decorator def func(x): return x
- 2 带参数的装饰器
import functools class Decorator(): def __init__(self, method=None): self._method = method def __call__(self, func): @functools.wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @Decorator('post') def func(x): return x
- 3 类装饰器应用实例
pass
大白话理解:
参考洋葱纹路,先从外到内再从内到外, 被装饰函数上层的代码属于从外到内, 被装饰函数下层的代码属于从内到外
我们以上面的函数装饰器实例为例:
-
api
定义好后,此时装饰器函数立即执行,自下而上装饰api
, 即 api= authenticated(accesstoken(api)) 拆解开来有如下步骤- api = accesstoken(api) --> inner2
- api = authenticated(inner2) --> inner1
此时的 api为装饰后的新
api
-
调用
api
, 此时有如下调用链
新api() --> inner1() [登录认证代码执行] - inner2() [鉴权代码执行] - api()[此时的api函数才是真正的初始定义的api] - 鉴权后执行 - [登录认证后执行], 如下
可以看到整个调用链有如洋葱纹理一样
自外而内
再自内而外
结论🐒
- 一般的装饰器在装饰api函数时登录验证在上 鉴权在下, 意即, 先登录 再 鉴权