在Python中的str性能

当分析一段python代码( python 2.63.2 )时,我发现把对象(在我的情况下是一个整数)转换为一个string的str方法几乎比使用string格式化要慢一个数量级。

这是基准

 >>> from timeit import Timer >>> Timer('str(100000)').timeit() 0.3145311339386332 >>> Timer('"%s"%100000').timeit() 0.03803517023435887 

有谁知道这是为什么? 我错过了什么吗?

'%s' % 100000由编译器评估,相当于运行时的一个常量。

 >>> import dis >>> dis.dis(lambda: str(100000)) 8 0 LOAD_GLOBAL 0 (str) 3 LOAD_CONST 1 (100000) 6 CALL_FUNCTION 1 9 RETURN_VALUE >>> dis.dis(lambda: '%s' % 100000) 9 0 LOAD_CONST 3 ('100000') 3 RETURN_VALUE 

%与运行时expression式不是(显着)比str更快:

 >>> Timer('str(x)', 'x=100').timeit() 0.25641703605651855 >>> Timer('"%s" % x', 'x=100').timeit() 0.2169809341430664 

请注意, str仍然稍微慢一些,因为@DietrichEpp说,这是因为str涉及查找和函数调用操作,而%编译为一个即时字节码:

 >>> dis.dis(lambda x: str(x)) 9 0 LOAD_GLOBAL 0 (str) 3 LOAD_FAST 0 (x) 6 CALL_FUNCTION 1 9 RETURN_VALUE >>> dis.dis(lambda x: '%s' % x) 10 0 LOAD_CONST 1 ('%s') 3 LOAD_FAST 0 (x) 6 BINARY_MODULO 7 RETURN_VALUE 

当然,以上是我testing的系统(CPython 2.7); 其他实现可能不同。

我们想到的一个原因是str(100000)涉及全局查找,但"%s"%100000不包含。 必须在全球范围内查找全球的情况。 这并没有考虑到整个差异:

 >>> Timer('str(100000)').timeit() 0.2941889762878418 >>> Timer('x(100000)', 'x=str').timeit() 0.24904918670654297 

正如thg435所指出的那样

 >>> Timer('"%s"%100000',).timeit() 0.034214019775390625 >>> Timer('"%s"%x','x=100000').timeit() 0.2940788269042969