我想知道为什么有这两种方法来遍历字典
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
据我所知,他们也是这样做的。还是有区别?
在这个特殊的例子中它们是一样的。如您所见:
>>> states.items()
dict_items([('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')])
>>> type(_)
<class 'dict_items'>
>>>
items
函数返回一个dict_items
对象。
它有一个__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']
>>>
这意味着它支持迭代。
但是如果你想用它做任何事情:
>>> 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
>>>
它会给出一个TypeError
。
dict_items
类类似于:
class dict_items:
...
def __iter__(self):
...
它只支持迭代。
然而如果你把它转换成list
:
>>> list(states.items())
[('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')]
>>>
它将给出一个常规的元组列表,这显然也是可迭代的,但在这种情况下完全不需要。
@juanpa。arrivillaga提到,使用list(states.items())
不必要地创建一个元组列表并迭代它,而不是直接迭代items-view。
在其他一些情况下,需要使用list
。如果你想把一个字典转换成一个元组列表,list(states.items())
是最好的选择。
您可能希望遍历项列表的主要原因是它允许您在迭代期间修改字典,向字典添加新项或删除旧项。
如果直接遍历字典并进行这样的修改,迭代将报错并崩溃。
如果您只修改属于现有键的值,它不会崩溃,但在这种情况下,与列表的迭代给您旧的值,而在字典上迭代直接给您当前的值(可能已经在早期项目中更改)。获取旧值可能是你想要的,例如,如果你编写一个生活游戏模拟器,需要从旧状态计算下一个状态,而不影响下一个状态的计算。
不需要是一个列表,只需要是项的某个副本,所以你不需要直接遍历字典。例如,可以使用tuple, dequeue甚至dict。
如果你不想修改,只是像你的玩具示例一样打印,那么创建列表只是毫无意义的浪费内存和时间。