18.6. 优化字符串操作
Description: Python from novice to pro
Keywords: Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free

# 深入 Python :Dive Into Python 中文版 Python 从新手到专家 [Dip_5.4b_CPyUG_Release] | Find:

## 18.6. 优化字符串操作

Soundex 算法的最后一步是对短结果补零和截短长结果。最佳的做法是什么？

这是目前在 `soundex/stage2/soundex2c.py` 中的做法：

        digits3 = re.sub('9', '', digits2)
        while len(digits3) < 4:
            digits3 += "0"
        return digits3[:4]

这里是 `soundex2c.py` 的表现：

    C:\samples\soundex\stage2>python soundex2c.py
    Woo             W000 12.6070768771
    Pilgrim         P426 14.4033353401
    Flingjingwaller F452 19.7774882003

思考的第一件事是以循环取代正则表达式。这里的代码来自 `soundex/stage4/soundex4a.py`：

        digits3 = ''
        for d in digits2:
            if d != '9':
                digits3 += d

`soundex4a.py` 快了吗？是的：

    C:\samples\soundex\stage4>python soundex4a.py
    Woo             W000 6.62865531792
    Pilgrim         P426 9.02247576158
    Flingjingwaller F452 13.6328416042

但是，等一下。一个从字符串去除字符的循环？我们可以用一个简单的字符串方法做到。这便是 `soundex/stage4/soundex4b.py`：

        digits3 = digits2.replace('9', '')

`soundex4b.py` 快了吗？这是个有趣的问题，它取决输入值：

    C:\samples\soundex\stage4>python soundex4b.py
    Woo             W000 6.75477414029
    Pilgrim         P426 7.56652144337
    Flingjingwaller F452 10.8727729362

`soundex4b.py` 中的字符串方法对于大多数名字比循环快，但是对于短小的情况 (很短的名字) 却比 `soundex4a.py` 略微慢些。性能优化并不总是一致的，对于一个情况快些，却可能对另外一些情况慢些。就此而言，大多数情况将会从改变中获益，所以就改吧，但是别忘了原则。

最后仍很重要的是，让我们检测算法的最后两步：以零补齐短结果和截短超过四字符的长结果。你在 `soundex4b.py` 中看到的代码就是做这个工作的，但是太没效率了。看一下 `soundex/stage4/soundex4c.py` 找出原因：

        digits3 += '000'
        return digits3[:4]

我们为什么需要一个 `while` 循环来补齐结果？我们早就知道我们需要把结果截成四字符，并且我们知道我们已经有了至少一个字符 (直接从 `source` 中拿过来的起始字符)。这意味着我们可以仅仅在输出的结尾添加三个零，然后截断它。不要害怕重新理解问题，从不太一样的角度看问题可以获得简单的解决方案。

我们丢弃 `while` 循环后从 `soundex4c.py` 中获得怎样的速度？太明显了：

    C:\samples\soundex\stage4>python soundex4c.py
    Woo             W000 4.89129791636
    Pilgrim         P426 7.30642134685
    Flingjingwaller F452 10.689832367

最后，还有一件事可以令这三行运行得更快：你可以把它们合并为一行。看一眼 `soundex/stage4/soundex4d.py`：

        return (digits2.replace('9', '') + '000')[:4]

在 `soundex4d.py` 中把所有代码放在一行可以比 `soundex4c.py` 稍微快那么一点：

    C:\samples\soundex\stage4>python soundex4d.py
    Woo             W000 4.93624105857
    Pilgrim         P426 7.19747593619
    Flingjingwaller F452 10.5490700634

它非常难懂，而且优化也不明显。这值得吗？我希望你有很好的见解。性能并不是一切。你在优化方面的努力应该与程序的可读性和可维护性相平衡。