深入理解Python闭包与递归:原理、应用与实践

news2025/3/20 20:58:32


 

目录

 

闭包

什么是闭包:

闭包的基本结构:

实现闭包的条件:

1.嵌套函数 

2.内函数引用外部函数的变量 

3.外部函数返回内部函数 

4.外部函数已经执行完毕 

递归函数

什么是递归函数:

递归函数条件

1.必须有个明确的结束条件  ———递归出口

2.每进行更深一步的递归,问题规模相比上一次递归都要有所减少

3.相邻两次重复之间有紧密联系

分析一下这段代码

1.函数定义:

2. 基准条件(Base Case)

3. 递归条件(Recursive Case)

典型的递归函数的例子

1到100的相加

 2.斐波那契数列

递归的优缺点

优点

缺点 

递归的应用场景 

递归的注意事项 


闭包

什么是闭包:

闭包是指在一个函数内部定义的函数,并且这个内部函数引用了外部函数的变量。即使外部函数已经执行完毕,内部函数仍然可以访问和操作这些变量

闭包的基本结构:

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function

closure = outer_function(10)
print(closure(5))  # 输出 15

接下来我为大家解释一下这段代码:

  • outer_function 是外部函数,它接受一个参数 x

  • inner_function 是内部函数,它接受一个参数 y,并且引用了外部函数的变量 x

  • outer_function 返回 inner_function,而不是调用它。

  • 当我们调用 outer_function(10) 时,它返回 inner_function,并且 x 被设置为 10

  • 然后我们调用 closure(5),实际上是在调用 inner_function(5),此时 x 仍然是 10,所以结果是 15

实现闭包的条件:

1.嵌套函数 

闭包必须在一个外部函数中定义一个内部函数。也就是说,函数内部再定义一个函数。

def outer_function():
    def inner_function():
        pass
    return inner_function

2.内函数引用外部函数的变量 

内部函数必须引用外部函数的变量(即自由变量)。这是闭包的核心,内部函数通过引用外部函数的变量来“记住”外部函数的环境。

def outer_function(x):
    def inner_function(y):
        return x + y  # 内部函数引用了外部函数的变量 x
    return inner_function

3.外部函数返回内部函数 

外部函数必须返回内部函数(而不是调用它)。这样,内部函数可以在外部函数执行完毕后继续存在,并且仍然可以访问外部函数的变量。

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function  # 返回内部函数,而不是调用它

closure = outer_function(10)
print(closure(5))  # 输出 15

4.外部函数已经执行完毕 

闭包的特性在于,即使外部函数已经执行完毕,内部函数仍然可以访问外部函数的变量。这是因为闭包将外部函数的变量“捕获”并保存在内部函数的环境中。

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function

closure = outer_function(10)  # 外部函数执行完毕,x 被设置为 10
print(closure(5))  # 内部函数仍然可以访问 x,输出 15

总结一下:

  1. 嵌套函数:在一个函数内部定义另一个函数。

  2. 内部函数引用外部函数的变量:内部函数必须引用外部函数的变量。

  3. 外部函数返回内部函数:外部函数返回内部函数,而不是调用它。

  4. 外部函数已经执行完毕:即使外部函数执行完毕,内部函数仍然可以访问外部函数的变量。

这些条件共同作用,使得闭包能够“记住”其定义时的环境,并在后续调用中继续使用这些环境中的变量。 


递归函数

什么是递归函数:

递归函数(Recursive Function)是指在函数的定义中调用函数自身的函数。递归是一种强大的编程技术,特别适用于解决可以分解为相似子问题的问题。理解递归的概念和应用场景,可以帮助你编写更加简洁和优雅的代码。

递归函数条件

1.必须有个明确的结束条件  ———递归出口

2.每进行更深一步的递归,问题规模相比上一次递归都要有所减少

3.相邻两次重复之间有紧密联系

递归的基本结构

def recursive_function(parameters):
    if base_case_condition(parameters):  # 基准条件
        return base_case_value
    else:
        # 递归条件
        return recursive_function(modified_parameters)

 

分析一下这段代码
1.函数定义:
  • recursive_function 是一个递归函数,它接受一个或多个参数 parameters

  • 参数 parameters 是递归函数的输入,通常用于表示当前问题的状态或规模。


    2. 基准条件(Base Case)
  • if base_case_condition(parameters):

    • 这是递归的终止条件。

    • base_case_condition(parameters) 是一个判断条件,用于检查当前参数是否满足递归终止的条件。

    • 如果满足基准条件,函数直接返回 base_case_value,不再进行递归调用。

    • 基准条件的作用:防止无限递归,确保递归最终能够终止。

 

示例: 

 在这个例子中,n == 0 是基准条件,当 n 为 0 时,递归停止,函数返回 1


