如何在Python中追加一个string到另一个string?

我想要一个有效的方法来在Python中追加一个string到另一个string。

var1 = "foo" var2 = "bar" var3 = var1 + var2 

有没有什么好的内置方法可以使用?

如果只有一个string的引用,并且将另一个string连接到结尾,则CPython现在特殊情况会尝试扩展string。

最终结果是该操作是摊销O(n)。

例如

 s = "" for i in range(n): s+=str(i) 

曾经是O(n ^ 2),但现在是O(n)。

源(bytesobject.c):

 void PyBytes_ConcatAndDel(register PyObject **pv, register PyObject *w) { PyBytes_Concat(pv, w); Py_XDECREF(w); } /* The following function breaks the notion that strings are immutable: it changes the size of a string. We get away with this only if there is only one module referencing the object. You can also think of it as creating a new string object and destroying the old one, only more efficiently. In any case, don't use this if the string may already be known to some other part of the code... Note that if there's not enough memory to resize the string, the original string object at *pv is deallocated, *pv is set to NULL, an "out of memory" exception is set, and -1 is returned. Else (on success) 0 is returned, and the value in *pv may or may not be the same as on input. As always, an extra byte is allocated for a trailing \0 byte (newsize does *not* include that), and a trailing \0 byte is stored. */ int _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) { register PyObject *v; register PyBytesObject *sv; v = *pv; if (!PyBytes_Check(v) || Py_REFCNT(v) != 1 || newsize < 0) { *pv = 0; Py_DECREF(v); PyErr_BadInternalCall(); return -1; } /* XXX UNREF/NEWREF interface should be more symmetrical */ _Py_DEC_REFTOTAL; _Py_ForgetReference(v); *pv = (PyObject *) PyObject_REALLOC((char *)v, PyBytesObject_SIZE + newsize); if (*pv == NULL) { PyObject_Del(v); PyErr_NoMemory(); return -1; } _Py_NewReference(*pv); sv = (PyBytesObject *) *pv; Py_SIZE(sv) = newsize; sv->ob_sval[newsize] = '\0'; sv->ob_shash = -1; /* invalidate cached hash value */ return 0; } 

很容易validation经验。

 $ python -m timeit -s“s =''”“for xrange(10):s + ='a'”
 1000000循环,最好是3:每循环1.85次
 $ python -m timeit -s“s =''”“我在xrange(100)中:s + ='a'”
 10000循环,最好是3:每循环16.8次
 $ python -m timeit -s“s =''”“for xrange(1000):s + ='a'”
 10000个循环,最好是每个循环3:158个usec
 $ python -m timeit -s“s =''”“for xrange(10000):s + ='a'”
 1000个循环,最好是3:1.71毫秒每个循环
 $ python -m timeit -s“s =''”“for xrange(100000):s + ='a'”
 10个循环,最好是3:每循环14.6毫秒
 $ python -m timeit -s“s =''”“for xrange(1000000):s + ='a'”
 10个循环,最好是每个循环3:173毫秒

不过要注意的是,这个优化不是Python规范的一部分。 据我所知,这只是在cPython实现。 例如,对pypy或jython进行相同的经验性testing可能会显示较旧的O(n ** 2)性能。

 $ pypy -m timeit -s“s =''”“我在xrange(10)中:s + ='a'”
 10000循环,最好是3:每循环90.8次
 $ pypy -m timeit -s“s =''”“我在xrange(100)中:s + ='a'”
 1000循环,每循环3:896最好
 $ pypy -m timeit -s“s =''”“我在xrange(1000)中:s + ='a'”
 100个循环,最好3个:每个循环9.03毫秒
 $ pypy -m timeit -s“s =''”“我在xrange(10000)中:s + ='a'”
 10个循环,最好是3:每循环89.5毫秒

到目前为止这么好,但是,

 $ pypy -m timeit -s“s =''”“我在xrange(100000)中:s + ='a'”
 10个循环,最好是每个循环12.8秒

甚至比二次方更糟糕。 所以pypy正在做一些对短string很好用的东西,但对于较大的string来说效果不好。

不要过早地优化。 如果你没有理由相信有string连接造成的速度瓶颈,那么只要坚持++=

 s = 'foo' s += 'bar' s += 'baz' 

也就是说,如果你的目标是Java的StringBuilder,那么规范的Python成语是将项目添加到列表中,然后使用str.join将它们连接在一起:

 l = [] l.append('foo') l.append('bar') l.append('baz') s = ''.join(l) 

别。

也就是说,在大多数情况下,您最好一次性生成整个string,而不是附加到现有的string。

例如,不要这样做: obj1.name + ":" + str(obj1.count)

相反:使用"%s:%d" % (obj1.name, obj1.count)

这将更容易阅读,更高效。

 str1 = "Hello" str2 = "World" newstr = " ".join((str1, str2)) 

str1和str2加上一个空格作为分隔符。 你也可以做"".join(str1, str2, ...)str.join()需要一个迭代,所以你必须把string放在一个列表或一个元组中。

这与内置方法的效率差不多。

这真的取决于你的应用程序。 如果你循环了数百个单词,并想将它们全部附加到列表中,那么.join()更好。 但如果你把一个长句放在一起,你最好用+=

如果您需要执行许多追加操作来构build大string,则可以使用StringIO或cStringIO。 界面就像一个文件。 即:你write给它附加文本。

如果你只是追加两个string,那就用+

 a='foo' b='baaz' a.__add__(b) out: 'foobaaz' 

基本上没有区别。 唯一一致的趋势是,Python似乎越来越慢,每个版本… 🙁


名单

 %%timeit x = [] for i in range(100000000): # xrange on Python 2.7 x.append('a') x = ''.join(x) 

Python 2.7

1循环,最好是3:每循环7.34

Python 3.4

1循环,最好是3: 7.99秒/循环

Python 3.5

1循环,最好是3:每循环8.48

Python 3.6

1循环,最好是3:每循环9.93


 %%timeit x = '' for i in range(100000000): # xrange on Python 2.7 x += 'a' 

Python 2.7

1循环,最好是3:每循环7.41秒

Python 3.4

1循环,最好是3:每循环9.08

Python 3.5

1循环,最好是3:每循环8.82

Python 3.6

1循环,最好是3:每循环9.24