题 使用'for'循环迭代字典


我对以下代码感到有点困惑:

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

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


2112
2017-07-20 22:27


起源




答案:


key 只是一个变量名。

for key in d:

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

对于Python 2.x:

for key, value in d.iteritems():

对于Python 3.x:

for key, value in d.items():

要自己测试,请更改单词 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())


3804
2017-07-20 22:29



添加一个忽略的原因,不要像这样访问值:在for循环中的d [key]导致密钥再次被哈希(获取值)。当字典很大时,这个额外的哈希将增加总时间。这在Raymond Hettinger的技术讲座中有所讨论 youtube.com/watch?v=anrOzOapJ2E - Harisankar Krishna Swamy
在Python 3.6中更改为 d.items() - Decoded
很好的答案,真正的天才在于改变 key 至 poop。感谢您的见解,@ sberry! - Mike Williamson


并不是密钥是一个特殊的单词,而是字典实现了迭代器协议。你可以在你的课堂上做到这一点,例如看到 这个问题 如何构建类迭代器。

在字典的情况下,它是在C级实现的。详细信息可在 PEP 234。特别是标题为“Dictionary Iterators”的部分:

  • 字典实现了一个返回高效的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 dict 是简写 for x in dict.iterkeys()


325
2017-07-20 23:52



在python3 dict.iterkeys()中,不再支持dict.itervalues()和dict.iteritems()。请改用dict.keys(),dict.values()和dict.items()。 - Sadik


迭代一个 dict 如您在此处所见,无需按特定顺序迭代其键:

编辑:(这是 不再是这样的 Python3.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)]

这为您提供了元组列表。当你像这样循环它们时,每个元组都被解压缩 k 和 v 自动:

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

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

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))

151
2017-07-21 01:27



从Python 3.7发行说明:“dict对象的插入顺序保存性质现在是Python语言规范的官方部分。” - Gregory Arenius


key 只是一个变量。

对于 Python2.X

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

... 或更好,

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)

44
2017-07-20 23:49





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

要迭代键值对,请使用 for k,v in s.iteritems()


39
2017-07-20 22:29



请注意,对于Python 3,它是 items() 代替 iteritems() - Andreas Fester


这是一个非常常见的循环习语。 in 是一个运营商。何时使用 for key in dict 什么时候必须 for key in dict.keys() 看到 David Goodger的Idiomatic Python文章


20
2017-07-20 22:42



当我阅读这些部分时 in,操作员部分是 在哪里检查存在。也许最好删除它 in is an operator 信息。 - Wolf


你可以用这个:

for key,val in d.items():
    print key, 'is the key for ', val

9
2018-01-14 14:42



它的帖子有点旧 - Sadi
@Sadi它不再是真的吗? - Basj


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

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

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


6
2018-05-25 13:42





使用'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知道如何退出a for 循环,或列表推导,或生成器表达式,或任何其他迭代上下文。一旦迭代器升起 StopIteration 它会一直提高它 - 如果你想再次迭代,你需要一个新的。

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

回到dicts

我们已经看到dicts在许多情况下迭代。我们所看到的是,无论何时我们迭代dict,我们都会得到密钥。回到原始示例:

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

如果我们想迭代值,我们需要使用 .values dicts的方法,或两者​​一起, .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)

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


4
2018-06-21 02:51





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

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

CPython dictobject.c


3
2017-11-03 05:16