Comparable classes in Python 3

后端 未结 5 1319
北恋
北恋 2020-11-30 07:54

What is the standard way of making a class comparable in Python 3? (For example, by id.)

5条回答
  •  自闭症患者
    2020-11-30 08:37

    For a full set of comparison functions I have used the following mixin, which you could put in say for example a mixin.py in your module.

    class ComparableMixin(object):
        def _compare(self, other, method):
            try:
                return method(self._cmpkey(), other._cmpkey())
            except (AttributeError, TypeError):
                # _cmpkey not implemented, or return different type,
                # so I can't compare with "other".
                return NotImplemented
    
        def __lt__(self, other):
            return self._compare(other, lambda s, o: s < o)
    
        def __le__(self, other):
            return self._compare(other, lambda s, o: s <= o)
    
        def __eq__(self, other):
            return self._compare(other, lambda s, o: s == o)
    
        def __ge__(self, other):
            return self._compare(other, lambda s, o: s >= o)
    
        def __gt__(self, other):
            return self._compare(other, lambda s, o: s > o)
    
        def __ne__(self, other):
            return self._compare(other, lambda s, o: s != o)
    

    To use the mixin above you need to implement a _cmpkey() method that returns a key of objects that can be compared, similar to the key() function used when sorting. The implementation could look like this:

    >>> from .mixin import ComparableMixin
    
    >>> class Orderable(ComparableMixin):
    ...
    ...     def __init__(self, firstname, lastname):
    ...         self.first = firstname
    ...         self.last = lastname
    ...
    ...     def _cmpkey(self):
    ...         return (self.last, self.first)
    ...
    ...     def __repr__(self):
    ...         return "%s %s" % (self.first, self.last)
    ...
    >>> sorted([Orderable('Donald', 'Duck'), 
    ...         Orderable('Paul', 'Anka')])
    [Paul Anka, Donald Duck]
    

    The reason I use this instead of the total_ordering recipe is this bug. It's fixed in Python 3.4, but often you need to support older Python versions as well.

提交回复
热议问题