简体   繁体   English

Python 中使用 list(dict.items()) 和 dict.items() 遍历字典的区别在哪里

[英]Where is the difference between iterating over a dictionary with list(dict.items()) and dict.items() in Python

I wonder why there are these two ways to iterate over a dictionary我想知道为什么有这两种方法来遍历字典

states = {
    'Oregon': 'OR',
    'Florida': 'FL',
    'California': 'CA',
    'New York': 'NY',
    'Michigan': 'MI'
}

for key, item in states.items():
    print(key, item)

for key, item in list(states.items()):
    print(key, item

As far as I understand, they do the same.据我了解,他们也是这样做的。 Or is there a difference?或者有区别吗?

Well they are the same in this particular example.那么在这个特定的例子中它们是相同的。 As you can see:如你看到的:

>>> states.items()
dict_items([('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')])
>>> type(_)
<class 'dict_items'>
>>> 

The items function returns a dict_items object. items function 返回一个dict_items object。

And it has a __iter__ attribute:它有一个__iter__属性:

>>> dir(states.items())
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'isdisjoint']
>>> 

Which means it supports iteration.这意味着它支持迭代。

But if you try anything with it:但是,如果您尝试使用它:

>>> states.items()[0]
Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    states.items()[0]
TypeError: 'dict_items' object is not subscriptable
>>> 

It would give a TypeError .它会给出一个TypeError

The dict_items class is something like: dict_items class 是这样的:

class dict_items:
    ...
    def __iter__(self):
        ...

It supports iteration but nothing else.它支持迭代,但仅此而已。

Whereas if you convert it to a list :而如果将其转换为list

>>> list(states.items())
[('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')]
>>> 

It would give a regular list of tuples, that is obviously iterable as well, but it is completely not needed in this situation.它会给出一个规则的元组列表,这显然也是可迭代的,但在这种情况下完全不需要。

As @juanpa.arrivillaga mentioned, using list(states.items()) needlessly creates a list of tuples and iterates over that instead of iterating over the items-view directly.正如@juanpa.arrivillaga 提到的,使用list(states.items())不必要地创建一个元组列表并对其进行迭代,而不是直接对项目视图进行迭代。

In some other situations, using list is required.在其他一些情况下,需要使用list If you want to convert a dictionary to a list of tuples, list(states.items()) would be the way to go.如果你想将字典转换为元组列表, list(states.items())将是 go 的方式。

The main reason you might want to iterate over a list of the items is that it allows you to modify the dict during the iteration, adding new items to the dict or removing old ones.您可能想要迭代项目列表的主要原因是它允许您在迭代期间修改字典,向字典添加新项目或删除旧项目。

If you iterate over the dict directly and make such modifications, the iteration will complain with an error and crash.如果您直接遍历字典并进行此类修改,则迭代将报错并崩溃。

It won't crash if you just modify the values belonging to existing keys, but in that case, the iteration with the list gives you the old values while iterating over the dict directly gives you the current (possibly already changed during earlier items) values.如果您只修改属于现有键的值,它不会崩溃,但在这种情况下,与列表的迭代会为您提供旧值,而直接迭代 dict 会为您提供当前(可能在早期项目中已更改)值. Getting the old values might be what you want if you for example write a game of life simulator and need to compute the next state from the old state, without the computation of the next state affecting itself.例如,如果您编写一个生活模拟器游戏并且需要从旧的 state 计算下一个 state,而不影响下一个 state 的计算,那么获取旧值可能就是您想要的。

Doesn't need to be a list, just needs to be some copy of the items, so you're not iterating over the dict directly.不需要是一个列表,只需要是项目的一些副本,所以你不会直接遍历字典。 Could for example use tuple, deqeue or even dict instead.例如,可以使用 tuple、deqeue 甚至 dict 代替。

If you don't want to modify but just print like in your toy example, then creating the list is just a pointless waste of memory and time.如果您不想修改而只是像玩具示例中那样打印,那么创建列表只是毫无意义地浪费 memory 和时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM