| 導航:起始頁 > Dive Into Python > 性能優化 > 優化字符串操作 | << >> | ||||
深入 Python :Dive Into Python 中文版Python 從新手到專家 [Dip_5.4b_CPyUG_Release] |
|||||
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
它非常難懂,而且優化也不明顯。這值得嗎?我希望你有很好的見解。性能并不是一切。你在優化方面的努力應該與程序的可讀性和可維護性相平衡。
<< 優化列表操作 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
小結 >> |