这篇文章主要介绍了Python中dictionary items()系列函数的用法,很实用的函数,需要的朋友可以参考下

本文实例讲述了Python中dictionary items()系列函数的用法,对Python程序设计有很好的参考借鉴价值。具体分析如下:

先来看一个示例:

import html # available only in Python 3.x
def make_elements(name, value, **attrs):
keyvals = [' %s="%s"' % item for item in attrs.items()]
attr_str = ''.join(keyvals)
element = '{value}{name}>'.format(
name = name,
attrs = attr_str,
value = html.escape(value))
return element
make_elements('item', 'Albatross', size='large', quantity=6)
make_elements('p', '')

该程序的作用很简单,就是生成HTML标签,注意html这个模块只能在Python 3.x才有。

起初我只是注意到,生成标签属性列表的keyvals这个dictionary类型变量构建的方式很有意思,两个%s对应一个item,所以就查阅了相关的资料,结果扯出了挺多的东西,在此一并总结。

注:下面所有Python解释器使用的版本,2.x 对应的是2.7.3,3.x 对应的是3.4.1

在 Python 2.x 里,官方文档里items的方法是这么说明:生成一个 (key, value) 对的list,就像下面这样:

>>> d = {'size': 'large', 'quantity': 6}
>>> d.items()
[('quantity', 6), ('size', 'large')]

在搜索的过程中,无意看到stackoverflow上这样一个问题:dict.items()和dict.iteritems()有什么区别? ,第一个答案大致的意思是这样的:

“起初 items() 就是返回一个像上面那样的包含dict所有元素的list,但是由于这样太浪费内存,所以后来就加入了(注:在Python 2.2开始出现的)iteritems(), iterkeys(), itervalues()这一组函数,用于返回一个 iterator 来节省内存,但是在 3.x 里items() 本身就返回这样的 iterator,所以在 3.x 里items() 的行为和 2.x 的 iteritems() 行为一致,iteritems()这一组函数就废除了。”

不过更加有意思的是,这个答案虽然被采纳,下面的评论却指出,这种说法并不准确,在 3.x 里 items() 的行为和 2.x 的 iteritems() 不一样,它实际上返回的是一个"full sequence-protocol object",这个对象能够反映出 dict 的变化,后来在 Python 2.7 里面也加入了另外一个函数 viewitems() 和 3.x 的这种行为保持一致

为了证实评论中的说法,我做了下面的测试,注意观察测试中使用的Python版本:

测试1(Python 2.7.3):Python 2.7.3 (default, Feb 27 2014, 19:58:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'size': 'large', 'quantity': 6}
>>> il = d.items()
>>> it = d.iteritems()
>>> vi = d.viewitems()
>>> il
[('quantity', 6), ('size', 'large')]
>>> it
>>> vi
dict_items([('quantity', 6), ('size', 'large')])
测试2(Python 3.4.1):Python 3.4.1 (default, Aug 12 2014, 16:43:01)
[GCC 4.9.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'size': 'large', 'quantity': 6}
>>> il = d.items()
>>> it = d.iteritems()
Traceback (most recent call last):
File "", line 1, in 
AttributeError: 'dict' object has no attribute 'iteritems'
>>> vi = d.viewitems()
Traceback (most recent call last):
File "", line 1, in 
AttributeError: 'dict' object has no attribute 'viewitems'
>>> il
dict_items([('size', 'large'), ('quantity', 6)])

可以看到在 Python 3.x 里面,iteritems() 和 viewitems() 这两个方法都已经废除了,而 item() 得到的结果是和 2.x 里面 viewitems() 一致的。

2.x 里 iteritems() 和 viewitems() 返回的内容都是可以用 for 来遍历的,像下面这样

>>> for k, v in it:
... print k, v
...
quantity 6
size large
>>> for k, v in vi:
... print k, v
...
quantity 6
size large

这两者的区别体现在哪里呢?viewitems() 返回的是view object,它可以反映出 dictionary 的变化,比如上面的例子,假如在使用 it 和 vi 这两个变量之前,向 d 里面添加一个key-value组合,区别就很容易看出来了。

>>> it = d.iteritems()
>>> vi = d.viewitems()
>>> d['newkey'] = 'newvalue'
>>> d
{'newkey': 'newvalue', 'quantity': 6, 'size': 'large'}
>>> vi
dict_items([('newkey', 'newvalue'), ('quantity', 6), ('size', 'large')])
>>> it
>>> for k, v in vi:
... print k, v
...
newkey newvalue
quantity 6
size large
>>> for k, v in it:
... print k, v
...
Traceback (most recent call last):
File "", line 1, in 
RuntimeError: dictionary changed size during iteration

在第三行中,我们像 d 里面插入了一个新的元素,vi 可以继续遍历,而且新的遍历能够反映出 d 的变化,但是在遍历 it 的时候,报错提示 dictionary 在遍历的时候大小发生了变化,遍历失败。

总结起来,在 2.x 里面,最初是 items() 这个方法,但是由于太浪费内存,所以加入了 iteritems() 方法,用于返回一个 iterator,在 3.x 里面将 items() 的行为修改成返回一个 view object,让它返回的对象同样也可以反映出原 dictionary 的变化,同时在 2.7 里面又加入了 viewitems() 向下兼容这个特性。

所以在 3.x 里面不需要再去纠结于三者的不同之处,因为只保留了一个 items() 方法。