网上有很多关于python性能的文章,你读的第一件事:不应该使用'+'连接字符串:避免使用s1 + s2 + s3,而是使用str.join
我尝试了以下内容:将两个字符串连接为目录路径的一部分:三种方法:
我不应该做的'+'
str.join
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
不应该完全相反吗?
字符串连接的大多数性能问题都是渐近性能的问题,因此当您连接许多长字符串时,差异变得最为显着.在您的示例中,您多次执行相同的连接.你没有构建任何长字符串,可能是python解释器正在优化你的循环.这可以解释为什么当你转移到str.join和path.join时,时间会增加 - 它们是更复杂的函数,不容易减少.(os.path.join会对字符串进行大量检查,以确定它们是否需要在连接之前以任何方式重写.为了便于携带,这会牺牲一些性能.)
顺便说一句,由于文件路径通常不是很长,因此为了便于携带,您几乎肯定希望使用os.path.join.如果连接的性能是一个问题,那么你的文件系统正在做一些非常奇怪的事情.
不应该完全相反吗?
不必要.我不太清楚Python的内部结构是否具体,但是一些常见的观察结果是你的第一个循环使用了一个简单的运算符+
,它很可能被运行时实现为原语.相反,其他循环首先必须解析模块名称,解析在那里找到的变量/类,然后在其上调用成员函数.
另一个注意事项是你的循环可能只是太小而不能产生大量数字.考虑到您的总体运行时间较短,这可能会使您的测试失效.
此外,您的测试用例高度专注于两个短字符串.这种情况从未给出边缘情况表现的清晰图像.
建议是关于串联许多字符串。
要计算s = s1 + s2 + ... + sn,
1)使用+。创建新的字符串s1 + s2,然后创建新的字符串s1 + s2 + s3,...,依此类推,因此涉及大量内存分配和复制操作。实际上,s1被复制n-1次,s2被复制n-2次,等等。
2)使用“” .join([s1,s2,...,sn])。串联完成一次,并且字符串中的每个字符仅被复制一次。
在您的代码中,每次迭代都会调用join,因此就像使用+一样。正确的方法是将项目收集到一个数组中,然后对其进行调用join。
编辑:修正错别字