💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 18.1. 概览 由于代码优化过程中存在太多的不明确因素,以至于你很难清楚该从何入手。 让我们从这里开始:_你真的确信你要这样做吗?_ 你的代码真的那么差吗?值得花时间去优化它吗?在你的应用程序的生命周期中,与花费在等待一个远程数据库服务器,或是等待用户输入相比,运行这段代码将花费多少时间? 第二,_你确信已经完成代码编写了吗?_ 过早的优化就像是在一块半生不熟的蛋糕上撒糖霜。你花费了几小时、几天 (或更长) 时间来优化你的代码以提高性能,却发现它不能完成你希望它做的工作。那是浪费时间。 这并不是说代码优化毫无用处,但是你需要检查一下整个系统,并且确定把时间花在这上面是值得的。在优化代码上每花费一分钟,就意味着你少了增加新功能、编写文档或者陪你的孩子玩或者编写单元测试的一分钟。 哦,是的,单元测试。不必我说,在开始性能优化之前你需要一个完全的单元测试集。你最不需要的就是在乱动你的算法时引入新的问题。 谨记着这些忠告,让我们来看一些优化 Python 代码的技术。我们要研究的代码是 Soundex 算法的实现。Soundex 是一种 20 世纪在美国人口普查中归档姓氏的方法。它把听起来相似的姓氏归在一起,使得在即便错误拼写的情况下调查者仍能查找到。Soundex 今天仍然因差不多的原因被应用着,当然现在用计算机数据库服务器了。大部分的数据库服务器都有 Soundex 函数。 Soundex 算法有几个差别不大的变化版本。这是本章使用的: 1. 名字的第一个字母不变。 2. 根据特定的对照表,将剩下的字母转换为数字: * B、 F、 P 和 V 转换为 1。 * C、 G、 J、 K、 Q、 S、 X 和 Z 转换为 2。 * D 和 T 转换为 3。 * L 转换为 4。 * M 和 N 转换为 5。 * R 转换为 6。 * 所有其他字母转换为 9。 3. 去除连续重复。 4. 去除所有 9。 5. 如果结果都少于四个字符 (第一个字母加上后面的三位字符),就以零补齐。 6. 如果结果超过四个字符,丢弃掉四位之后的字符。 比如,我的名字 `Pilgrim` 被转换为 P942695。没有连续重复,所以这一步不需要做。然后是去除 9,剩下 P4265。太长了,所以你把超出的字符丢弃,剩下 P426。 另一个例子:`Woo` 被转换为 W99,变成 W9,变成 W,然后以补零成为 W000。 这是 Soundex 函数的第一次尝试: ## 例 18.1. `soundex/stage1/soundex1a.py` 如果您还没有下载本书附带的样例程序, 可以 [下载本程序和其他样例程序](http://www.woodpecker.org.cn/diveintopython/download/diveintopython-exampleszh-cn-5.4b.zip "Download example scripts")。 ``` import string, re charToSoundex = {"A": "9", "B": "1", "C": "2", "D": "3", "E": "9", "F": "1", "G": "2", "H": "9", "I": "9", "J": "2", "K": "2", "L": "4", "M": "5", "N": "5", "O": "9", "P": "1", "Q": "2", "R": "6", "S": "2", "T": "3", "U": "9", "V": "1", "W": "9", "X": "2", "Y": "9", "Z": "2"} def soundex(source): "convert string to Soundex equivalent" # Soundex requirements: # source string must be at least 1 character # and must consist entirely of letters allChars = string.uppercase + string.lowercase if not re.search('^[%s]+$' % allChars, source): return "0000" # Soundex algorithm: # 1\. make first character uppercase source = source[0].upper() + source[1:] # 2\. translate all other characters to Soundex digits digits = source[0] for s in source[1:]: s = s.upper() digits += charToSoundex[s] # 3\. remove consecutive duplicates digits2 = digits[0] for d in digits[1:]: if digits2[-1] != d: digits2 += d # 4\. remove all "9"s digits3 = re.sub('9', '', digits2) # 5\. pad end with "0"s to 4 characters while len(digits3) < 4: digits3 += "0" # 6\. return first 4 characters return digits3[:4] if __name__ == '__main__': from timeit import Timer names = ('Woo', 'Pilgrim', 'Flingjingwaller') for name in names: statement = "soundex('%s')" % name t = Timer(statement, "from __main__ import soundex") print name.ljust(15), soundex(name), min(t.repeat()) ``` ## 进一步阅读 * Soundexing and Genealogy 给出了 Soundex 发展的年代表以及地域变化。