使用“ for”循环遍历字典

问题:使用“ for”循环遍历字典

以下代码使我有些困惑:

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

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

I am a bit puzzled by the following code:

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

What I don’t understand is the key portion. How does Python recognize that it needs only to read the key from the dictionary? Is key a special word in Python? Or is it simply a variable?


回答 0

key 只是一个变量名。

for key in d:

只会循环遍历字典中的键,而不是键和值。要遍历键和值,可以使用以下命令:

对于Python 3.x:

for key, value in d.items():

对于Python 2.x:

for key, value in d.iteritems():

要测试自己,请将单词更改keypoop

在Python 3.x中,iteritems()替换为simple items(),它返回由dict支持的类似set的视图,iteritems()但效果更好。在2.7中也可用viewitems()

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

key is just a variable name.

for key in d:

will simply loop over the keys in the dictionary, rather than the keys and values. To loop over both key and value you can use the following:

For Python 3.x:

for key, value in d.items():

For Python 2.x:

for key, value in d.iteritems():

To test for yourself, change the word key to poop.

In Python 3.x, iteritems() was replaced with simply items(), which returns a set-like view backed by the dict, like iteritems() but even better. This is also available in 2.7 as viewitems().

The operation items() will work for both 2 and 3, but in 2 it will return a list of the dictionary’s (key, value) pairs, which will not reflect changes to the dict that happen after the items() call. If you want the 2.x behavior in 3.x, you can call list(d.items()).


回答 1

并不是说键是一个特殊的词,而是字典实现了迭代器协议。您可以在您的类中执行此操作,例如,有关如何构建类迭代器的信息,请参见此问题

对于字典,它是在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 dict是的简写for x in dict.iterkeys()

在Python 3中dict.iterkeys()dict.itervalues()dict.iteritems()不再受支持。使用dict.keys()dict.values()dict.items()代替。

It’s not that key is a special word, but that dictionaries implement the iterator protocol. You could do this in your class, e.g. see this question for how to build class iterators.

In the case of dictionaries, it’s implemented at the C level. The details are available in PEP 234. In particular, the section titled “Dictionary Iterators”:

  • Dictionaries implement a tp_iter slot that returns an efficient iterator that iterates over the keys of the dictionary. […] This means that we can write

    for k in dict: ...
    

    which is equivalent to, but much faster than

    for k in dict.keys(): ...
    

    as long as the restriction on modifications to the dictionary (either by the loop or by another thread) are not violated.

  • Add methods to dictionaries that return different kinds of iterators explicitly:

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

    This means that for x in dict is shorthand for for x in dict.iterkeys().

In Python 3, dict.iterkeys(), dict.itervalues() and dict.iteritems() are no longer supported. Use dict.keys(), dict.values() and dict.items() instead.


回答 2

遍历一个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)]

这给您一个元组列表。当你遍历他们这个样子,每个元组是解压到kv自动:

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

如果循环的主体只有几行,则在遍历a时使用kv作为变量名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))

Iterating over a dict iterates through its keys in no particular order, as you can see here:

Edit: (This is no longer the case in Python3.6, but note that it’s not guaranteed behaviour yet)

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

For your example, it is a better idea to use dict.items():

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

This gives you a list of tuples. When you loop over them like this, each tuple is unpacked into k and v automatically:

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

Using k and v as variable names when looping over a dict is quite common if the body of the loop is only a few lines. For more complicated loops it may be a good idea to use more descriptive names:

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

It’s a good idea to get into the habit of using format strings:

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

回答 3

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)

key is simply a variable.

For Python2.X:

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

… or better,

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

For Python3.X:

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

回答 4

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

要遍历键值对,请在Python 2中使用for k,v in s.iteritems(),在Python 3中for k,v in s.items()

When you iterate through dictionaries using the for .. in ..-syntax, it always iterates over the keys (the values are accessible using dictionary[key]).

To iterate over key-value pairs, in Python 2 use for k,v in s.iteritems(), and in Python 3 for k,v in s.items().


回答 5

这是一个非常常见的循环习惯用法。in是运算符。有关何时使用for key in dict和何时使用的信息,for key in dict.keys()请参阅David Goodger的Idiomatic Python文章(归档副本)

This is a very common looping idiom. in is an operator. For when to use for key in dict and when it must be for key in dict.keys() see David Goodger’s Idiomatic Python article (archived copy).


回答 6

使用“ 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']

返回字典

我们已经看到在许多情况下都会反复进行命令。我们看到的是,每当我们迭代一个字典时,我们都会得到密钥。回到原始示例:

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

如果要遍历值,则需要使用.valuesdicts方法,或同时使用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)

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

Iterating over dictionaries using ‘for’ loops

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

How does Python recognize that it needs only to read the key from the dictionary? Is key a special word in Python? Or is it simply a variable?

It’s not just for loops. The important word here is “iterating”.

A dictionary is a mapping of keys to values:

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

Any time we iterate over it, we iterate over the keys. The variable name key is only intended to be descriptive – and it is quite apt for the purpose.

This happens in a list comprehension:

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

It happens when we pass the dictionary to list (or any other collection type object):

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

The way Python iterates is, in a context where it needs to, it calls the __iter__ method of the object (in this case the dictionary) which returns an iterator (in this case, a keyiterator object):

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

We shouldn’t use these special methods ourselves, instead, use the respective builtin function to call it, iter:

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

Iterators have a __next__ method – but we call it with the builtin function, 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

When an iterator is exhausted, it raises StopIteration. This is how Python knows to exit a for loop, or a list comprehension, or a generator expression, or any other iterative context. Once an iterator raises StopIteration it will always raise it – if you want to iterate again, you need a new one.

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

Returning to dicts

We’ve seen dicts iterating in many contexts. What we’ve seen is that any time we iterate over a dict, we get the keys. Back to the original example:

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

If we change the variable name, we still get the keys. Let’s try it:

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

If we want to iterate over the values, we need to use the .values method of dicts, or for both together, .items:

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

In the example given, it would be more efficient to iterate over the items like this:

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

But for academic purposes, the question’s example is just fine.


回答 7

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

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

请注意,键值周围的括号很重要,如果没有括号,则会出现ValueError“没有足够的值要解压”。

I have a use case where I have to iterate through the dict to get the key, value pair, also the index indicating where I am. This is how I do it:

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

Note that the parentheses around the key, value is important, without the parentheses, you get an ValueError “not enough values to unpack”.


回答 8

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

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

CPython的dictobject.c

You can check the implementation of CPython’s dicttype on GitHub. This is the signature of method that implements the dict iterator:

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

CPython dictobject.c


回答 9

要遍历键,使用起来比较慢,但效果更好my_dict.keys()。如果您尝试执行以下操作:

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

这将导致运行时错误,因为在程序运行时更改了密钥。如果您绝对希望减少时间,请使用此for key in my_dict方法,但已被警告;)。

To iterate over keys, it is slower but better to use my_dict.keys(). If you tried to do something like this:

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

it would create a runtime error because you are changing the keys while the program is running. If you are absolutely set on reducing time, use the for key in my_dict way, but you have been warned ;).


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

输出:

This will print the output in Sorted order by Values in ascending order.

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)

Output: