为什么f字符串比str()解析值快?

时间:2019-06-13 20:01:49

标签: python python-3.x python-3.6 python-internals f-string

我正在玩f字符串(请参阅PEP 498),因此我决定检查f字符串解析的速度(例如f“ {1}”),与通常的str进行比较解析(例如str(1))。但是令我惊讶的是,当我使用timeit函数检查两种方法的速度时,我发现 那

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

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

甚至是repr func,在大多数情况下,它们都比str cast快

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

我想知道为什么吗?我以为f弦在内部调用了str,但是现在,我有点困惑了,有什么想法吗?提前致谢!

PD:就像有人想知道的那样:

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

1 个答案:

答案 0 :(得分:12)

简单的答案是因为f-strings are part of the language's grammar and syntax.另一方面,str()调用需要先查找符号表,然后再进行函数调用。

这是一个类似的示例,它对整数变量进行插值,并将其与常量值插值进行对比。

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)

当您使用 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

CALL_FUNCTION指令中的所有工作都是繁重的工作,f字符串肯定没有这种开销-至少在这种情况下,因为不需要eval进行任何操作。 / p>