当前位置: 首页 > news >正文

Python 函数式编程全攻略:从理论到实战的深度解析

本文深入剖析 Python 函数式编程,详细讲解其概念、核心特性(迭代器、生成器等)、内置函数及相关模块(itertoolsfunctools ),结合丰富示例与直观图表,助力读者全面掌握函数式编程技巧,提升编程能力与代码质量。

目录

函数式编程概念

Python 函数式编程特性

内置函数与函数式编程

itertools 模块

重点知识点扩展

(一)生成器在数据处理中的应用

(二)itertools模块在组合问题中的应用

(三)函数式编程与面向对象编程的结合

总结


函数式编程概念

函数式编程将问题分解为一系列函数,强调函数的输入输出关系,理想情况下函数无内部状态,只根据输入产生输出,避免副作用。它与过程式、声明式、面向对象编程方式不同,各有特点。多范式语言如 Python,允许在程序不同部分采用不同编程方式 。

编程方式特点示例语言
过程式一连串处理输入的指令C、Pascal、Unix shells
声明式描述问题,由语言实现决定计算方式SQL
面向对象操作对象,对象有内部状态和方法Smalltalk、Java
函数式分解为函数,避免副作用ML 家族、Haskell

函数式编程具有形式证明、模块化、组合性强以及易于调试和测试等优点 。虽然形式证明在实际中应用困难,但模块化使得程序更易理解和维护,组合性方便复用代码,易于调试和测试则提高了开发效率 。

Python 函数式编程特性

  1. 迭代器:迭代器是表示数据流的对象,支持__next__()方法,每次返回数据流中的下一个元素,无元素时抛出StopIteration异常 。iter()函数可将可迭代对象转换为迭代器,许多内置数据类型(列表、字典、字符串等)都支持迭代 。

# 迭代器使用示例
L = [1, 2, 3]
it = iter(L)
print(next(it))  
print(next(it))  
print(next(it))  
  1. 生成器表达式和列表推导式:生成器表达式和列表推导式借鉴自 Haskell 语言,用于对迭代器元素进行操作或筛选 。生成器表达式返回迭代器,延迟计算,适合处理大量数据或无限数据流;列表推导式返回列表 。

# 生成器表达式示例
line_list = ['  line 1 \n', 'line 2   \n',' \n ', '']
stripped_iter = (line.strip() for line in line_list)
# 列表推导式示例
stripped_list = [line.strip() for line in line_list]

生成器表达式和列表推导式的异同及使用场景总结:

比较项目生成器表达式列表推导式
语法使用圆括号()使用方括号[]
返回结果返回一个迭代器对象,延迟计算,只有在迭代时才计算值返回一个列表,立即计算并存储所有结果
内存占用在处理大量数据或无限数据流时,内存占用小,因为不会一次性生成所有数据处理大量数据时可能占用较多内存,因为要存储整个列表
使用场景适用于处理大数据集或需要惰性求值的场景,如处理大文件、无限序列等适用于需要立即获取所有结果并进行后续列表操作(如排序、索引访问)的场景
示例:
# 生成器表达式处理大文件,假设文件有大量行数据
with open('large_file.txt', 'r') as file:# 只在需要时逐行读取并处理,不会一次性加载所有行到内存line_lengths = (len(line) for line in file)  for length in line_lengths:print(length)
​
# 列表推导式获取所有满足条件的数的平方,立即得到结果列表
squares = [num ** 2 for num in range(10) if num % 2 == 0]  
print(squares)  
  1. 生成器:生成器是特殊函数,包含yield关键字,返回一个支持生成器协议的迭代器 。生成器函数执行到yield时,会暂停并保留局部变量,下次调用__next__()方法时恢复执行 。

# 生成器函数示例
def generate_ints(N):for i in range(N):yield i
​
​
gen = generate_ints(3)
print(next(gen))  
print(next(gen))  
print(next(gen)) 
 

生成器还支持向其传递值,通过send()方法可向生成器发送值,yield成为表达式可接收值 。此外,throw()用于在生成器内部抛出异常,close()用于结束迭代 。

# 向生成器传递值示例
def counter(maximum):i = 0while i < maximum:val = (yield i)if val is not None:i = valelse:i += 1
​
​
it = counter(10)
print(next(it))  
print(next(it))  
print(it.send(8))  

内置函数与函数式编程

Python 的一些内置函数与函数式编程紧密相关,如map()filter()enumerate()sorted()any()all()zip()等 。这些函数对可迭代对象进行操作,提供了便捷的功能 。

1. map()函数

map(f, iterA, iterB, ...) 函数会根据提供的函数f对多个可迭代对象(iterAiterB等)的对应元素进行处理,并返回一个迭代器。例如,对列表中的每个元素进行平方操作:

