【问题标题】:Python: Trouble with looping nested dictionaryPython:循环嵌套字典的问题
【发布时间】:2021-11-07 18:50:53
【问题描述】:

我想遍历字典中的键, 然后看看嵌套字典是否有一定的值。

但是,我在语法上有点挣扎。 这是我写的:

dict = {
    "Bull's eye": {"Points": 50, "Range": 60},
    "Bull": {"Points": 25, "Range": range(55, 59)},
    "Outer value": {"Points": range(0, 20), "Range": range(1, 54)},
}
number = 2
for key in dict.keys():
    if number in dict[key]["Range"]:
        print(f"Value is in {key}")

错误:“TypeError:'int' 类型的参数不可迭代”

请注意,“数字”值位于“外部值”内的“范围”字典中。 所以当循环在嵌套字典中找到这个值时,我希望 if 语句为 True

【问题讨论】:

  • 为什么要在内置类型之后命名变量?我觉得这是一件应该(强烈)劝阻的常见事情
  • 这种方法的问题是,如果你稍后再做some_other_fancy_dict = dict(),那么你会立即遇到错误

标签: python dictionary for-loop syntax nested


【解决方案1】:

这是因为您拥有第一本字典 "Bull's eye": {"Points": 50, "Range": 60}。在这里,键只是一个 int,因此您不能使用 in 关键字,因为 int 是不可迭代的。如果您使用该语法,则字典键需要是可迭代类型,例如

dict = {
    "Bull's eye": {"Points": 50, "Range": (60,)},
    "Bull": {"Points": 25, "Range": range(55, 59)},
    "Outer value": {"Points": range(0, 20), "Range": range(1, 54)},
}

【讨论】:

    【解决方案2】:

    我建议你试试这个例子:(应该按原样工作)

    dict = {
        "Bull's eye": {"Points": 50, "Range": [60]},
        "Bull": {"Points": 25, "Range": range(55, 59)},
        "Outer value": {"Points": range(0, 20), "Range": range(1, 54)},
    }
    number = 2
    [print(key) for key in dict.keys() if number in dict.get(key).get('Range')]
    

    【讨论】:

      【解决方案3】:

      问题是Range 字段有不同的数据类型,但in 运算符假定是可迭代的(由range 函数产生)。正如 BTables 所指出的,您有几个选项,您可以确保您的 dict 仅包含可迭代对象 - 或者,您可以检查循环中的数据类型。

      for key, value in dict_.items():
          range_ = value["Range"]
          if isinstance(range_, range) and number in range_:
              print(f"Value is in {key}")
          elif isinstance(range_, int) and number == range_:
              print(f"Value equals {key}")
      

      请注意,我还调整了代码以使用一些最佳实践,例如使用尾随下划线 (_) 以防名称已经是内置函数或保留关键字(即,我重命名了您的 dict变量为dict_)。此外,您可以直接循环遍历字典的项目,而不是仅遍历需要在循环中索引字典的键。

      【讨论】:

        【解决方案4】:

        由于您检查值​​的方式,您的代码会引发 TypeError。其中一些值是整数,而其他值是 Range 类型。您可以检查 2 是否在范围内,但您无法检查 2 是否在整数中。

        您可以使用 try/except 块来解决此问题:

        my_dict = {
            "Bull's eye": {"Points": 50, "Range": 60},
            "Bull": {"Points": 25, "Range": range(55, 59)},
            "Outer value": {"Points": range(0, 20), "Range": range(1, 54)},
        }
        number = 2   
        for key, sub_dict in my_dict.items():
            try:
                if number in sub_dict["Range"]:
                    print(f"number '{number}' is in key '{key}'")
            except TypeError:
                if number == sub_dict["Range"]:
                    print(f"number '{number}' is in key '{key}'")
        

        【讨论】:

          【解决方案5】:

          除了@BTables 的回答,如果你好奇为什么错误说不是iterable 的原因,是因为python 有几种方法可以解决a in B 指令,首先它检查特殊方法__contains__是否存在于B中,如果不是,它将尝试迭代B(也就是如果它有特殊方法__iter__)并进行线性搜索以找到元素

          >>> class A:
                  def __iter__(self):
                      yield from range(10)
          
                  
          >>> a=A()
          >>> a
          <__main__.A object at 0x0000027DC8646CD0>
          >>> list(a)
          [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
          >>> 1 in a
          True
          >>> class B:
                  def __iter__(self):
                      yield from range(10)
                  def __contains__(self, item):
                      return False
          
              
          >>> b=B()
          >>> 1 in b
          False
          >>>
          

          int 类两者都没有,因此出现错误

          【讨论】:

            猜你喜欢
            • 2021-12-19
            • 2018-07-13
            • 1970-01-01
            • 2017-09-20
            • 2017-07-22
            • 2022-06-15
            • 2017-08-23
            相关资源
            最近更新 更多