前六章都是单文件功夫,本章解决「代码长大之后」的组织问题:模块(文件)→ 包(目录)→ import 机制 → 标准库地图。这一章也是「Python 为什么生态无敌」的答案:机制简单 + 标准库(batteries included)太全。
# mymath.py
PI = 3.14159
def circle_area(r):
return PI * r ** 2
def _helper(x): # 下划线开头:约定「内部」,from-import 不带走
return x * 2
# main.py
import mymath # 导入模块(整个文件)
mymath.circle_area(2) # 用:模块名.成员
from mymath import circle_area # 只导入成员
circle_area(2)
from mymath import circle_area as ca # 起别名
import numpy as np # 社区惯例别名(np、pd、plt)
四种 import 风格的取舍:import module(全带,前缀清晰,推荐默认)、from module import 成员(常用成员直接用)、as 别名(惯例缩写)、from module import *(污染命名空间,禁止)。模块只导入一次(之后用缓存,sys.modules 里查;这也是第 3 章「import 的副作用只跑一遍」的原因:模块顶层代码在首次 import 时执行)。
模块多了按目录分装,带 __init__.py 的目录就是包:
myproject/
├── main.py
└── utils/
├── __init__.py # 可以是空文件,也可以做包的「门面」
├── text.py # from utils.text import clean
└── net.py
from utils.text import clean # 包名.模块名.成员
from utils import net # 或导入模块再 net.call()
__init__.py 的进阶用法:在里面写 from .text import clean,让使用者 from utils import clean 直接拿(把包的内部结构藏起来,对外只露接口——软件工程课第 4 章接口设计的 Python 版)。.py 文件内的 if __name__ == "__main__": 也在此讲透:每个模块有 __name__ 属性,被 import 时是模块名,直接运行时是 "__main__"——这个 if 是「既当库又当脚本」的双面开关,每个正式的 .py 都该有。
Python 找模块的顺序:内置 → sys.path 列表(当前目录排第一!)+ site-packages(第 1 章 venv 的安装地)。两个经典炸点全由此而来:
包的发布第三方(pip install 装的那些)遵循同一机制,只是放在 site-packages;第 1 章的 venv 之所以能隔离,就是在 sys.path 里换了一套 site-packages。
def bmi(weight: float, height: float) -> float:
return weight / height ** 2
def find(user_id: int, cache: dict[str, str] | None = None) -> str | None:
...
类型注解(3.5+)是提示而非强制(运行时不查,传错类型照样跑);配上 mypy 静态检查器(mypy main.py),在跑之前抓住类型错误(第 2 章动态类型的现代解药)。大项目标配,库的文档也靠注解自解释。语法要点:list[str]、dict[str, int](3.9+ 内置泛型),str | None 表示「或 None」(3.10+ 的联合类型写法,老代码用 Optional[str])。
「Python 自带电池」——常用需求先查标准库再找三方包。按用途分区的速查地图(每个都值得 help() 一下):
| 需求 | 模块 | 代表 API |
|---|---|---|
| 命令行参数 | argparse | 解析 --flag 选项(第 10 章实战) |
| 数学/随机 | math, random, statistics | ceil, choice, mean |
| 时间 | datetime | datetime.now(), timedelta |
| 文本/正则 | re, json, csv | re.findall, json.load(第 10 章) |
| 文件/路径 | pathlib, shutil, os | glob, copy, walk(第 5 章) |
| 数据结构加强 | collections | Counter(一行数词频!), deque, defaultdict |
| 迭代工具 | itertools | product, groupby, combinations |
| 调试 | logging, pprint | 日志(替代 print)、美化打印 |
| 系统/子进程 | os, subprocess | 跑外部命令 |
| 网络 | urllib | 最基础的 HTTP(第 10 章用 requests) |
collections.Counter 单独点名(最常用彩蛋):
from collections import Counter
words = "to be or not to be".split()
Counter(words) # {'to': 2, 'be': 2, 'or': 1, 'not': 1}
Counter(words).most_common(2) # [('to', 2), ('be', 2)]
第 4 章手写的词频统计器,标准库一行。**「先搜标准库」**是 Pythonic 的核心习惯:你写的每个工具函数,九成标准库已有更好的版本。
models.py,把输入输出逻辑拆成 io_utils.py,主程序 main.py import 它们;验证 python main.py 和 python -c "from models import Student" 双模式(顺带理解 name 开关)。