【问题标题】:Problem with Python dict's __new__ methodPython dict 的 __new__ 方法有问题
【发布时间】:2020-02-12 15:10:52
【问题描述】:

你好,我正在上课

class multiset(dict):

  def __new__(cls,iterabile):
      d = dict()
      for i in iterabile:
          if i not in d.keys():
              d[i] = iterabile.count(i)
      return super().__new__(cls,d)

这个类是一个自定义字典,它从输入列表中创建一个字典,其中键是元素,值是列表中键元素的出现次数。 问题是 super().__new__(cls,d) 返回这个错误:

Traceback(最近一次调用最后一次):

文件“”,第 1 行,在 m = 多集([1,1,1,2,1,3,2,3])

TypeError: 无法将字典更新序列元素 #0 转换为序列

【问题讨论】:

  • 不确定最佳解决方案,但问题是 dict.__init__ 被原始列表调用 super().__new__ 创建对象。
  • 您可以覆盖__init__ 并确保使用适当的元素调用super().__init__,但最好不要使用新语义覆盖__new__dict.__new__ 接受一个可迭代的参数,但它应该是一个可迭代的键/值对。
  • 可能最好的办法就是不要子类dict;多重集不是dict 的一种,尽管您可以使用dict实现多重集。
  • @chepner 它也不适用于键/值对,我尝试了 super().__new__(cls,d.items())
  • __new__ 不关心字典并忽略它。如果您覆盖 __init__ 并且只使用相同的参数调用 super().__init__,您将看到错误来自 __init__,而不是 __new__

标签: python dictionary


【解决方案1】:

改为使用__init__() 并且不要创建显式的新字典,因为self 已经是字典,因为multiset 继承自字典:

class multiset(dict):

  def __init__(self,iterable):
      for i in iterable:
          if i not in self.keys():
              self[i] = iterable.count(i)

m = multiset([1,1,1,2,1,3,2,3])
print( m )
# prints: {1: 4, 2: 2, 3: 2}

但正如 ndclt 指出的那样,collections.Counter 已经这样做了。

【讨论】:

    【解决方案2】:

    来自Python documentation

    dict() 构造函数直接从键值对序列构建字典:

    >>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
    {'sape': 4139, 'guido': 4127, 'jack': 4098}
    

    你给 dict 构造函数super().__new__(cls,d) 调用dict.__init__ 一个字典而不是键值对。

    为什么不使用Counter,它看起来像做你想做的事并且表现得像字典:

    >>> from collections import Counter
    >>> Counter([1,1,1,2,1,3,2,3])                                                                                                                         
    Counter({1: 4, 2: 2, 3: 2})
    >>> Counter([1,1,1,2,1,3,2,3])[1]
    4
    

    【讨论】:

    • dict.__new__ 实际上并不关心;它忽略了论点。 dict.__init__dict.__new__ 返回抱怨可迭代参数后被调用。
    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 2018-04-01
    • 2023-03-18
    • 2021-05-23
    • 1970-01-01
    相关资源
    最近更新 更多