Python:递归函数及装饰器函数

上一篇:

Python:函数的位置传参、关键词传参及其可变性和解包操作-CSDN博客

目录

一、递归函数

1.1 定义

1.2 关键特点

 1.3 基本步骤

 1.4 经典示例

二、装饰器

2.1 闭包 

2.1.1 定义

2.1.2  闭包的优缺点

 2.2 基本装饰器

2.3  带参装饰器

 2.4 装饰器链

2.5  类装饰器

 三、两者总结


一、递归函数

1.1 定义

递归函数是指函数在其定义中直接或间接调用自身的一种函数。它通过将复杂问题分解为更小的同类子问题来求解。

1.2 关键特点

  • 终止条件(Base Case):防止无限递归,必须存在明确的退出条件。

  • 递归调用(Recursive Case):函数调用自身,逐步缩小问题规模。

  • 问题简化:每次递归都使问题规模减小

 1.3 基本步骤

  • 定义递归函数:在函数体内调用函数自身。

  • 设定终止条件:确保递归能终止。

  • 逐步简化问题:通过传递较小的参数递归求解,直至终止条件满足。

 1.4 经典示例

阶乘计算:

  • n! = n * (n-1) * (n-2) * ... * 1

  • 递归公式:n! = n * (n-1)!,终止条件:0! = 1

代码示例:

def factorial(n):
    # 终止条件:n为0或1时,返回1
    if n == 0 or n == 1:
        return 1
    # 递归调用:n * (n-1)!
    return n * factorial(n - 1)

# 测试
print(factorial(6))  # 输出 720

 斐波那契数列:

斐波那契数列(Fibonacci sequence)是一种经典的数列,它的特点是从第 3 项开始,每一项都等于前两项之和。前两项通常定义为:

  • F(0) = 0

  • F(1) = 1

从 F(2) 开始:

  • F(2) = F(1) + F(0) = 1 + 0 = 1

  • F(3) = F(2) + F(1) = 1 + 1 = 2

使用递归的思想实现斐波那契数列,代码示例:

def fib(n):
    if n == 0 or n == 1:  # 终止条件
        return n
    return fib(n - 1) + fib(n - 2)  # 递归调用

内存分配:

每次递归调用会在内存中创建新的栈帧,存储局部变量,调用结束后栈帧释放

二、装饰器

装饰器是Python对闭包思想的具体语法实现,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

  • 日志记录:可以使用装饰器来记录函数的输入、输出或执行时间。

  • 认证和授权:装饰器可以用于检查用户是否有权限执行特定操作。

  • 缓存:装饰器可以缓存函数的结果,从而提高执行效率。

  • 参数验证:可以使用装饰器来验证函数的输入参数是否符合预期。

  • 代码注入:装饰器可以在函数的执行前后注入额外的代码。

装饰器是一种修改函数或类行为的语法糖,本质上是一个高阶函数(接收函数并返回新函数)。
核心思想:在不修改原函数代码的前提下,增强其功能。

2.1 闭包 

2.1.1 定义

闭包必须满足以下三个条件:

  • 必须有一个内嵌函数

  • 内嵌函数必须引用外部函数中变量

  • 外部函数返回值必须是内嵌函数

2.1.2  闭包的优缺点

优点

  • 逻辑连续,当闭包作为另一个函数调用参数时,避免脱离当前逻辑而单独编写额外逻辑。

  • 方便调用上下文的局部变量。

  • 加强封装性,是第2点的延伸,可以达到对变量的保护作用。

缺点

引用在,空间不灭:闭包使得函数中的变量保存在内存中,内存消耗很大

示例:

# file : closure.py
def make_power(y):
    def fn(x):
        return x ** y
    return fn
pow2 = make_power(2)
print("5的平方是:", pow2(5))
pow3 = make_power(3)
print("6的立方是:", pow3(6))

 2.2 基本装饰器

基本结构:

def decorator(func):          # 外层函数接受被装饰函数
    def wrapper(*args, **kwargs):  # 内层包装函数
        # 增强功能代码
        result = func(*args, **kwargs)  # 调用原函数
        # 增强功能代码
        return result
    return wrapper            # 返回包装函数

示例:

def my_decorator(func):
    print("I am decorator")

    def wrapper():
        print("Something is happening before the function is called.")
        func()  # 调用传入的函数
        print("Something is happening after the function is called.")

    return wrapper

@my_decorator  # 应用装饰器
def say_hello():
    print("Hello!")


print("say_hello is:", say_hello)  # 装饰器装饰之后的函数
say_hello()  # 调用经过装饰器之后的函数
  • my_decorator 是一个接受一个函数 func 作为参数的装饰器。

  • wrapper 函数在被装饰函数前后添加了额外的操作。

  • 使用 @my_decoratorsay_hello 函数装饰,使其在调用前后执行 wrapper 中的代码。

2.3  带参装饰器

def repeat(num):
    print('...函数名...()...函数执行...')

    def decorator(func):
        print('...装饰器...()...装饰器执行...')

        def wrapper(*args, **kwargs):
            for _ in range(num):
                func(*args, **kwargs)

        return wrapper

    return decorator

@repeat(3)  # 应用装饰器,重复执行下面的函数3次
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")  # 调用被装饰的函数
  • repeat 是一个接受参数的装饰器工厂函数,它返回一个装饰器。

  • decorator 是真正的装饰器,它接受一个函数 func 作为参数。

  • wrapper 函数重复执行被装饰的函数 num 次。

 2.4 装饰器链

def uppercase(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()

    return wrapper

def exclamation(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + "!"

    return wrapper

@exclamation
@uppercase
def say_hello(name):
    return f"Hello, {name}"

greeting = say_hello("Bob")
print(greeting)  # 输出 "HELLO, BOB!"
  • uppercase 和 exclamation 是两个装饰器,分别将文本转换为大写和添加感叹号。

  • 使用 @exclamation@uppercase 创建装饰器链,它们按照声明的顺序依次应用。

2.5  类装饰器

class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Something is happening before the function is called.")
        result = self.func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result

@MyDecorator  # 应用类装饰器
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Charlie")  # 调用被装饰的函数
  • MyDecorator 是一个类装饰器,它接受一个函数 func 作为参数并在 __call__ 方法中执行额外操作。

 三、两者总结

  • 递归的优雅性:适合处理树形结构(如文件遍历、XML解析)和分治算法(如快速排序)。

  • 装饰器的灵活性:通过横向扩展(AOP思想)解决日志、权限等横切关注点。

  • 对比:

    • 递归是纵向分解问题,装饰器是横向增强功能。

    • 递归需警惕性能陷阱,装饰器需注意过度嵌套导致的可读性下降。

  • 递归:“自己调用自己,分而治之”。

  • 装饰器:“穿马甲的函数,不改源码加功能”。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值