nums = [1, 2, 3, 4]
squared_nums = list(map(lambda x: x ** 2, nums))
print(squared_nums)  

在这个例子中,map()函数将匿名函数lambda x: x ** 2应用到nums列表的每个元素上,返回一个包含平方值的迭代器,最后通过list()函数将迭代器转换为列表输出。如果有多个可迭代对象,map()会按顺序对它们的对应元素进行操作:

nums1 = [1, 2, 3]
nums2 = [4, 5, 6]
result = list(map(lambda x, y: x + y, nums1, nums2))
print(result)  

这里map()函数将lambda x, y: x + y应用到nums1nums2的对应元素上,实现了两个列表对应元素相加。

2. filter()函数

filter(predicate, iter) 函数用于过滤可迭代对象中的元素。它接受一个谓词函数predicate(该函数返回布尔值)和一个可迭代对象iter,返回一个包含所有使谓词函数返回True的元素的迭代器。例如,过滤出列表中的偶数:

nums = [1, 2, 3, 4, 5, 6]
even_nums = list(filter(lambda x: x % 2 == 0, nums))
print(even_nums)  

在这个例子中,filter()函数使用匿名函数lambda x: x % 2 == 0筛选出nums列表中的偶数元素,并返回一个迭代器,再通过list()转换为列表。

3. enumerate()函数

enumerate(iter, start=0) 函数用于为可迭代对象中的元素计数,返回一个包含计数(从start开始,默认为 0)和元素的元组的迭代器。在遍历列表时获取元素索引非常有用:

fruits = ['apple', 'banana', 'cherry']
for index, fruit in enumerate(fruits):print(f'Index {index}: {fruit}')

4. sorted()函数

sorted(iterable, key=None, reverse=False) 函数将可迭代对象中的元素收集到一个列表中进行排序,并返回排序后的列表。key参数可以指定一个函数来定制排序规则,reverse参数用于指定是否降序排序:

nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
sorted_nums = sorted(nums)
print(sorted_nums)  
sorted_nums_desc = sorted(nums, reverse=True)
print(sorted_nums_desc)  
# 根据元素的绝对值进行排序
nums_with_neg = [-3, 1, -4, 1, -5, 9, 2, 6, -5, 3, 5]
sorted_by_abs = sorted(nums_with_neg, key=abs)
print(sorted_by_abs)  

5. any()all()函数

any(iter) 函数用于判断可迭代对象中是否有任何一个元素为真(在 Python 中,非零数值、非空容器等都被视为真),如果有则返回True,否则返回Falseall(iter) 函数则判断可迭代对象中的所有元素是否都为真,只有所有元素都为真时才返回True

bool_list1 = [True, False, True]
bool_list2 = [False, False, False]
print(any(bool_list1))  
print(any(bool_list2))  
print(all(bool_list1))  
print(all(bool_list2))  

6. zip()函数

zip(iterA, iterB, ...) 函数从多个可迭代对象中依次选取单个元素组成元组,并返回一个包含这些元组的迭代器。当可迭代对象长度不一致时,返回的迭代器长度与最短的可迭代对象相同:

list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
zipped = list(zip(list1, list2))
print(zipped)  

itertools 模块

itertools模块提供了许多用于处理迭代器的函数,可分为创建新迭代器、处理迭代器元素、选取部分输出、给输出分组等几类 。

1. 创建新迭代器count()生成无限等分数据流,cycle()无限重复可迭代对象,repeat()重复元素,chain()连接多个可迭代对象,islice()对迭代器进行切片,tee()复制迭代器 。

import itertools
# count()示例
count_iter = itertools.count(10, 5)
print(next(count_iter))  
# cycle()示例
cycle_iter = itertools.cycle([1, 2, 3])
print(next(cycle_iter))  
print(next(cycle_iter))  

2. 其他功能函数:该模块还有如accumulate()用于计算累加值,product()计算多个可迭代对象的笛卡尔积等函数,为处理迭代器提供了更多便利 。

重点知识点扩展

(一)生成器在数据处理中的应用

在数据处理场景中,生成器可用于处理大文件,避免一次性加载大量数据到内存。例如,处理一个超大的日志文件,逐行读取并分析日志内容:

def read_log_file(file_path):with open(file_path, 'r') as file:for line in file:yield line
​
​
log_generator = read_log_file('large_log_file.log')
for line in log_generator:# 进行日志分析操作,如查找特定关键字if 'error' in line.lower():print(line)

(二)itertools模块在组合问题中的应用

在解决组合相关问题时,itertools模块的函数非常有用。比如,计算多个列表中元素的所有组合:

import itertools
​
list1 = [1, 2]
list2 = ['a', 'b']
list3 = ['x', 'y']
combinations = list(itertools.product(list1, list2, list3))
print(combinations)  

