📦 Python 零基础入门系列(十一):模块和包
构建可复用的代码库,告别"脚本小子"时代
📢 系列说明 :
在前九篇中我们掌握了基础语法,第十篇深入了闭包和装饰器。随着代码量的增加,将所有代码写在一个文件里会变得难以维护。
本文将教你如何使用模块(Module) 和 包(Package) 来组织代码,让项目结构清晰、易于复用。
📅 更新时间:2026 年 3 月 28 日
🎯 本篇你将学到 :模块导入机制、
__name__变量、包的创建与__init__.py、常用标准库模块⏱️ 预计阅读时间 :50-60 分钟 | 💻 实践时间:40-50 分钟
📌 前置知识:已完成前九篇(特别是函数基础)
✍️ 作者:书到用时方恨少!
🌟 前言:为什么要模块化?
想象一下,如果你要开发一个大型游戏,所有的代码(角色、地图、战斗、网络、UI)都写在一个文件里,这个文件可能会有几万行代码。这不仅难读,而且修改一处代码可能会导致整个程序崩溃。
模块化就是将一个大程序分解为多个独立的、功能单一的文件(模块),然后通过导入机制将它们组合起来。这就像组装电脑,主板、CPU、内存条各司其职,坏了哪个换哪个,不需要重造整台电脑。
1. 模块基础
1.1 什么是模块
在 Python 中,一个 .py 文件就是一个模块。模块可以包含函数、类、变量和可执行代码。
示例:创建一个简单的模块
python
# 文件名: my_module.py
def greet(name):
return f"Hello, {name}!"
PI = 3.14159
class Calculator:
@staticmethod
def add(a, b):
return a + b
1.2 import 语句详解
使用 import 可以导入整个模块。导入后,通过 模块名.属性名 的方式访问。
python
# main.py
import my_module
print(my_module.greet("Alice")) # Hello, Alice!
print(my_module.PI) # 3.14159
calc = my_module.Calculator()
print(calc.add(5, 3)) # 8
1.3 from ... import 用法
如果你只想使用模块中的某个特定函数或变量,可以使用 from ... import,这样可以直接使用名称,无需加模块前缀。
python
# main.py
from my_module import greet, PI
from my_module import Calculator
print(greet("Bob")) # Hello, Bob! (无需 my_module.greet)
print(PI) # 3.14159
别名(Alias) :
如果模块名太长,可以使用 as 设置别名。
python
import my_module as mm
print(mm.greet("Charlie"))
# 常见的第三方库别名
import numpy as np
import pandas as pd
1.4 模块搜索路径
当你导入一个模块时,Python 解释器会按照以下顺序查找模块:
- 当前目录:首先在运行脚本的同一目录下查找。
- 环境变量
PYTHONPATH:如果设置了该环境变量,Python 会去这些目录查找。 - 标准库目录 :Python 安装路径下的
lib目录。 - 第三方库目录(site-packages):通过 pip 安装的库通常在这里。
你可以通过 sys.path 查看具体的搜索路径列表:
python
import sys
for path in sys.path:
print(path)
2. 模块进阶
2.1 __name__ 和 __main__
这是 Python 中一个非常重要的惯用法(Idiom)。
__name__:每个模块都有一个内置变量__name__。- 如果模块是被导入的,
__name__的值是模块的文件名(不带.py)。 - 如果模块是被直接执行的,
__name__的值是字符串"__main__"。
- 如果模块是被导入的,
用途:利用这个特性,我们可以让一个模块既可以作为脚本独立运行,也可以作为模块被导入。
python
# script.py
def main():
print("这是主程序逻辑")
def helper():
print("这是一个辅助函数")
# 只有当直接运行此文件时,才执行 main()
if __name__ == "__main__":
main()
print(f"__name__ 的值是: {__name__}")
else:
print(f"模块被导入,__name__ 的值是: {__name__}")
运行效果:
python script.py:输出 "这是主程序逻辑"。- 在另一个文件中
import script:不会输出 "这是主程序逻辑",只加载函数定义。
2.2 模块的缓存与重新加载
Python 为了提高效率,导入过的模块会被缓存在 sys.modules 字典中。这意味着,同一个模块在一个程序运行期间只会被导入和执行一次。
如果你在交互式环境中修改了模块代码,想重新加载,可以使用 importlib 模块:
python
import importlib
import my_module
importlib.reload(my_module) # 强制重新加载
3. 包的概念
当项目变得更大时,仅仅使用模块还不够,我们需要层级结构。包(Package) 就是包含其他模块或子包的模块,它本质上是一个目录。
3.1 什么是包
要成为一个包,目录必须满足以下条件:
- 目录中必须包含一个名为
__init__.py的文件(在 Python 3.3+ 中,这个文件可以省略,称为"命名空间包",但显式定义它仍是最佳实践)。 - 目录中包含
.py文件(子模块)。
示例目录结构:
my_project/
├── main.py
└── utils/ # 这是一个包
├── __init__.py
├── math_tools.py # 子模块
└── string_tools.py # 子模块
3.2 __init__.py 的作用
这个文件在导入包时会被自动执行,它有三个主要作用:
- 标识包:告诉 Python 这是一个包而不是普通文件夹。
- 初始化代码:可以在这里写包加载时的初始化逻辑。
- 定义
__all__:控制from package import *时导入哪些模块。
示例 __init__.py:
python
# utils/__init__.py
print("Utils 包被加载了!")
# 定义 __all__ 控制 * 导入
__all__ = ['math_tools', 'string_tools']
3.3 包的导入方式(相对导入 vs 绝对导入)
绝对导入 (推荐):
从项目根目录或 Python 路径开始导入。
python
# 在 main.py 中
from utils.math_tools import add
from utils import string_tools
相对导入 :
在包内部使用,. 代表当前目录,.. 代表上一级目录。
python
# 在 utils/math_tools.py 中想导入同级的 string_tools
from .string_tools import process_string
# 在 utils/subpackage/module.py 中想导入上级的 math_tools
from ..math_tools import add
4. 常用标准库模块
Python 有非常强大的"自带电池"(Batteries Included),以下是几个最常用的内置模块:
4.1 os 模块 - 操作系统接口
用于处理文件和目录路径、环境变量等。
python
import os
# 获取当前工作目录
print(os.getcwd())
# 列出目录下的文件
print(os.listdir('.'))
# 创建目录
os.makedirs('new_folder', exist_ok=True)
# 路径拼接(跨平台兼容)
path = os.path.join('folder', 'subfolder', 'file.txt')
print(path)
4.2 sys 模块 - 系统相关
提供访问解释器变量和函数的接口。
python
import sys
# 打印命令行参数
print("命令行参数:", sys.argv)
# 退出程序
# sys.exit("程序出错,即将退出")
# 查看 Python 版本
print(sys.version)
4.3 json 模块 - 数据序列化
用于将 Python 对象(字典、列表)与 JSON 字符串互相转换,常用于 Web 开发和配置文件。
python
import json
# Python 对象转 JSON 字符串
data = {"name": "Tom", "age": 18}
json_str = json.dumps(data)
print(json_str) # {"name": "Tom", "age": 18}
# JSON 字符串转 Python 对象
loaded_data = json.loads(json_str)
print(loaded_data['name']) # Tom
# 读写文件
with open('data.json', 'w') as f:
json.dump(data, f) # 直接写入文件
4.4 datetime 模块 - 日期时间
处理日期和时间。
python
from datetime import datetime, timedelta
# 获取当前时间
now = datetime.now()
print(now)
# 格式化输出
print(now.strftime("%Y-%m-%d %H:%M:%S"))
# 时间计算
tomorrow = now + timedelta(days=1)
print("明天:", tomorrow)
5. 综合实战
5.1 创建自己的工具包
让我们按照之前的目录结构,创建一个简单的工具包。
目录结构:
bash
calculator_project/
├── main.py
└── calculator/
├── __init__.py
├── basic.py
└── advanced.py
代码实现:
-
calculator/basic.py:pythondef add(a, b): return a + b def subtract(a, b): return a - b -
calculator/advanced.py:pythonimport math def sqrt(x): return math.sqrt(x) def power(base, exp): return base ** exp -
calculator/__init__.py:python# 将子模块的内容导入到包的命名空间,方便用户直接从包导入 from .basic import add, subtract from .advanced import sqrt, power # 定义 __all__ 方便 IDE 提示和 * 导入 __all__ = ['add', 'subtract', 'sqrt', 'power'] -
main.py:python# 因为 __init__.py 的设计,我们可以这样直接导入 from calculator import add, sqrt print(add(10, 5)) # 15 print(sqrt(16)) # 4.0
5.2 发布和使用第三方包(pip 基础)
虽然本篇主要讲内置模块,但了解如何使用外部包是必要的。
Python 有一个庞大的第三方库生态系统,通过 pip(包管理器)安装。
常用命令:
bash
# 安装包
pip install requests
# 在代码中使用
import requests
response = requests.get('https://httpbin.org/get')
print(response.status_code)
# 导出当前环境依赖
pip freeze > requirements.txt
# 根据文件安装依赖
pip install -r requirements.txt
🎉 结语
通过本篇的学习,你已经掌握了 Python 项目组织的核心------模块和包。
- 你学会了如何将代码拆分为
.py文件(模块)。 - 你理解了
if __name__ == "__main__":的作用,这是编写可复用脚本的关键。 - 你掌握了如何构建目录结构(包)来管理大型项目。
- 你熟悉了
os,sys,json,datetime等常用"自带电池"。
下一步建议 :
尝试把你之前写的代码(比如计算器、学生管理系统)重构为模块化的结构。将功能函数放在一个模块中,将主程序逻辑放在另一个模块中。
🚀 下一篇预告 :《Python 零基础入门系列(十二):文件操作详解》
我们将学习如何读写硬盘上的文件,这是数据持久化的基础。
📅 更新时间 :2026 年 3 月 29 日
✍️ 作者:书到用时方恨少!