如何在Python集中获取对象的引用

时间:2016-12-21 19:29:53

标签: python set

假设我有一个包含对象的集合。

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)。 但它正在使用线性搜索。还有更好的办法吗?

1 个答案:

答案 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不那么“聪明”,从可读性的角度来看几乎总是一场胜利。