why () is () and [] is [] work in other way?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Apr 27 07:09:34 EDT 2012


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"?

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.


>> 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.

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.



-- 
Steven



More information about the Python-list mailing list