我搜索答案为什么a is None
的工作速度比a == None
快。我使用此代码测量时间:
>>> timeit.timeit("1 is None", number=10000000)
0.4035069934390217
>>> timeit.timeit("1 == None", number=10000000)
0.8190256083633187
The documentation表示a is b
具有等效is_(a, b)
功能,而a == b
具有等效功能eq(a, b)
。那么,为什么is_
函数比eq
更快?
我在一些文章中读到is_()
仅比较对象的标识符,eq()
进行“深度比较”。但我在文档中找不到这些信息。这些信息是否正确?我可以在哪里阅读更多相关信息?
答案 0 :(得分:9)
对身份(is
)的测试就是简单的指针比较(两个值是同一个对象)。
对平等的测试需要做更多的工作;例如,对于列表,它确实需要测试两个列表中每个元素的相等性,直到某些东西测试为相等为负,或者测试了最短列表中的所有元素。
请注意,两个运算符在测试时完全不同:
>>> lsta = []
>>> lstb = lsta
>>> lsta is listb
True
>>> lstc = []
>>> lsta is listc
False
>>> lsta == listc
True
仅仅因为两个物体相等并不意味着它们是同一个物体; is
测试后者。
答案 1 :(得分:2)
以下是实施比较的Python源代码(is
,==
,<=
等):
static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
int res = 0;
switch (op) {
case PyCmp_IS:
res = (v == w);
break;
...
default:
return PyObject_RichCompare(v, w, op);
is
仅在一行代码中实现,这是一个简单的C指针比较。一些Python原语根据此比较相等(因为实习,或者因为它们是单True
,False
和None
)。
另一方面,eq
使用PyObject_RichCompare
,这是使用辅助函数do_richcompare
实现的:
richcmpfunc f;
PyObject *res;
int checked_reverse_op = 0;
if (v->ob_type != w->ob_type &&
PyType_IsSubtype(w->ob_type, v->ob_type) &&
(f = w->ob_type->tp_richcompare) != NULL) {
checked_reverse_op = 1;
res = (*f)(w, v, _Py_SwappedOp[op]);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if ((f = v->ob_type->tp_richcompare) != NULL) {
res = (*f)(v, w, op);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if (!checked_reverse_op && (f = w->ob_type->tp_richcompare) != NULL) {
res = (*f)(w, v, _Py_SwappedOp[op]);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
这会检查参数类型并可能尝试多个比较函数(__eq__
方法),然后才能确定答案。比较方法可能会做无限制的工作(例如list.__eq__
必须检查列表的每个元素,可能是递归的),但即使在x == None
的简单情况下,类型检查和所有额外的工作也将金额与is
相比真正的减速。