/* 执行丰富的比较,在请求比较时引发 TypeError不支持运算符.*/静态 PyObject *do_richcompare(PyObject *v, PyObject *w, int op){丰富的cmpfunc f;PyObject *res;int check_reverse_op = 0;如果 (v-> ob_type != w-> ob_type &&PyType_IsSubtype(w->ob_type, v->ob_type) &&(f = w->ob_type->tp_richcompare) != NULL) {check_reverse_op = 1;res = (*f)(w, v, _Py_SwappedOp[op]);//我们正在执行这个如果(res != Py_NotImplemented)返回资源;Py_DECREF(res);}如果((f = v-> ob_type-> tp_richcompare)!= NULL){res = (*f)(v, w, op);//而不是这个.如果(res != Py_NotImplemented)返回资源;Py_DECREF(res);}如果 (!checked_reverse_op && (f = w->ob_type->tp_richcompare) != NULL) {res = (*f)(w, v, _Py_SwappedOp[op]);如果(res != Py_NotImplemented)返回资源;Py_DECREF(res);}这两个版本很相似,除了 Python 2.7 版本使用 RICHCOMPARE 宏检查 PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE 而不是 ob_type->tp_richcompare != NULL代码>.在两个版本中,第一个 if 块的计算结果为 true.根据文档中的描述,人们可能会认为是错误的具体部分是:f = w->ob_type->tp_richcompare != NULL(对于 Py3)/PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE.但是,文档说 tp_richcompare 被子类继承:richcmpfunc PyTypeObject.tp_richcompare一个可选的指向富比较函数的指针...该字段与 tp_compare 和 tp_hash 一起被子类型继承...在 2.x 版本中,PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE 也会评估为真,因为 Py_TPFLAGS_HAVE_RICHCOMPARE 标志为真,如果 tp_richcompare、tp_clear 和 tp_traverse 是真的,所有这些都是从父母.所以,即使 B 没有提供它自己的丰富的比较方法,它仍然返回一个非 NULL 值,因为它的父类提供了它.正如其他人所说,这似乎是一个文档错误;子类实际上不需要覆盖父类的 __eq__ 方法,它只需要提供一个,即使通过继承.In python 2.7.6, suppose that I have a class that defines __eq__ and a subclassthereof:>>> class A(object):... def __eq__(self,other):... print self.__class__,other.__class__... return True... >>> class B(A):... pass... Now I create an object of each class, and want to compare them:>>> a = A()>>> b = B()>>> a==bThe result I get:<class '__main__.B'> <class '__main__.A'>This shows that the interpreter is calling b.__eq__(a), instead of a.__eq__(b) asexpected.The documentation states (emphasis added):Since the subclass B does not override the __eq__ operator, shouldn't a.__eq__(b)be called instead of b.__eq__(a)? Is this expected behavior, or a bug? It is contrary to the documentation as I read it: am I misreading the documentation or missing something else?Some related questions:This answer quotes the documentation that I quoted above. In that case the final question involved a comparison between an object of built in type (1) and an an instanceof a new style class. Here, I'm specifically comparing an instance of a parent classwith an instance of a subclass which does not override the rop() method of itsparent (in this case, __eq__ is both op() and rop()).In this case, python actually does call b.__eq__(a) instead of a.__eq__(b) first, even though class B does not explicitly override A. 解决方案 Here's the code that implements the described logic:Python 2.7:/* Macro to get the tp_richcompare field of a type if defined */#define RICHCOMPARE(t) (PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE) \ ? (t)->tp_richcompare : NULL)...static PyObject *try_rich_compare(PyObject *v, PyObject *w, int op){ richcmpfunc f; PyObject *res; if (v->ob_type != w->ob_type && PyType_IsSubtype(w->ob_type, v->ob_type) && (f = RICHCOMPARE(w->ob_type)) != NULL) { res = (*f)(w, v, _Py_SwappedOp[op]); // We're executing this if (res != Py_NotImplemented) return res; Py_DECREF(res); } if ((f = RICHCOMPARE(v->ob_type)) != NULL) { res = (*f)(v, w, op); // Instead of this. if (res != Py_NotImplemented) return res; Py_DECREF(res); } if ((f = RICHCOMPARE(w->ob_type)) != NULL) { return (*f)(w, v, _Py_SwappedOp[op]); } res = Py_NotImplemented; Py_INCREF(res); return res;}Python 3.x:/* 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; 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]); // We're executing this if (res != Py_NotImplemented) return res; Py_DECREF(res); } if ((f = v->ob_type->tp_richcompare) != NULL) { res = (*f)(v, w, op); // Instead of this. 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); } The two version are similar, except that the Python 2.7 version uses a RICHCOMPARE macro that checks PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE instead of ob_type->tp_richcompare != NULL.In both versions, the first if block is evaluating to true. The specific piece that one would perhaps expect to be false, going by the description in the docs, is this: f = w->ob_type->tp_richcompare != NULL (for Py3) / PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE. However, the docs say that tp_richcompare is inherited by child classes:With the 2.x version, PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE will also evaluate to true, because the Py_TPFLAGS_HAVE_RICHCOMPARE flag is true if tp_richcompare, tp_clear, and tp_traverse are true, and all of those are inherited from the parent.So, even though B doesn't provide its own rich comparison method, it still returns a non-NULL value because its parent class provides it. As others have stated, this seems to be a doc bug; the child class doesn't actually need to override the __eq__ method of the parent, it just needs to provide one, even via inheritance. 这篇关于python 的 a==b 调用 b.__eq__(a),对于没有覆盖的子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-29 16:41