替换算法
替换算法(Substitute Algorithm)把一个函数的整个实现换成更清楚的写法,行为不变。 它解决的痛是:一段代码绕了远路,读的人要在心里跑一遍才懂,而其实有一个一眼就能看懂的写法。
一个签到系统要从到场名单里找出第一个嘉宾。最早只有三位嘉宾,于是写成了三个 if。
"""找第一个嘉宾:替换前。"""
def found_guest(people: list[str]) -> str: for p in people: if p == "张三": return "张三" if p == "李四": return "李四" if p == "王五": return "王五" return ""
if __name__ == "__main__": print(found_guest(["小林", "李四", "张三"]))
# 输出:# 李四// 找第一个嘉宾:替换前。function foundGuest(people: string[]): string { for (const p of people) { if (p === "张三") return "张三"; if (p === "李四") return "李四"; if (p === "王五") return "王五"; } return "";}
console.log(foundGuest(["小林", "李四", "张三"]));
// 输出:// 李四"""找第一个嘉宾:替换后。"""
GUESTS = {"张三", "李四", "王五"}
def found_guest(people: list[str]) -> str: return next((p for p in people if p in GUESTS), "")
if __name__ == "__main__": print(found_guest(["小林", "李四", "张三"]))
# 输出:# 李四// 找第一个嘉宾:替换后。const GUESTS = new Set(["张三", "李四", "王五"]);
function foundGuest(people: string[]): string { return people.find((p) => GUESTS.has(p)) ?? "";}
console.log(foundGuest(["小林", "李四", "张三"]));
// 输出:// 李四替换后一行说完了“在名单里找第一个是嘉宾的人”。嘉宾名单单独成了一个集合,加第四位嘉宾只加一个名字,不用再写一个 if。
定义与适用场景
Section titled “定义与适用场景”替换算法:用一个更简单、更清楚的实现替换函数的整个函数体,前提是行为完全相同。它适合在你发现了更好的写法时使用,最常见的是发现标准库已经提供了同样的功能(next、find、any、sorted、Counter)。替换前先确认有测试覆盖这个函数的各种输入,换完立即跑;如果原来的实现很长,先用提炼函数把它拆小,再一块一块替换,比一次整个替换安全。
什么时候别用
Section titled “什么时候别用”旧算法和新算法在边界情况上不完全一样时(空列表、重复元素、顺序),这已经不是重构而是改行为,要当成功能改动处理,单独测试、单独提交。为了性能而换算法也不算这个手法,那是优化,见第 58 章。