Python 3中的可比较类
在Python 3中,怎样才能让一个类可以进行比较呢?比如说,可以通过ID来比较。
6 个回答
1
从Python 3.7开始,你可以使用@dataclass
这个功能:
from dataclasses import dataclass
@dataclass(order=True)
class MyObject(object):
def __init__(self, *, name=None):
self.name = name
15
为了拥有一整套的比较功能,我使用了下面这个混合类(mixin),你可以把它放在你的模块里的一个文件,比如叫 mixin.py。
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)
要使用上面的混合类,你需要实现一个叫 _cmpkey() 的方法,这个方法会返回一个可以进行比较的对象的关键字,类似于排序时用的 key() 函数。实现的方式可以是这样的:
>>> 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]
我之所以使用这个方法而不是 total_ordering 的做法,是因为这个bug。这个问题在 Python 3.4 中已经修复,但有时候你还需要支持旧版本的 Python。
48
要让类之间可以比较,你只需要实现一个叫做 __lt__
的方法,并且用 functools.total_ordering
来装饰这个类。如果可以的话,你还应该提供一个 __eq__
方法。这样做可以自动提供其他比较操作符,这样你就不需要自己去写它们了。