On Sat, 2 May 2020 at 20:50, Serhiy Storchaka <storch...@gmail.com> wrote: > > 02.05.20 21:34, Ahmed Amr пише: > > I see there are ways to compare them item-wise, I'm suggesting to bake > > that functionality inside the core implementation of such indexed > > structures. > > Also those solutions are direct with tuples and lists, but it wouldn't > > be as direct with arrays-lists/tuples comparisons for example. > > If make `(1, 2, 3) == [1, 2, 3]` we would need to make `hash((1, 2, 3)) > == hash([1, 2, 3])`.
This is the key point. Much of the other discussion in this thread seems to be bogged down in the mathematical interpretation of tuples and sequences but if I was to take something from maths here it would be the substitution principle of equality: https://en.wikipedia.org/wiki/Equality_(mathematics)#Basic_properties What the substitution principle essentially says is if x == y then f(x) == f(y) for any function f such that f(x) is well defined. What that means is that I should be able to substitute x for y in any context where x would work without any change of behaviour. We don't need to do any deep maths to see how that principle can be applied in Python but if you try to follow it rigorously then you'll see that there are already counterexamples in the language for example >>> x = 1000 >>> y = 1000.0 >>> f = lambda z: 100**z >>> x == y True >>> f(x) # fine <snip> >>> f(y) # not fine Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <lambda> OverflowError: (34, 'Result too large') Given a list x and a tuple y with equivalent elements x and y will not be interchangeable because one is not hashable and the other is not mutable so there are functions where one is usable but the other is not. Following the same reasoning set/frozenset should not compare equal. In SymPy there are many different mathematical objects that people feel should (on mathematical grounds) compare "equal". This happens enough that there is a section explaining this in the tutorial: https://docs.sympy.org/latest/tutorial/gotchas.html#equals-signs The terms "structural equality" and "mathematical equality" are used to distinguish the different kinds of equality with == being used for the structural sense. For example the sympy expression Pow(2, 2, evaluate=False) gives an object that looks like 2**2. This does mathematically represent the number 4 but the expression itself is not literally the number 4 so the two expressions are mathematically equal but not structurally equal: >>> from sympy import Pow >>> p = Pow(2, 2, evaluate=False) >>> p 2**2 >>> p.doit() 4 >>> p == 4 False >>> p.doit() == 4 True This distinction is important because at the programmatic level p and 4 are not interchangeable. For example p being a Pow has attributes base and exp that 4 will not have. In sympy most objects are immutable and hashable and are heavily used in sets and dicts. Following the substitution principle matters not least because Python has baked the use of ==/__eq__ into low-level data structures so objects that compare equal with == will literally be interchanged: >>> {1, 1.0} {1} >>> {1.0, 1} {1.0} All the same many sympy contributors have felt the need to define __eq__ methods that will make objects of different types compare equal and there are still examples in the sympy codebase. These __eq__ methods *always* lead to bugs down the line though (just a matter of time). I've come to the seemingly obvious conclusion that if there is *any* difference between x and y then it's always better to say that x != y. Oscar _______________________________________________ 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/ZBTK2RSH3QVHCJY42JNBIFEYTO6LERLS/ Code of Conduct: http://python.org/psf/codeofconduct/