PY-08 常用模块
08 · 常用模块(Standard Library)
📅 预计 60 分钟 | ⭐ 按考点掌握即可
✍️ 本讲配套练习:本地python grader.py 08,或网页练习
Python 自带一套「家用工具箱」,import 就能用,这就是标准库。前面学的 print、len 是内置功能;今天的 math、random、json、datetime、re、collections 是工具箱里的常备工具。原则:别人造好的轮子别自己造。本讲 15 题,建议学一节练对应题。
8.1 导入方式
import 像从抽屉里拿工具,三种拿法:
import math # 整盒拿:用 math.sqrt(16)
from os import path # 只拿一件:直接 path.join(...)
import random as r # 起小名:r.randint(1, 100)
from collections import Counter 最常用——只拿要用的,代码更短。但注意命名冲突:自己定义了 sqrt 再 from math import sqrt,后者覆盖前者,全名导入最稳。
⚠️ 常见错误:import 时机
import 放文件顶部集中管理。别在函数内部 import——虽合法但每次调用重复加载。
8.2 math —— 随身计算器
math 就是计算器。** 能做乘方,但开方、取整、三角函数还得靠它:
import math
math.sqrt(16) # 开平方 → 4.0(结果一定是 float)
math.pow(2, 10) # 2 的 10 次方 → 1024.0
math.ceil(3.2) # 向上取整 → 4(ceil 天花板)
math.floor(3.7) # 向下取整 → 3(floor 地板)
math.hypot(3, 4) # 直角边 3、4 的斜边 → 5.0
math.pi, math.e # 圆周率、自然常数
ceil/floor 就是天花板/地板:快递费 2.01 按 3 元收是 ceil,跑 2.9 公里按 2 公里算是 floor。
练习: ex01(圆面积)、ex07(斜边)。
⚠️ 常见错误:float 干扰显示
sqrt返回 float,f"{math.sqrt(16)}"得到4.0。判分对 float 有容差,展示时记得 round。
8.3 random —— 抽签盒
random 是抽签盒,做游戏、抽样都靠它。核心记住:它是伪随机——由种子(seed)决定,同一种子结果一样,因此可复现。
import random
random.random() # [0,1) 浮点数
random.randint(1, 100) # 1~100 整数,含两端 ⭐
random.choice(["a","b","c"]) # 随机抽一个
random.sample(range(100), 5) # 不重复抽 5 个
random.shuffle(lst) # 原地打乱(返回 None!)
random.seed(2026) # 固定种子,之后结果可复现
random.randint(1, 6) # 每次跑都一样
测试、判分时固定 seed 就能得到稳定输出。
练习: ex06(掷骰子,判分靠固定 seed)。
⚠️ 常见错误:随机不可测、shuffle 返回 None
① 随机输出不可预测,别写依赖随机结果的测试(除非固定 seed)。②shuffle原地修改并返回None,lst = random.shuffle(lst)会把列表变成 None。③ 不重复抽用sample,允许重复用choices。
8.4 datetime —— 日历与闹钟
datetime 管时间。两个核心操作:格式化(时间变字符串)和解析(字符串变时间)。
from datetime import datetime, timedelta
now = datetime.now() # 当前时间
now.strftime("%Y-%m-%d %H:%M:%S") # → '2026-08-02 09:50:00' ⭐
d = datetime(2027, 12, 25) # 构造具体时间
diff = d - now # 时间差 timedelta
diff.days # 相差天数
格式串常见符:%Y 四位年、%m 月、%d 日、%H 时、%M 分、%S 秒。大小写敏感:%Y(年) vs %y(两位年)、%m(月) vs %M(分)。
t = datetime.strptime("2027-12-25", "%Y-%m-%d") # 字符串→时间 ⭐
s = now.strftime("%Y年%m月%d日") # 时间→字符串 '2026年08月02日'
口诀:strptime 是 p 进 str 出,strftime 是 f 出 str。now + timedelta(days=7) 就是下周。
练习: ex04(日期差)。
⚠️ 常见错误:格式串大小写、strptime 严格匹配
①%m是月、%M是分钟,写错不报错但结果错。②strptime要求字符串和格式串严格一致,多空格或 0 就ValueError。③ 别把参数顺序记反,格式串永远在前。
8.5 collections —— 工具箱的升级配件
① Counter —— 计数器,统计次数一行顶十行:
from collections import Counter
c = Counter(["a","b","a","c","a","b"]) # Counter({'a': 3, 'b': 2, 'c': 1})
c.most_common(1) # [('a', 3)] ⭐
② defaultdict —— 带默认值的字典。普通字典访问不存在的键会 KeyError,它有"初始装备":
from collections import defaultdict
c = defaultdict(int) # 默认值 0
for ch in "hello":
c[ch] += 1 # 键不存在也敢直接加
print(dict(c)) # {'h': 1, 'e': 1, 'l': 2, 'o': 1}
defaultdict(list) 默认空列表,defaultdict(set) 默认空集合。
③ namedtuple —— 带名字的元组。普通元组 (3,4) 只能 p[0]、p[1],命名元组能用名字取:
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)
p.x, p.y # 3 4,比 p[0] 好读
仍是元组不可修改,适合坐标、成绩这类固定几项的数据。
④ deque —— 双端队列,两头快速进出,还有轮转 rotate:
from collections import deque
d = deque([1, 2, 3, 4, 5])
d.rotate(-2) # 整体左移 2 位
print(list(d)) # [3, 4, 5, 1, 2] ⭐
rotate(2) 右移、rotate(-2) 左移。轮播、循环队列一行搞定。
练习: ex03(Counter)、ex09(defaultdict)、ex10(deque.rotate)、ex11(namedtuple)、ex15(defaultdict+排序)。
⚠️ 常见错误:defaultdict 传工厂函数、namedtuple 不可改
①defaultdict(int)传工厂函数(不带括号),写defaultdict(0)会TypeError。②namedtuple不可变,p.x = 5报AttributeError,要改就重建。③Counter是字典子类,能比较、能加减。
8.6 json —— 快递打包与拆包
json 是程序间交换数据的标准快递箱。JSON 文本长得像 Python 字典,但它是纯字符串。
- 打包(Python → JSON 字符串):
json.dumps - 拆包(JSON 字符串 → Python):
json.loads
import json
data = json.loads('{"title": "哪吒", "rate": 9.0}') # → {'title': '哪吒', 'rate': 9.0}
s = json.dumps({'name': '哪吒', 'rate': 9.0}, ensure_ascii=False)
print(s) # → {"name": "哪吒", "rate": 9.0}
默认 json.dumps 会把中文转成 \uXXXX,写中文应用务必加 ensure_ascii=False。
练习: ex02(loads)、ex08(dumps)。
⚠️ 常见错误:中文变 \uXXXX、类型不支持
① 忘了ensure_ascii=False,中文全变\uXXXX。② JSON 只支持基本类型,set、datetime直接 dumps 会TypeError。③loads格式不合法抛JSONDecodeError,解析外部数据要 try。
8.7 re —— 找规律
re 是"找规律"的终极工具:写一个模式,让程序按模式匹配文本,就像在电话簿里搜"所有 138 开头的 11 位号码"。
常用元字符:
| 元字符 | 含义 | 例子 |
|---|---|---|
\d |
一个数字 | a1b 匹配 1 |
\w |
字母/数字/下划线 | a_1 |
\s |
空白 | 空格/Tab |
. |
任意一个字符 | a.c 匹配 abc |
* |
前一个出现 0 次或多次 | a* 匹配空/a/aaa |
+ |
前一个出现 1 次或多次 | a+ 不匹配空 |
? |
前一个出现 0 次或 1 次 | colou?r |
{2,4} |
前一个出现 2~4 次 | \d{11} |
^ $ |
开头 / 结尾 | ^abc、xyz$ |
[a-z] |
字符集任一个 | [0-9] 等价 \d |
import re
re.findall(r"\d+", "a1b22c333") # ['1', '22', '333'] 找所有 ⭐
re.search(r"\d+", "abc123") # 找第一个,返回 match 对象
re.match(r"\d+", "123abc") # 只匹配开头,开头不是数字则 None
re.sub(r"\d", "#", "a1b2") # 替换 → 'a#b#'
分工:findall 找全部返回列表、search 找第一个、match 只匹配开头、sub 替换。字符串前加 r(原始字符串),否则 \d 被当转义符。
分组提取——括号圈出要留的部分:
m = re.search(r"(\w+)@\w+\.\w+", "contact: tom@example.com")
m.group(1) # 'tom' ⭐
手机号验证——fullmatch 要求整串匹配:
re.fullmatch(r"1\d{10}", "13812345678") # 非 None 即合法
替换打码——保留前 3 后 4:
re.sub(r"(1\d{2})\d{4}(\d{4})", r"\1****\2", "联系 13812345678 尽快")
# → '联系 138****5678 尽快'
\1、\2 在替换串里引用第 1、2 分组。
练习: ex05(findall)、ex12(sub+分组)、ex15(findall)。
⚠️ 常见错误:贪婪、忘 r、group 索引
① 正则默认贪婪,r"a.*c"匹配a...c...c会吞到最后一个 c,想要最短用非贪婪r"a.*?c"。② 忘了r前缀,\d报错。③search返回 None 时调group(1)会崩,先if m:。④ 分组从 1 编号,group(0)是整体。
8.8 os.path / sys / time / hashlib —— 系统与文件
① os.path —— 路径小助手。拼、拆、查路径,跨平台自动适配分隔符:
import os
os.path.join("data", "report.txt") # 'data/report.txt' ⭐
os.path.exists("a.txt") # 是否存在
os.path.isfile("a.txt") # 是否文件
os.path.basename("data/report.txt") # 'report.txt' ⭐
os.path.splitext("report.txt") # ('report', '.txt') ⭐
os.path.dirname("data/report.txt") # 'data'
② sys —— 命令行参数。argv[0] 是程序文件名,argv[1:] 才是参数:
import sys
# 命令行:python my.py 2026 08 02
sys.argv # ['my.py', '2026', '08', '02'],全是字符串!
要用数字先 int() 转换。
③ time —— 时间戳。time.time() 返回 1970 年 1 月 1 日至今的秒数,用来计时:
import time
time.strftime("%Y-%m-%d", time.gmtime(0)) # '1970-01-01' ⭐
time.strftime("%Y-%m-%d", time.gmtime(86400)) # '1970-01-02'
用 gmtime(UTC)避免本地时区干扰。
④ hashlib —— 哈希指纹。文本算成一串固定长度"指纹",同样输入永远同样输出,几乎无法反推,常用于存密码:
import hashlib
hashlib.sha256("hello".encode()).hexdigest()
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
sha256() 收字节,字符串要先 .encode()。
练习: ex13(os.path)、ex14(hashlib)、ex15(综合,sys.argv)。
⚠️ 常见错误:路径拼接、argv 索引、hashlib 忘 encode
① 手写"data/" + "report.txt"在 Windows 会出问题,永远用os.path.join。②sys.argv从 0 开始且全是字符串,没传参访问argv[1]索引越界。③sha256("hello")报TypeError,必须.encode()。④time.localtime依赖时区,判分验证用gmtime更稳。
💡 记忆口诀
- strptime p 进 str 出,strftime f 出 str
\d数字、\w字母、+一个以上dumps出字符串、loads进字典defaultdict(int)传工厂函数不带括号shuffle原地改返回 None
📌 双语术语表(本讲)
| 中文 | English |
|---|---|
| 模块 | module |
| 导入 | import |
| 标准库 | standard library |
| 正则表达式 | regular expression |
| 时间戳 | timestamp |
| 计数 | counter |
| 随机数 | random number |
| 序列化 | serialize |
| 哈希 | hash |
| 双端队列 | deque |
⭐ 本讲考点清单
os.path.join/exists/basename/splitext- 正则
\d+、findall/search/sub、分组与\1引用、fullmatch手机号验证 random.randint/choice/sample/shuffle,seed复现datetime.now()+strftime/strptime,timedelta日期差Counter.most_common、defaultdict、namedtuple、deque.rotatemath.sqrt/floor/ceil/powjson.loads/dumps(ensure_ascii=False)sys.argv、hashlib.sha256、time.gmtime/strftime