2009-01-24 50 views
10

网上有很多关于python性能的文章,您首先阅读的内容是:连接字符串不应该使用'+'来完成:避免使用s1 + s2 + s3,而使用str.joinpython字符串连接性能

我试过如下:连接两个字符串作为目录路径的一部分:三种方法:

  1. '+',我不应该这样做
  2. str.join
  3. os.path.join

这里是我的代码:

import os,time 

s1='/part/one/of/dir' 
s2='part/two/of/dir' 
N=10000 

t=time.clock() 
for i in xrange(N): 
    s=s1+os.sep+s2 
print time.clock()-t 

t=time.clock() 
for i in xrange(N): 
    s=os.sep.join((s1,s2)) 
print time.clock()-t 

t=time.clock() 
for i in xrange(N): 
    s=os.path.join(s1,s2) 
print time.clock()-t 

这里的结果(Python 2.5中的WinXP)

0.0182201927899 
0.0262544541275 
0.120238186697 

它不应该是完全倒过来?

+1

如果我可以,我建议重命名你的问题“Python字符串连接性能”的称号,只是这样它更明显,谁可能提交重复的问题的人。 – 2009-01-24 22:35:21

+1

此外,主题略有偏离,但您可能需要查看'timeit'模块以进行计时。 – 2009-01-24 22:35:59

回答

4

确实,你不应该使用'+'。你的例子是相当特别的,尝试使用相同的代码:

s1='*'*100000 
s2='+'*100000 

然后第二个版本(str.join)快得多。

12

字符串连接的大多数性能问题都是渐近性能问题,所以当您连接很多长字符串时,差异会变得最为重要。在您的示例中,您正在多次执行相同的级联。你没有建立任何长字符串,可能是python解释器正在优化你的循环。这可以解释为什么当你移动到str.join和path.join时,时间会增加 - 它们是更复杂的函数,并不容易被减少。 (os.path.join会对字符串进行很多检查,看它们是否需要在连接之前以任何方式进行重写。为了便于携带,这牺牲了一些性能。)

顺便说一句,既然文件路径通常不会很长,为了便于携带,几乎可以肯定地使用os.path.join。如果连接的性能是一个问题,那么你对文件系统做了一些非常奇怪的事情。

5

它不应该完全相反吗?

不一定。我不清楚Python的内部结构是否足够详细,但是一些常见的观察是你的第一个循环使用了一个简单的运算符+,它很容易被运行时实现为基元。相比之下,其他循环首先必须解析模块名称,解析在那里找到的变量/类,然后调用其上的成员函数。

另一个需要注意的是你的循环可能太小而不能产生显着的数字。考虑到你的整体运行时间很少,这可能会让你的测试失效。

另外,您的测试用例对两个短字符串高度专业化。这种情况从来不能清楚地说明边缘案件的表现。

4

该建议是关于连接很多字符串。

要计算s = s1 + s2 + ...+ sn,

1)使用+。创建一个新的字符串s1 + s2,然后创建一个新的字符串s1 + s2 + s3,...等等,因此涉及大量的内存分配和复制操作。实际上,s1被复制n-1次,s2被复制n-2次,...等。

2)使用“”.join([s1,s2,...,sn])。连接完成一次,字符串中的每个字符只被复制一次。

在你的代码中,每次迭代都会调用join,所以就像使用+一样。正确的方法是收集数组中的项目,然后调用join。

编辑:固定错字

1

字符串连接(+)具有上CPython的一个优化的实施方式。但是在Jython或IronPython等其他体系结构上可能并非如此。所以当你希望你的代码在这些解释器上很好地执行时,你应该在字符串上使用.join()方法。 os.path.join()专门用于加入文件系统路径。它也处理不同的路径分隔符。这将是构建文件名的正确方法。

0

我想添加一个链接到python维基,其中有关于字符串连接的注释,并且“这一部分在python2.5中有些不对,Python 2.5字符串连接是相当快的”。

我相信字符串连接自2.5以来有了很大的改进,尽管str.join仍然更快(特别是对于大字符串),但您不会看到像旧版Python版本那样的改进。

http://wiki.python.org/moin/PythonSpeed/PerformanceTips#StringConcatenation