第 24 章 Python 标准库精选
24.1 collections
deque — 双端队列
from collections import deque
# 两端 O(1) 操作
d = deque([1, 2, 3])
d.appendleft(0) # deque([0, 1, 2, 3])
d.append(4) # deque([0, 1, 2, 3, 4])
d.popleft() # 0
d.pop() # 4
# 固定长度(自动丢弃旧元素)
history = deque(maxlen=5)
for i in range(10):
history.append(i)
print(history) # deque([5, 6, 7, 8, 9], maxlen=5)
# 旋转
d = deque([1, 2, 3, 4, 5])
d.rotate(2) # deque([4, 5, 1, 2, 3]) — 右旋
d.rotate(-2) # deque([1, 2, 3, 4, 5]) — 左旋
ChainMap — 链式映射
from collections import ChainMap
defaults = {"color": "red", "size": 10}
user_prefs = {"color": "blue"}
cli_args = {"size": 20}
# 优先级: cli_args > user_prefs > defaults
config = ChainMap(cli_args, user_prefs, defaults)
print(config["color"]) # blue(来自 user_prefs)
print(config["size"]) # 20(来自 cli_args)
# 修改只影响第一个映射
config["new_key"] = "value"
print(cli_args) # {'size': 20, 'new_key': 'value'}
Counter — 计数器
from collections import Counter
# 计数
words = "the quick brown fox jumps over the lazy dog the fox".split()
c = Counter(words)
print(c.most_common(3)) # [('the', 3), ('fox', 2), ('quick', 1)]
# 运算
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
print(c1 + c2) # Counter({'a': 4, 'b': 3})
print(c1 - c2) # Counter({'a': 2})
print(c1 & c2) # Counter({'a': 1, 'b': 1}) — 取最小值
print(c1 | c2) # Counter({'a': 3, 'b': 2}) — 取最大值
# 统计字符
Counter("abracadabra") # Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
defaultdict — 默认值字典
from collections import defaultdict
# 自动初始化
word_groups = defaultdict(list)
for word in ["apple", "banana", "avocado", "blueberry", "cherry"]:
word_groups[word[0]].append(word)
print(dict(word_groups))
# {'a': ['apple', 'avocado'], 'b': ['banana', 'blueberry'], 'c': ['cherry']}
# 嵌套 defaultdict
tree = lambda: defaultdict(tree)
config = tree()
config["database"]["host"] = "localhost"
config["database"]["port"] = 5432
24.2 contextlib — 上下文管理器工具集
from contextlib import contextmanager, suppress, redirect_stdout, closing
# contextmanager — 用生成器创建上下文管理器
@contextmanager
def timer(label):
import time
start = time.perf_counter()
try:
yield
finally:
elapsed = time.perf_counter() - start
print(f"[{label}] {elapsed:.4f}s")
with timer("计算"):
sum(range(1_000_000))
# suppress — 安全忽略异常
import os
with suppress(FileNotFoundError):
os.remove("不存在的文件.txt")
# redirect_stdout — 重定向标准输出
from io import StringIO
f = StringIO()
with redirect_stdout(f):
print("这些内容被重定向了")
output = f.getvalue()
# closing — 确保 close() 被调用
from urllib.request import urlopen
with closing(urlopen("https://example.com")) as page:
content = page.read()
# ExitStack — 动态管理多个上下文
from contextlib import ExitStack
with ExitStack() as stack:
files = [stack.enter_context(open(f"file{i}.txt", "w")) for i in range(3)]
for i, f in enumerate(files):
f.write(f"file {i}")
# 所有文件在退出时自动关闭
24.3 enum — 枚举类型
from enum import Enum, IntEnum, Flag, auto
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
print(Color.RED) # Color.RED
print(Color.RED.name) # "RED"
print(Color.RED.value) # 1
print(Color(1)) # Color.RED
print(Color["RED"]) # Color.RED
print(list(Color)) # [Color.RED, Color.GREEN, Color.BLUE]
# auto() 自动赋值
class Direction(Enum):
NORTH = auto() # 1
SOUTH = auto() # 2
EAST = auto() # 3
WEST = auto() # 4
# IntEnum — 可以和整数比较
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
print(Priority.HIGH > Priority.LOW) # True
print(Priority.HIGH > 2) # True
# Flag — 可以组合的标志
class Permission(Flag):
READ = auto()
WRITE = auto()
EXECUTE = auto()
perms = Permission.READ | Permission.WRITE
print(Permission.READ in perms) # True
print(Permission.EXECUTE in perms) # False
# 枚举用于 match-case
def handle_color(color: Color):
match color:
case Color.RED:
return "红色"
case Color.GREEN:
return "绿色"
case Color.BLUE:
return "蓝色"
24.4 logging — 日志系统
import logging
# 基本配置
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)
# 五个级别
logger.debug("调试信息")
logger.info("一般信息")
logger.warning("警告")
logger.error("错误")
logger.critical("严重错误")
# 带变量的日志(推荐 % 风格,避免不必要的字符串格式化)
user = "Alice"
logger.info("用户 %s 登录", user)
# 记录异常
try:
1 / 0
except ZeroDivisionError:
logger.exception("计算出错") # 自动附加堆栈信息
进阶配置
import logging
from logging.handlers import RotatingFileHandler
# 创建 logger
logger = logging.getLogger("myapp")
logger.setLevel(logging.DEBUG)
# 控制台 handler
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(logging.Formatter("[%(levelname)s] %(message)s"))
# 文件 handler(自动轮转)
file_handler = RotatingFileHandler(
"app.log", maxBytes=5*1024*1024, backupCount=3
)
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(
logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
)
logger.addHandler(console)
logger.addHandler(file_handler)
24.5 argparse — 命令行参数解析
import argparse
parser = argparse.ArgumentParser(description="文件处理工具")
# 位置参数
parser.add_argument("input", help="输入文件路径")
# 可选参数
parser.add_argument("-o", "--output", default="output.txt", help="输出文件路径")
parser.add_argument("-n", "--lines", type=int, default=10, help="处理行数")
parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
parser.add_argument("--format", choices=["json", "csv", "txt"], default="txt")
args = parser.parse_args()
print(f"输入: {args.input}")
print(f"输出: {args.output}")
print(f"行数: {args.lines}")
print(f"详细: {args.verbose}")
python tool.py input.txt -o result.txt -n 100 -v --format json
python tool.py --help
24.6 datetime — 日期与时间处理
from datetime import datetime, date, time, timedelta, timezone
# 当前时间
now = datetime.now()
utc_now = datetime.now(timezone.utc)
# 创建
dt = datetime(2026, 3, 31, 14, 30, 0)
d = date(2026, 3, 31)
t = time(14, 30, 0)
# 格式化
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2026-03-31 14:30:00
print(now.isoformat()) # 2026-03-31T14:30:00.123456
# 解析
dt = datetime.strptime("2026-03-31", "%Y-%m-%d")
# 时间差
delta = timedelta(days=7, hours=3)
next_week = now + delta
diff = datetime(2026, 12, 31) - now
print(f"还有 {diff.days} 天到年底")
# 时区
from zoneinfo import ZoneInfo # Python 3.9+
shanghai = ZoneInfo("Asia/Shanghai")
tokyo = ZoneInfo("Asia/Tokyo")
shanghai_now = datetime.now(shanghai)
tokyo_now = shanghai_now.astimezone(tokyo)
print(f"上海: {shanghai_now}")
print(f"东京: {tokyo_now}")
24.7 struct — 处理 C 结构体二进制数据
import struct
# 打包: Python 值 → bytes
data = struct.pack(">I2sf", 1, b"Hi", 3.14) # 大端序: uint32, 2字符, float
print(data) # b'\x00\x00\x00\x01Hi@H\xf5\xc3'
print(len(data)) # 10
# 解包: bytes → Python 值
values = struct.unpack(">I2sf", data)
print(values) # (1, b'Hi', 3.140000104904175)
# 常用格式符:
# b/B: int8/uint8 h/H: int16/uint16
# i/I: int32/uint32 q/Q: int64/uint64
# f: float32 d: float64
# s: 字符串(bytes) ?: bool
# >: 大端 <: 小端 =: 本地 !: 网络字节序
# 读取二进制文件头
def read_bmp_header(filename):
with open(filename, "rb") as f:
header = f.read(14)
magic, size, _, _, offset = struct.unpack("<2sIHHI", header)
return {
"magic": magic,
"file_size": size,
"data_offset": offset,
}
24.8 abc — 抽象基类
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float: ...
@abstractmethod
def perimeter(self) -> float: ...
def __repr__(self):
return f"{type(self).__name__}(area={self.area():.2f})"
# 注册虚拟子类
class Circle:
def __init__(self, r):
self.r = r
def area(self):
return 3.14159 * self.r ** 2
def perimeter(self):
return 2 * 3.14159 * self.r
Shape.register(Circle)
print(isinstance(Circle(5), Shape)) # True
24.9 typing — 类型提示扩展
from typing import (
Any, Union, Optional, Literal, Final, TypeAlias,
TypeVar, Generic, Protocol, TypedDict, NamedTuple,
overload, runtime_checkable, get_type_hints,
)
# overload — 函数重载签名
@overload
def process(x: int) -> str: ...
@overload
def process(x: str) -> int: ...
def process(x):
if isinstance(x, int):
return str(x)
return len(x)
# get_type_hints — 运行时获取类型信息
class User:
name: str
age: int
print(get_type_hints(User))
# {'name': <class 'str'>, 'age': <class 'int'>}
24.10 dataclasses — 数据类
from dataclasses import dataclass, field, asdict, astuple, fields, replace
@dataclass(frozen=True, slots=True)
class Config:
host: str = "localhost"
port: int = 8080
debug: bool = False
tags: tuple[str, ...] = ()
config = Config(host="0.0.0.0", tags=("web", "api"))
# 工具函数
print(asdict(config)) # 转为字典
print(astuple(config)) # 转为元组
# replace — 创建修改后的副本
dev_config = replace(config, debug=True, port=3000)
# fields — 获取字段信息
for f in fields(Config):
print(f"{f.name}: {f.type} = {f.default}")
本章小结:Python 标准库是”自带电池”理念的体现。
collections扩展了内置容器,contextlib简化了上下文管理,enum提供了类型安全的枚举,logging是生产级日志方案,datetime处理日期时间,struct桥接二进制数据。善用标准库,减少外部依赖。