python函数装饰器
声明:博主并没有系统学习过python语言,在实际项目中遇到关于python不懂的语法,这里仅作为个人学习积累笔记
1.1 python函数相关基础
深入了解python函数装饰器移步:Python 函数装饰器
下面的笔记来源于上述链接
python中将函数赋值给变量,并不会执行该函数,函数只有加括号才会被调用
def hi():print("")greet = hi # 函数hi不会被调用,只是将函数赋值给了变量
hi() # 函数会被执行
# 若要通过greet来执行hi函数
greet() # 变量变为了函数
函数中嵌套函数,所有的嵌套函数会被一同执行,并且嵌套函数不能被外界单独访问
def hi():def greet():……def welcome():……
hi() #调用函数hi()则greet() welcome()会被一同调用
函数中嵌套函数时,从中返回某个特定嵌套函数
def hi(name="func1"):def greet():……def welcome():……if name == "func1":return greetelse:return welcome
a = hi() # 将hi()函数返回的函数赋值给a
print(a()) #调用a函数,即返回的greet函数
函数作为另一个函数的参数传入
def hi():……def func2(func1): print(func1())
func2(hi) #将函数hi作为参数传入函数func2,在func2中执行hi函数
1.2 装饰器的核心作用
Python函数装饰器是一种高阶函数,其核心作用是在不修改原函数代码的情况下动态扩展函数功能。这种特性使得装饰器在代码复用、功能解耦、逻辑增强等方面具有独特优势。
简单了解装饰器的其中一个作用:
动态功能扩展:为函数添加额外行为
装饰器的核心能力是在不改变原函数内部代码的情况下,为其包裹新的功能逻辑。
例如实现函数调用日志记录:
def log_decorator(func):def wrapper(*args, **kwargs):print(f"[LOG] 开始执行 {func.__name__},参数:{args}")result = func(*args, **kwargs) # 调用原函数print(f"[LOG] {func.__name__} 执行完成,结果:{result}")return resultreturn wrapper@log_decorator # 等价于 add = log_decorator(add) 将原函数add作为参数传递给log_decorator函数
def add(a, b): # add变量被重新绑定为log_decorator(add)的返回值(即内部函数wrapper)return a + badd(3, 5)
# 输出:
# [LOG] 开始执行 add,参数:(3, 5)
# [LOG] add 执行完成,结果:8
装饰器的应用阶段(代码加载时)当Python解释器加载@log_decorator语法时,会立即执行装饰器函数log_decorator:
函数调用阶段(运行时)当执行add(3, 5)时,实际调用的是被装饰后的wrapper函数
执行顺序
调用 add(3,5)
│
├─> 进入 wrapper(3,5)
│ ├─> 执行 [LOG] 开始执行 add,参数:(3,5)
│ ├─> 调用 func(3,5) → 原始add函数
│ │ └─> 计算 3+5=8
│ └─> 执行 [LOG] add 执行完成,结果:8
│
└─> 返回最终结果8
1.3 python函数装饰器的实际应用:请求限流
控制API调用频率:防止服务被恶意高频调用
def rate_limit(max_calls, period):def decorator(func):calls = []def wrapper(*args):now = time.time()# 清除超时记录calls[:] = [t for t in calls if now - t < period]if len(calls) >= max_calls:raise Exception("请求过于频繁")calls.append(now)return func(*args)return wrapperreturn decorator@rate_limit(5, 60) # 每分钟最多5次, rate_limit返回decorator, decorator接收api_request函数
def api_request(): # api_request = rate_limit(api_request)# 调用外部API
代码结构拆解,该代码通过装饰器工厂实现了一个滑动窗口请求限流器,其核心结构分为三层:
rate_limit(max_calls, period):#装饰器工厂,接收最大调用次数(max_calls)和时间周期(period秒),返回实际装饰器decorator
decorator(func):#接收被装饰函数(如api_request),通过闭包维护调用时间记录列表calls,返回包装函数wrapper
wrapper(*args):#实现限流逻辑,包含时间窗口清理、调用计数验证、异常抛出等核心功能
Python普通函数与闭包函数对比分析
普通函数
(1)独立定义,无嵌套结构
(2)每次调用均为独立上下文,无状态记忆能力
使用普通函数实现计数器
缺点:全局变量不安全,多实例无法并存
count = 0 # 全局变量易被篡改
def increment():global countcount += 1return count
print(increment()) # 1
print(increment()) # 2
闭包函数
(1)嵌套函数结构,内部函数捕获外部函数变量
(2)通过闭包环境实现状态持久化
使用闭包函数实现计数器
def create_counter():count = 0def counter():nonlocal countcount += 1return countreturn counter # 每个实例独立计数
counter1 = create_counter()
counter2 = create_counter()
print(counter1()) # 1(实例1独立计数)
print(counter2()) # 1(实例2独立计数)