【问题标题】:First dictionary element of a set is mysteriously turned into an integer [duplicate]集合的第一个字典元素神秘地变成了一个整数[重复]
【发布时间】:2021-10-28 09:13:22
【问题描述】:

我正在尝试编写一个可散列的字典:

class HashableDict(dict):
    def __hash__(self):
        return hash(frozenset(self.items()))

但是,这会导致意外行为。如果我创建一个这样的集合:

x = HashableDict({0: 1})
y = HashableDict({0: 2})
print(set((x, y)))

正如预期的那样,这将打印{{0: 1}, {0: 2}}。但是,如果我创建以下集合:

x = HashableDict({0: 1})
print(set(x))

Python3.9 打印 {0}。如果我改用{x}(即打印{0: 1}),则不会发生这种情况。更神秘的是,下面的代码:

A = set(x)
A.add(y)
print(A)

打印{0, {0: 2}}。所以这只发生在集合的第一个元素上......

我做错了什么?请注意,我还尝试添加与__hash__ 一致的__eq__ 方法,但这并不能解决它:

def __eq__(self, other):
    return frozenset(self.items()) == frozenset(other.items())

【问题讨论】:

    标签: python set


    【解决方案1】:

    set 构造函数接受一个可迭代对象作为参数,并创建一个包含所有可迭代对象元素的集合。由于迭代 dict 只会迭代键,因此您会得到一组键:

    set(x) # takes x and turns it into a set!
    

    然而,你想要一个set 包含 x

    set([x])  # takes a list containing x and turns it into a set
    # {x}  # is the equivalent
    

    请注意,{x}set(x)相同,无论 x 的类型如何!

    另见What is the difference between a list of a single iterable `list(x)` vs `[x]`? 以及与此“集合文字与构造函数”有关的许多其他重复项

    【讨论】:

      【解决方案2】:

      您需要指定项目

      class HashableDict(dict):
          def __hash__(self):
              return hash(frozenset(self.items()))
      
      
      x = HashableDict({0: 1})
      y = HashableDict({0: 2})
      print({x, y})
      
      print(set(x.items()))
      

      会给

      {{0: 1}, {0: 2}}
      {(0, 1)}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-08
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-14
        • 2015-10-04
        • 2017-03-11
        相关资源
        最近更新 更多