3. 递归条件(Recursive Case)
  • else:

    • 如果基准条件不满足,函数进入递归条件。

    • 在递归条件中,函数会调用自身(即 recursive_function),但传入的参数会被修改(modified_parameters)。

    • 修改参数的目的是将问题规模缩小,逐步逼近基准条件。

      def factorial(n):
          if n == 0:  # 基准条件
              return 1
          else:  # 递归条件
              return n * factorial(n - 1)

      在这个例子中,factorial(n - 1) 是递归调用,每次递归调用时,n 的值都会减小,逐步逼近基准条件 n == 0

典型的递归函数的例子

1.

1到100的相加

(一般方法)

# def add():
#     s=0
#     for i in range(1,101):
#         s +=i
#     print(s)
# add()

采用递归

# def add(n):
#     if n ==1:
#         return 1
#
#     return n +add(n-1)
# print(add(100))

 2.斐波那契数列

def fibonacci(n):
    if n == 0:  # 基准条件
        return 0
    elif n == 1:  # 基准条件
        return 1
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)  # 递归条件

print(fibonacci(10))  # 输出 55

这个例子中:

  • 当 n 为 0 或 1 时,函数返回相应的基准值。

  • 否则,函数返回 fibonacci(n - 1) + fibonacci(n - 2),即前两个斐波那契数的和。

递归的优缺点

优点

  1. 简洁性:递归代码通常比迭代代码更简洁和易读。

  2. 自然表达:对于某些问题(如树遍历、分治算法等),递归提供了一种自然的表达方式

缺点 

 

  1. 性能问题:递归可能会导致大量的函数调用,增加栈的深度,从而影响性能。

  2. 栈溢出:如果递归深度过大,可能会导致栈溢出错误。

  3. 重复计算:在某些情况下(如斐波那契数列的简单递归实现),递归可能会导致大量的重复计算。

递归的应用场景 

  1. 树和图的遍历:递归非常适合用于树和图的遍历(如深度优先搜索)。

  2. 分治算法:许多分治算法(如归并排序、快速排序)都使用递归来分解问题。

  3. 动态规划:递归常用于动态规划问题的初始实现,然后可以通过记忆化或迭代来优化。

递归的注意事项 

  1. 确保基准条件正确:基准条件是递归终止的关键,必须确保它能够正确终止递归。

  2. 避免无限递归:如果递归条件没有正确地向基准条件靠近,可能会导致无限递归,最终导致栈溢出。

  3. 考虑性能问题:对于性能敏感的应用,可能需要将递归转换为迭代,或使用记忆化来优化递归。

总结一下: 递归函数是一种强大的编程工具,特别适用于解决可以分解为相似子问题的问题。理解递归的基本概念、优缺点和应用场景,可以帮助你编写更加简洁和优雅的代码。然而,递归也需要谨慎使用,特别是在性能敏感的应用中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2318578.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SeaCMS代码审计

漏洞描述 漏洞分析 根据漏洞描述定位漏洞代码 当actionsaveCus或者save时,可以进行一个文件写入,不过文件类型被进行了限制,只有html,htm,js,txt,css 虽然这里并不能写入php文件,但是当actionadd或者custom时,这里进行…

好看的网络安全登录页面 vue http网络安全

一、http协议 http协议是一种网络传输协议,规定了浏览器和服务器之间的通信方式。位于网络模型中的应用层。(盗图小灰。ヾ(◍∇◍)ノ゙) 但是,它的信息传输全部是以明文方式,不够安全,…

Unity--GPT-SoVITS接入、处理GPTAPI的SSE响应流

GPT-SoVITS GPT-SoVITS- v2(v3也可以,两者对模型文件具有兼容) 点击后 会进入新的游览器网页 ----- 看了一圈,发现主要问题集中在模型的训练很需要CPU,也就是模型的制作上,问题很多,如果有现有…

Redis哈希槽机制的实现

Redis哈希槽机制的实现 Redis集群使用哈希槽(Hash Slot)来管理数据分布,整个集群被划分为固定的16384个哈希槽。当我们在集群中存储一个键时,Redis会先对键进行哈希运算,得到一个哈希值。然后,Redis将该哈…

docker pull 提示timeout

通过命令行拉取对应的mysql版本提示网络超时。 开始排查,首先确认是否能浏览器访问。ok的,可以正常访问。 终端curl 排查嗯 有问题 改了下 终端 vim ~/.zshrc 加入 export HTTP_PROXY"http://127.0.0.1:7890" export HTTPS_PROXY"…

(超详细) ETL工具之Kettle

