python - 为什么 f-strings 比 str() 更快地解析值?
问题描述
我在玩 f-strings(见PEP 498),我决定检查 f-string 解析的速度,(例如f"{1}"
)与通常的 str 解析(例如str(1)
)相比。但令我惊讶的是,当我用timeit函数检查这两种方法的速度时,我发现 f-strings 更快。
>>> 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 字符串是语言语法和句法的一部分。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-strings 肯定没有的开销——至少在这种情况下,因为什么都不需要eval
。
推荐阅读
- r - 更改背景颜色 R posterdown
- python - 如何获取特定时间段的推文抓取?
- postgresql - Postgres concurrent transactions unexpected issue
- python - 如何通过 python API 使用 CPLEX 为基于 MILP 的 VRP 问题提供初始解决方案?
- python - 将识别列表中的空字符串并在那里打印标记/符号的函数(Python Tic-Tac-Toe)
- c# - C# 我们可以通过使用别名来使用异步吗?
- ios - Xcode:更改 UIButton 图像定位
- c++ - VSCode:自动缩进 c++ 代码(没有任何其他格式)
- reactjs - ModuleNotFoundError:找不到模块:错误:无法解析“/vercel/path0/components”中的“../config”
- java - 我将如何在 golang 中使用来自 java 的 AES/CCM/NoPadding 密码?