【问题标题】:Understanding python object membership for sets了解集合的 python 对象成员资格
【发布时间】:2011-04-10 10:01:24
【问题描述】:

如果我理解正确,调用对象的 __cmp__() 函数是为了评估集合中的所有对象,同时确定对象是否是集合的成员或“在”集合中。 但是,这似乎不是集合的情况:

class MyObject(object):
    def __init__(self, data):
        self.data = data

    def __cmp__(self, other):
        return self.data-other.data

a = MyObject(5)
b = MyObject(5)

print a in [b]          //evaluates to True, as I'd expect
print a in set([b])     //evaluates to False

那么,如何在集合中测试对象成员资格?

【问题讨论】:

    标签: python collections membership set cmp


    【解决方案1】:

    集合在幕后使用字典,因此“in”语句检查对象是否作为键存在于字典中。由于您的对象没有实现散列函数,因此对象的默认散列函数使用对象的 id。因此,即使 a 和 b 是等价的,它们也不是同一个对象,这就是正在测试的对象。

    【讨论】:

      【解决方案2】:
      >>> xs = []
      >>> set([xs])
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: unhashable type: 'list'
      

      你来了。集合使用哈希,与字典非常相似。这对性能非常有帮助(成员资格测试是 O(1),并且许多其他操作都依赖于成员资格测试),并且它也很好地符合集合的语义:集合项必须是唯一的,不同的项会产生不同的哈希,而相同的哈希指出(嗯,理论上)重复。

      由于默认的__hash__ 只是id(恕我直言,这是相当愚蠢的),继承object__hash__ 的类的两个实例将永远不会散列到相同的值(好吧,除非地址空间大于sizeof 哈希)。

      【讨论】:

        【解决方案3】:

        __hash__ 方法添加到您的类会产生以下结果:

        class MyObject(object):
            def __init__(self, data):
                self.data = data
        
            def __cmp__(self, other):
                return self.data - other.data
        
            def __hash__(self):
                return hash(self.data)
        
        
        a = MyObject(5)
        b = MyObject(5)
        
        print a in [b] # True
        print a in set([b]) # Also True!
        

        【讨论】:

        • 这正是我想要的。谢谢:)
        • // 还有 - 用于发现我的非 Python 原生评论习惯。
        【解决方案4】:

        正如其他人指出的那样,您的对象没有 __hash__,因此它们使用默认 id 作为哈希,您可以按照 Nathon 的建议覆盖它,但是请阅读 the docs about __hash__,特别是关于何时应该和不应该这样做的要点。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-09-19
          • 1970-01-01
          • 2011-08-27
          • 2017-01-29
          • 2021-10-10
          • 2011-07-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多