网站首页 > 技术文章 正文
函数式编程
基本概念
函数式编程(Functional Programming)是一种编程范式,它将计算视为数学函数的求值,避免改变状态和使用可变数据。Python 虽然不是纯函数式语言,但提供了丰富的函数式编程特性。
核心概念
1、纯函数 (Pure Functions)
(1)相同输入总是产生相同输出
(2)没有副作用(不修改外部状态)
示例:
2、不可变性
(1)数据一旦创建就不能被修改
(2)任何"修改"操作都返回新对象。
示例:
3、一等函数
函数可以像变量一样被传递和使用。
与面向对象编程对比
高阶函数
变量可以指向函数
以Python内置的求绝对值的函数abs()为例,调用该函数用以下代码:
但是如果只写abs呢?
可见,abs(-10)是函数调用,而abs是函数本身。
要获得函数调用结果,我们可以把结果赋值给变量。
但是,如果把函数本身赋值给变量呢
结论:函数本身也可以赋值给变量,即:变量可以指向函数。
如果一个变量指向了一个函数,那么可否通过该变量来调用这个函数?用代码验证一下:
说明变量f现在已经指向了abs函数本身。直接调用abs()函数和调用变量f()完全相同。
函数名也是变量
函数名其实就是指向函数的变量,对于abs()这个函数,完全可以把函数名abs看成变量,它指向一个可以计算绝对值的函数。
如果把abs指向其他对象,会有什么情况发生
把abs指向10后,就无法通过abs(-10)调用该函数了!因为abs这个变量已经不指向求绝对值函数而是指向一个整数10。
注意:由于abs函数实际上是定义在import builtins模块中的,所以要让修改abs变量的指向在其它模块也生效,要用import builtins; builtins.abs = 10。
传入函数
既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
一个简单的高阶函数:
当我们调用add(-5, 6, abs)时,参数x,y和f分别接收-5,6和abs,根据函数定义,我们可以推导计算过程为:
用代码验证一下:
编写高阶函数,就是让函数的参数能够接收别的函数。
map
基本概念
map() 是 Python 内置函数,用于对可迭代对象的每个元素应用指定函数。
语法
map(function, iterable)
特点
1、惰性求值:返回的是迭代器而非列表
2、可以处理多个可迭代对象
3、不会修改原始数据
重要特性
1、返回 map 对象:需要用 list() 转换才能查看结果
2、惰性求值:只在需要时才计算
3、内存友好:不会一次性创建所有结果
示例代码
等价于for循环
应用场景
1、数据清洗和转换
2、类型转换
3、并行处理多个序列
总结
map() 适用于需要对序列每个元素执行相同操作的场景,是函数式编程的重要工具。
reduce
基本概念
reduce(function, sequence[, initial]) 函数对序列中的元素进行累积计算,将前面的计算结果与下一个元素一同传入函数进行计算。
特点
1、需要从 functools 模块导入
2、将序列"缩减"为单个值
3、可以指定初始值
示例代码
等价for循环
应用场景
1、计算累积值(求和、求积等)
2、查找最大值/最小值
3、实现更复杂的聚合操作
性能考虑
1、map 通常比等效的列表推导式或 for 循环稍快
2、reduce 在某些情况下可能不如显式循环清晰
3、Python 3 中 map 和 reduce 都返回迭代器,节省内存
现代替代方案
对于简单操作,列表推导式通常更 Pythonic
filter
基本概念
filter() 是 Python 内置函数,用于过滤可迭代对象中满足条件的元素。
语法
filter(function, iterable)
基本用法
特殊用法
1、function 为 None
2、使用自定义函数
应用场景
1、数据清洗
2、条件筛选
3、文件处理
重要特性
1、返回 filter 对象:需要用 list() 转换才能查看结果
2、惰性求值:只在需要时才计算
3、保持原序:结果保持原始顺序
总结
filter() 适用于需要根据条件筛选数据的场景,是数据处理的重要工具。
模块
基本概念
模块是Python程序组织的基本单元,它允许你将相关的代码组织在一起,实现代码的复用和命名空间的管理。
模块是一个包含 Python 定义和语句的 .py 文件。文件名就是模块名(去掉 .py 后缀)。模块可以包含:
1、函数定义
2、类定义
3、变量
4、可执行代码
主要作用
1、代码复用
将常用功能封装成模块,供多个程序使用。
2、命名空间管理
避免命名冲突
3、代码组织
将大型程序分解为多个逻辑单元。
4、共享和分发
便于代码的共享和分发
创建模块
创建一个简单的模块 mymodule.py
导入模块
1、基本导入方式
import 模块名
2、导入特定内容
3、导入所有内容(不推荐)
4、给模块或导入项起别名
模块的搜索路径
当导入一个模块时,Python 解释器按以下顺序搜索模块:
1、内置模块
Python 自带的模块(如 sys, math 等)
2、当前目录
执行脚本所在的目录
3、PYTHONPATH
环境变量中指定的目录列表
4、安装的第三方模块
如 pip 安装的包(通常在 site-packages 目录)
可以通过 sys.path 查看模块搜索路径。
模块的特殊属性
每个模块都有一些内置的特殊属性
__name__
模块名称
用途
1、当模块被直接运行时,__name__ 的值是 "__main__"
2、当模块被导入时,__name__ 的值是模块的实际名称
3、用于区分模块是被直接执行还是被导入。
__file__
模块对应的文件路径
用途
1、获取模块的文件位置
2、构建相对于模块位置的文件路径
3、动态加载资源文件
__doc__
模块的文档字符串
__package__
模块所属的包名
其他说明
Python模块中的__name__等双下划线包围的属性是特殊属性(Special Attributes),也称为魔术属性或内置属性。这些属性由Python解释器自动创建和维护。
双下划线语法的含义
双下划线开头和结尾的属性格式(__attribute__)在Python中有特殊意义:
1、这是Python的命名约定,表示这些属性具有特殊功能。
2、由Python解释器内部管理,不应该被用户随意修改。
3、提供了访问Python内部机制的接口。
注意事项
1、不要随意修改
这些属性由Python管理,修改可能导致意外行为 。
2、只读性质
大多数特殊属性是只读的
3、命名冲突
避免创建与内置特殊属性同名的自定义属性
4、文档规范
遵循PEP 8等Python编码规范
5、这种双下划线语法是Python设计哲学的体现,提供了一种清晰的方式来区分普通属性和具有特殊功能的系统属性。
模块的重新加载
默认情况下,模块只会在第一次导入时执行。如果需要重新加载模块(如在交互式环境中修改了模块),可以使用:
模块的最佳实践
1、模块命名
(1)使用小写字母和下划线(如 my_module.py)
(2)避免与 Python 关键字或内置模块重名
2、模块文档
(1)在模块开头添加文档字符串
(2)说明模块的功能、使用方法和示例
3、导入顺序
(1)标准库模块
(2)第三方模块
(3)本地应用/库模块
每组导入之间用空行分隔
4、避免循环导入
模块A导入模块B,同时模块B又导入模块A
5、使用 if __name__ == '__main__'
(1)将模块的直接执行代码放在这个判断中
(2)避免模块被导入时执行不必要的代码
模块的高级主题
1、编译的Python文件(.pyc)
(1)Python 会将模块编译为字节码(存储在 __pycache__ 目录)
(2)加快后续的导入速度
(3).pyc 文件是平台无关的。
2、模块的缓存
(1)导入的模块会被缓存到 sys.modules 字典中。
(2)可以通过 sys.modules 查看已加载的模块
3、模块的包属性
当模块位于包中时,__package__ 属性表示其所属的包名
常见的问题
1、ModuleNotFoundError/ImportError
常见原因
1、模块不在Python搜索路径中
2、模块文件名拼写错误
3、缺少__init__.py文件(对于包)
4、Python版本与环境不匹配
解决方法
2、循环导入
问题现象
1、模块A导入模块B,同时模块B又导入模块A
2、导致部分变量/函数未定义
示例:
解决方法
1、重构代码,提取公共部分到第三个模块
2、将导入语句移到函数内部(延迟导入)
3、使用接口模式减少直接依赖。
3、模块作为脚本执行时的路径问题
现象
1、相对导入失败(ImportError: attempted relative import with no known parent package)
2、找不到同级模块
解决方法
包
基本概念
1、包是 Python 模块的组织方式,它通过目录层次结构来组织相关的模块,使得大型项目的代码结构更加清晰和可维护。
2、包是一个包含 __init__.py 文件的目录,该目录下可以包含:
(1)Python 模块(.py 文件)
(2)子包(子目录)
(3)其他资源文件
主要作用
1、命名空间管理
避免模块命名冲突
2、代码组织
将功能相关的模块组织在一起
3、模块复用
方便代码的共享和分发
4、分层结构
支持多级模块层次
包的创建与结构
基本包结构
__init__.py 文件的作用
1、标识目录为 Python 包(Python 3.3+ 可以省略,但推荐保留)
2、初始化包代码(包被导入时执行)
3、定义 __all__ 列表控制 from package import * 的行为
4、集中导入子模块方便用户使用。
包的导入方式
1、导入整个包
import 包名
2、从包导入模块
from 包名 import 模块
3、从子包导入模块
4、导入特定内容
5、相对导入(包内部使用)
包的最佳实践
1、清晰的层次结构
(1)按功能划分包和子包
(2)避免过深的嵌套(一般不超过3-4层)
2、__init__.py 的使用
(1)可以留空,但最好包含包的文档字符串
(2)集中导入常用模块方便用户使用
(3)定义 __all__ 控制公开接口
3、命名规范
(1)包名使用小写字母和下划线
(2)避免与标准库和知名第三方包重名
(3)保持模块和包名简短但有描述性
4、依赖管理
(1)在 setup.py 中明确声明依赖。
(2)避免循环导入。
5、文档
(1)每个包和模块包含文档字符串。
(2)在 __init__.py 中写包级别的文档
包与模块的区别
核心概念
1、模块 (Module) = 一个 .py 文件
2、包 (Package) = 包含多个模块的文件夹
类比理解
模块 = 一本书
包 = 一个书架(装多本书)
文件结构对比
导入方式
关键标识
1、模块:.py 文件
2、包:包含 __init__.py 的文件夹
使用场景
1、模块:单一功能,独立文件
2、包:相关功能组合,代码组织
总结
简单记忆:模块是文件,包是文件夹;包装模块,模块实现功能。
猜你喜欢
- 2025-08-02 百张图文字 10 秒提?Python + 微信 OCR 批量识别神操作
- 2025-08-02 一文讲清怎么利用Python Django实现Excel数据表的导入导出功能
- 2025-08-02 彻底搞懂Python 中的 import 与 from import
- 2025-08-02 告别重复劳动!用Python轻松实现办公自动化(零基础入门)
- 2025-08-02 Pycharm导入python项目
- 2025-08-02 Python接口自动化之常见用例读取方法介绍
- 2025-08-02 用Python开发一个可调用工具的AI Agent,实现电脑配置专业评价
- 2025-08-02 Python魔法文件:__init__.py全面解析
- 2025-08-02 Python 文件操作与读取:从基础到进阶的全面指南
- 2025-08-02 栋察宇宙(二十一):Python 文件操作全解析
- 08-06生产环境中使用的十大 Python 设计模式
- 08-06面试必备:Python内存管理机制(建议收藏)
- 08-06服务端开发面试必背——消息队列及它的主要用途和优点。附代码
- 08-06Python 栈:深度解析与应用
- 08-06Python中的多进程
- 08-06Python Logging 最佳实践
- 08-06Python并发数据结构实现原理
- 08-06用SendGrid和Redis队列用Python调度国际空间站的电子邮件
- 最近发表
- 标签列表
-
- python中类 (31)
- python 迭代 (34)
- python 小写 (35)
- python怎么输出 (33)
- python 日志 (35)
- python语音 (31)
- python 工程师 (34)
- python3 安装 (31)
- python音乐 (31)
- 安卓 python (32)
- python 小游戏 (32)
- python 安卓 (31)
- python聚类 (34)
- python向量 (31)
- python大全 (31)
- python次方 (33)
- python桌面 (32)
- python总结 (34)
- python浏览器 (32)
- python 请求 (32)
- python 前端 (32)
- python验证码 (33)
- python 题目 (32)
- python 文件写 (33)
- python中的用法 (32)