参考python核心变成第二版
列表解析
在介绍生成器表达式之前,先来介绍一下列表解析
列表解析(List comprehesions) 是一个非常有用,简单而且灵活的工具,可以用来动态地创建列表。
- map() 对所有的列表成员应用一个操作
- filter() 基于一个条件表达式过滤列表成员
- lamda() 允许快速地创建只有一行的函数对象
举例:返回列表中的奇数
>>> myseq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> filter(lambda x: x % 2, myseq)
使用列表解析式
>>> myseq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [x for x in myseq if x % 2]
以上输出结果:[1, 3, 5, 7, 9]
说明:
列表解析的一个不足就是必要生成所有的数据,用以创建整个列表。这可能对大量的数据的迭代器有负面效应。
生成器表达式
生成器表达式列表解析的一个扩展。(1) 与列表解析非常相似,它们的基本语法基本相同。(2) 生成器并不真正地创建数字列表, 而是返回一个生成器
,这个生成器每次计算出一个条目之后,把此条目"产生"(yield)
出来。(3) 生成器表达式使用了"延迟计算",在内存中更加有效
语法对比
- 列表解析
[expr for iter_var in iterable if cond_expr]- 生成器表达式
(expr for iter_var in iterable if cond_expr)
(1)磁盘举例
列表解析式
>>> path = os.getcwd() + '/test.txt'
>>> f = open(path, 'r')
>>> f.seek(0)
>>> sum([ len(word) for line in f for word in line.split()])
35
生成器表达式
>>> path = os.getcwd() + '/test.txt'
>>> f = open(path, 'r')
>>> f.seek(0)
>>> sum(len(word) for line in f for word in line.split())
35
(2)交叉配对举例
生成器表达式好像是懒惰的列表解析(反而成了它主要的优势),可以用来处理其他列表或者生成器
>>> rows = [1, 2, 3, 17]
>>> def cols():
... yield 56
... yield 2
... yield 1
...
>>> x = ((i, j) for i in rows for j in cols())
>>> x
at 0x10c9e5fa0>
>>> for pair in x:
... print pair
...
(1, 56)
(1, 2)
(1, 1)
(2, 56)
(2, 2)
(2, 1)
(3, 56)
(3, 2)
(3, 1)
(17, 56)
(17, 2)
(17, 1)
(3)交叉配对举例
使用列表解析
>>> path = os.getcwd() + '/test.txt'
>>> f = open(path, 'r')
>>> alllines = [len(x.strip()) for x in f]
>>> f.close()
>>> max(alllines)
27
使用生成器
>>> f = open(path, 'r')
>>> longest = max(len(x.strip()) for x in f)
>>> f.close()
>>> longest
27
其中test.txt内容为
hello-1
hello-2
hello-3
hello-4
this is a test, a test test
hello-5