Python中与Java的Comparable等价的是什么?
我有一个字典,格式如下:
{ <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 个回答
因为你可以把你的类别实例放进字典里,所以你肯定已经重写了 __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')
与其在字典中使用 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}
a
和 b
是不同的实例,所以它们的 id
不一样,但它们的哈希值是相同的:
assert id(a) != id(b)
assert hash(a)==hash(b)
这表明 b
是 mydict
中一个可以接受的键:
print(mydict[a])
# 1
print(mydict[b])
# 1
顺便说一下,不用管 __cmp__
。在 Python 3 中:
应该把
cmp()
函数当作不存在,__cmp__()
这个特殊方法也不再支持。要进行排序的话用__lt__()
,用__eq__()
配合__hash__()
,以及根据需要使用其他比较方法。
首先:使用 True
和 False
(布尔值)来代替 '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