3

我搜索答案为什么a is Nonea == None. 我使用以下代码测量时间:

>>> timeit.timeit("1 is None", number=10000000)
0.4035069934390217
>>> timeit.timeit("1 == None", number=10000000)
0.8190256083633187

该文档说,a is b具有功能等价is_(a, b)a == b具有功能等价eq(a, b)。那么,为什么is_函数比eq?

我读过一些is_()只比较对象标识符eq()并进行“深度比较”的文章。但我在文档中找不到此信息。这些信息是否正确?我可以在哪里阅读更多相关信息?

4

2 回答 2

9

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

测试平等需要做的工作不止于此;例如,对于列表,它确实需要测试两个列表中每个元素的相等性,直到某些东西对相等性测试为阴性或最短列表中的所有元素都经过测试。

请注意,这两个运算符的测试内容完全不同:

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

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

于 2013-01-31T17:39:26.930 回答
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 原语比较相等(因为实习,或者因为它们是单例,如True,FalseNone)。

另一方面,eq使用PyObject_RichCompare辅助函数实现的uses 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.

于 2013-01-31T17:52:00.947 回答