Why are f-strings faster than str() to parse values?

心已入冬 提交于 2020-01-03 08:28:12

问题


I was playing around with f-strings, (see PEP 498), and I decided to check the speed of the f-string parse, (e.g. f"{1}") in comparison with the usual str parse (e.g str(1)). But for my surprise, when I checked the velocity of both methods with the timeit function, I found out that

>>> from timeit import timeit
>>> timeit("f'{1}'")
0.1678762999999961

whereas

>>> timeit("str(1)")
0.3216999999999999

or even the repr func, which in most of the cases is faster than str cast

>>> timeit("repr(1)")
0.2528296999999995

I wonder why is that? I thought that the f-strings called str internally, but now, I'm a bit confused, any ideas? Thanks in advance!

PD: Just if anyone is wondering:

assert f"{1}" == str(1) == repr(1)

回答1:


The simple answer is because f-strings are part of the language's grammar and syntax. The str() call on the other hand requires a symbol table lookup, followed by a function call.

Here's a similar example which interpolates an integer variable, contrast this with the constant value interpolation.

x = 1                                                                                                                                

%timeit f'{1}'                                                                                                                       
%timeit f'{x}'   
%timeit str(1)                                                                                                                                                                                                                                       
%timeit str(x)                                                                                                                       

113 ns ± 2.25 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
166 ns ± 4.71 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
342 ns ± 23.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
375 ns ± 11.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

The difference in the behaviour is obvious when you look at the disassembled byte code with dis.

import dis

dis.dis("f'{x}'")                                                                                                                    
  1           0 LOAD_NAME                0 (x)
              2 FORMAT_VALUE             0
              4 RETURN_VALUE

dis.dis("str(x)")                                                                                                                     
  1           0 LOAD_NAME                0 (str)
              2 LOAD_NAME                1 (x)
              4 CALL_FUNCTION            1
              6 RETURN_VALUE

The heavy lifting is all in the CALL_FUNCTION instruction, an overhead which f-strings certainly don't have -- at least in this case, as nothing needs to be eval'd.



来源:https://stackoverflow.com/questions/56587807/why-are-f-strings-faster-than-str-to-parse-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!