python 生成器详述

参考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

你可能感兴趣的:(python 生成器详述)