你需要编写一个__eq__
函数来定义如何比较对象的相等性。如果你想排序,那么应该有一个__cmp__
函数,并且最好是用__cmp__
来实现__eq__
。
def __eq__(self, other):
return cmp(self, other) == 0
如果您计划将对象放入集合或字典中,那么您可能还应该实现__hash__
,如果这样做,则绝对需要。对象的默认哈希值是id(),这使得所有对象都是唯一的(即唯一性不基于对象内容)。
我为执行此类等价比较的类编写了一个基类/接口。您可能会发现它很有用:
class Comparable(object):
def attrs(self):
raise Exception("Must be implemented in concrete sub-class!")
def __values(self):
return (getattr(self, attr) for attr in self.attrs())
def __hash__(self):
return reduce(lambda x, y: 37 * x + hash(y), self.__values(), 0)
def __cmp__(self, other):
for s, o in zip(self.__values(), other.__values()):
c = cmp(s, o)
if c:
return c
return 0
def __eq__(self, other):
return cmp(self, other) == 0
def __lt__(self, other):
return cmp(self, other) < 0
def __gt__(self, other):
return cmp(self, other) > 0
if __name__ == '__main__':
class Foo(Comparable):
def __init__(self, x, y):
self.x = x
self.y = y
def attrs(self):
return ('x', 'y')
def __str__(self):
return "Foo[%d,%d]" % (self.x, self.y)
def foo_iter(x):
for i in range(x):
for j in range(x):
yield Foo(i, j)
for a in foo_iter(4):
for b in foo_iter(4):
if a<b: print "%(a)s < %(b)s" % locals()
if a==b: print "%(a)s == %(b)s" % locals()
if a>b: print "%(a)s > %(b)s" % locals()
派生类必须实现
attrs()
方法,该方法返回一个元组或列表,其中包含对象的属性,这些属性对其身份(即使其成为什么)做出了贡献。最重要的是,代码正确处理具有多个属性的等价性,这是老派的代码,经常被错误地执行。