Python 标准库是个大宝藏,但很多人只会用 os 和 sys。今天挑了 5 个冷门但超实用的内置模块,用过的都说真香。
1. 用 pprint 美化打印复杂数据
搜一下 Stack Overflow,排第一的答案通常长这样:
data = {'users': [{'name': 'Alice', 'scores': [90, 85, 92]}, {'name': 'Bob', 'scores': [78, 88, 95]}], 'count': 2}print(data)
# 输出结果挤在一行,没有结构层次# {'users': [{'name': 'Alice', 'scores': [90, 85, 92]}, {'name': 'Bob', 'scores': [78, 88, 95]}], 'count': 2}
老手一般这么写:
from pprint import pprintdata = { 'users': [ {'name': 'Alice', 'scores': [90, 85, 92]}, {'name': 'Bob', 'scores': [78, 88, 95]} ], 'count': 2}pprint(data, width=60, depth=10)
# 结果一目了然{'count': 2, 'users': [{'name': 'Alice', 'scores': [90, 85, 92]}, {'name': 'Bob', 'scores': [78, 88, 95]}]}
pprint 自动缩进和换行,让嵌套的字典/列表结构一目了然。width 控制行宽,
depth 限制嵌套深度。
调试复杂数据结构时比 print 好用百倍。
2. 用 weakref 避免循环引用
大多数人第一反应是这样的:
class Node: def __init__(self, value): self.value = value self.parent = None # 强引用,可能导致循环引用 self.children = []
更简单专业的方法:
import weakrefclass Node: def __init__(self, value): self.value = value self._parent = None self.children = [] @property def parent(self): return self._parent() if self._parent else None @parent.setter def parent(self, node): self._parent = weakref.ref(node) if node else Noneroot = Node('root')child = Node('child')child.parent = rootroot.children.append(child)print(child.parent.value) # 'root'
weakref 创建不增加引用计数的弱引用,当对象无强引用时自动回收。树形结构中子节点引用父节点用弱引用,避免循环引用导致内存泄漏。
3. 用 sys.getsizeof 查看对象内存
大多数人第一反应是这样的:
# 不知道数据结构占多少内存data = list(range(1000))
用对了工具,代码量直接砍半:
import sysprint(sys.getsizeof([])) # 56 bytes (空列表)print(sys.getsizeof(list(range(1000)))) # ~8856 bytesprint(sys.getsizeof(tuple(range(1000)))) # ~8048 bytesprint(sys.getsizeof(set(range(1000)))) # ~32984 bytesprint(sys.getsizeof('hello')) # 54 bytes
sys.getsizeof 返回对象自身占用的字节数(不包括引用对象)。对比不同数据结构的内存开销,有助于选择合适的容器。
tuple 比 list 更省内存。
4. 用 argparse 解析命令行参数
很多教程会教你这么写:
import sysif len(sys.argv) > 1: filename = sys.argv[1]else: filename = 'default.txt'# 没有帮助信息,没有类型检查
试试这个:
import argparseparser = argparse.ArgumentParser(description='Process files')parser.add_argument('filename', help='Input file')parser.add_argument('-o', '--output', default='out.txt')parser.add_argument('-n', '--count', type=int, default=10)parser.add_argument('-v', '--verbose', action='store_true')args = parser.parse_args()print(f'Input: {args.filename}, Output: {args.output}')
argparse 自动生成帮助信息、校验参数类型、处理默认值。支持位置参数、可选参数、布尔开关等,是 CLI 工具开发的标准方案。
5. 用 struct 处理二进制数据
看起来没问题,但其实有更好的方式:
# 手动解析二进制协议data = b'\x01\x00\x00\x00\x48\x65\x6c\x6c\x6f'version = data[0]# 还要处理字节序...
其实标准库早就有答案了:
import struct# 打包: 将 Python 值转为二进制packed = struct.pack('>BH4s', 1, 1024, b'Test')print(packed) # b'\x01\x04\x00Test'# 解包: 从二进制提取值version, length, name = struct.unpack('>BH4s', packed)print(f'v{version}, len={length}, name={name.decode()}')
struct 模块用于 Python 值和 C 结构体二进制数据之间的转换。> 表示大端序,B=uint8, H=uint16, 4s=4字节字符串。
解析网络协议和二进制文件的利器。
速查表
| 场景 | 别这样写 | 试试这样 |
|---|
| 打印复杂数据挤一行 | print(data) 一大坨 | pprint(data) 自动格式化 |
| 树形结构内存泄漏 | self.parent = node 强引用 | weakref.ref(node) 弱引用 |
| 不知道对象占多少内存 | 瞎猜 | sys.getsizeof(obj) 精确查看 |
| 手动解析 sys.argv | sys.argv[1] 裸取 | argparse 自动校验+帮助 |
| 手动解析二进制协议 | 切片+字节序处理 | struct.pack/unpack 一行搞定 |
以上就是内置模块的 5 个实用技巧,每个都是我在实际项目中踩过坑才总结出来的。千里之行始于足下,慢慢积累,你的代码质量会发生质的改变。
评论区聊聊:这 5 个技巧里哪个你之前不知道?
下期预告:调试技巧专场
关于作者
写了 10 年 Python,赶上了机器学习的热潮,又撞上了大模型的浪头,每次以为学明白了,行业又变了一次。
把自己踩过的坑、走过的弯路、看过的热闹,说给还在路上的人听。
关注「鲁叶的Python」,和你一起穿越迷茫期。