2.2 列表推导和生成器表达式

标准的列表推导写法:

>>> symbols = '$¢£¥€¤' 
>>> codes = [ord(symbol) for symbol in symbols] 
>>> codes 
[36, 162, 163, 165, 8364, 164]

通常的原则是,只用列表推导来创建新的列表,并且尽量保持简短。如果列表推导的代码超过了两行,你可能就要考虑是不是得用 for 循环重写了。就跟写文章一样,并没有什么硬性的规则,这个度得你自己把握。

filter 和 map 合起来能做的事情,列表推导也可以做,而且还不需要借助难以理解和阅读的 lambda 表达式:

>>> symbols = '$¢£¥€¤' 
>>> beyond_ascii = [ord(s) for s in symbols if ord(s) > 127] 
>>> beyond_ascii 
[162, 163, 165, 8364, 164] 
>>> beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols))) 
>>> beyond_ascii 
[162, 163, 165, 8364, 164]

虽然也可以用列表推导来初始化元组、数组或其他序列类型,但是生成器表达式是更好的选择。这是因为生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建立一个完整的列表,然后再把这个列表传递到某个构造函数里。前面那种方式显然能够节省内存。

生成器表达式的语法跟列表推导差不多,只不过把方括号换成圆括号而已。

>>> symbols = '$¢£¥€¤' 
>>> tuple(ord(symbol) for symbol in symbols) ➊ 
(36, 162, 163, 165, 8364, 164) 
>>> import array 
>>> array.array('I', (ord(symbol) for symbol in symbols)) ➋ 
array('I', [36, 162, 163, 165, 8364, 164])

➊ 如果生成器表达式是一个函数调用过程中的唯一参数,那么不需要额外再用括号把它围起来。
➋ array 的构造方法需要两个参数,因此括号是必需的。array 构造方法的第一个参数指定了数组中数字的存储方式

使用列表推导计算笛卡儿积:

>>> colors = ['black', 'white'] 
>>> sizes = ['S', 'M', 'L'] 
>>> tshirts = [(color, size) for color in colors for size in sizes] 
>>> tshirts 
[('black', 'S'), ('black', 'M'), ('black', 'L'), ('white', 'S'), ('white', 'M'), ('white', 'L')]

使用生成器表达式计算笛卡儿积:

>>> colors = ['black', 'white'] 
>>> sizes = ['S', 'M', 'L'] 
>>> for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes):
>>>     print(tshirt) 
black S 
black M 
black L 
white S 
white M 
white L

两种方法不同的是,用到生成器表达式之后,内存里不会留下一个有 6 个组合的 列表,因为生成器表达式会在每次 for 循环运行时才生成一个组合。如果要计算两个各有 1000 个元素的列表的笛卡儿积,生成器表达式就可以帮忙省掉运行 for 循环的开销,即一个含有 100 万个元素的列表。

原文地址:https://www.cnblogs.com/wjw2018/p/10629309.html