[Jordan Adler <jordan.m.ad...@gmail.com>] > Through the course of work on the future polyfills that mimic the behavior > of Py3 builtins across versions of Python, we've discovered that the > equality check behavior of at least some builtin types do not match the > documented core data model. > > Specifically, a comparison between a primitive (int, str, float were tested) > and an object of a different type always return False, instead of raising > a NotImplementedError. Consider `1 == '1'` as a test case. > > Should the data model be adjusted to declare that primitive types are > expected to fallback to False, or should the cpython primitive type's > __eq__ implementation fallback to raise NotImplementedError?
Nope ;-) This isn't a "data model" issue. Look instead at the Standard Library manual's section on Built-In Types, under heading Comparisons: """ Objects of different types, except different numeric types, never compare equal. ... The <, <=, > and >= operators will raise a TypeError exception when comparing a complex number with another built-in numeric type, when the objects are of different types that cannot be compared, or in other cases where there is no defined ordering. """ It's not an object's responsibility to arrange for that. It's done for them by default, and objects only need to supply their own rich comparison methods if they don't want the defaults. For example, when comparing an int with another type, all the int rich comparison methods _do_ return NotImplemented: >>> f = 4 >>> f.__eq__("abc") NotImplemented It's at a higher level that comparison logic says "OK, I gave both comparands a chance, and they both returned NotImplemented. So one last chance (from object.c's do_richcompare())": /* If neither object implements it, provide a sensible default for == and !=, but raise an exception for ordering. */ 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; } Then the Py_EQ case of that delivers: >>> f == "abc" False and the Py_NE case: >>> f != "abc" True despite that (or because of that ;-) ): >>> f.__eq__("abc") NotImplemented >>> "abc".__eq__(f) NotImplemented Note that there's nothing special about builtin types here. All types are treated alike. _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com