This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author ncoghlan
Recipients eric.araujo, francescor, javawizard, lregebro, ncoghlan, python-dev, rhettinger
Date 2011-07-16.12:42:48
SpamBayes Score 4.440892e-15
Marked as misclassified No
Message-id <1310820169.74.0.234816502661.issue10042@psf.upfronthosting.co.za>
In-reply-to
Content
NotImplemented is a speed and maintainability hack - the runtime cost and additional code complexity involved in doing the same operator signalling via exceptions would be prohibitive (check Objects/abstract.c in the CPython source if you want the gory details). As far as an implementation of @total_ordering that correctly handles NotImplemented goes, yes, I absolutely agree we should do this correctly. The fact that it is *hard* is an argument in *favour* of us getting it right, as there is a decent chance that manually written comparison operations will also stuff it up. That said, I don't think sane_total_ordering quite gets the semantics right, either. Some helper functions in the closure would let the existing lambda functions be updated to do the right thing (and I believe the semantics I have used below are the correct ones for handling NotImplemented in @total_ordering). (I haven't actually run this code as yet, but it should give a clear idea of what I mean) def not_op(op, other): # "not a < b" handles "a >= b" # "not a <= b" handles "a > b" # "not a >= b" handles "a < b" # "not a > b" handles "a <= b" op_result = op(other) if op_result is NotImplemented: return op_result return not op_result def op_or_eq(op, self, other): # "a < b or a == b" handles "a <= b" # "a > b or a == b" handles "a >= b" op_result = op(other) if op_result: # Short circuit OR, as op is True # NotImplemented is also passed back here return op_result return self.__eq__(other) def not_op_and_not_eq(op, self, other): # "not (a < b or a == b)" handles "a > b" # "not a < b and a != b" is equivalent # "not (a > b or a == b)" handles "a < b" # "not a > b and a != b" is equivalent op_result = op(other) if op_result: # Short circuit AND, as not_op is False # NotImplemented is also passed back here if op_result is NotImplemented: return op_result return not op_result return self.__ne__(other) def not_op_or_eq(op, self, other): # "not a <= b or a == b" handles "a >= b" # "not a >= b or a == b" handles "a <= b" op_result = op(other) if op_result is NotImplemented: return op_result if op_result: return self.__eq__(other) # Short circuit OR, as not_op is True return not op_result def op_and_not_eq(op, self, other): # "a <= b and not a == b" handles "a < b" # "a >= b and not a == b" handles "a > b" op_result = op(other) if op_result is NotImplemented: return op_result if op_result: return self.__ne__(other) # Short circuit AND, as op is False return op_result The conversion table then looks like: convert = { '__lt__': [ ('__gt__', lambda self, other: not_op_and_not_eq(self.__lt__, self, other)), ('__le__', lambda self, other: op_or_eq(self.__lt__, self, other)), ('__ge__', lambda self, other: not_op(self.__lt__, other)) ], '__le__': [ ('__ge__', lambda self, other: not_op_or_eq(self.__le__, self, other)), ('__lt__', lambda self, other: op_and_not_eq(self.__le__, self, other)), ('__gt__', lambda self, other: not_op(self.__le__, other)) ], '__gt__': [ ('__lt__', lambda self, other: not_op_and_not_eq(self.__gt__, self, other)), ('__ge__', lambda self, other: op_or_eq(self.__gt__, self, other)), ('__le__', lambda self, other: not_op(self.__gt__, other)) ], '__ge__': [ ('__le__', lambda self, other: not_op_or_eq(self.__ge__, self, other)), ('__gt__', lambda self, other: op_and_not_eq(self.__ge__, self, other)), ('__lt__', lambda self, other: not_op(self.__ge__, other)) ] }
History
Date User Action Args
2011-07-16 12:42:49ncoghlansetrecipients: + ncoghlan, rhettinger, eric.araujo, lregebro, francescor, python-dev, javawizard
2011-07-16 12:42:49ncoghlansetmessageid: <1310820169.74.0.234816502661.issue10042@psf.upfronthosting.co.za>
2011-07-16 12:42:49ncoghlanlinkissue10042 messages
2011-07-16 12:42:48ncoghlancreate