大多数 Python 开发者都知道 json、os、datetime,也许还会用到 collections。
可一旦遇到稍微「特别」一点的问题,第一反应往往就是:
去 PyPI 搜一个库。
有时候,这确实是正确的选择。
但更多时候,你安装了一个依赖,只是为了完成 Python 十年前就已经帮你解决好的事情。
Python 标准库并不算特别「性感」。
有些模块名字让人摸不着头脑;有些 API 仿佛是三个委员会分别设计出来的;官方文档里的示例虽然技术上没问题,但很多时候几乎没有什么参考价值。
然而,即便如此,标准库里依旧藏着不少真正能帮你节省大量开发时间的工具。
下面这 10 个模块,我认为值得每一位 Python 开发者了解。
也许你已经用过其中几个。
没关系。
这并不是一份「冷门模块大全」,而是一份实用到值得更多关注,却经常被忽略的模块清单。
1. dataclasses:让代码少写很多,却更清晰
如果你已经在使用 Data Classes,那很好。
但它依然值得排在这份名单里。
我之前提到过,在真正的大型生产项目里,我不会频繁使用 dataclass。
这并不是因为它不好,而是因为很多成熟项目已经拥有自己的数据模型体系。
例如:
- • 有的更关注数据校验、序列化、数据库映射以及 Schema 自动生成
相比之下,dataclass 的优势——少写几行样板代码——反而没那么重要了。
但是,在下面这些场景,它依旧非常优秀:
例如:
from dataclasses import dataclass
@dataclass
class Server:
host: str
port: int = 8000
use_ssl: bool = False
server = Server(host="api.example.com")
print(server)
你没有写:
但它已经自动帮你生成好了。
输出结果:
Server(host='api.example.com', port=8000, use_ssl=False)
这意味着,你可以很快搭建出一组对象,把它们组合起来,快速验证整个设计是否合理。
对于前期建模来说,它几乎没有学习成本。
还可以让对象变成「不可修改」
只需要加一个参数:
from dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: float
y: float
然后:
point = Point(10, 20)
point.x = 30
Python 会直接抛出异常。
当然,需要说明一点:
frozen=True 并不意味着真正意义上的深度不可变(Deep Immutable)。
举个例子:
@dataclass(frozen=True)
class User:
tags: list[str]
虽然 User 自己不能修改属性:
user.tags = []
会报错。
但是:
user.tags.append("Python")
依然可以执行。
因为列表本身仍然是可变对象。
Python 不会替你阻止所有危险操作。
不过,大多数情况下,这已经足够满足需求。
所以,dataclass 并不是 Pydantic 的替代品。
它最大的价值在于:
让你能够优雅地表示数据,而不用一次又一次重复编写那些毫无意义的样板代码。
2. pathlib:终于不用再拼字符串处理路径了
我现在依然经常看到这样的代码:
import os
path = os.path.join(
"my_project",
"config",
"settings.toml",
)
它当然没问题。
几十年来大家都是这么写的。
但是,自从有了 pathlib,这件事明显舒服了很多。
from pathlib import Path
base = Path("my_project")
settings_file = (
base
/ "config"
/ "settings.toml"
)
print(settings_file)
第一次看到 / 运算符拼路径时,很多人都会觉得:
这是什么写法?
但只要习惯之后,再回头看 os.path.join(),反而觉得有些机械和啰嗦。
Path 对象远不止表示路径
它还提供了大量常用文件操作。
例如:
from pathlib import Path
settings_file = (
Path("my_project")
/ "config"
/ "settings.toml"
)
settings_file.parent.mkdir(
parents=True,
exist_ok=True,
)
settings_file.write_text(
"[server]\nport = 8000\n",
encoding="utf-8",
)
if settings_file.exists():
print(settings_file.stat().st_size)
几乎所有常见文件操作,它都已经封装好了:
例如递归寻找所有 Python 文件:
from pathlib import Path
for file in Path("src").rglob("*.py"):
print(file)
最大的优点是:
它屏蔽了不同操作系统之间路径表示方式的差异。
Windows:
C:\project\data
Linux:
/home/user/project/data
你完全不用操心。
当然,也有少数老旧第三方库仍然要求字符串路径:
some_library(str(settings_file))
不过现在越来越多的新库已经支持 PathLike 对象,这种转换越来越少见。
pathlib 不会让文件操作变得有趣。
毕竟,文件系统本来也没什么有趣的。
但它至少让这件事情,没那么令人烦躁。