网易首页 > 网易号 > 正文 申请入驻

8 个真正能减少重复代码的 Python 标准库

0
分享至


你本周写的 Python 代码里,至少有三处是在重复做标准库已经替你写好的事。手写 __init__、手动维护 dict 缓存、两层嵌套 for 加 append、os.path.join 来回拼字符串——这些事不是你不会写,是你没用上已经在你电脑里等着的工具。

去年底写过一篇《 别再重复造轮子了!Python 这 10 个内置模块真能造 》(dis、singledispatch、ast、atexit 等冷门模块巡礼)。那篇侧重"你可能不知道的冷门模块"。今天这篇换一个切口: 只讲你会在本周代码里遇到的样板消除器 。8 个模块,全是 Python 3.10+ 标准库自带,零依赖,直接 import。验证依据为 cpython 源码和 Python 3.12 官方文档。

每个模块一个 before/after 对比,附上最容易被踩的坑——什么时候不该用它。

01 dataclasses — 你的数据类为什么还在手写 __init__

消灭了什么__init____repr____eq__ 的手写。

# Before — 15 行样板
class Task:
def __init__(self, title, assignee, done=False):
self.title = title
self.assignee = assignee
self.done = done
def __repr__(self):
return f"Task(title={self.title!r}, assignee={self.assignee!r}, done={self.done!r})"
def __eq__(self, other):
if not isinstance(other, Task):return NotImplemented
return(self.title, self.assignee, self.done) == (other.title, other.assignee, other.done)

# After — 4 行
fromdataclassesimportdataclass

@dataclass(frozen=True, slots=True)
class Task:
title: str
assignee: str
done: bool = False

slots=True (3.10+)额外减少 20–35% 内存占用。 frozen=True 让实例不可变——配置对象、模型对象的天然选择。

不该用的场景 :需要自定义 __init__ 做复杂参数校验或类型转换时,直接写普通类更清晰。 dataclasses 的职责是"存数据",不是"做逻辑"。

02 functools.cache — 重复计算缓存一行搞定

消灭了什么 :手写 dict 缓存 + key 管理。

# Before — 手动缓存
_fib_cache = {0: 0, 1: 1}
def fib(n):
ifnnot in_fib_cache:
_fib_cache[n] = fib(n - 1) + fib(n - 2)
return_fib_cache[n]

# After — 一行装饰器
fromfunctoolsimportcache

@cache
def fib(n):
ifn < 2:returnn
returnfib(n - 1) + fib(n - 2)

@cache (3.9+)是 @LRU_cache(maxsize=None) 的简化版,内部用 dict 存结果,适合纯函数且参数空间有限的场景。注意它 不保证线程安全 ——多线程并发写同一个 @cache 函数时可能出现竞态条件(cpython 只在 maxsize>0 时持有 LRU 链表的锁, maxsize=Nonedict.setdefault 不加锁)。同一个 functools 里还有 partial (预填函数参数)、 @wraps (保留装饰器里的原始函数签名)、 reduce (序列累积)。

不该用的场景 :函数有副作用(写文件、调 API、读数据库),或者参数空间无界——缓存无限增长会吃满内存。此时换 @lru_cache(maxsize=256) 加个上限。

03 itertools — 你还在一层层嵌套 for 吗

消灭了什么 :2–3 层嵌套 for + 手动 append

# Before — 6 行嵌套
pairs =
forcolorin["red", "blue", "green"]:
forsizein["S", "M", "L"]:
pairs.append((color, size))


# After — 1 行
fromitertoolsimportproduct
pairs = list(product(["red", "blue", "green"], ["S", "M", "L"]))

关键在"惰性"—— product 返回迭代器不创建中间列表,内存 O(1) 而非 O(n)。上面的代码包在 list 里是为了展示结果——实际使用时如果不需要全部组合,不要转 list ,保持惰性才能省内存。 chain 展平多层可迭代对象, combinations 生成组合, groupby 按键分组。

不该用的场景(踩坑率最高)groupby 要求输入 预先按 key 排序 ,否则静默丢数据。

04 collections — defaultdict 消灭"if key not in dict"

消灭了什么 :每次访问 dict 前的防御检查。

# Before — 每次都得检查
counts = {}
forwordinwords:
ifwordnot incounts:
counts[word] = 0
counts[word] += 1


# After
fromcollectionsimportdefaultdict
counts = defaultdict(int)
forwordinwords:
counts[word] += 1

Counter(words)defaultdict(int) 更终极——一行搞定计数。 deque(maxlen=n) 是固定窗口 FIFO 队列, namedtuple 是轻量不可变数据容器。

不该用的场景defaultdict 访问不存在的 key 时会 自动创建并插入 ,这是副作用。在需要严格 key 校验的场景(比如读取配置时不应接受非预期 key),用普通 dict + .get 更安全。

05 pathlib — 别再 os.path.join 了

消灭了什么os.path.join 的字符串拼接地狱。

# Before — 跨平台易错
importos
path = os.path.join("data", "logs", "app.log")
with open(path)asf: ...


# After — / 运算符 + 对象方法
frompathlibimportPath
path = Path("data") / "logs" / "app.log"
text = path.read_text(encoding="utf-8")
files = list(Path("logs").glob("*.log"))

/ 运算符( __truediv__ 重载)比字符串拼接直观得多。 glob 返回生成器, read_text / write_text 一行搞定读写。

不该用的场景 :与 C 扩展交互时,大部分期望 str 而非 Path 对象,需显式 str(path) 。WindowsPath 和 PosixPath 跨平台行为有细微差异。

06 enum — 用类型安全替代魔法字符串

消灭了什么 :散落各处的字符串常量。

# Before — 拼写错误只能在运行时发现
def handle(status):
ifstatus == "pending": ...
elifstatus == "running": ...
elifstatus == "done": ...

# After — IDE 补全 + mypy 在编译期拦住
fromenumimportEnum, auto

class Status(Enum):
PENDING = auto
RUNNING = auto
DONE = auto

def handle(status: Status):
ifstatus == Status.PENDING: ...

auto 消除手动编号, StrEnum (3.11+)让枚举值自动兼容字符串接口。

不该用的场景 :枚举值需要运行时动态注册(比如插件系统从配置文件加载状态),enum 的静态特性反而是限制。

07 contextlib — 上下文管理不需要写类

消灭了什么 :为了一行 with 写完整的 __enter__ / __exit__ 类。

# Before — 10 行类
class timer:
def __enter__(self):
self.start = perf_counter
return self
def __exit__(self, *args):
self.elapsed = perf_counter - self.start

# After — 生成器函数
fromcontextlibimportcontextmanager
fromtimeimportperf_counter

@contextmanager
def timer:
start = perf_counter
yield
print(f"elapsed: {perf_counter - start:.3f}s")

contextlib.suppress(ValueError) 一行消掉 try: ... except ValueError: pass 的空异常处理块。

不该用的场景 :上下文逻辑复杂到需要多个 yield 或异常恢复分支时,老老实实写类。 @contextmanager 只能 yield 一次,切分支不是它的强项。

08 textwrap — 多行字符串别再手调缩进了

消灭了什么 :多行字符串前面那个对齐噩梦。

# Before — 手动调缩进,一改内容就歪
def help:
return "Usage: mytool [OPTIONS]\n\n" \
"Options:\n" \
" -h, --help Show this message\n" \
" -v, --verbose Verbose output"

# After — dedent 自动移除公共前导空白
fromtextwrapimportdedent

def help:
returndedent("""\
Usage: mytool [OPTIONS]

Options:
-h, --help Show this message
-v, --verbose Verbose output""")

嵌在函数里的多行字符串不用再为了对齐缩进破坏可读性。 textwrap.shorten("长文本", width=40, placeholder="...") 一行替代手动截断 + 拼接省略号。

不该用的场景dedent 假设所有行共享相同的前导空白模式——如果多行字符串内部缩进不一致(比如混合了 tab 和空格),结果不可预测。

09 写在最后:一图胜千言


特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
重庆彭水发生山体垮塌有人员被埋,附近商户:听到很大声响,救援人员马上赶到

重庆彭水发生山体垮塌有人员被埋,附近商户:听到很大声响,救援人员马上赶到

潇湘晨报
2026-07-17 12:04:13
队报:奥利塞决定离开拜仁,已询问姆巴佩关于皇马的情况

队报:奥利塞决定离开拜仁,已询问姆巴佩关于皇马的情况

懂球帝
2026-07-17 05:38:09
世界杯将颁发冠军戒指 FIFA:将美国传统引入足坛

世界杯将颁发冠军戒指 FIFA:将美国传统引入足坛

体坛周报
2026-07-17 08:51:19
特朗普确认将出席世界杯决赛,预计将亲自颁发冠军奖杯!冠军将获定制戒指,还将向全球球迷发售!“感到恶心”,英法均无心季军战

特朗普确认将出席世界杯决赛,预计将亲自颁发冠军奖杯!冠军将获定制戒指,还将向全球球迷发售!“感到恶心”,英法均无心季军战

每日经济新闻
2026-07-17 10:55:07
哈兰德携女友现身意大利陶尔米纳,白衣造型浪漫庆女友 22 岁生辰

哈兰德携女友现身意大利陶尔米纳,白衣造型浪漫庆女友 22 岁生辰

墨薷桃桃
2026-07-17 08:21:38
A股:今天,周五,A股为何突然大跳水?原因有两点!

A股:今天,周五,A股为何突然大跳水?原因有两点!

