Python 零基础入门系列(十一):模块和包

📦 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 解释器会按照以下顺序查找模块:

  1. 当前目录:首先在运行脚本的同一目录下查找。
  2. 环境变量 PYTHONPATH:如果设置了该环境变量,Python 会去这些目录查找。
  3. 标准库目录 :Python 安装路径下的 lib 目录。
  4. 第三方库目录(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 什么是包

要成为一个包,目录必须满足以下条件:

  1. 目录中必须包含一个名为 __init__.py 的文件(在 Python 3.3+ 中,这个文件可以省略,称为"命名空间包",但显式定义它仍是最佳实践)。
  2. 目录中包含 .py 文件(子模块)。

示例目录结构

复制代码
my_project/
├── main.py
└── utils/                  # 这是一个包
    ├── __init__.py
    ├── math_tools.py       # 子模块
    └── string_tools.py     # 子模块

3.2 __init__.py 的作用

这个文件在导入包时会被自动执行,它有三个主要作用:

  1. 标识包:告诉 Python 这是一个包而不是普通文件夹。
  2. 初始化代码:可以在这里写包加载时的初始化逻辑。
  3. 定义 __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

代码实现

  1. calculator/basic.py

    python 复制代码
    def add(a, b):
        return a + b
    
    def subtract(a, b):
        return a - b
  2. calculator/advanced.py

    python 复制代码
    import math
    
    def sqrt(x):
        return math.sqrt(x)
    
    def power(base, exp):
        return base ** exp
  3. calculator/__init__.py

    python 复制代码
    # 将子模块的内容导入到包的命名空间,方便用户直接从包导入
    from .basic import add, subtract
    from .advanced import sqrt, power
    
    # 定义 __all__ 方便 IDE 提示和 * 导入
    __all__ = ['add', 'subtract', 'sqrt', 'power']
  4. 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 日

✍️ 作者:书到用时方恨少!

相关推荐
Lenyiin2 小时前
深度剖析 C 语言标准IO库:stdio 实现原理与实战指南
c语言·开发语言
阿kun要赚马内2 小时前
Python面向对象编程:封装性
开发语言·python
Yao.Li2 小时前
PVN3D TensorRT 环境配置指南
人工智能·python·具身智能
郝学胜-神的一滴2 小时前
巧解括号序列分解问题:栈思想的轻量实现
开发语言·数据结构·c++·算法·面试
zzwq.2 小时前
Python面向对象编程(OOP)基础详解
python
代码改善世界2 小时前
【C++初阶】string类(一):从基础到实战
开发语言·c++
计算机安禾2 小时前
【数据结构与算法】第15篇:队列(二):链式队列的实现与应用
c语言·开发语言·数据结构·c++·学习·算法·visual studio