python中的str性能


88

在分析一段python代码(python 2.6最多3.2)时,我发现 str将对象(在我的情况下为整数)转换为字符串的方法比使用字符串格式化慢了一个数量级。

这是基准

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

有谁知道为什么会这样吗?我想念什么吗?


2
那又如何'{}'.format(100000)
2012年

那是最慢但也是最灵活的。
卡·斯巴德拉

Answers:


106

'%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        

%运行时表达式的速度(不是)明显快于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        

当然,以上对于我在(CPython 2.7)上测试的系统都是正确的;其他实现可能会有所不同。


确实,这似乎是原因,我刚刚尝试了一下,而字符串格式化的速度仅比快大约5%str。感谢您的回答。没有理由在任何地方更改代码:-)
卡·斯巴德拉

2
进一步详细说明:str该名称可以反弹到字符串类型以外的其他名称,但是str.__mod__不能替换字符串格式(即方法),这允许编译器进行优化。编译器并没有在优化方面做很多事情,但是它做的比您想像的要多:)
Karl Knechtel 2012年

4
...这里要学习的课程是:切勿在此类测试中使用文字!
UncleZeiv 2012年

这个特定的博客条目可能会让您感兴趣:skymind.com/~ocrow/python_string。它包含与上面提供的类似的各种字符串连接方法的基准测试表。
亚伦·牛顿

14

我想到的一个原因是str(100000)涉及全局查找但"%s"%100000不涉及全局查找的事实。在str全球拥有在全球范围内进行查找。这不能说明全部差异:

>>> 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.