明心
2026-07-17 11:43:55
世界杯决赛裁判揭晓!斯洛文尼亚名哨任主裁:曾执法阿根廷输沙特

世界杯决赛裁判揭晓!斯洛文尼亚名哨任主裁:曾执法阿根廷输沙特

风过乡
2026-07-17 08:11:57
6分59秒监控视频曝光:男子快递站杀害村书记,站门口打110报警;二审维持死刑判决

6分59秒监控视频曝光:男子快递站杀害村书记,站门口打110报警;二审维持死刑判决

大风新闻
2026-07-16 23:30:41
1000万辆新能源车,正驶向“八年斩杀线”,你的车在其中吗?

1000万辆新能源车,正驶向“八年斩杀线”,你的车在其中吗?

有观点
2026-07-17 08:32:57
多国担忧美国干涉内政,“中国贡献”获得更多认可,皮尤调查“中国好感度”持续提升

多国担忧美国干涉内政,“中国贡献”获得更多认可,皮尤调查“中国好感度”持续提升

环球网资讯
2026-07-17 07:04:23
32名在编,人员经费900多万:长沙市体育局2024年决算账单

32名在编,人员经费900多万:长沙市体育局2024年决算账单

马小白
2026-07-17 11:47:31
突发悲剧!重庆彭水发生山体大规模垮塌,现场照片流出,普通人几乎没有充足避险时间

突发悲剧!重庆彭水发生山体大规模垮塌,现场照片流出,普通人几乎没有充足避险时间

火山詩话
2026-07-17 11:09:06
NBA总裁萧华公开喊话:希望詹姆斯尽快决定下家 影响联盟赛程制定

NBA总裁萧华公开喊话:希望詹姆斯尽快决定下家 影响联盟赛程制定

醉卧浮生
2026-07-17 07:21:05
突发!美军连炸伊朗5座桥,伊朗要求封锁曼德海峡,胡塞武装已部署导弹!中东多国遭袭,特朗普想扩大打击,施压伊朗重返谈判

突发!美军连炸伊朗5座桥,伊朗要求封锁曼德海峡,胡塞武装已部署导弹!中东多国遭袭,特朗普想扩大打击,施压伊朗重返谈判

每日经济新闻
2026-07-17 12:31:15
湖南一女子掉落资江漂流12公里,不会游泳全靠本能让头仰在水面上,警方搜寻1小时20分钟将其成功救回

湖南一女子掉落资江漂流12公里,不会游泳全靠本能让头仰在水面上,警方搜寻1小时20分钟将其成功救回

大风新闻
2026-07-17 11:11:22
多条战线交火,美伊绞杀战打响,伊朗突换战术,特朗普恐怕没想到

多条战线交火,美伊绞杀战打响,伊朗突换战术,特朗普恐怕没想到

闻识
2026-07-16 09:58:21
韩国股市今日休市

韩国股市今日休市

每日经济新闻
2026-07-17 08:06:05
欧弟一家5口移居到日本,买了230万的别墅,每个月生活费是25万

欧弟一家5口移居到日本,买了230万的别墅,每个月生活费是25万

椰黄娱乐
2026-07-16 11:58:23
我有种预感,张子枫她很难再红了,不是因为她演技不行,过度消瘦外形大变丢辨识度

我有种预感,张子枫她很难再红了,不是因为她演技不行,过度消瘦外形大变丢辨识度

南万说娱26
2026-07-17 10:00:32
川普宣布:在军队开过重型卡车的退伍军人,可自动获得卡车驾照,取代非法移民卡车司机

川普宣布:在军队开过重型卡车的退伍军人,可自动获得卡车驾照,取代非法移民卡车司机

大洛杉矶LA
2026-07-17 04:46:27
2026-07-17 14:20:49
侃故事的阿庆
侃故事的阿庆
几分钟看完一部影视剧,诙谐幽默的娓娓道来
821文章数 8995关注度
往期回顾 全部

科技要闻

Kimi K3突然登顶!价格也涨到了美国档

头条要闻

"中国+1"战略最大受益者越南 出现十年罕见贸易逆差

头条要闻

"中国+1"战略最大受益者越南 出现十年罕见贸易逆差

体育要闻

雷暴致阿根廷队航班延误滞留亚特兰大,决赛备战或只剩1天

娱乐要闻

深扒邹市明的情史!爱得太卑微

财经要闻

创业板指半日跌4.71% 超4300股下挫

汽车要闻

小鹏MONA L03上市为什么选在慕尼黑?

态度原创

本地
艺术
旅游
公开课
军事航空

本地新闻

人生必去清单:那达慕大会开嗨!

艺术要闻

90后海归女硕士,做全国最冷门的职业,意外火出圈

旅游要闻

很多人去腾冲只逛和顺古镇,错过这座古木园,等于白来一趟滇西!

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

伊朗议长:这是一场“生存之战”

无障碍浏览 进入关怀版