前言
列表推导式构建列表的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列。自python2.7以后,列表推导和生成器表达式的概念就应用到了字典上,所以就有了字典推导,以后我们还会遇到集合推导(此处暂不讨论)。因此,如果想要更好的学习字典推导,需要对列表推导和生成器表达式进行充分对掌握。
为什么使用推导式,推导式的应用让代码的可读性更强。接下来,我们就一同来验证为什么说“可读性更强”。
1.列表推导
示例1:把letter字符串变成Unicode码位的列表
In [1]: letter='abcdefghr'
In [2]: codes=[]
In [3]: for letter in letter:
...: codes.append(ord(letter))
...:
In [4]: codes
Out[4]: [97, 98, 99, 100, 101, 102, 103, 104, 114]
示例2:把letter字符串变成Unicode码位的列表的另外一个写法(即列表推导)
In [1]: letter='abcdefghr'
In [2]: codes=[ord(letter) for letter in letter]
In [3]: codes
Out[3]: [97, 98, 99, 100, 101, 102, 103, 104, 114]
如上两个示例,最终达到的效果是一致的。但是明显可以看出,示例2的可读性更强。大家可能会问,是不是以后就使用列表推导不再使用for循环来呢?其实不然。通常的原则是,只用列表推导来创建新的列表,并且尽量保持简短。如果列表推导的代码超过了两行,可能就要考虑是不是要用for循环重写了。实际上,没有硬性规则要求什么时候用什么,或者必须用什么,如何用怎么用,还是需要自己把握。
2.生成器表达式
与列表推导相比,生成器表达式是初始化元组、数组或其他序列类型的更好选择。原因是生成器表达式遵守了迭代器协议,它是逐个的产出元素,而不是构造完整列表后,把列表传递到函数里。生成器表达式与列表推导的语法差不多,不同的是列表推导使用方括号,而生成器表达式使用的是圆括号。
示例1:使用生成器表达式初始化元组和数组
#初始化元组
In [1]: letter='abcdefghr'
In [2]: tuple=tuple(ord(letter) for letter in letter)
In [3]: tuple
Out[3]: (97, 98, 99, 100, 101, 102, 103, 104, 114)
#初始化数组
In [4]: import array
In [5]: array.array('I',(ord(letter) for letter in letter))
Out[5]: array('I', [97, 98, 99, 100, 101, 102, 103, 104, 114])
如果生成器表达式是函数调用的唯一参数,则不需要再加另外一个圆括号。
array的构造方法有两个参数,第一个参数确定了数字的存储方式。与初始化元组不同,该处有两个参数,所以生成器表达式需要用圆括号括起来。
3.字典推导
字典推导可以从任何以键值对作为元素的可迭代对象中构建出字典。
下面例子就展示了利用字典推导可以把一个装满元组的列表编程两个不同的字典。
创建一个包含成对数据的data_name列表,它将直接用在后续字典的构造方法中,具体如下:
In [1]: data_name=[(1561,'祁俊超'),(1560,'邓亚鑫'),(1559,'黎荣梅'),(1557,'卢雪'),
(1556,'武晓蒙'),(1555,'黄国全'),(1554,'黎荣梅'),(1551,'姚文通'),
(1550,'曾丹丹'),(1548,'武晓蒙')]
In [2]: data_name
Out[2]:
[(1561, '祁俊超'),
(1560, '邓亚鑫'),
(1559, '黎荣梅'),
(1557, '卢雪'),
(1556, '武晓蒙'),
(1555, '黄国全'),
(1554, '黎荣梅'),
(1551, '姚文通'),
(1550, '曾丹丹'),
(1548, '武晓蒙')]
更改data_name列表中数据对的左右位置,姓名为键,编号为值。具体如下:
In [3]: name_code={name:code for code,name in data_name}
In [4]: name_code
Out[4]:
{'祁俊超': 1561,
'邓亚鑫': 1560,
'黎荣梅': 1554,
'卢雪': 1557,
'武晓蒙': 1548,
'黄国全': 1555,
'姚文通': 1551,
'曾丹丹': 1550}
同上面的操作相反,用编号为键,姓名为值,并且过滤掉编号大于或等于1560的姓名。具体如下:
In [5]: {code:name for name,code in name_code.items() if code>=1560}
Out[5]: {1561: '祁俊超', 1560: '邓亚鑫'}
如果对列表推导对概念以及书写方式已熟知,那么理解字典推导相对容易些。如果对列表推导还不熟知,那么现在应该是掌握它导时候了,因为字典推导导表达形式在其他数据类型中慢慢得以体现。同时,使用列表推导和字典推导可以实现对数据的过滤效果。