'{0}'.format()比使用IPython%timeit的str()和'{}'.format()更快,否则使用纯Python

vis*_*ell 14 python cpython

所以它是一个CPython的东西,不太确定它与其他实现有相同的行为.

'{0}'.format()str()和更快'{}'.format().我发布了Python 3.5.2的结果,但是,我尝试使用Python 2.7.12并且趋势是相同的.

%timeit q=['{0}'.format(i) for i in range(100, 100000, 100)]
%timeit q=[str(i) for i in range(100, 100000, 100)]
%timeit q=['{}'.format(i) for i in range(100, 100000, 100)]

1000 loops, best of 3: 231 µs per loop
1000 loops, best of 3: 298 µs per loop
1000 loops, best of 3: 434 µs per loop
Run Code Online (Sandbox Code Playgroud)

文档object.__str__(self)

str(object)内置函数调用format()print()计算对象的"非正式"或可打印的字符串表示形式.

所以,str()format()调用相同的object.__str__(self)方法,但速度的差异来自哪里?

更新 @StefanPochmann和@Leon在评论中指出,他们得到了不同的结果.我尝试用它来运行它python -m timeit "...",它们是正确的,因为结果是:

$ python3 -m timeit "['{0}'.format(i) for i in range(100, 100000, 100)]"
1000 loops, best of 3: 441 usec per loop

$ python3 -m timeit "[str(i) for i in range(100, 100000, 100)]"
1000 loops, best of 3: 297 usec per loop

$ python3 -m timeit "['{}'.format(i) for i in range(100, 100000, 100)]"
1000 loops, best of 3: 420 usec per loop
Run Code Online (Sandbox Code Playgroud)

所以似乎IPython正在做一些奇怪的事......

新问题:将对象转换为str速度的首选方法是什么?

Jim*_*ard 7

由于某些原因,IPython时序刚刚关闭(但是,当在不同的单元格中使用较长格式的字符串进行测试时,它表现得稍好一些).也许在相同的单元格中执行是不对的,不知道.

无论哪种方式,"{}"都比"{pos}"它快一点,比"{name}"它们慢得多str.

str(val)是将对象转换为最快的方法str; 它直接调用对象' __str__(如果存在),并返回结果字符串.其他的,比如format,(或str.format)由于额外的函数调用(对format自身)而包括额外的开销; 处理任何参数,解析格式字符串然后调用__str__它们的args.

对于str.format方法"{}"使用自动编号; 从文档中的一小部分格式语法:

版本3.1中更改:位置参数说明符可以省略,因此'{} {}'等效于'{0} {1}'.

也就是说,如果您提供表单的字符串:

"{}{}{}".format(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

CPython 立即知道这相当于:

"{0}{1}{2}".format(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

使用包含表示位置的数字的格式字符串; CPython不能假设一个严格增加的数字(从头开始0)并且必须解析每一个括号以使其正确,在此过程中减慢一些事情:

"{1}{2}{0}".format(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

这就是为什么它也不允许将这两者混合在一起:

"{1}{}{2}".format(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

ValueError当你试图这样做时,你会得到一个好的回报:

ValueError: cannot switch from automatic field numbering to manual field specification
Run Code Online (Sandbox Code Playgroud)

它也抓住了这些定位PySequence_GetItem,我很确定它是快速的,至少与PyObject_GetItem[见下一个]相比.

对于"{name}"值,CPython总是有额外的工作要做,因为我们处理的是关键字参数而不是位置参数; 这包括为调用构建字典以及生成LOAD用于加载keys和值的更多字节码指令的方法.函数调用的关键字形式总是会引入一些开销.此外,PyObject_GetItem由于其通用性质,实际使用的抓取似乎会产生一些额外的开销.