On Thu, May 07, 2020 at 11:04:16AM -0400, Dan Sommers wrote: > On Thu, 7 May 2020 21:18:16 +1000 > Steven D'Aprano <st...@pearwood.info> wrote: > > > > The strongest equality is the "is" operator > > > > Please don't encourage the conceptual error of thinking of `is` as > > *equality*, not even a kind of equality. It doesn't check for equality, > > it checks for *identity* and we know that there is at least one object > > in Python where identical objects aren't equal: > > > > py> from math import nan > > py> nan is nan > > True > > py> nan == nan > > False > > We'd better agree to disagree on this one.
Why? In what way is there any room for disagreement at all? This isn't a matter of subjective opinion, like what's the best Star Wars film or whether pineapple belongs on pizza. This is a matter of objective fact, like whether Python strings are Unicode or not. Whatever we might feel about equality and identity in the wider philosophical sense, in the *Python programming sense* the semantic meaning of the two operators are orthogonal: * some equal objects are not identical; * and some identical objects are not equal. It is a matter of fact that in Python `is` tests for object identity, not equality: https://docs.python.org/3/reference/expressions.html#is-not If you wish to agree with Bertrand Meyer that reflexivity of equality is one of the pillars of civilization: https://bertrandmeyer.com/2010/02/06/reflexivity-and-other-pillars-of-civilization/ and therefore Python gets equality wrong, you are welcome to that opinion, but whether we like it or not equality in Python is not necessarily reflexive and as a consequence objects may be identical (i.e. the same object) but not equal. Float and Decimal NANs are the most obvious examples. You don't even need to look at such exotic objects as NANs to see that `is` does not test for equality. None of these will return True: [] is [] 1.5 is Fraction(3, 2) (a := {}) is a.copy() even though the operands are clearly equal. [...] > YAGNI is how I feel about an operator that compares sequences element by > element. Remember that list-to-list and tuple-to-tuple already perform the same sequence element-by-element comparison. All this proposal adds is *duck-typing* to the comparison, for when it doesn't matter what the container type is, you care only about the values in the container. Why be forced to do a possibly expensive (and maybe very expensive!) manual coercion to a common type just to check the values for equality element by element, and then throw away the coerced object? If you have ever written `a == list(b)` or similar, then You Already Needed It :-) > People can write their own functions. :-) Or add your .EQ. > function to the standard library (or even to builtins, and no, I don't > have a good name). True, but there are distinct advantages to operators over functions for some operations. See Guido's essay: https://neopythonic.blogspot.com/2019/03/why-operators-are-useful.html > > It is only that wanting to compare two ordered containers for equality > > of their items without regard to the type of container is a reasonably > > common and useful thing to do. > > > Even if we don't want list==tuple to return True -- and I don't! -- we > > surely can recognise that sometimes we don't care about the > > container's type, only it's elements. > > Do "reasonably common," "useful," and "sometimes" meet the bar for a new > operator? (That's an honest question and not a sharp stick.) It depends on how common and useful, and how easy it is to find a good operator. It might be a brilliant idea stymied by lack of a good operator. We might be forced to use a function because there are no good operators left any more, and nobody wants Python to turn into Perl or APL. > FWIW, I agree: list != tuple. When's the last time anyone asked for > the next element of a tuple? Any time you have written: for obj in (a, b, c): ... you are asking for the next element of a tuple. A sample from a test suite I just happen to have open at the moment: # self.isprime_functions is a tuple of functions to test for func in self.isprime_functions: for a in (3, 5, 6): self.assertFalse(sqrt_exists(a, 7)) for a in (2, 6, 7, 8, 10): self.assertFalse(sqrt_exists(a, 11)) -- Steven _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ABSJEK5QQQCBSG3PU7L3BS7NE3KMG4V6/ Code of Conduct: http://python.org/psf/codeofconduct/