在Python中打印字符串的最有效方法是什么?

3 投票
3 回答
2416 浏览
提问于 2025-04-16 06:45

根据这个优化建议网站 http://wiki.python.org/moin/PythonSpeed/PerformanceTips,连接字符串时应该使用

out = "<html>%(head)s%(prologue)s%(query)s%(tail)s</html>" % locals()
而不是
out = "<html>" + head + prologue + query + tail + "</html>" 我的问题是,如果我想打印这个值,而不是存储它,这样做是否一样?另外,把连续的打印语句放在一行上会更快吗?比如说,使用

print "Some word"
print "Another line"
print "something else"

还是

print '''Some word
Another line
something else'''

谢谢!

3 个回答

2

打印的时候其实不需要把内容拼接在一起:

print "<html>", head, prologue, query, tail, "</html>"

这样做效果是一样的(最后加个逗号可以防止出现\n):

print "<html>",
print head,
...
print "</html>"

我觉得答案是“不”,打印的时候不需要拼接,这样会让速度变慢。不过你最好不要只听我的,自己写几个测试用timeit来测一下效果。

6

字符串连接的效率得到了提升,特别是在只有一个字符串引用的情况下,这种情况是比较常见的。你可以查看 stringobject.c 中的 PyString_ConcatAndDel。

通常来说,在循环中进行字符串连接的效率是线性的,因为字符串只有一个引用。

下面是一个简单的实验来展示这种行为。当字符串没有空间扩展时,id() 的值会发生变化。

>>> s = ""
>>> prev_id = None
>>> for i in range(1000):
...  s += "*"
...  if prev_id != id(s):
...   print id(s), len(s)
...   prev_id = id(s)
... 
3077352864 1
3077437728 2
3077434328 9
3077428384 17
3077379928 25
3077291808 33
3077712448 41
3077358800 49
3077394728 57
3077667680 65
3077515120 73
3077354176 81
3077576488 89
3077559200 97
3077414248 105
3077670336 113
3077612160 121
3077707040 129
3077526040 137
3077571472 145
3077694944 153
3077595936 161
3077661904 169
3077552608 177
3077715680 185
3077583776 193
3077244304 201
3077604560 209
3077510392 217
3077334304 225
144468768 233
144787416 245
144890104 389
5

你的问题其实不是关于如何高效打印字符串,而是关于如何格式化字符串以便输出。在这方面,你应该使用 format,因为它的功能比简单的拼接要强大得多。不过,我这里有一些关于拼接的说明。


编辑:重新写了一些细节

打印的过程并不重要。关键在于,有些编程语言在处理字符串拼接时的方式,可能会导致拼接很多字符串时效率变得很低。简单来说,拼接两个字符串时,你需要先遍历第一个字符串的所有字符,然后再把第二个字符串的所有字符加上去。所以如果你要拼接十个字符串,首先你要遍历第一个字符串,然后把第二个字符串加上去;接着你要遍历第一个和第二个字符串的组合,再把第三个字符串加上去,依此类推。

如果拼接的实现方式很简单粗暴,就会让你做比必要的工作多得多。实际上,在早期版本的Python中,这确实是个问题。不过,@gnibbler在评论中提到,后来的版本已经对此进行了优化,所以这个问题基本上就不存在了。

在Python中,拼接字符串的标准方式是 "".join(...)。这种方式完全避免了可能出现的问题,而且也是标准的做法。如果你想通过追加的方式来构建字符串,可以看看 StringIO

>>> from io import StringIO
>>> foo = StringIO()
>>> for letter in map(chr, range(128)):
...     foo.write(letter)
...
>>> foo.seek(0)
0
>>> foo.read()
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\
x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABC
DEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f'

撰写回答