static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w) {
int res = 0;
switch (op) {
case PyCmp_IS:
res = (v == w);
break;
case PyCmp_IS_NOT:
res = (v != w);
break;
...
}
可以看出,is 和 is not 比较的就是 v 和 w 这俩个指针变量!而指针变量本质上是一个内存地址,它在 32 位系统中就是一个 32 整数,在 64 位系统中就是一个 64 位整数。
PyObject *
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
{
PyObject *res;
assert(Py_LT <= op && op <= Py_GE);
if (v == NULL || w == NULL) {
if (!PyErr_Occurred())
PyErr_BadInternalCall();
return NULL;
}
if (Py_EnterRecursiveCall(" in comparison"))
return NULL;
res = do_richcompare(v, w, op);
Py_LeaveRecursiveCall();
return res;
}
这个函数主要是对参数的检查,真正做事的是 do_richcompare :
/* Perform a rich comparison, raising TypeError when the requested comparison
operator is not supported. */
static PyObject *
do_richcompare(PyObject *v, PyObject *w, int op)
{
richcmpfunc f;
PyObject *res;
int checked_reverse_op = 0;
/* 第一种情况 */
...
/* 第二种情况 */
...
/* 第三种情况 */
...
/* 第四种情况 */
...
Py_INCREF(res);
return res;
}
这里分为几种情况:
1、v 和 w 类型不同,w 是 v 的子类,w 如果重载了某个 richcompare 方法,则调用 w 中的 richcompare 方法:
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);
}
例子:
In [1]: class A:
...: pass
...:
In [2]: class B(A):
...: def __eq__(self, o):
...: print('eq richcompare in B')
...: return True
...:
In [3]: a = A()
In [4]: b = B()
In [5]: a == b
eq richcompare in B
Out[5]: True
2、v 和 w 类型不同,或者 w 不是 v 的子类,或者 w 没有相应的 richcompare 方法,如果 v 定义了相应的 richcompare 方法,就调用 v 中相应的 richcompare 方法:
if ((f = v->ob_type->tp_richcompare) != NULL) {
res = (*f)(v, w, op);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
例子:
In [1]: class A:
...: def __eq__(self, o):
...: print('eq richcompare in A')
...:
In [2]: class B:
...: pass
...:
In [3]: class C(A):
...: pass
...:
In [4]: class D(B):
...: def __eq__(self, o):
...: print('eq richcompare in D')
...:
In [5]: a = A()
In [6]: b = B()
In [7]: c = C()
In [8]: d = D()
In [9]: a == b
eq richcompare in A
In [10]: a == c
eq richcompare in A
In [11]: a == d
eq richcompare in A
3、w 不是 v 的子类,v 中没有定义或者继承相应的 richcompare 方法而 w 中定义了相应的 richcompare 方法,就调用 w 中相应的 richcompare 方法:
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);
}
例子,接第二种情况的例子:
In [12]: c == d
eq richcompare in A
In [13]: b == d
eq richcompare in D
以上三种情况总结起来就是:如果 w 是 v 的子类对象,优先调用 w 相应的 richcompare 方法,否则,v 和和 w 中谁有就调用谁的。
如果 v 和 w 都没有相应的 richcompare 方法,那么默认的处理是:
switch (op) {
case Py_EQ:
res = (v == w) ? Py_True : Py_False;
break;
case Py_NE:
res = (v != w) ? Py_True : Py_False;
break;
default:
PyErr_Format(PyExc_TypeError,
"'%s' not supported between instances of '%.100s' and '%.100s'",
opstrings[op],
v->ob_type->tp_name,
w->ob_type->tp_name);
return NULL;
}
可以看到如果比较的是 == 和 !=,结果又回到 v 和 w 指针变量的直接比较,和 is 比较的结果相同,否则会引发一个类型错误。
例子:
In [1]: class A:
...: pass
...:
In [2]: class B:
...: pass
...:
In [3]: a = A()
In [4]: b = B()
In [5]: a == b
Out[5]: False
In [6]: a is b
Out[6]: False
In [7]: a != b
Out[7]: True
In [8]: a is not b
Out[8]: True
In [9]: a > b
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-1e61210fe837> in <module>()
----> 1 a > b
TypeError: '>' not supported between instances of 'A' and 'B'
static PyObject *
object_richcompare(PyObject *self, PyObject *other, int op)
{
PyObject *res;
switch (op) {
case Py_EQ:
/* Return NotImplemented instead of False, so if two
objects are compared, both get a chance at the
comparison. See issue #1393. */
res = (self == other) ? Py_True : Py_NotImplemented;
Py_INCREF(res);
break;
case Py_NE:
/* By default, __ne__() delegates to __eq__() and inverts the result,
unless the latter returns NotImplemented. */
if (self->ob_type->tp_richcompare == NULL) {
res = Py_NotImplemented;
Py_INCREF(res);
break;
}
res = (*self->ob_type->tp_richcompare)(self, other, Py_EQ);
if (res != NULL && res != Py_NotImplemented) {
int ok = PyObject_IsTrue(res);
Py_DECREF(res);
if (ok < 0)
res = NULL;
else {
if (ok)
res = Py_False;
else
res = Py_True;
Py_INCREF(res);
}
}
break;
default:
res = Py_NotImplemented;
Py_INCREF(res);
break;
}
return res;
}
In [1]: class A:
...: pass
...:
In [2]: class B:
...: def __ne__(self, o):
...: print('ne richcompare in B')
...: return False
...:
In [3]: a1 = A()
In [4]: a2 = A()
In [5]: a3 = a1
In [6]: a1 == a2
Out[6]: False
In [7]: a1 == a3
Out[7]: True
In [8]: a1 != a2
Out[8]: True
In [9]: b1 = B()
In [10]: b2 = B()
In [11]: b1 == b2
Out[11]: False
In [12]: b1 != b2
ne richcompare in B
Out[12]: False
In [13]: a1 <= a2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-7ba1adc4bd61> in <module>()
----> 1 a1 <= a2
TypeError: '<=' not supported between instances of 'A' and 'A'
总结
本文深入源码,剖析了 is 和 == 的区别和联系,总的来说就是:
is 比较的是俩个对象内存地址是不是一样,即是否是同一个对象
== 是 richcompare 的一种,除非对象的类型重写了 tp_richcompare,否则默认的 == 比较的也是俩个对象的内存地址,和 is 一致