【问题标题】:使用“for”循环遍历字典
【发布时间】:2011-03-18 17:12:22
【问题描述】:

我对下面的代码有点疑惑:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print (key, 'corresponds to', d[key])

我不明白的是key 部分。 Python 如何识别它只需要从字典中读取键? key 是 Python 中的特殊词吗?还是只是一个变量?

【问题讨论】:

  • 我们知道在 Python 字典中作为一组键:值对,要求键是唯一的(在一个字典中)。一对大括号创建一个空字典:{}。在大括号内放置一个逗号分隔的键:值对列表会将初始键:值对添加到字典中。不,key 不是 Python 中的特殊词。这里的 key 只是一个变量名。
  • 你试过了吗:for key, value in d.items():

标签: python dictionary


【解决方案1】:

key 只是一个变量名。

for key in d:

将简单地遍历字典中的键,而不是键和值。要遍历键和值,您可以使用以下内容:

对于 Python 3.x:

for key, value in d.items():

对于 Python 2.x:

for key, value in d.iteritems():

要自己测试,请将单词 key 更改为 poop

在 Python 3.x 中,iteritems() 被简单地替换为 items(),它返回一个由 dict 支持的类似集合的视图,就像 iteritems() 一样,但更好。 这在 2.7 中也可以作为 viewitems() 使用。

items() 操作适用于 2 和 3,但在 2 中它将返回字典的 (key, value) 对的列表,这不会反映在 items() 调用之后发生的字典更改。如果想要 3.x 中的 2.x 行为,可以调用list(d.items())

