Set and {} comparison confusion

Alex Martelli aleaxit at yahoo.com
Thu Sep 9 09:42:07 EDT 2004


Roman Yakovenko <roman.yakovenko at actimize.com> wrote:
   ...
> I don't agree with you. I can compare properties of some object.
> For example I can compare cows:
>  one python is longer then other ( length )
>  one python is heavier then other ( weight )
>  one python is older then other ( age )
> 
> But I can't define meaningful operator "<" on pythons.
> I can compare pythons only property by property. I don't thing
> that next code is meaningful
> 
> def __lt__( self, other_python ):
>       return self.length < other_python.length \
>              and self.weight < other_python.weight \
>              and self.age < other_python.age 
> 
> I see this code as meaningless on python's.  

Of course it's meaningless, it cannot entirely respect the properties
which I gave and you asserted you fully understand, no matter how you
define the companion ==.  Consider three Pythons, ignore age for
simplicity without loss of generality, represent them only by (L, W)
pairs: a=(4,20) b=(5,30) c=(6,10).
Now a < b by this definition.  However neither a<c nor c<a so a==c.
Also, neither b<c nor b>c so b==c.  But then by transitivity of == it
must be a==b which conflicts with the already esablished a<b !!!

Semantically valid definitions of < can easily be obtained, e.g.

def _props(self): return self.length, self.weight, self.age
def __lt__(self, other): return self._props() < other._props()
def __eq__(self, other): return self._props() == other._props()

Thanks to Python's natural lexicographical comparisons, this is very
easy to read meaningfully: when you need to order pythons you place them
shorter-first, within a group of identical length you place them
lighter-first, within a subgroup of identical length and weight you
place them younger-first, and you consider 'equal' (it's a valid
equivalence relationship) two pythons who coincide in all three
attributes you consider.  Easy as pie.

Whether this is "meaningful" in some vague handwaving sense depends on
your application's higher purpose and the laws of nature (or business,
or whatever) that apply to the case.  Perhaps these attributes are good
predictors of a python's food intake, for example, and thus the ordering
might be very meaningful to a python-feeding application, but have
little correlation with suppleness and beauty of skin and thus would be
meaningless to a serpent-skin purse making application (but then, the
_equality_ would also be pretty doubtful...!).

Look at it another way: is alphabetically ordering people by first name
and surname "meaningful"?  Not as a predictor of pretty much anything,
and yet it's so incredibly practical and useful that it's essentially
universal among cultures using the Latin alphabet (and many others).
But that's because the proper, lexicographical rules (ensuring NON
meanigless ordering...) are applied; if you tried an AND based
comparison of firstnames and surnames, just as you did above for
pythons' attributes, THAT would be meaningless AND useless.

Quite apart from the quibbles on the meaning of the word "meaning" and
derived ones, I hope this shows you that you didn't fully grasp the
requirements -- if you did, you'd never have coded __lt__ that way.  Be
sure to code __lt__ in a way that DOES respect the requirements (most
often, plain Python comparison on tuples of significant properties is
easiest AND handiest to ensure compatibility of __eq__ and __lt__!) or
you can expect many more surprises.


> > Ah, isn't set documented to need hashable elements?  It should be.  Of
> > course, _why_ your class appears to be hashable when it defines __eq__
> > and not __hash__ I dunno -- Python should diagnose that, but it does't
> > appear to...
> 
> It is my fault too. All my classes derives from object. object do
implements __hash__
> function. I think I should raise exception if somebody tries to insert
object into
> set \ dictionary

I thought it did, if the object defines __eq__ and doesn't redefine
_hash__.  I'll look into what's going on...


Alex



More information about the Python-list mailing list