Python for 循环长字符串中的字符串连接

Python String Concatenation in for loop long strings

我已经多次听说您不应该在 for 循环中进行字符串连接,因为字符串是不可变的,因此它会将连接计算为一个新的字符串实例,然后重新分配标识符。因此,如果结果有 n 个字符,则时间复杂度为 O(n^2)

坏: 在 O(n^2) 中运行。迭代“+”连接。

letters = ""
for c in document:
    if c.isalpha():
        letters += c

好: 在 O(n) 中运行。迭代追加,最后一个 "".join()

document = ""
temp = []
for c in document:
    if c.isalpha(): 
        temp.append(c)
letters = "".join(temp)

同时我也看到了

"Some later implementations of the Python interpreter have developed an optimization to allow such code to complete in linear time,.."

那么第一个方案应该也可以吧?它是最新 python 版本中的优化吗?

首先,你应该为你编写最易读的代码;仅当您遇到运行时问题时,才应该考虑优化:

letters = "".join(c for c in document if c.isalpha())

对于当前的 CPython 实现,join 比“+”快。

>>> def test():
...   s = ""
...   for x in range(1000):
...     s += 'x'
... 
>>> timeit.timeit(test)
157.9563412159987
>>> def test():
...   s = []
...   for x in range(1000):
...     s.append('x')
...   s = ''.join(s)
... 
>>> timeit.timeit(test)
147.74276081599965

关键是一些实现。不是全部。如果你想确保你的代码在 python 的所有实现上都能快速运行,那么使用 str.join。根据文档的大小,不同的方法会更快。但是,"".join(...) 非常 pythonic,人们会更快地理解您的意图。因此,除非您有 lots of small 文档,否则请坚持使用 str.join.

但是,要在 str.join+= 上获得 10 倍的速度提升,请使用 str.translate。不过,此解决方案专门用于删除单个字符。

from string import digits
translation_table = str.maketrans("", "", digits) 
# first two args about translating characters, third is for removing characters
letters = document.translate(translation_table)

速度提高的原因是 python 需要为文档中的每个字符创建一个新字符串。 str.translate 不需要这样做,所以速度更快。