【讨论】:

  • 添加一个被忽略的不访问值的原因:for 循环内的 d[key] 导致键再次被散列(以获取值)。当字典很大时,这个额外的散列会增加总时间。 Raymond Hettinger 的技术讲座 youtube.com/watch?v=anrOzOapJ2E 对此进行了讨论
  • 可能有必要提到项目将以不可预测的顺序迭代,需要sorted 来稳定它。
  • @HarisankarKrishnaSwamy 有什么替代方案?
  • @yugr 你为什么这么说?文档说Keys and values are iterated over in insertion order. [docs.python.org/3/library/…
  • @yugr 从 Python 3.7 开始,字典是按插入顺序排列的,这是一种语言特性。见stackoverflow.com/a/39980744/9428564
【解决方案2】:

不是 key 是一个特殊的词,而是字典实现了迭代器协议。你可以在课堂上这样做,例如请参阅 this question 了解如何构建类迭代器。

就字典而言,它是在 C 级别实现的。详细信息可在PEP 234 中找到。特别是标题为“字典迭代器”的部分:

  • 字典实现了一个 tp_iter 槽,它返回一个有效的 迭代字典键的迭代器。 [...] 这 表示我们可以写

    for k in dict: ...
    

    相当于,但比

    快得多
    for k in dict.keys(): ...
    

    只要限制修改字典 (通过循环或另一个线程)没有被违反。

  • 为返回不同类型的字典添加方法 显式迭代器:

    for key in dict.iterkeys(): ...
    
    for value in dict.itervalues(): ...
    
    for key, value in dict.iteritems(): ...
    

    这意味着for x in dictfor x in dict.iterkeys() 的简写。

在 Python 3 中,dict.iterkeys()dict.itervalues()dict.iteritems() 不再受支持。请改用dict.keys()dict.values()dict.items()

【讨论】:

    【解决方案3】:

    遍历 dict 会以无特定顺序遍历其键,如您在此处所见:

    (这是 no longer the case in Python 3.6,但请注意,这还不是保证行为。)

    >>> d = {'x': 1, 'y': 2, 'z': 3}
    >>> list(d)
    ['y', 'x', 'z']
    >>> d.keys()
    ['y', 'x', 'z']
    

    对于您的示例,最好使用dict.items()

    >>> d.items()
    [('y', 2), ('x', 1), ('z', 3)]
    

    这会给你一个元组列表。当你像这样循环它们时,每个元组都会自动解包到 kv 中:

    for k,v in d.items():
        print(k, 'corresponds to', v)
    

    如果循环体只有几行,在循环dict 时使用kv 作为变量名是很常见的。对于更复杂的循环,使用更具描述性的名称可能是个好主意:

    for letter, number in d.items():
        print(letter, 'corresponds to', number)
    

    养成使用格式字符串的习惯是个好主意:

    for letter, number in d.items():
        print('{0} corresponds to {1}'.format(letter, number))
    

    【讨论】:

    • 来自 Python 3.7 发行说明:“dict 对象的插入顺序保存特性现在是 Python 语言规范的官方部分。”
    【解决方案4】:

    key 只是一个变量。

    对于Python2.X

    >>> d = {'x': 1, 'y': 2, 'z': 3} 
    >>> for my_var in d:
    >>>     print my_var, 'corresponds to', d[my_var]
    
    x corresponds to 1
    y corresponds to 2
    z corresponds to 3
    

    ...或更好,

    d = {'x': 1, 'y': 2, 'z': 3} 
    
    for the_key, the_value in d.iteritems():
        print the_key, 'corresponds to', the_value
    

    对于Python3.X

    d = {'x': 1, 'y': 2, 'z': 3} 
    
    for the_key, the_value in d.items():
        print(the_key, 'corresponds to', the_value)
    

    【讨论】:

      【解决方案5】:

      当您使用 for .. in ..-syntax 遍历字典时,它总是遍历键(可以使用 dictionary[key] 访问值)。

      要遍历键值对,请使用以下命令:

      • for k,v in dict.iteritems() 在 Python 2 中
      • for k,v in dict.items() 在 Python 3 中

      【讨论】:

      • 请注意,对于 Python 3,它是 items() 而不是 iteritems()
      【解决方案6】:

      这是一个非常常见的循环习语。 in 是一个操作员。关于何时使用for key in dict 以及何时必须使用for key in dict.keys(),请参阅David Goodger's Idiomatic Python article (archived copy)

      【讨论】:

      【解决方案7】:

      我有一个用例,我必须遍历 dict 以获取键、值对以及指示我所在位置的索引。我就是这样做的:

      d = {'x': 1, 'y': 2, 'z': 3} 
      for i, (key, value) in enumerate(d.items()):
         print(i, key, value)
      

      请注意,键和值周围的括号很重要,没有它们,您会得到ValueError“没有足够的值来解包”。

      【讨论】:

      • 这与问题有什么关系?
      • 我不喜欢在这里使用i。这意味着值以一致的顺序迭代,事实并非如此
      【解决方案8】:

      使用“for”循环遍历字典

      d = {'x': 1, 'y': 2, 'z': 3} 
      for key in d:
          ...
      

      Python 如何识别它只需要从 字典?键是 Python 中的一个特殊词吗?或者它只是一个 变量?

      不仅仅是for 循环。这里重要的词是“迭代”。

      字典是键到值的映射:

      d = {'x': 1, 'y': 2, 'z': 3} 
      

      任何时候我们迭代它,我们都会迭代键。变量名称key 仅用于描述性 - 它非常适合此目的。

      这发生在列表推导中:

      >>> [k for k in d]
      ['x', 'y', 'z']
      

      当我们将字典传递给列表(或任何其他集合类型对象)时会发生这种情况:

      >>> list(d)
      ['x', 'y', 'z']
      

      Python 迭代的方式是,在需要的上下文中,它调用对象(在本例中为字典)的 __iter__ 方法,该方法返回一个迭代器(在本例中为 keyiterator 对象):

      >>> d.__iter__()
      <dict_keyiterator object at 0x7fb1747bee08>
      

      我们自己不应该使用这些特殊方法,而是使用各自的内置函数来调用它,iter

      >>> key_iterator = iter(d)
      >>> key_iterator
      <dict_keyiterator object at 0x7fb172fa9188>
      

      迭代器有一个 __next__ 方法 - 但我们使用内置函数 next 调用它:

      >>> next(key_iterator)
      'x'
      >>> next(key_iterator)
      'y'
      >>> next(key_iterator)
      'z'
      >>> next(key_iterator)
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      StopIteration
      

      当迭代器耗尽时,它会引发StopIteration。这就是 Python 知道退出 for 循环、列表推导、生成器表达式或任何其他迭代上下文的方式。一旦迭代器引发StopIteration,它就会一直引发它——如果你想再次迭代,你需要一个新的。

      >>> list(key_iterator)
      []
      >>> new_key_iterator = iter(d)
      >>> list(new_key_iterator)
      ['x', 'y', 'z']
      

      返回字典

      我们已经看到 dicts 在许多情况下进行迭代。我们所看到的是,任何时候我们遍历一个字典,我们都会得到密钥。回到原来的例子:

      d = {'x': 1, 'y': 2, 'z': 3} 
      for key in d:
      

      如果我们更改变量名,我们仍然会得到键。让我们试试吧:

      >>> for each_key in d:
      ...     print(each_key, '=>', d[each_key])
      ... 
      x => 1
      y => 2
      z => 3
      

      如果我们想遍历这些值,我们需要使用 dicts 的.values 方法,或者两者一起使用,.items

      >>> list(d.values())
      [1, 2, 3]
      >>> list(d.items())
      [('x', 1), ('y', 2), ('z', 3)]
      

      在给出的示例中,像这样遍历项目会更有效:

      for a_key, corresponding_value in d.items():
          print(a_key, corresponding_value)
      

      但出于学术目的,这个问题的例子很好。

      【讨论】:

        【解决方案9】:

        您可以在 GitHub 上查看 CPython 的 dicttype 的实现。这是实现 dict 迭代器的方法的签名:

        _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
                     PyObject **pvalue, Py_hash_t *phash)
        

        CPython dictobject.c

        【讨论】:

          【解决方案10】:

          这将按排序的顺序打印输出,按升序排列。

          d = {'x': 3, 'y': 1, 'z': 2}
          
          def by_value(item):
              return item[1]
          
          for key, value in sorted(d.items(), key=by_value):
              print(key, '->', value)
          

          输出:

          y -> 1
          z -> 2
          x -> 3
          

          【讨论】:

          • 我不认为这是被问到的问题。问题是关于 key 以及为什么 python 在没有 .items() 或 .keys() 选项的情况下从字典中提取键。
          【解决方案11】:

          要遍历键,使用my_dict.keys() 会更慢但更好。如果你尝试做这样的事情:

          for key in my_dict:
              my_dict[key+"-1"] = my_dict[key]-1
          

          它会产生运行时错误,因为您在程序运行时更改了密钥。如果您绝对要减少时间,请使用for key in my_dict 方式,但您已被警告。

          【讨论】:

          • 为什么使用my_dict.keys() 比直接遍历字典“更好”?对字典的迭代清楚地记录为产生键。当您回答这个问题时,您似乎想到了 Python 2,因为在 Python 3 for key in my_dict.keys()在迭代期间更改字典大小仍然会遇到同样的问题
          【解决方案12】:

          如果您正在寻找一个清晰直观的示例:

          cat  = {'name': 'Snowy', 'color': 'White' ,'age': 14}
          for key , value in cat.items():
             print(key, ': ', value)
          

          结果:

          name:  Snowy
          color:  White
          age:  14
          

          【讨论】:

            【解决方案13】:

            对于字典的迭代,可以使用下面的代码。

            dictionary= {1:"a", 2:"b", 3:"c"}
            
            #To iterate over the keys
            for key in dictionary.keys():
                print(key)
            
            #To Iterate over the values
            for value in dictionary.values():
                print(value)
            
            #To Iterate both the keys and values
            for key, value in dictionary.items():
                print(key,'\t', value)
            

            【讨论】:

              【解决方案14】:

              Python 中的字典是键值对的集合。每个键都连接到一个值,您可以使用一个键来访问与该键关联的值。键的值可以是数字、字符串、列表,甚至是另一个字典。在这种情况下,将每个“键值对”威胁为表中的单独行:d 是您的表,有两列。 key 是第一列, key[value] 是你的第二列。您的 for 循环是迭代表的标准方法。

              【讨论】:

                【解决方案15】:

                让我们直奔主题。如果单词 key 只是一个变量,正如您所提到的,那么主要需要注意的是,当您在字典上运行 'FOR LOOP' 时,它只运行 'keys' 并忽略 'values'

                d = {'x': 1, 'y': 2, 'z': 3} 
                for key in d:
                    print (key, 'corresponds to', d[key])
                

                不如试试这个:

                d = {'x': 1, 'y': 2, 'z': 3} 
                for i in d:
                    print (i, 'corresponds to', d[i])
                

                但是如果你使用类似的函数:

                d = {'x': 1, 'y': 2, 'z': 3}
                print(d.keys())
                

                在上述情况下,'keys' 不是一个变量,而是一个函数。

                【讨论】:

                  猜你喜欢
                  • 2013-02-20
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-18
                  • 1970-01-01
                  • 2014-06-07
                  相关资源
                  最近更新 更多