On 4/27/2012 13:09, Steven D'Aprano wrote:
On Thu, 26 Apr 2012 18:02:31 +0200, Kiuhnm wrote:
On 4/26/2012 16:00, Adam Skutt wrote:
C# and Python do have a misfeature: '==' is identity comparison only if
operator== / __eq__ is not overloaded. Identity comparison and value
comparison are disjoint operations, so it's entirely inappropriate to
combine them.
They're not "disjoint", in fact one almost always implies the other (*).
Python's idea is that, by default, any object is equal to itself and
only itself. The fact that this is equivalent to "identity comparison"
is just a coincidence, from a conceptual point of view.
Define your terms: what do you mean by "equal"?
a and b are equal iff
a = a
a = b => b = a
a = b and b = c => a = c
If some of this properties are violated, we're talking of something else.
The fact that you can define '==' whatever way you want is irrelevant. I
call that "calling 'equality' something which shouldn't be regarded as
such and making Python comply with it anyway."
The complication is that "equal" has many meanings. Does 1/2 equal 2/4?
Well, yes, numerically, but numerical equality is not the only useful
sense of equality -- not even for mathematicians! Although the convention
to write "1/2 = 2/4" is too strong to discard, there are areas of
mathematics where 1/2 and 2/4 are not treated as equal regardless of
numerical equality.
http://en.wikipedia.org/wiki/Mediant_%28mathematics%29
In Python, "equal" can have any meaning we like, because we can override
__eq__. For most meaningful equality comparisons, we expect that X should
always equal itself, even if it doesn't equal anything else, and so __eq__
defaulting to an identity comparison if you don't override it makes good
sense.
Some people (e.g. the creator of Eiffel, Bertrand Meyer) argue that
identity should *always* imply equality (reflexivity). I disagree, but
regardless, reflexivity is *almost always* the right thing to do.
When it comes to equality, Python defaults to sensible behaviour. By
default, any object supports equality. By default, "a == a" is true for
any object a. If you want to define a non-reflexive type, you have to do
so yourself. If you want to define a type that doesn't support equality
at all, you have to do so yourself. But both use-cases are vanishingly
rare, and rather troublesome to use. It would be stupid for Python to
make them the default behaviour.
After all, Python is a tool, not a philosophy. There's no need to force
the user to start from a blank slate and define everything from first
principles when you can start with the common tools you normally need,
and add or subtract from it as needed.
(*) nan == nan is false, but, at least conceptually, a 'NotComparable'
exception should be raised instead. That wouldn't be very useful,
though.
NANs are comparable. By definition, NAN != x for every x. They're just
not reflexive.
As I said, I know they are but I think they shouldn't, at least
conceptually.
I don't necessarily mind if the two operations have the same symbol, as
long as there's some other way in-context to determine which operation
is occurring. This is the case in C and C++, for example.
Python's way is much much cleaner.
Nope. Automatically substituting identity equality for value equality
is wrong. While rare, there are legitimate reasons for the former to
be True while the latter is False.
There shouldn't be, to be fair.
I disagree. Violating reflexivity has its uses. NANs are the classic
example.
Useful... maybe, conceptually sound... no.
Conceptually, NaN is the class of all elements which are not numbers,
therefore NaN = NaN. The conceptually correct way would be to check for
'NaN' explicitly.
Another example is if you redefine "==" to mean something other than
"equals". If your class treats == as something other than equality, there
is no need for a==a to necessarily return True.
Then it wouldn't be equality anymore. I can always call a cat 'dog'.
Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list