Python 中的递归函数与装饰器详解

在 Python 编程中,递归函数装饰器函数 是两个非常强大且常见的高级编程技巧。它们分别用于解决重复性计算问题和增强函数功能而不修改其本身逻辑。本文将带你深入了解这两个概念,并通过斐波那契数列、日志记录、性能监控等典型场景来展示它们的实际应用。


一、递归函数

1.1 什么是递归?

递归是一种在函数内部调用自身的编程技术。它特别适用于具有“自相似”结构的问题,例如树形结构遍历、数学上的阶乘、斐波那契数列等。

✅ 一个完整的递归函数通常包括:

  • 基准条件(Base Case):停止递归的条件;
  • 递归步骤(Recursive Step):函数调用自身以简化问题。

1.2 斐波那契数列实现

斐波那契数列是一个经典的递归应用场景。定义如下:

  • F(0) = 0
  • F(1) = 1
  • F(n) = F(n-1) + F(n-2), 当 n ≥ 2

示例代码:

def Fibonacci(n):
    if n < 2:
        return n
    return Fibonacci(n - 1) + Fibonacci(n - 2)

print(Fibonacci(40))  # 输出: 102334155

🔍 分析:

  • 这是一个最简单的递归实现。
  • 然而,由于每次递归都产生两个子调用,导致大量重复计算。
  • 时间复杂度为 O(2ⁿ),效率极低,尤其当 n 较大时(如 n=40)会明显感受到延迟。

二、装饰器函数

2.1 什么是装饰器?

装饰器本质上是一个函数,它接受另一个函数作为参数并返回一个新的函数。它可以用来在不修改原始函数的前提下为其添加新功能,比如:

  • 日志记录
  • 性能监控
  • 权限验证
  • 输入输出处理

✅ 装饰器是 Python 面向切面编程(AOP)的核心实现手段之一。


2.2 基本结构与语法糖

装饰器的基本结构如下:

def decorator(fn):
    def wrapper(*args, **kwargs):
        # 前置操作
        result = fn(*args, **kwargs)
        # 后置操作
        return result
    return wrapper

使用装饰器时,我们使用 @decorator 的语法糖:

@decorator
def say():
    print("Hello World")

这等价于:

say = decorator(say)

2.3 实战:带日志记录与性能监控的装饰器

下面是一个典型的装饰器应用:在函数执行前后记录日志,并统计执行时间。

import time

def decorator(fn):
    print('...装饰器被调用...')
    print('装饰的函数', fn)

    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = fn(*args, **kwargs)
        end_time = time.time()

        with open('./test.txt', mode='a', encoding='utf-8') as f:
            f.write(f'{fn.__name__}被调用...执行时间:{end_time - start_time:.2f} s\n')

        return result

    return wrapper

应用于模型生成函数:

@decorator
def Qwen():
    time.sleep(3)
    return 'Qwen模型生成的内容'

@decorator
def LLM():
    time.sleep(1)
    return 'LLM模型生成的内容'

generator = Qwen()
print('...正在调用Qwen模型...', generator)

generator = LLM()
print('...正在调用LLM模型...', generator)

运行结果: 


2.4 多层装饰器链

你可以为一个函数叠加多个装饰器,形成装饰器链。注意执行顺序是从下往上,即先调用离函数最近的装饰器

def decorator1(fn):
    print('装饰器1...')
    def wrapper(*args, **kwargs):
        result = fn(*args, **kwargs)
        return result[::-1]  # 反转字符串
    return wrapper

def decorator2(fn):
    print('装饰器2...')
    def wrapper(*args, **kwargs):
        result = fn(*args, **kwargs)
        return result.upper()  # 转换为大写
    return wrapper

@decorator1
@decorator2
def hell():
    return 'hello world'

print(hell())  # 输出: DLROW OLLEH

执行流程说明:

  1. 先执行 decorator2(hell),返回一个包装后的函数;
  2. 再执行 decorator1(wrapper_from_decorator2)
  3. 最终调用的是 wrapper_from_decorator1()
  4. 所以字符串先是变成大写,然后被反转。

三、总结与建议

技术 特点 推荐使用场景
递归函数 结构清晰,符合人类思维习惯 数学问题、树/图遍历、分治算法
装饰器函数 功能扩展性强,保持代码干净 日志记录、权限控制、性能分析、缓存机制
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