深色模式
第 06 章 · 模块与包:学会用现成的轮子
本章目标
会导入别人写好的模块,会把自己的代码拆成模块,认识一批"必须知道"的标准库。
6.1 什么是模块
一个 .py 文件就是一个模块。模块里可以放变量、函数、类,别的文件导入后就能用。
python
import math
print(math.sqrt(16)) # 4.0
print(math.pi) # 3.1415926535897936.2 四种导入写法
python
import math # ① 最推荐:来源清楚
print(math.sqrt(9))
import math as m # ② 起别名(社区习惯:numpy as np)
print(m.sqrt(9))
from math import sqrt, pi # ③ 只导入需要的名字
print(sqrt(9))
from math import * # ④ 不推荐:污染命名空间,看不出 sqrt 从哪来建议:日常用 ①,写数据分析用 ②,明确只用一两个函数时用 ③。
6.3 写自己的模块
目录结构:
text
myproject/
├── main.py
└── tools.pytools.py:
python
def add(a, b):
return a + b
def is_even(n):
return n % 2 == 0main.py:
python
import tools
print(tools.add(1, 2)) # 3
print(tools.is_even(4)) # Trueif __name__ == "__main__": 是干什么的
python
# tools.py
def add(a, b):
return a + b
if __name__ == "__main__":
# 只有"直接运行 tools.py"时才执行;
# 被 import 时不会执行,避免做多余的事 / 干扰别人
print(add(1, 2))一句话:给模块写的"自测代码"放这里。
6.4 模块从哪里找
导入时 Python 按顺序找:
- 当前脚本所在目录
- 环境变量
PYTHONPATH指定的目录 - 标准库目录
- 第三方库目录(
site-packages,pip 装的东西在这里)
查看搜索路径:
python
import sys
print(sys.path)⚠️ 最大的坑:自己的文件叫了标准库的名字(比如 random.py、json.py、email.py),导入就会出乱子。取名时避开。
6.5 包(package):一堆模块的文件夹
text
mypkg/
├── __init__.py # 有这个文件(可以为空)才是"包"
├── math_tools.py
└── text_tools.pypython
from mypkg import math_tools
from mypkg.text_tools import clean
print(math_tools.add(1, 2))
print(clean(" hi "))现代 Python 支持"命名空间包"(没有
__init__.py也行),但自己写项目加上__init__.py最稳妥。
6.6 必知的标准库(官方第 6/10/11 章精选)
标准库就是"Python 自带的工具箱",不用安装就能用。
⚠️ 阅读提示:本节是速览,先挑下面 5 个用熟就够 ——
pathlib(路径/文件)、datetime(时间)、re(文本匹配)、collections(计数/分组)、random(随机)。 其它小节第一遍只扫一眼,别在这里背 API;第 10 章会把常用模块重讲一遍,带更多能直接抄的例子。
路径与文件
python
from pathlib import Path # 推荐:跨平台,不用管斜杠方向
p = Path("data") / "a.txt"
print(p.name, p.suffix, p.parent)
print(p.exists())
import os
print(os.getcwd()) # 当前目录
print(os.listdir(".")) # 列目录
import glob
print(glob.glob("*.py")) # 通配符找文件字符串与正则
python
s = "2026-09-18"
print(s.replace("-", "/")) # 2026/09/18
print(s.split("-")) # ['2026', '09', '18']
print("/".join(["a", "b"])) # a/b
import re
m = re.search(r"\d{4}-\d{2}-\d{2}", "今天是 2026-09-18 星期五")
print(m.group()) # 2026-09-18
print(re.findall(r"\d+", "a1b22c333")) # ['1', '22', '333']正则常用符号:\d 数字、\w 字母数字下划线、. 任意字符、+ 一次以上、* 零次以上、{2,4} 次数范围、[] 字符集。
数学与随机
python
import math, random
print(math.floor(3.7), math.ceil(3.2)) # 3 4
print(round(3.456, 2)) # 3.46
print(random.randint(1, 6)) # 掷骰子
print(random.choice(["石头", "剪刀", "布"]))
items = [1, 2, 3, 4]
random.shuffle(items) # 原地打乱
print(random.sample(items, 2)) # 随机抽 2 个日期时间
python
from datetime import datetime, timedelta
now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2026-09-18 08:30:00
tomorrow = now + timedelta(days=1)
d = datetime.strptime("2026-09-18", "%Y-%m-%d")
print(d.year, d.month, d.day)系统与命令行
python
import sys
print(sys.argv) # 命令行参数
import subprocess
result = subprocess.run(["python", "--version"], capture_output=True, text=True)
print(result.stdout)数据与算法(重点推荐)
python
from collections import Counter, defaultdict
c = Counter("hello") # 计数神器
print(c.most_common(2)) # [('l', 2), ('h', 1)]
d = defaultdict(list)
d["水果"].append("苹果") # 键不存在时自动建空列表
from itertools import combinations, product
print(list(combinations([1, 2, 3], 2))) # [(1,2), (1,3), (2,3)]其它"内置电池"(第一遍可跳过,用到再查)
| 模块 | 用途 |
|---|---|
json | 读写 JSON(第 07 章) |
csv | 读写表格 |
hashlib | 计算哈希/校验文件 |
uuid | 生成唯一 ID |
zipfile / tarfile | 压缩解压 |
timeit | 测代码跑多快 |
logging | 正经的日志(代替 print) |
argparse | 写命令行工具的参数解析 |
sqlite3 | 自带的轻量数据库 |
threading | 多线程(了解) |
decimal | 精确小数(算钱用) |
6.7 练一练
- 写一个
mytext.py模块,提供count_words(text)和clean(text)两个函数,再写main.py导入使用。 - 在
mytext.py里加if __name__ == "__main__":自测代码,验证 import 时不执行、直接运行才执行。 - 用
re从一个字符串里提取出所有手机号。 - 用
collections.Counter统计一句话中出现最多的 3 个单词。
本章关键词
import / from ... import、as、__name__ == "__main__"、sys.path、包与 __init__.py、pathlib、re、datetime、collections、itertools