(三)函数式编程与面向对象编程的结合

在实际项目中,函数式编程和面向对象编程可以结合使用。例如,在一个图形绘制系统中,图形对象可以用面向对象方式表示,而图形的变换操作可以使用函数式编程风格实现。

class Shape:def __init__(self, x, y):self.x = xself.y = y
​
​
def move_shape(shape, dx, dy):return Shape(shape.x + dx, shape.y + dy)
​
​
square = Shape(10, 10)
moved_square = move_shape(square, 5, 5)

总结

Python 的函数式编程提供了独特的编程视角和强大的工具集。通过迭代器、生成器、内置函数和itertools模块等,开发者可以编写出更简洁、高效、易维护的代码。函数式编程的优点,如模块化、组合性和易于调试测试,使其在处理复杂问题时表现出色。在实际编程中,结合函数式编程与其他编程方式,可以充分发挥 Python 的多范式特性,提升开发效率和代码质量。

  • TAG:Python、函数式编程、迭代器、生成器、itertools 模块

官方文档:Python 官方文档 - 函数式编程指引,提供了最权威和详细的知识点说明,是深入学习的重要参考。

相关文章:

Python 函数式编程全攻略:从理论到实战的深度解析

本文深入剖析 Python 函数式编程&#xff0c;详细讲解其概念、核心特性&#xff08;迭代器、生成器等&#xff09;、内置函数及相关模块&#xff08;itertools、functools &#xff09;&#xff0c;结合丰富示例与直观图表&#xff0c;助力读者全面掌握函数式编程技巧&#xff…...

Ollama 在 LangChain 中的使用

文章目录 一、langChain 介绍二、环境安装1.依赖库安装2.下载模型 三、基本使用示例1.使用 ChatPromptTemplate 进行对话2.流式输出3.工具调用4.多模态模型调用 四、进阶使用1.使用 ConversationChain 进行对话2.自定义提示模板3.构建一个简单的 RAG 问答系统 五、遇到问题与解…...

使用apt-rdepends制作软件离线deb安装包

使用apt-rdepends制作软件离线deb安装包 除基础软件外&#xff0c;还要获取软件依赖包。 依赖包工具安装 apt-get install apt-rdependsapt-rdepends工具使用 使用apt-rdepends工具&#xff0c;递归方式分析软件依赖&#xff0c;下载软件包本体&#xff0c;和依赖包。制作时…...

根据POD名称生成 三部曲:get、describe、log、exec

#!/bin/bash# 定义颜色变量 RED\033[0;31m GREEN\033[0;32m YELLOW\033[0;33m NC\033[0m # No Color# 检查是否传入 Pod 名称作为参数 if [ -z "$1" ]; then# 如果没有传参&#xff0c;则提示用户输入 Pod 名称echo -e "${YELLOW}Please enter the Pod name:${…...

SQL sever数据导入导出实验

1.创建数据库TCP-H &#xff08;1&#xff09;右键“数据库”&#xff0c;点击“新建数据库”即可 &#xff08;2&#xff09;用sql语言创建&#xff0c;此处以创建数据库DB_test为例&#xff0c;代码如下&#xff1a; use master;go--检查在当前服务器系统中的所有数据里面…...

python环境的yolov11.rknn物体检测

1.首先是我手里生成的一个yolo11的.rknn模型&#xff1a; 2.比对一下yolov5的模型&#xff1a; 2.1 yolov5模型的后期处理&#xff1a; outputs rknn.inference(inputs[img2], data_format[nhwc])np.save(./onnx_yolov5_0.npy, outputs[0])np.save(./onnx_yolov5_1.npy, outpu…...

I2C、SPI、UART

I2C&#xff1a;串口通信&#xff0c;同步&#xff0c;半双工&#xff0c;双线&#xff08;数据线SDA时钟线SCL&#xff09;&#xff0c;最大距离1米到几米 SPI&#xff08;串行外设接口&#xff09;&#xff1a;串口通信&#xff0c;同步&#xff0c;全双工&#xff0c;四线&…...

如何监控和优化 MySQL 中的慢 SQL

如何监控和优化 MySQL 中的慢 SQL 前言一、什么是慢 SQL&#xff1f;二、如何监控慢 SQL&#xff1f;1. 启用慢查询日志启用方法&#xff1a;日志内容&#xff1a; 2. 使用 mysqldumpslow 分析日志 三、如何分析慢 SQL&#xff1f;1. 使用 EXPLAIN 分析执行计划使用方法&#x…...

13-二叉树最小深度-深度优先(DFS)

一、定义 什么是二叉树的最小深度&#xff1f; 二叉树的最小深度是指从根节点到最近的叶子节点的最短路径上的节点数。叶子节点是指没有子节点的节点。 举个例子&#xff1a; 1/ \2 3/ 4 这棵树的最小深度是 2&#xff0c;因为从根节点 1 到叶子节点 3 的路径最短&#x…...

