假设我有一个包含对象的集合。
class C(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return 'C({}):{}'.format(self.value, id(self))
def __eq__(self, other):
return self.value == other.value
def __hash__(self):
return hash(self.value)
cset = {C(1), C(2)}
print 'cset:', cset
cset: set([C(1):140241436167120, C(2):140241436167184])
我想在集合中找到一个对象,并获得对该对象的引用。
c1 = C(1)
print 'c1:', c1
found, = cset & {c1}
print 'way1 found:', found
found, = {c1} & cset
print 'way2 found:', found
c1: C(1):140241436167248
way1 found: C(1):140241436167248
way2 found: C(1):140241436167248
这些方式都不好;返回对c1(id = 140241436167248)的引用,而不是对集合中的对象(id = 140241436167120)。
只是为了展示我想要的东西,快速而肮脏的方式是这样的。
found, = [x for x in cset if x == c1]
print 'way3 found:', found
way3 found: C(1):140241436167120
这种方式返回我想要的,对集合中对象的引用(id = 140241436167120)。 但它正在使用线性搜索。还有更好的办法吗?
答案 0 :(得分:2)
问题在于您尝试使用set
作为映射。这不会很好......
相反,不要使您的对象显式为哈希。如果您有唯一性约束,请使用字典将值映射到实例而不是集合。字典可以像set
一样轻松地强制实现唯一性,它提供了您想要的映射行为。
if c1.value in cdict:
c1 = cdict[c1.value] # Trade in the `c1` we have for one already in `cdict`
此外,使用dict
不那么“聪明”,从可读性的角度来看几乎总是一场胜利。