列表——理解 | 第二部分 类型与操作 —— 第 4 章: 介绍 python 对象类型 |《学习 python:强大的面向对象编程(第 5 版)》| python 技术论坛-金年会app官方网

未匹配的标注

除了序列操作和列表方法,python包括了一个更高级的被称为列表理解表达式的操作,它被证明为是一个处理如矩阵这种结构的有力方法。比如,假设我们需要提取出示例矩阵的第二列。通过简单的索引抓取行很容易,因为矩阵是按行存储的,但使用列表理解来获取列几乎一样容易:

>>> col2 = [row[1] for row in m] # 收集列中的项
2
>>> col2
[2, 5, 8]
>>> m # 矩阵没变
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

列表理解起源于集合标记法;它们是通过对序列中的每个项,一次一个,从左到右地运行一个表达式来构建一个新列表的一种方法。列表理解被编码在方括号中(提醒你它们创建列表的事实)且由一个表达式和一个共享一个变量名(这里是 row)的循环结构组成。前面的列表理解基本意外着它所说的:“把矩阵m中每行的row[1]给我,放入新列表中。” 这个结果是一个包含矩阵的第2列的新列表。

列表理解在实践中可以更复杂:

>>> [row[1]   1 for row in m] # 给第2列的每项都加1
[3, 6, 9]
>>> [row[1] for row in m if row[1] % 2 == 0] # 剔除奇数项
[2, 8]

比如,这里的第一个操作在收集的每个项上都添加1,第二个操作使用一个if从句——使用%模数表达式(除法余数)——来过滤掉结果中的奇数。列表理解创建结果的新列表,但它们被用来迭代任何可迭代对象——这个术语我们将在后面详细讨论。比如,这里我们使用列表理解来迭代一个坐标和字符串的硬编码列表:

>>> diag = [m[i][i] for i in [0, 1, 2]] # 从矩阵收集一个对角线
>>> diag
[1, 5, 9]
>>> doubles = [c * 2 for c in 'spam'] # 重复字符串中的字符
>>> doubles
['ss', 'pp', 'aa', 'mm']

这些表达式也能被用来收集多个值,只要我们将那些值包裹在一个嵌套集合中。下面展示了range——一个内置函数的使用,并且需要一个包裹的list来中显示它的所有值(只在3.x中,2.x一次性将整个列表创建在内存中):

>>> list(range(4)) # 0..3 (在 3.x 中需要 list())
[0, 1, 2, 3]
>>> list(range(−6, 7, 2)) # −6 到  6 步进 2 (在 3.x 中需要 list())
[−6, −4, −2, 0, 2, 4, 6]
>>> [[x ** 2, x ** 3] for x in range(4)] # 多个值, "if" 过滤
[[0, 0], [1, 1], [4, 8], [9, 27]]
>>> [[x, x / 2, x * 2] for x in range(−6, 7, 2) if x > 0]
[[2, 1, 4], [4, 2, 8], [6, 3, 12]]

正如你可能知道的,列表理解,和类似内置函数 mapfilter 的相似函数,在这个预览章节中太过复杂以至于不能更深入地讨论。这个简短介绍的主要目的是展示python在其武器库中包括了简单和高级的工具。列表理解是一个可选功能,但它们往往在实践中非常有用且经常提供一个很大的处理速度优势。它们还适用于任何类型的python序列,和一些非序列的类型。在本书后面你将听到关于它们更多的知识。

然而,作为一个预览,你会发现在最近的python中,理解语法已经被推广到其他作用:当前它不仅仅可以创建列表。比如,在小括号中包裹一个理解还可以用来创建按需产生结果的生成器。为了展示,内置的sum对序列中的项求和——在本例中,按需对我们矩阵的行中的所有项求和:

>>> g = (sum(row) for row in m) # 创建一个行的和的生成器
>>> next(g) # 这里不需要 iter(g)
6
>>> next(g) # 运行迭代协议 next()
15
>>> next(g)
24

内置的 map 也可以做类似的工作,通过生成对各项运行一个函数的结果,每次一个,并应请求生成。就像 range,在python 3.x中将它包裹在 list 中强迫它返回它的所有值;这在2.x中是不需要的,在那里 map 一次性创建了结果列表作为代替,且在其他自动迭代的上下文中也不需要,除非还需要多次扫描或类列表行为:

>>> list(map(sum, m)) # 对m中的项映射 sum 函数
[6, 15, 24]

在python 2.7 和 3.x中,理解语法还可以被用来创建集合字典

>>> {sum(row) for row in m} # 创建一个行的和的集合
{24, 6, 15}
>>> {i : sum(m[i]) for i in range(3)} # 创建行的和的键/值表
{0: 6, 1: 15, 2: 24}

事实上,列表,集合,字典,和生成器都能由3.x 和 2.7中的理解创建:

>>> [ord(x) for x in 'spaam'] # 字符序数值列表
[115, 112, 97, 97, 109]
>>> {ord(x) for x in 'spaam'} # 集合移除了重复
{112, 97, 115, 109}
>>> {x: ord(x) for x in 'spaam'} # 字典的键是唯一不重复的
{'p': 112, 'a': 97, 's': 115, 'm': 109}
>>> (ord(x) for x in 'spaam') # 值的生成器
 at 0x000000000254dab0>

然而,要理解像生成器,集合,和字典这些对象,我们必须前进。

本文章首发在 金年会app官方网 网站上。

上一篇 下一篇
讨论数量: 0



暂无话题~
网站地图