用于循环长字符串的Python String Concatenation

Python String Concatenation in for loop long strings

本问题已经有最佳答案,请猛点这里访问。

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

错误:在o(n^2)中运行

1
2
3
4
letters =""
for c in document:
    if c.isalpha():
        letters += c

好:在O(N)中运行

1
2
3
4
5
6
document =""
temp = []
for c in document:
    if c.isalpha():
        temp.append(c)
letters ="".join(temp)

同时我读到了

"Python解释器的一些后期实现开发了一种优化,允许此类代码在线性时间内完成。"

所以第一个解决方案也应该是好的?这是最新的python版本中的优化吗?


首先,您应该为自己编写最可读的代码;只有在运行时出现问题时,才应该考虑优化:

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

对于当前的cpython实现,join比"+"更快。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> 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(...)是一种非常具有脓毒性的东西,人们会更快地理解你的意图。所以,除非你有很多小文件,否则还是坚持使用str.join

然而,为了使str.join+=的速度都提高10倍,则使用str.translate。但是,此解决方案专门用于删除单个字符。

1
2
3
4
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不需要这样做,因此速度更快。


str是不变的,但list不是不变的。更好的方法是:

1
2
3
4
my_list = []
for c in my_string:
    if c.isalpha():
        my_list.append(c)

然而,从时间上来说,.append()是非常昂贵的操作(因为您在这里谈论的是复杂性)。检查:这里是我为另一个答案做的比较。更好的方法是:

1
my_list = [c for c in my_string if c.isalpha()]

现在您可以将此list转换为string,如下所示:

1
''.join(my_list)