在Python中,连接字符串的首选方法是什么?

2024-03-29 11:50:15 发布

您现在位置:Python中文网/ 问答频道 /正文

由于Python的string无法更改,我想知道如何更有效地连接字符串?

我可以这样写:

s += stringfromelsewhere

或者像这样:

s = []
s.append(somestring)

later

s = ''.join(s)

在写这个问题的时候,我发现一篇关于这个话题的好文章。

http://www.skymind.com/~ocrow/python_string/

但这是在Python2.x中,所以问题是Python3中有什么变化吗?


Tags: 字符串comhttpstringwww文章join话题
3条回答

如果要连接许多值,则两者都不需要。附加一份清单是很贵的。你可以用StringIO来做。尤其是当你在大量的操作中积累起来的时候。

from cStringIO import StringIO
# python3:  from io import StringIO

buf = StringIO()

buf.write('foo')
buf.write('foo')
buf.write('foo')

buf.getvalue()
# 'foofoofoo'

如果您已经从其他操作返回了完整的列表,那么只需使用''.join(aList)

来自python常见问题解答:What is the most efficient way to concatenate many strings together?

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

编辑:我很傻,结果被向后粘贴,使其看起来像是添加到列表比cStringIO快。我还添加了bytearray/str concat的测试,以及使用带有更大字符串的更大列表的第二轮测试。(python 2.7.3)

ipython大型字符串列表测试示例

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

在Python>;=3.6中,新的f-string是连接字符串的有效方法。

>>> name = 'some_name'
>>> number = 123
>>>
>>> f'Name is {name} and the number is {number}.'
'Name is some_name and the number is 123.'

将字符串附加到字符串变量的最佳方式是使用++=。这是因为它可读性和速度。他们也一样快,你选择哪一个是口味的问题,后一个是最常见的。以下是timeit模块的计时:

a = a + b:
0.11338996887207031
a += b:
0.11040496826171875

但是,那些建议有列表并附加到列表中,然后加入这些列表的人这样做是因为将字符串附加到列表中可能比扩展字符串要快得多。在某些情况下,这是真的。例如,这里有一个 一百万个一个字符串的追加,首先是一个字符串,然后是一个列表:

a += b:
0.10780501365661621
a.append(b):
0.1123361587524414

好吧,事实证明,即使结果字符串有一百万个字符长,追加也更快。

现在,让我们尝试将1000个字符长的字符串追加十万次:

a += b:
0.41823482513427734
a.append(b):
0.010656118392944336

因此,结束字符串的长度约为100MB。那是相当缓慢的,添加到列表中要快得多。这个时间不包括最后的a.join()。那要多长时间?

a.join(a):
0.43739795684814453

欧普斯。即使在这种情况下,append/join也比较慢。

那么,这个建议是从哪里来的呢?Python2?

a += b:
0.165287017822
a.append(b):
0.0132720470428
a.join(a):
0.114929914474

好吧,如果您使用非常长的字符串(通常不是这样的,您会有一个内存为100MB的字符串),那么append/join的速度会略快一些

但真正的关键是Python 2.3。我甚至不给你看时间,因为太慢了,还没结束。这些测试突然需要分钟。除了append/join,它和后面的Pythons一样快。

是的。在石器时代的Python中,字符串连接非常慢。但是在2.4版本中,它已经不再是(或者至少是Python2.4.7),所以使用append/join的建议在2008年就过时了,当时Python2.3停止更新,您应该停止使用它。:-)

(更新:当我更仔细地进行测试时发现,对于Python 2.3上的两个字符串,使用++=也更快。使用''.join()的建议一定是个误会)

不过,这是CPython。其他实现可能有其他问题。这也是为什么过早优化是万恶之源的另一个原因。除非你先测量一下,否则不要使用所谓的“更快”的技术。

因此,进行字符串连接的“最佳”版本是使用+或+=。如果这对你来说很慢,这是不太可能的,那就做点别的。

那么,为什么在代码中要使用大量的append/join呢?因为有时候会更清楚。尤其是当您应该连接在一起的内容应该用空格、逗号或换行符分隔时。

相关问题 更多 >