Taking one step back out of the realm of mathematical definition, however, the original idea was simply to distinguish what I now understand to be "totally ordered" types from other types, be they "partially ordered" or unordered — not even having a full complement of rich comparison operators or having all but using them in weirder ways than sets do.
It sounds like you want a mechanism to blacklist certain types (such as sets) from being considered totally ordered while assuming that everything else with the right operators is totally ordered.
ABCs and classes in general are usually whitelists that inform the user that the implementation satisfies certain properties. They're explicit rather than implicit.
If you want to validate arguments, you're being conservative and safe. It's safer to require that an argument is on a whitelist - if the user forgets the whitelist, the validation will fail, the user will be reminded, and they can fix it. For example they can register their class as a virtual subclass. If the user forgets to put their type on a blacklist, then the argument validation can't do its job.
I suggest having ABCs PartiallyOrdered and TotallyOrdered, where:
- TotallyOrdered is a subclass of PartiallyOrdered, as is the case mathematically. - Most familiar types with the operators are TotallyOrdered. - Sets are merely PartiallyOrdered. - sorted, min and max will require Iterable[TotallyOrdered]. - @functools.total_ordering automatically registers the class as TotallyOrdered.
Some use cases probably exist that require PartiallyOrdered but where TotallyOrdered is optional and irrelevant.
Users that want to take a generous blacklist approach can check that `<operators are present> and not (isinstance(x, PartiallyOrdered) and not isinstance(x, TotallyOrdered))` or equivalently `<operators are present> and (not isinstance(x, PartiallyOrdered) or isinstance(x, TotallyOrdered))` which would exclude sets and any other case where the person who defined the class thought about this stuff.