51单片机入门_10_数码管动态显示(数字的使用;简单动态显示;指定值的数码管动态显示)

接上篇的数码管静态显示&#xff0c;以下是接上篇介绍到的动态显示的原理。 动态显示的特点是将所有位数码管的段选线并联在一起&#xff0c;由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选&#xff…...

代码补全『三重奏』:EverEdit如何用上下文识别+语法感知+智能片段重构你的编码效率!

1 代码自动完成 1.1 应用场景 在编辑文档时&#xff0c;为了提高编辑效率&#xff0c;编辑器一般都会带有自动完成功能&#xff0c;比如&#xff1a;输入括号时自动补全另一半&#xff0c;输入文字时&#xff0c;自动补全剩下的部分。 1.2 使用方法 1.2.1 自动缩进 单击主菜…...

电脑系统损坏,备份文件

一、工具准备 1.U盘&#xff1a;8G以上就够用&#xff0c;注意会格式化U盘&#xff0c;提前备份U盘内容 2.电脑&#xff1a;下载Windows系统并进行启动盘制作 二、Windows启动盘制作 1.微软官网下载启动盘制作工具微软官网下载启动盘制作工具https://www.microsoft.com/zh-c…...

Token Statistics Transformer:线性注意力革命,重新定义Transformer效率天花板

“TOKEN STATISTICS TRANSFORMER: LINEAR-TIME ATTENTION VIA VARIATIONAL RATE REDUCTION” 由Ziyang Wu等人撰写。文章提出一种新型Transformer注意力算子&#xff0c;通过对最大编码率降低&#xff08; M C R 2 MCR^{2} MCR2&#xff09;目标的变分形式进行展开优化得到&…...

Django 5实用指南(二)项目结构与管理

2.1 Django5项目结构概述 当你创建一个新的 Django 项目时&#xff0c;Django 会自动生成一个默认的项目结构。这个结构是根据 Django 的最佳实践来设计的&#xff0c;以便开发者能够清晰地管理和维护项目中的各种组件。理解并管理好这些文件和目录结构是 Django 开发的基础。…...

JAVA监听器(学习自用)

一、什么是监听器 servlet监听器是一种特殊的接口&#xff0c;用于监听特定的事件&#xff08;如请求创建和销毁、会话创建和销毁、上下文的初始化和销毁&#xff09;。 当Web应用程序中反生特定事件时&#xff0c;Servlet容器就会自动调用监听器中相应的方法来处理这些事件。…...

Ubuntu下mysql主从复制搭建

本文介绍mysql 8.4主从集群的搭建&#xff0c;从单个机器安装到集群的配置&#xff0c;整体走了一遍&#xff0c;希望对大家有帮助。mysql 8.4和之前的版本命令上有些变化&#xff0c;大家用来参考。 0、环境 ubuntu&#xff1a; 22.04mysql&#xff1a;8.4 1、安装mysql 1…...

VirtualBox 中使用 桥接网卡 并设置 MAC 地址

在 VirtualBox 中使用 桥接网卡 并设置 MAC 地址&#xff0c;可以按照以下步骤操作&#xff1a; 步骤 1&#xff1a;设置桥接网卡 打开 VirtualBox&#xff0c;选择你的虚拟机&#xff0c;点击 “设置” (Settings)。进入 “网络” (Network) 选项卡。在 “适配器 1” (Adapt…...

Ubuntu 20 掉显卡驱动的解决办法

目录 问题背景解决办法Step1&#xff1a;首先查看当前linux内核Step2&#xff1a;重启Step3&#xff1a;进入ubuntu advanced &#xff08;即高级选项&#xff09;Step4&#xff1a;查看有哪些linux内核Step5&#xff1a;如果滚回老板kernel还是没有驱动&#xff0c;就找到驱动…...

EasyPoi系列之框架集成及基础使用

EasyPoi系列之框架集成及基础使用 1 EasyPoi1.1 gitee仓库地址 2 EasyPoi集成至SpringBoot2.1 maven引入jar包 3 EasyPoi Excel导出3.1 基于实体对象导出3.1.1 Excel 注解3.1.2 编写实体3.1.3 编写导出方法3.1.4 导出效果 3.2 基于模板导出3.2.1 编写模板文件3.2.2 编写导出方法…...

Web后端 Tomcat服务器

一 Tomcat Web 服务器 介绍&#xff1a; Tomcat是一个开源的Java Servlet容器和Web服务器&#xff0c;由Apache软件基金会开发。它实现了Java Servlet和JavaServer Pages (JSP) 技术&#xff0c;用于运行Java Web应用程序。Tomcat轻量、易于配置&#xff0c;常作为开发和部署…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...