为什么 f 字符串比 str() 解析值更快?
Why are f-strings faster than str() to parse values?
我在玩 f-strings(见 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 to my surprise, when I checked the speed of both methods with the timeit 函数,我发现
f 弦更快。
>>> 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)
简单的答案是因为 f-strings are part of the language's grammar and syntax. 另一方面,str()
调用需要符号 table 查找,然后是函数调用。
下面是一个对整数变量进行插值的类似示例,将其与常量值插值进行对比。
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-strings 肯定没有的开销——至少在这种情况下,因为不需要 eval
'd.
我在玩 f-strings(见 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 to my surprise, when I checked the speed of both methods with the timeit 函数,我发现
f 弦更快。
>>> 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)
简单的答案是因为 f-strings are part of the language's grammar and syntax. 另一方面,str()
调用需要符号 table 查找,然后是函数调用。
下面是一个对整数变量进行插值的类似示例,将其与常量值插值进行对比。
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-strings 肯定没有的开销——至少在这种情况下,因为不需要 eval
'd.