乐趣区

关于python:翻译实用的Python编程0604Moregenerators

目录 | 上一节 (6.3 生产者 / 消费者) | [下一节 (7 高级主题)]()

6.4 无关生成器的更多信息

本节介绍其它与生成器相干的主题,包含生成器表达式(generator expressions)和 itertools 模块。

生成器表达式

生成器表达式能够了解为列表解析式(list comprehension)的生成器版本:

>>> a = [1,2,3,4]
>>> b = (2*x for x in a)
>>> b
<generator object at 0x58760>
>>> for i in b:
...   print(i, end=' ')
...
2 4 6 8
>>>

生成器表达式与列表列表解析式的区别:

  • 不结构列表
  • 惟一有用的目标是迭代
  • 一旦被生产,无奈重复使用

生成器表达式语法:

(<expression> for i in s if <conditional>)

生成器表达式也能够用作函数参数:

sum(x*x for x in a)

生成器表达式可利用于任何迭代:

>>> a = [1,2,3,4]
>>> b = (x*x for x in a)
>>> c = (-x for x in b)
>>> for i in c:
...   print(i, end=' ')
...
-1 -4 -9 -16
>>>

生成器表达式在代码中的一个主要用途是:对序列进行计算,但只应用一次后果。例如,跳过文件中的所有正文。

f = open('somefile.txt')
lines = (line for line in f if not line.startswith('#'))
for line in lines:
    ...
f.close()

应用生成器,代码运行更快并且占用的内存更少,相似利用于流的过滤器。

为什么应用生成器

  • 许多问题以迭代的模式进行示意会更清晰

    • 对汇合中的元素进行遍历,并执行某些操作(如查找、替换,批改等)。
    • 解决管道(processing pipelines)可利用于各种数据处理问题。
  • 内存效率更高

    • 只在须要的时候才生成值。
    • 不结构宏大的列表。
    • 可对流数据进行操作。
  • 生成器表达式激励代码复用

    • 从应用迭代的代码中拆散出迭代。
    • 构建迭代函数工具箱,混合搭配(mix-n-match)应用各种工具。

itertools 模块

itertools 是 Python 自带的一个库模块,蕴含各种函数,旨在帮忙开发迭代器 / 生成器。

itertools.chain(s1,s2)
itertools.count(n)
itertools.cycle(s)
itertools.dropwhile(predicate, s)
itertools.groupby(s)
itertools.ifilter(predicate, s)
itertools.imap(function, s1, ... sN)
itertools.repeat(s, n)
itertools.tee(s, ncopies)
itertools.izip(s1, ... , sN)

itertools 模块中所有的函数都能够迭代地解决数据。并且,这些函数实现了各类迭代模式。

无关生成器的更多信息能够查看 PyCon ’08 上的 Generator Tricks for Systems Programmers 教程。

练习

在上一节练习中,咱们编写代码监督写入日志文件的数据,并将其解析为行序列。

本次练习将以上一节练习中的代码为根底,所以请确保 Data/stocksim.py 仍在运行。

练习 6.13:生成器表达式

生成器表达式是列表解析式的生成器版本。示例:

>>> nums = [1, 2, 3, 4, 5]
>>> squares = (x*x for x in nums)
>>> squares
<generator object <genexpr> at 0x109207e60>
>>> for n in squares:
...     print(n)
...
1
4
9
16
25

与列表解析式不同,生成器表达式只能应用一次。因而,如果你遍历完生成器中的所有元素后,再次对生成器进行遍历,那么你将满载而归。

>>> for n in squares:
...     print(n)
...
>>>

练习 6.14:函数参数中的生成器表达式

有时,生成器表达式会作为函数参数应用。尽管这看起来有点怪,但请尝试以下试验:

>>> nums = [1,2,3,4,5]
>>> sum([x*x for x in nums])    # A list comprehension
55
>>> sum(x*x for x in nums)      # A generator expression
55
>>>

在下面的示例中,如果正在操作宏大的列表,那么应用生成器的第二个版本占用的内存会显著缩小。

portfolio.py 文件中,咱们执行了一些与列表相干的计算,请尝试将其替换为生成器表达式。

练习 6.15:简化代码

通常,对于简略的生成器函数,能够应用生成器表达式进行替换。例如,与其这样编写函数:

def filter_symbols(rows, names):
    for row in rows:
        if row['name'] in names:
            yield row

不如应用生成器表达式进行替换:

rows = (row for row in rows if row['name'] in names)

请批改 ticker.py 程序来适当地应用生成器表达式。

目录 | 上一节 (6.3 生产者 / 消费者) | [下一节 (7 高级主题)]()

注:残缺翻译见 https://github.com/codists/practical-python-zh

退出移动版