Python字符串拼接与str.join的速度对比如何?

96 投票
7 回答
96150 浏览
提问于 2025-04-16 00:03

因为我在这个讨论中的回答引起了一些评论,我想知道使用 += 操作符和 ''.join() 方法之间的速度差别有多大。

那么,这两者的速度比较到底怎么样呢?

7 个回答

11

我之前的代码是错的,看来用+来连接字符串通常会更快(尤其是在新版本的Python和新硬件上)

以下是一些时间记录:

Iterations: 1,000,000       

在Windows 7上运行Python 3.3,使用Core i7处理器

String of len:   1 took:     0.5710     0.2880 seconds
String of len:   4 took:     0.9480     0.5830 seconds
String of len:   6 took:     1.2770     0.8130 seconds
String of len:  12 took:     2.0610     1.5930 seconds
String of len:  80 took:    10.5140    37.8590 seconds
String of len: 222 took:    27.3400   134.7440 seconds
String of len: 443 took:    52.9640   170.6440 seconds

在Windows 7上运行Python 2.7,使用Core i7处理器

String of len:   1 took:     0.7190     0.4960 seconds
String of len:   4 took:     1.0660     0.6920 seconds
String of len:   6 took:     1.3300     0.8560 seconds
String of len:  12 took:     1.9980     1.5330 seconds
String of len:  80 took:     9.0520    25.7190 seconds
String of len: 222 took:    23.1620    71.3620 seconds
String of len: 443 took:    44.3620   117.1510 seconds

在Linux Mint上运行Python 2.7,使用一些较慢的处理器

String of len:   1 took:     1.8840     1.2990 seconds
String of len:   4 took:     2.8394     1.9663 seconds
String of len:   6 took:     3.5177     2.4162 seconds
String of len:  12 took:     5.5456     4.1695 seconds
String of len:  80 took:    27.8813    19.2180 seconds
String of len: 222 took:    69.5679    55.7790 seconds
String of len: 443 took:   135.6101   153.8212 seconds

下面是代码:

from __future__ import print_function
import time

def strcat(string):
    newstr = ''
    for char in string:
        newstr += char
    return newstr

def listcat(string):
    chars = []
    for char in string:
        chars.append(char)
    return ''.join(chars)

def test(fn, times, *args):
    start = time.time()
    for x in range(times):
        fn(*args)
    return "{:>10.4f}".format(time.time() - start)

def testall():
    strings = ['a', 'long', 'longer', 'a bit longer', 
               '''adjkrsn widn fskejwoskemwkoskdfisdfasdfjiz  oijewf sdkjjka dsf sdk siasjk dfwijs''',
               '''this is a really long string that's so long
               it had to be triple quoted  and contains lots of
               superflous characters for kicks and gigles
               @!#(*_#)(*$(*!#@&)(*E\xc4\x32\xff\x92\x23\xDF\xDFk^%#$!)%#^(*#''',
              '''I needed another long string but this one won't have any new lines or crazy characters in it, I'm just going to type normal characters that I would usually write blah blah blah blah this is some more text hey cool what's crazy is that it looks that the str += is really close to the O(n^2) worst case performance, but it looks more like the other method increases in a perhaps linear scale? I don't know but I think this is enough text I hope.''']

    for string in strings:
        print("String of len:", len(string), "took:", test(listcat, 1000000, string), test(strcat, 1000000, string), "seconds")

testall()
12

注意:这个基准测试是非正式的,计划重新进行,因为它没有全面展示这些方法在处理更长字符串时的表现。正如@Mark Amery在评论中提到的,+=的速度并不总是比使用f-字符串快,而str#join在实际使用中并没有明显慢很多。

这些指标可能已经过时,因为后续的CPython版本,特别是3.11,带来了显著的性能提升。


现有的回答写得很好,研究也很深入,但这里再提供一个针对Python 3.6时代的回答,因为现在我们有了字面字符串插值(也就是f-字符串):

>>> import timeit
>>> timeit.timeit('f\'{"a"}{"b"}{"c"}\'', number=1000000)
0.14618930302094668
>>> timeit.timeit('"".join(["a", "b", "c"])', number=1000000)
0.23334730707574636
>>> timeit.timeit('a = "a"; a += "b"; a += "c"', number=1000000)
0.14985873899422586

测试是在2012年的Retina MacBook Pro上使用CPython 3.6.5进行的,配备2.3 GHz的Intel Core i7处理器。

135

来自:高效的字符串连接

方法 1:

def method1():
  out_str = ''
  for num in xrange(loop_count):
    out_str += 'num'
  return out_str

方法 4:

def method4():
  str_list = []
  for num in xrange(loop_count):
    str_list.append('num')
  return ''.join(str_list)

现在我意识到这些方法并不完全代表所有情况,第四种方法是先把字符串添加到一个列表里,然后再遍历这个列表,把每个项连接起来,但这也算是一个合理的例子。

使用字符串的 join 方法比直接连接字符串要快得多。

为什么呢?因为字符串是不可变的,不能直接修改。如果想改变一个字符串,就得创建一个新的字符串(就是把两个字符串连接起来)。

alt text

撰写回答