【问题标题】:Keys are not unique for a python dictionary!python字典的键不是唯一的!
【发布时间】:2011-07-24 00:03:59
【问题描述】:

这里有一个愚蠢的新手问题 对于 python 字典 q len(set(q.keys())) != len(q.keys())。这甚至可能吗?

【问题讨论】:

  • 你能把发生这种情况的字典贴出来吗?
  • 这其实是不可能的。
  • @user 您可能会遇到溢出错误。 len(q.keys())len(set(q.keys())) 的值是多少?
  • 不应该出现溢出。这不应该发生,除非__hash__ 有缺陷和/或您没有__eq__/__ne__ 重载。
  • 抱歉,我想我找到了问题所在。 __ne__ 没有超载。感谢大家的帮助

标签: python dictionary hashtable


【解决方案1】:

如果您违反dict 的要求并更改其哈希值,就会发生这种情况。

当一个对象在dict中使用时,它的哈希值不能改变,它与其他对象的相等性不能改变。其他属性可能会改变,只要它们不影响它在 dict 中的显示方式。

(这确实 not 意味着永远不允许更改哈希值。这是一个常见的误解。哈希值本身可能会更改。只有dict 要求键哈希是不可变的,而不是__hash__ 本身。)

以下代码将一个对象添加到 dict,然后从 dict 下更改其哈希值。 q[a] = 2 然后将 a 添加为字典中的新键,即使它已经存在;由于哈希值发生了变化,字典没有找到旧值。这再现了您所看到的特殊性。

class Test(object):
    def __init__(self, h):
        self.h = h
    def __hash__(self):
        return self.h

a = Test(1)
q = {}
q[a] = 1
a.h = 2
q[a] = 2

print q

# True:
print len(set(q.keys())) != len(q.keys())

【讨论】:

    【解决方案2】:

    字典和集合的底层代码基本相同,因此您通常可以认为len(set(d.keys()) == len(d.keys()) 是一个不变量。

    也就是说,set 和 dicts 都依赖 __eq__ 和 __hash__ 来识别唯一值并组织它们以进行有效搜索。因此,如果它们返回不一致的结果(或违反“a==b 暗示 hash(a)==hash(b)”的规则,那么就无法强制执行不变量:

    >>> from random import randrange
    >>> class A():
        def __init__(self, x):
            self.x = x
        def __eq__(self, other):
            return bool(randrange(2))
        def __hash__(self):
            return randrange(8)
        def __repr__(self):
            return '|%d|' % self.x
    
    
    >>> s = [A(i) for i in range(100)]
    >>> d = dict.fromkeys(s)
    >>> len(d.keys())
    29
    >>> len(set(d.keys()))
    12
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2019-02-08
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      • 1970-01-01
      • 2019-04-11
      相关资源
      最近更新 更多