str and bytes objects are immutable, therefore concatenating many
strings together is inefficient as each concatenation creates a new
object. In the general case, the total runtime cost is quadratic in
the total string length.
To accumulate many str objects, the recommended idiom is to place them
into a list and call str.join() at the end:
chunks = []
for s in my_strings:
chunks.append(s)
result = ''.join(chunks)
(another reasonably efficient idiom is to use io.StringIO)
To accumulate many bytes objects, the recommended idiom is to extend a
bytearray object using in-place concatenation (the += operator):
result = bytearray()
for b in my_bytes_objects:
result += b
try:
from cStringIO import StringIO
except:
from io import StringIO
source = ['foo']*1000
%%timeit buf = StringIO()
for i in source:
buf.write(i)
final = buf.getvalue()
# 1000 loops, best of 3: 1.27 ms per loop
%%timeit out = []
for i in source:
out.append(i)
final = ''.join(out)
# 1000 loops, best of 3: 9.89 ms per loop
%%timeit out = bytearray()
for i in source:
out += i
# 10000 loops, best of 3: 98.5 µs per loop
%%timeit out = ""
for i in source:
out += i
# 10000 loops, best of 3: 161 µs per loop
## Repeat the tests with a larger list, containing
## strings that are bigger than the small string caching
## done by the Python
source = ['foo']*1000
# cStringIO
# 10 loops, best of 3: 19.2 ms per loop
# list append and join
# 100 loops, best of 3: 144 ms per loop
# bytearray() +=
# 100 loops, best of 3: 3.8 ms per loop
# str() +=
# 100 loops, best of 3: 5.11 ms per loop
将字符串附加到字符串变量的最佳方法是使用
+
或+=
。这是因为它可读性强,速度快。它们的速度也一样快,你选择哪一种取决于你的品味,后者是最常见的。以下是timeit
模块的计时:但是,那些建议创建列表并附加到列表中,然后加入这些列表的人这样做是因为将字符串附加到列表中可能比扩展字符串快得多。在某些情况下,这可能是真的。例如,这里有一个例子 一个字符串的百万个附加项,首先是字符串,然后是列表:
好的,即使结果字符串有一百万个字符长,追加速度也更快
现在,让我们尝试将1000个字符长的字符串追加十万次:
因此,结束字符串的长度约为100MB。这相当慢,添加到列表要快得多。这个时间不包括最后的
a.join()
。那需要多长时间分组。事实证明,即使在这种情况下,append/join速度也较慢
那么,这一建议来自何方?Python 2
嗯,如果您使用非常长的字符串(通常不是,内存中会有一个100MB的字符串),那么append/join会稍微快一点
但真正的关键是Python 2.3。我甚至不会告诉你时间,因为它太慢了,还没有结束。这些测试突然花费了分钟。除了append/join,它的速度和后面的python一样快
是的。早在石器时代,Python中的字符串连接非常缓慢。但是在2.4上它不再是了(或者至少是Python2.4.7),所以使用append/join的建议在2008年过时了,当时Python2.3停止更新,您应该停止使用它。:-)
(更新:当我更仔细地进行测试时,发现在Python2.3上使用
+
和+=
对于两个字符串也更快。使用''.join()
的建议肯定是一个误解)然而,这是CPython。其他实现可能有其他问题。这就是为什么过早优化是万恶之源的另一个原因。不要使用被认为“更快”的技术,除非你先测量它
因此,进行字符串连接的“最佳”版本是使用+或+=。如果这对你来说太慢了,这是不太可能的,那就做点别的吧
那么为什么我要在代码中使用大量的append/join呢?因为有时候它实际上更清晰。特别是当您应该连接在一起的内容应该用空格、逗号或换行符分隔时
在Python中>;=3.6,新的f-string是连接字符串的有效方法
如果要连接许多值,则两者都不需要。附加一份清单是昂贵的。您可以使用StringIO来实现这一点。尤其是当你在大量的操作中建立它的时候
如果您已经从其他操作返回了一个完整的列表,那么只需使用
''.join(aList)
从python常见问题解答:What is the most efficient way to concatenate many strings together?
编辑:我很傻,把结果向后粘贴,让它看起来像是附加到列表中比cStringIO更快。我还添加了bytearray/str-concat的测试,以及使用更大字符串的更大列表的第二轮测试。(python 2.7.3)
ipython大型字符串列表测试示例
相关问题 更多 >
编程相关推荐