[Python-Dev] Definition of equality check behavior (original) (raw)
Jordan Adler jordan.m.adler at gmail.com
Wed May 8 11:51:58 EDT 2019
- Previous message (by thread): [Python-Dev] Definition of equality check behavior
- Next message (by thread): [Python-Dev] Definition of equality check behavior
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Ahh, I didn't locate the documentation on the NotImplemented constant <https://docs.python.org/3/library/constants.html#NotImplemented> as I was checking 2.7's docs, so I wasn't aware of the layer of indirection and fallback behavior for the operator. Sorry about that!
Based on that, the right call here is to adjust newstr to return that singleton where appropriate.
On Tue, May 7, 2019 at 9:23 PM Tim Peters <tim.peters at gmail.com> wrote:
[Jordan Adler <jordan.m.adler at 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 dorichcompare())": /* If neither object implements it, provide a sensible default for == and !=, but raise an exception for ordering. */ switch (op) { case PyEQ: res = (v == w) ? PyTrue : PyFalse; break; case PyNE: res = (v != w) ? PyTrue : PyFalse; break; default: PyErrFormat(PyExcTypeError, "'%s' not supported between instances of '%.100s' and '%.100s'", opstrings[op], v->obtype->tpname, w->obtype->tpname); return NULL; } Then the PyEQ case of that delivers: >>> f == "abc" False and the PyNE 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. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20190508/ac8b1267/attachment-0001.html>
- Previous message (by thread): [Python-Dev] Definition of equality check behavior
- Next message (by thread): [Python-Dev] Definition of equality check behavior
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]