Kettle简介 kettle最早是一个开源的ETL工具,后命名为Pentaho Data Integration。由JAVA开发,支持跨平台运行,其特性包括:支持100%无编码、拖拽方式开发ETL数据管道,可对接包括传统数据库、文件、大数据平台、接口、流…

random_masking 函数测试

文章目录 1. description2. excel3. pytorch code 1. description 功能:按一定比例的随机部分样本,简单来说就是按照一定的比例将行向量从小到大的顺序提取出来。思考1: 用了均匀分布,并且按照一定比例,取前prob概率来…

TDengine 中的流式计算

简介 TDengine 中的流计算,功能相当于简化版的 FLINK , 具有实时计算,计算结果可以输出到超级表中存储,同时也可用于窗口预计算,加快查询速度。 创建流式计算 CREATE STREAM [IF NOT EXISTS] stream_name [stream_o…

Java 大视界 -- Java 大数据在智慧交通自动驾驶仿真与测试数据处理中的应用(136)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

JVM的一些知识

JVM简介 JVM 是 Java Virtual Machine 的简称,意为 Java 虚拟机。 虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。常见的虚拟机:JVM、VMwave、Virtual Box。 JVM 和其他两个虚拟机的区别: VMw…

C语言每日一练——day_7

引言 针对初学者,每日练习几个题,快速上手C语言。第七天。(连续更新中) 采用在线OJ的形式 什么是在线OJ? 在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中用…

Java使用FFmpegFrameGrabber进行视频拆帧,结合Thumbnails压缩图片保存到文件夹

引入依赖 <dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.17</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ja…

用hexo初始化博客执行hexo init时碰到的问题

用hexo初始化博客执行hexo init时碰到的问题 $ hexo init myblog INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git fatal: unable to access https://github.com/hexojs/hexo-starter.git/: SSL certificate problem: unable to get local issuer cer…

4.1--入门知识扫盲,ISO知识体系介绍(看一遍,协议啥的全部记住)

OSI七层模型&#xff1a;网络世界的"七重天"生存指南&#xff08;附快递小哥版图解&#xff09; “如果你觉得网络分层很抽象&#xff0c;那就想象自己在寄快递” —— 来自一个被三次握手逼疯的程序员 开场白&#xff1a;网络通信就像送外卖 假设你要给隔壁妹子送奶…

AI训练如何获取海量数据,论平台的重要性

引言&#xff1a;数据——AI时代的“新石油” 在人工智能和大模型技术飞速发展的今天&#xff0c;数据已成为驱动技术进步的 “ 燃料 ”。无论是训练聊天机器人、优化推荐算法&#xff0c;还是开发自动驾驶系统&#xff0c;都需要海量、多样化的数据支持。 然而&#xff0c;获…

Git 使用SSH登陆

一、SSH介绍 SSH连接相比于HTTP连接会简单一点&#xff0c;因为SSH连接通过了私钥与公钥进行身份认证&#xff0c;这样就不需要像HTTP一样&#xff0c;每次clone或者操作仓库都需要输入密码 其中私钥和密钥是需要在自己电脑上生成的&#xff0c;通过命令即可生成一个私钥和一个…

织梦DedeCMS修改文章【标题、短标题、关键词】长度限制

在后台虽然可以设置标题的长度&#xff0c;但是数据库的字段固定是60个字符&#xff0c;短标题是36字符&#xff0c;关键词30字符&#xff0c;所以这里教大家修改一下织梦DedeCMS修改【标题】【短标题】【关键词】长度限制 一、后台配置 1、进入dede后台管理 -> 系统 ->…

Powershell WSL部署ubuntu22.04.5子系统

前提条件WSL 安装 wsl 安装参考1wsl 安装csdn参考2wsl 百度网盘离线下载 本地目录安装ubuntu22.04.5 子系统 powershell 管理员打开执行(实现,下载安装ubuntu子系统,用户创建,远程ssh登录设置,防火墙端口开放)子系统IP 查看方法wsl

umi自带的tailwindcss修改为手动安装

1》为什么改为手动&#xff1f; 主要是为了解决这个报错问题&#xff0c;虽然重新运行也可解决&#xff0c;但是总是要运行2-3次&#xff0c;比较麻烦 2》如何手动 1&#xff0c;先在devDependencies下安装这两个包 pnpm install postcss8.5.1 -D "autoprefixer"…

麒麟V10 arm cpu aarch64 下编译 RocketMQ-Client-CPP 2.2.0

国产自主可控服务器需要访问RocketMQ消息队列&#xff0c;最新的CSDK是2020年发布的 rocketmq-client-cpp-2.2.0 这个版本支持TLS模式。 用默认的版本安装遇到一些问题&#xff0c;记录一下。 下载Releases apache/rocketmq-client-cpp GitHubhttps://github.com/apache/roc…