为什么is_(a,b)函数比python 2.7.3中的eq(a,b)工作得更快?

时间:2013-01-31 17:31:31

标签: python python-2.7

我搜索答案为什么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()进行“深度比较”。但我在文档中找不到这些信息。这些信息是否正确?我可以在哪里阅读更多相关信息?

2 个答案:

答案 0 :(得分:9)

对身份(is)的测试就是简单的指针比较(两个值是同一个对象)。

对平等的测试需要做更多的工作;例如,对于列表,它确实需要测试两个列表中每个元素的相等性,直到某些东西测试为相等为负,或者测试了最短列表中的所有元素。

请注意,两个运算符在测试时完全不同:

>>> lsta = []
>>> lstb = lsta
>>> lsta is listb
True
>>> lstc = []
>>> lsta is listc
False
>>> lsta == listc
True

仅仅因为两个物体相等并不意味着它们是同一个物体; is测试后者。

答案 1 :(得分:2)

以下是实施比较的Python源代码(is==<=等):

Python/ceval.c:4501

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原语根据此比较相等(因为实习,或者因为它们是单TrueFalseNone)。

另一方面,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相比真正的减速。