我正在玩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)
答案 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>