多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Python核心语法(六):模块

Python核心语法(六):模块 Python核心语法六模块前言前六篇我们梳理了数据存储与运算、流程控制语句、数据容器、函数、正则表达式、类型注解程序已经能存数据、做判断、管理集合、封装代码、处理文本、给代码贴标签了。但你有没有发现一个问题代码越写越多全堆在一个文件里找个函数要滚半天屏而且有些功能别人早就写好了——发 HTTP 请求、算日期、生成随机数——难道每次都自己造轮子这一篇整理模块——Python 组织代码和复用代码的核心机制。学会它你的代码才能真正工程化一个文件拆成多个文件别人写好的工具一键拿过来用。这是从小白迈向进阶的必修课也是 AI 时代更重要的能力大模型的训练数据决定了它知道哪些模块你报错时它能一眼看出是 import 出了问题靠的就是对模块体系的理解。模块主要分为四大块模块的导入import、from import、as 起别名四种写法各取所需自定义模块自己写 .py 文件给别人导入含__name__ __main__经典写法包文件夹形式的模块__init__.py的作用相对导入初步第三方库pip 安装与换源、虚拟环境初步一、模块是什么1.生活中的类比你家里有工具箱锤子、螺丝刀、药箱感冒药、创可贴、文具盒笔、尺子。写代码时不需要把所有工具都摆在桌面上——需要锤子时喊一声把工具箱里的锤子拿来就行。模块就是 Python 世界的工具箱。模块Module一个 .py 文件就是一个模块。文件里定义的函数、变量、类都可以被别的文件导入使用。模块名就是文件名不含 .py 后缀。2.为什么要用模块复用写一次到处用。Python 自带的 time、random、json 模块全世界的 Python 工程师都在用同一份代码。分类管理按功能拆文件——处理日期的放 date_utils.py处理文件的放 file_utils.py项目再大也不乱。避免命名冲突模块像一个姓氏。my_utils.format 和 other_utils.format 可以共存就像张家的锤子和李家的锤子互不干扰。3.Python 模块的三种来源来源说明例子内置模块装完 Python 就有直接 importtime、random、json、os第三方模块别人写好放网上pip 装了才能用requests、numpy、pandas自定义模块你自己写的 .py 文件my_utils.py二、模块的导入1.四种导入方式语法效果适合场景import 模块名导入整个模块最常用代码清晰import 模块名 as 别名导入并起别名名字太长或避免重名from 模块名 import 工具只导入某个工具只用一两个函数时from 模块名 import *导入所有工具图省事不推荐见注意方式一import 模块名importtimeprint(开始)time.sleep(1)# 暂停1秒再执行函数名前面必须带模块名.print(结束)输出结果开始 停顿约1秒后 结束*注意import 语句要写在文件顶部函数定义之外。虽然 Python 允许写在函数内部或文件中部但写在顶部是行业规范打开文件一眼看清依赖了哪些模块。方式二起别名importtimeast t.sleep(1)print(OK)起别名最常见的场景是给第三方库起短名——全世界 Python 工程师的行业黑话importnumpyasnp# 数据计算库importpandasaspd# 表格数据处理库importmatplotlib.pyplotasplt# 画图库*注意别名一旦起好全文件只能用别名原名失效。起了 import numpy as np 之后再写 numpy.array(…) 会报 NameError: name ‘numpy’ is not defined。方式三from … import …fromtimeimportsleepprint(开始)sleep(1)# 不用写 time. 前缀了print(结束)*注意from import 拿到的工具是复制到当前文件不是引用过来。如果之后源模块的值变了当前文件里的不会跟着变对函数、类这类整体没影响影响的是变量——想深究可以搜模块缓存与导入副作用。方式四from … import *不推荐fromtimeimport*sleep(1)print(OK)一行导入模块里的所有工具不用写前缀。看着方便但问题很大假如导入了两个模块都有 format 函数后导入的会悄悄覆盖先导入的而且你根本察觉不到。除非写临时小脚本正式代码别这么写。*注意import * 会污染命名空间——它把对方所有名字一股脑倒进你的文件名字冲突了都不报错排起错来非常痛苦。优先用 import 模块名 或 from 模块名 import 具体工具。2.导入同名工具冲突frommathimportpowfrombuiltinsimportpow# 假设两个模块都有 powprint(pow(2,10))输出结果1024上面的例子为了演示两个模块都有 powmath.pow 和内置的 pow实际不需要 import builtins——重点是后导入的覆盖先导入的。这里两次导入最终生效的是 builtins.pow恰好功能一样所以看不出来。*注意同名的工具后 import 的胜出。上面的例子为了演示实际写代码时拿不准就老老实实用 import 模块名用 模块名.工具 访问永远不会冲突。三、自定义模块1.自己写一个模块新建文件 my_utils.py# my_utils.py —— 一个自定义模块defformat_price(price):把数字格式化成价格字符串returnf¥{price:.2f}PI3.14159在同一个文件夹里新建 main.pyimportmy_utilsprint(my_utils.format_price(9.5))print(my_utils.PI)输出结果¥9.50 3.14159*注意自定义模块的查找路径import my_utils 能成功是因为两个文件在同一个文件夹里。Python 会先在当前文件所在目录找找不到再去安装目录找。把 my_utils.py 删了会报 ModuleNotFoundError。2.__name__ __main__最经典的写法模块文件里除了提供工具往往还有自我测试代码。但如果直接写# my_utils.pydefformat_price(price):returnf¥{price:.2f}# 自我测试代码print(format_price(9.5))main.py 一导入它测试代码也跟着执行了——我们只想用工具不想看你测试__name__就是解决这个问题的。name是每个模块的内置属性模块被直接运行时__name__等于__main__被导入时__name__等于模块名。# my_utils.pydefformat_price(price):returnf¥{price:.2f}if__name____main__:# 只有直接运行这个文件才执行被导入时不执行print(自测,format_price(9.5))# main.pyimportmy_utilsprint(my_utils.format_price(19.9))print(my_utils.__name__)# 看看被导入时 __name__ 是什么输出结果¥19.90 my_utils直接运行 my_utils.py 会输出自测 ¥9.50运行 main.py 时自测代码被跳过。这就是每个正规 Python 项目的标准写法看 GitHub 上任何开源项目源码几乎每个文件末尾都有这个 if。*注意直接运行的文件__name__一定是 “main”。所以每个项目只能有一个主入口文件其他被导入的文件__name__是各自的模块名。别把 ifname “main” 写在每个文件里当摆设它只保护被导入的场景。3.限制导入__all__模块可以声明我只愿意公开哪些工具# my_utils.py__all__[format_price]# 只公开 format_pricedefformat_price(price):returnf¥{price:.2f}def_internal_helper():return这是内部工具不希望外人用frommy_utilsimport*print(format_price(9.5))# 正常__all__ 名单里有它print(_internal_helper())# NameError名单里没它根本没被导入进来输出结果运行 main.py¥9.50 第4行报 NameError: name _internal_helper is not defined*注意__all__是导入名单不是禁止名单——不在名单里的名字压根不会随 import * 进来所以报的是 NameError没这个名字而不是 ImportError。但显式点名导入 from my_utils import _internal_helper 照样能成功__all__拦不住——它不提供强制保护只是约定。另外下划线开头的名字如 _internal_helper默认表示内部使用约定俗成不要去碰。四、包1.为什么要用包模块一多光靠文件名分类就不够了——工具箱、药箱、文具盒都堆在一个抽屉里还是要乱。包就是抽屉里再分格子。包Package一个文件夹里面放着多个模块且文件夹里有__init__.py文件Python 3.3 该文件可以为空甚至可以没有但有它最规范。my_project/ ├── main.py └── utils/ ← 这就是一个包 ├── __init__.py ← 包的身份证 ├── str_utils.py └── file_utils.py2.导入包里的模块# main.pyimportutils.str_utilsprint(utils.str_utils.reverse(hello))或者起别名让代码短一点importutils.str_utilsassuprint(su.reverse(hello))或者直接导入工具fromutils.str_utilsimportreverseprint(reverse(hello))输出结果三种写法效果一样olleh*注意import utils.str_utils 中的点号是层级从左往右一层层找先找 utils 文件夹包再找里面的 str_utils 模块。用了这种方式调用时必须写全utils.str_utils.reverse(…)偷懒写 str_utils.reverse(…) 会报 NameError。3.__init__.py的作用空着不写也可以但很多项目会在里面写快捷入口# utils/__init__.pyfromutils.str_utilsimportreversefromutils.file_utilsimportread_file这样用户导入时体验更好# main.pyimportutilsprint(utils.reverse(hello))# 不用写 utils.str_utils.reverse 这么长输出结果olleh*注意__init__.py里的代码会在包被导入时自动执行一次所以它天然适合做预加载/快捷入口。它本身的__name__是包名如 “utils”不是 “main”。五、第三方库与 pip1.安装第三方库内置模块直接 import 就能用第三方库必须先安装。pip 是 Python 的应用商店pip install requests装完即可导入importrequests resprequests.get(https://www.baidu.com)print(resp.status_code)输出结果2002.换源加速pip 默认从国外服务器下载国内访问慢。换成国内镜像源以清华源为例pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple想一劳永逸把镜像设为默认pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple*注意装库尽量别乱用 --user 或 sudo管理员。多项目共享一个 Python 环境时各项目依赖不同版本的库会互相打架。现代做法是每个项目一个独立的虚拟环境venv感兴趣可以先搜 venv 入门本篇先记住装库、虚拟环境这对搭档。3.常库速查表库名用途pip 安装名requests发 HTTP 请求爬虫、调接口requestsnumpy数值计算AI 必备底座numpypandas表格数据处理Excel 替代品pandasmatplotlib画图折线图、柱状图matplotlibopenpyxl读写 Excel 文件openpyxl*注意安装名和导入名可能不同最典型的例子读写图片的 Pillow 库pip 安装名是 pillow导入名却是 PILfrom PIL import Image。装不上/导不进时先查一下安装名 vs 导入名。4.安装失败常见原因报错关键词原因解决Could not find a distribution库名拼错/没换源检查拼写加 -i 换国内源No module named ‘xxx’装了但没装到当前 Python用 python -m pip install xxx 确保装进哪个 Pythonpip 版本过旧现代库需要新版 pippython -m pip install --upgrade pipSSL 错误公司网络代理/拦截换源重试或配置代理*注意一台电脑可能装了多个 Pythonpip 不一定对应你正在用的那个 Python最保险的命令是 python -m pip install 库名——以 python 开头确保哪个 Python 运行就装进哪个 Python。4.1 用 requirements.txt 管理依赖项目做完要发给别人或者部署到服务器总不能让对方一个个猜装了哪些库。标准做法是在项目根目录写 requirements.txtrequests2.31.0 numpy1.26 pandas一行一个库 锁死版本 最低版本只写名字表示不限版本。别人拿到项目一条命令装齐pip install -r requirements.txt*注意requirements.txt 是项目的配料表。没有它换台电脑你的项目就跑不起来有了它一条命令还原环境。这是团队协作的标配GitHub 开源项目几乎人人都有这个文件。六、易混淆知识点对比1.import 的四种方式方式写法调用时优点缺点import 模块import timetime.sleep(1)清晰、无冲突风险每次都带前缀import 别名import numpy as npnp.array(…)短只能用别名from import 工具from time import sleepsleep(1)少打字多个来源容易冲突from import *from time import *sleep(1)最省事污染命名空间不推荐2.__name__的两种取值场景__name__的值if__name__ __main__内的代码文件被直接运行“main”执行文件被导入模块名如 my_utils跳过3.模块 vs 包对比项模块包本质一个 .py 文件一个带__init__.py的文件夹导入写法import my_utilsimport utils.str_utils点号表示层级需要__init__.py不需要规范上需要适合工具少、项目小工具多、项目大4.pip install 的三种来源写法从哪装适合场景pip install requestsPyPI 官方仓库默认日常 95% 场景pip install xxx -i 镜像地址指定镜像源国内网络慢pip install githttps://…直接装 GitHub 项目库还没发布到 PyPI 时七、小结模块就是一个 .py 文件模块名 文件名去掉 .py。import 一次全项目可用。四种导入方式import 模块名最稳、加 as 起别名numpy → np、from … import 工具局部引用、from … import *不推荐污染命名空间。__name__是模块的身份牌直接运行是 “main”被导入是模块名。ifname “main” 保护测试代码不被执行。__all__是模块的公开名单但只对 import * 生效不提供强制保护。包是带__init__.py的文件夹import 点号是层级__init__.py可写快捷入口。pip 安装第三方库python -m pip install 库名 最保险避免多个 Python 装错地方requirements.txt 是项目配料表换机一条命令还原环境。装库的坑安装名≠导入名pillow → PIL多 Python 环境最容易装错国内网络记得换源。
返回列表