结合我的评论和@khelwood 的评论:
TL;DR:
在分析两次比较的字节码时,它揭示了'time'
and 'time'
字符串被分配给同一个对象。因此,预先身份检查(在 C 级)是比较速度提高的原因。
相同对象分配的原因是,作为实施细节,CPython 实习生字符串仅包含“名称字符”(即字母和下划线字符)。这可以实现对象的身份检查。
字节码:
import dis
In [24]: dis.dis("'time'=='time'")
1 0 LOAD_CONST 0 ('time') # <-- same object (0)
2 LOAD_CONST 0 ('time') # <-- same object (0)
4 COMPARE_OP 2 (==)
6 RETURN_VALUE
In [25]: dis.dis("'time'=='1234'")
1 0 LOAD_CONST 0 ('time') # <-- different object (0)
2 LOAD_CONST 1 ('1234') # <-- different object (1)
4 COMPARE_OP 2 (==)
6 RETURN_VALUE
作业时间:
在使用分配进行时间测试时也可以看到“加速”。将两个变量分配(和比较)到同一字符串比将两个变量分配(和比较)到不同字符串要快。底层逻辑正在执行对象比较,进一步支持这一假设。这将在下一节中得到证实。
In [26]: timeit.timeit("x='time'; y='time'; x==y", number=1000000)
Out[26]: 0.0745926329982467
In [27]: timeit.timeit("x='time'; y='1234'; x==y", number=1000000)
Out[27]: 0.10328884399496019
Python源代码:
正如 @mkrieger1 和 @Masklinn 在他们的评论中所提供的,源代码 https://github.com/python/cpython/blob/main/Objects/unicodeobject.c#L11134 for unicodeobject.c
首先执行指针比较,如果True
,立即返回。
int
_PyUnicode_Equal(PyObject *str1, PyObject *str2)
{
assert(PyUnicode_CheckExact(str1));
assert(PyUnicode_CheckExact(str2));
if (str1 == str2) { // <-- Here
return 1;
}
if (PyUnicode_READY(str1) || PyUnicode_READY(str2)) {
return -1;
}
return unicode_compare_eq(str1, str2);
}
附录:
-
参考答案 https://stackoverflow.com/a/47529318/6340496很好地说明了如何读取反汇编的字节码输出。由@Delgan 提供
-
参考答案 https://stackoverflow.com/a/42685254/6340496它很好地描述了 CPython 的字符串驻留。由@ShadowRanger 提供