我有以下表格的字典:
{ <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?
答案 0 :(得分:12)
首先:使用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
答案 1 :(得分:2)
而不是使用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
s,但它们的哈希值是相同的:
assert id(a) != id(b)
assert hash(a)==hash(b)
这表明b
中的mydict
是可接受的密钥:
print(mydict[a])
# 1
print(mydict[b])
# 1
PS。不要打扰__cmp__
。 In Python 3:
应该将cmp()函数视为已消失,
__cmp__()
不再支持特殊方法。使用__lt__()
进行排序,__eq__()
__hash__()
{{1}},以及其他必要的丰富比较。
答案 2 :(得分:2)
由于您显然可以将类别实例放入dict中,因此必须已覆盖__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 :(得分:1)
可能有快捷方式,例如使用元组,但对您的问题的一般答案是:为您的类实现__eq__()
,以便cmp()将使用它而不是测试身份。
答案 4 :(得分:1)
要使in
和其他比较运算符起作用,您必须实现__hash__
和__cmp__
(或“{”1}}之类的“丰富”比较方法。请参阅Python reference。