好文分享 — Joining Strings in Python: A 'Huh' Moment
開門見山, CPython str.join()
以下 2 種寫法:
- Generator
' '.join(s for s in strs)
- List Comprehension
' '.join([s for s in strs])
沒想到,上面 2 種比較結果是 List Comprehension 比較快!而且記憶體用量是差不多的!
The reason for this is, as Trey said, that the str.join() implementation in CPython uses a two pass approach. It first calculates how big the result should be and allocates the memory, and then joins the text.
原因是 CPython 的 str.join()
實作方式需要先計算結果的長度並分配記憶體,最後再串接字串。如果我們丟 generator 進去,它就需要額外步驟把 generator 的結果跑出來,再做計算長度、分配記憶體、串接字串。所以,前述 2 種寫法,使用 list comprehension 較快是贏在不需要把 generator 的結果跑出來這段。
p.s. 這實作方式未來會不會變就不知道了
以前看到這 2 種寫法會不加思索以為用 Generator 的方式不僅記憶體利用效率好還比較快, “Joining Strings in Python: A “Huh” Moment” 1 文真的顛覆我的認知,有興趣的話可以花點時間閱讀原文,原文也有提供 CPython 底層程式碼連結,滿足你我的好奇心!
Joining Strings in Python: A “Huh” Moment
噢對,如果你使用的是 PyPy, 就不用在意這個問題了,該文作者實驗結果是 list comprehension 版本比較慢(也是我們預期的結果)。
想實際玩看看的話,以下連結可以玩看看,可以調整 numbers
數值, 1_000
的話,大概在伯仲之間,改成 10_000
就可以感受到差異了: