【问题标题】:Iterating over dictionary items(), values(), keys() in Python 3在 Python 3 中迭代字典 items()、values()、keys()
【发布时间】:2011-04-06 17:08:05
【问题描述】:

如果我理解正确,在 Python 2 中,iter(d.keys())d.iterkeys() 相同。但是现在,d.keys() 是一个视图,它位于列表和迭代器之间。视图和迭代器有什么区别?

也就是说,在 Python 3 中,有什么区别

for k in d.keys()
    f(k)

for k in iter(d.keys())
    f(k)

另外,这些差异如何在一个简单的for 循环中显示出来(如果有的话)?

【问题讨论】:

    标签: python python-3.x dictionary iterator


    【解决方案1】:

    我不确定这是否能很好地回答您的问题,但希望它能解释一下 Python 2 和 3 在这方面的区别。

    在 Python 2 中,iter(d.keys())d.iterkeys() 并不完全相同,尽管它们的行为相同。第一个,keys() 将返回字典的键列表的副本,iter 将在此列表上返回一个迭代器对象,第二个完整的键列表的副本永远不会构建。

    d.keys() 在 Python 3 中返回的视图对象是 iterable(即可以从它们中生成迭代器),所以当你说 for k in d.keys() 时,Python 会为你创建迭代器。因此,您的两个示例的行为将相同。

    keys() 的返回类型变化的意义在于 Python 3 的视图对象是动态的。即,如果我们说 ks = d.keys() 然后添加到 d 那么 ks 将反映这一点。在 Python 2 中,keys() 返回字典中当前所有键的列表。比较:

    Python 3

    >>> d = { "first" : 1, "second" : 2 }
    >>> ks = d.keys()
    >>> ks
    dict_keys(['second', 'first'])
    >>> d["third"] = 3
    >>> ks
    dict_keys(['second', 'third', 'first'])
    

    Python 2.x

    >>> d = { "first" : 1, "second" : 2 }
    >>> ks = d.keys()
    >>> ks
    ['second', 'first']
    >>> d["third"] = 3
    >>> ks
    ['second', 'first']
    

    由于 Python 3 的 keys() 返回动态对象,Python 3 没有(也不需要)单独的 iterkeys 方法。

    进一步说明

    在 Python 3 中,keys() 返回一个dict_keys 对象,但如果我们在for 循环上下文for k in d.keys() 中使用它,则隐式创建一个迭代器。所以for k in d.keys()for k in iter(d.keys()) 之间的区别在于迭代器的隐式和显式创建。

    另一个区别是,虽然它们都是动态的,但请记住,如果我们创建一个显式迭代器,那么它只能使用一次,而视图可以根据需要重复使用。例如

    >>> ks = d.keys()
    >>> 'first' in ks
    True
    >>> 'second' in ks
    True
    >>> i = iter(d.keys())
    >>> 'first' in i
    True
    >>> 'second' in i
    False             # because we've already reached the end of the iterator
    

    另外,请注意,如果我们创建一个显式迭代器,然后修改 dict,那么迭代器就会失效:

    >>> i2 = iter(d.keys())
    >>> d['fourth'] = 4
    >>> for k in i2: print(k)
    ...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    RuntimeError: dictionary changed size during iteration
    

    在 Python 2 中,鉴于 keys 的现有行为,需要一个单独的方法来提供一种在不复制键列表的情况下进行迭代的方法,同时仍保持向后兼容性。因此iterkeys()

    【讨论】:

    • 2.7 中有.viewkeys()。返回视图。 docs.python.org/library/stdtypes.html#dict.viewkeys
    • 谢谢。我了解 Python 2 的 d.keys() 有何不同。但是我仍然对 Python 2 中的 d.iterkeys()、Python 3 中的 d.keys() 和 Python 3 中的 iter(d.keys()) 之间的区别感到困惑。据我所知,它们都是动态的,而且它们都没有构建预先列出?
    • for 循环中iter(d.keys())d.keys() 之间没有区别,因为python 内部调用iter 本身。 python 2.x d.iterkeys() 和 py3k iter(d.keys()) 之间也没有区别:两者都返回字典键迭代器。所以这三个几乎都是一样的。
    猜你喜欢
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    相关资源
    最近更新 更多