程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

python学习教程-第九节内容(函数、模块、包)

hfteth 2025-08-02 18:21:36 技术文章 7 ℃

函数式编程

基本概念

函数式编程(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、包:相关功能组合,代码组织

总结

简单记忆:模块是文件,包是文件夹;包装模块,模块实现功能

最近发表
标签列表