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

我可以这样写:

s += stringfromelsewhere

或者像这样:

s = []

s.append(somestring)
    
# later
    
s = ''.join(s)

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

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

但它在Python 2.x中。,所以问题是Python 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常见问题:将多个字符串连接在一起的最有效方法是什么?

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

其他回答

你也可以使用这个(更有效)。(https://softwareengineering.stackexchange.com/questions/304445/why-is-s-better-than-for-concatenation)

s += "%s" %(stringfromelsewhere)

在稳定和交叉实现方面,通过“+”来使用字符串连接是最糟糕的连接方法,因为它不支持所有值。PEP8标准不鼓励这种做法,鼓励长期使用format()、join()和append()。

引用自链接的“编程建议”部分:

例如,不要依赖于CPython对a += b或a = a + b形式的语句的就地字符串连接的有效实现。即使在CPython中,这种优化也是脆弱的(它只对某些类型有效),并且在不使用折算的实现中根本不存在。在库的性能敏感部分,应该使用" .join()形式。这将确保跨各种实现的连接以线性时间发生。

如果要连接的字符串是字面量,则使用字符串字面量连接

re.compile(
        "[A-Za-z_]"       # letter or underscore
        "[A-Za-z0-9_]*"   # letter, digit or underscore
    )

如果你想对字符串的一部分进行注释(如上所述),或者如果你想对文本的一部分而不是全部使用原始字符串或三引号,这是非常有用的。

因为这发生在语法层,所以它使用零连接操作符。

在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.'

你可以用不同的方法来做。

str1 = "Hello"
str2 = "World"
str_list = ['Hello', 'World']
str_dict = {'str1': 'Hello', 'str2': 'World'}

# Concatenating With the + Operator
print(str1 + ' ' + str2)  # Hello World

# String Formatting with the % Operator
print("%s %s" % (str1, str2))  # Hello World

# String Formatting with the { } Operators with str.format()
print("{}{}".format(str1, str2))  # Hello World
print("{0}{1}".format(str1, str2))  # Hello World
print("{str1} {str2}".format(str1=str_dict['str1'], str2=str_dict['str2']))  # Hello World
print("{str1} {str2}".format(**str_dict))  # Hello World

# Going From a List to a String in Python With .join()
print(' '.join(str_list))  # Hello World

# Python f'strings --> 3.6 onwards
print(f"{str1} {str2}")  # Hello World

我通过以下文章创建了这个小摘要。

Python 3的f-Strings:改进的字符串格式化语法(指南)(还包括速度测试) 格式化字符串字面量 字符串连接和格式化 Python中的分割、连接和连接字符串