Python中与Java的Comparable等价的是什么?

14 投票
5 回答
16087 浏览
提问于 2025-04-16 22:57

我有一个字典,格式如下:

{ <Category('Simulate', 'False', 'False', 'False', 'INTERMEDIATE')>: {'link': u'/story/4/tvb-adapters-simulator-simulatorAdapter/SimulatorAdapter', 'name': u'Simulate'}, 
  <Category('View Results', 'True', 'False', 'True', 'INTERMEDIATE')>: {'link': '/story/step/3', 'name': u'View Results'}, 
  <Category('Analyze', 'True', 'False', 'False', 'FINAL')>: {'link': '/story/step/2', 'name': u'Analyze'}}

Category是一个类,代表数据库中的一个实例。现在我有了以下这个实例:

    <Category('Analyze', 'True', 'False', 'False', 'FINAL')>

现在这个实例和之前的那个不一样。我的意思是,我从数据库获取了所有的值,然后创建了这个字典。过了一段时间,我又得到了一个ID,并从数据库中取出了实例。现在它们不是同一个对象。我需要检查这个实例是否在字典里,但是:

instance in disctionary

这将返回false。现在我可以采取一种比较麻烦的方法,逐个检查字典里的值是否匹配,但Python有没有更聪明的方法来做到这一点?我想要的类似于Java中的Comparable。

5 个回答

2

因为你可以把你的类别实例放进字典里,所以你肯定已经重写了 __hash__ 这个方法。现在你只需要重写 __eq__ 这个方法就可以了:

class Category(object):
    # you must have overwritten `__hash__` like this already
    def __hash__(self):
        return hash((self.attr1, self.attr2, ... ))

    # now you just need tis
    def __eq__(self, other):
        return isinstance(other, Category) and \
               (self.attr1, self.attr2, ... ) == (other.attr1, other.attr2, ... )

其实你应该把整个类都扔掉,改用 collections.namedtuple 来代替:

Category = collections.namedtuple('Category', 'attr1 attr2 attr3')
3

与其在字典中使用 Category 的实例(比如 Category('Analyze', 'True', 'False', 'False', 'FINAL'))作为键,不如直接使用相关的元组(比如 ('Analyze', 'True', 'False', 'False', 'FINAL'))更合适。

如果你确实想用 Category 的实例作为字典的键,那你需要定义 __hash____eq__ 这两个方法。比如:

class Category(object):
    def __init__(self,*args):
        self.args=args
    def __hash__(self):
        # Note that this assumes that Category's hash value is immutable
        # i.e. self.args does not change.
        return hash(self.args)
    def __eq__(self,other):
        return self.args == other.args

a=Category('Analyze', 'True', 'False', 'False', 'FINAL')
b=Category('Analyze', 'True', 'False', 'False', 'FINAL')

mydict={a:1}

ab 是不同的实例,所以它们的 id 不一样,但它们的哈希值是相同的:

assert id(a) != id(b)
assert hash(a)==hash(b)

这表明 bmydict 中一个可以接受的键:

print(mydict[a])
# 1
print(mydict[b])
# 1

顺便说一下,不用管 __cmp__。在 Python 3 中:

应该把 cmp() 函数当作不存在,__cmp__() 这个特殊方法也不再支持。要进行排序的话用 __lt__(),用 __eq__() 配合 __hash__(),以及根据需要使用其他比较方法。

17

首先:使用 TrueFalse(布尔值)来代替 'True''False'(字符串)。

一般来说,在Python中,你可以让所有东西都可以进行比较。你只需要为你的类定义一些特定的方法(比如 __eq____lt__ 等等)。

比如说,我想比较类A的实例,而这个比较应该只是对 s 成员进行不区分大小写的字符串比较:

class A(object):
    def __init__(self, s=''):
        self.s = s

    def __eq__(self, other):
        return self.s.lower() == other.s.lower()

a = A('aaaa')
b = A('AAAA')
print a == b # prints True
b = A('bbbb')
print a == b # prints False

撰写回答