生成器就是一个在行为上和迭代器非常类似的对象.   是个对象!

迭代,顾名思意就是不停的代换的意思,迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。

迭代器就是用于迭代操作(for 循环)的对象。它像列表一样可以迭代获取其中的每一个元素,任何实现了 __next__ 方法(python2 是 next)的对象都可以称为迭代器。

它与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy evaluation)方式返回元素,这正是它的优点。比如列表含有中一千万个整数,需要占超过400M的内存,而迭代器只需要几十个字节的空间。因为它并没有把所有元素装载到内存中,而是等到调用 next 方法时候才返回该元素(call by need 的方式),本质上 for 循环就是不断地调用迭代器的next方法。

我们自定义一个迭代器,以斐波那契数列为例:

class Fib:

def __init__(self):

self.prev = 0

self.curr = 1

def __iter__(self):

return self

def __next__(self):

value = self.curr

self.curr += self.prev

self.prev = value

return value

>>> f = Fib()

>>> list(islice(f, 0, 10))

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Fib既是一个可迭代对象(因为它实现了 __iter__方法)又是一个迭代器(因为实现了 __next__方法)。实例变量 prev和 curr用户维护迭代器内部的状态。每次调用 next()方法的时候做两件事:

为下一次调用 next()方法修改状态

为当前这次调用生成返回结果

迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。

 

生成器

然而在 Python 中还有一种函数,用关键字 yield 来返回值,这种函数叫生成器函数,函数被调用时会返回一个生成器对象,生成器本质上还是一个迭代器,也是用在迭代操作中,因此它有和迭代器一样的特性,唯一的区别在于实现方式上不一样,后者更加简洁

关系

生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写 __iter__()和 __next__()方法了,只需要一个 yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值

如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)

要创建一个generator,有很多种方法:

1.只要把一个列表生成式的[]改成(),就创建了一个generator,又叫生成器表达式(generator expression)

>>> L = [x * x for x in range(10)]

>>> L

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> g = (x * x for x in range(10))

>>> g

<generator object <genexpr> at 0x104feab40>

打印出generator的每一个元素呢?

如果要一个一个打印出来,可以通过generator的next()方法:

>>> g.next()

0

>>> g.next()

1

>>> g.next()

4

......

不断调用next()方法实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

>>> g = (x * x for x in range(10))

>>> for n in g:

...     print n

...

0

1

4

9

16

25

36

49

64

81

2.如果推算的算法比较复杂,可以用函数来实现

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator.

最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

举个简单的例子(很清楚了),定义一个generator,依次返回数字1,3,5:

>>> def odd():

...     print 'step 1'

...     yield 1

...     print 'step 2'

...     yield 3

...     print 'step 3'

...     yield 5

...

>>> o = odd()  ----->返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。

>>> o.next()

step 1

1

>>> o.next()

step 2

3

>>> o.next()

step 3

5

>>> o.next()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

StopIteration

可以看到,odd不是普通函数,而是generator,在执行过程中,遇到yield就中断,下次又继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用nex

把函数改成generator后,我们基本上从来不会用next()来调用它,而是直接使用for循环来迭代:

例子:比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

(1)用函数实现:

def fib(max):

n, a, b = 0, 0, 1

while n < max:

print b

a, b = b, a + b

n = n + 1

输出:

>>> fib(6)

1

1

2

3

5

8

(2)要把fib函数变成generator,只需要把print b改为yield b就可以了:

def fib(max):

n, a, b = 0, 0, 1

while n < max:

yield b

a, b = b, a + b

n = n + 1

输出:

>>> fib(6)

<generator object fib at 0x104feaaa0>

把函数改成generator后,我们基本上从来不会用next()来调用它,而是直接使用for循环来迭代:

>>> for n in fib(6):

...     print n

...

1

1

2

3

5

8

python中的迭代器和生成器学习笔记总结的更多相关文章

  1. python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器

    1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...

  2. 终于理解Python中的迭代器和生成器了!

    迭代器和生成器 目录 迭代器和生成器 可迭代对象和迭代器 基础概念 判断 for循环本质 不想用for循环迭代了,如何使用迭代器? 列表推导式 生成器Generator 概念 如何实现和使用? 生成器 ...

  3. Python中的迭代器和生成器

    本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述: 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后 ...

  4. python中的迭代器与生成器

    迭代器 迭代器的引入 假如我现在有一个列表l=['a','b','c','d','e'],我想取列表中的内容,那么有几种方式? 1.通过索引取值 ,如了l[0],l[1] 2.通过for循环取值 fo ...

  5. Python3 迭代器与生成器 - 学习笔记

    可迭代对象(Iterable) 迭代器(Iterator) 定义 迭代器和可迭代对象的区别 创建一个迭代器 创建一个迭代器类 使用内置iter()函数 StopIteration异常 生成器(gene ...

  6. Python 中的map和reduce学习笔记

    map和reduce都是Python中的内置函数 map函数接受两个参数,第一个参数是函数,第二个参数是列表,将函数依次作用于列表中的元素,并返回一个元素 reduce同样以函数和列表作为参数,区别在 ...

  7. Python中的迭代器、生成器

    from collections import Iterable, Iterator 1. 可迭代(iterable)对象 参考官网链接 class I: def __init__(self, v): ...

  8. Python中的迭代器、生成器、装饰器

    1. 迭代器  1 """ 2 iterator 3 迭代器协议: 对象必须提供一个next()方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIterati ...

  9. python 中的迭代器和生成器简单介绍

    可迭代对象和迭代器 迭代(iterate)意味着重复,就像 for 循环迭代序列和字典那样,但实际上也可使用 for 循环迭代其他对象:实现了方法 __iter__ 的对象(迭代器协议的基础). __ ...

随机推荐

  1. JS-nodejs--nodewebkit--npm穿墙cnpm

    npm install 本地安装与全局安装的区别 本地安装1. 将安装包放在 ./node_modules 下(运行npm时所在的目录)2. 可以通过 require() 来引入本地安装的包 全局安装 ...

  2. 数字货币量化教程——使用itertools实现各种排列组合

    在量化数据处理中,经常使用itertools来完成数据的各种排列组合以寻找最优参数 一.数据准备 import itertools items = [1, 2, 3] ab = ['a', 'b'] ...

  3. 构建更好的客户端 JavaScript 应用

    你可能注意到了,最近的一段时间越来越多的Web应用有变复杂的趋势,重心从服务端慢慢向着客户端转移. 这是个正常的趋势么?我不知道.支持和反对者的讨论就像是在讨论复活者和圣诞节哪一个更好一样; 很难说哪 ...

  4. oracle(四) 常用语句

    1.分页 select t2.* from (select rownum row, t1.*  from your_table where rownum < ?) t2 where t2.row ...

  5. InnoSQL HA Suite的实现原理与配置说明 InnoSQL的VSR功能Virtual Sync Replication MySQL 5.5版本引入了半同步复制(semi-sync replicaiton)的功能 MySQL 5.6支持了crash safe功能

    InnoSQL HA Suite的实现原理与配置说明  InnoSQL的VSR功能Virtual Sync Replication MySQL 5.5版本引入了半同步复制(semi-sync repl ...

  6. 安恒X计划12月月赛

    ezweb 主要是序列化问题.没有PHP环境,在线运行的.实例化对象之后修改一下file.然后echo输出序列化的结果.不过下面有一个正则检查.数字前加一个+,影响了正则的匹配,但是对于序列化的还原没 ...

  7. [LeetCode] 122. Best Time to Buy and Sell Stock II_Easy tag: Dynamic Programming

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  8. 2018-2019-2 网络对抗技术 20165324 Exp4:恶意代码分析

    2018-2019-2 网络对抗技术 20165324 网络对抗技术 Exp4:恶意代码分析 课下实验: 实践目标 是监控你自己系统的运行状态,看有没有可疑的程序在运行. 是分析一个恶意软件,就分析E ...

  9. Jmeter接口自动化测试 (四)(持续构建)

    本文转载至http://www.cnblogs.com/chengtch/p/6145867.html  Jmeter是压力测试.接口测试工具,Ant是基于Java的构建工具,具有跨平台的作用,jen ...

  10. matlab中的containers.Map()

    matlab中的containers.Map() 标签: matlabcontainers.Map容器map 2015-10-27 12:45 1517人阅读 评论(1) 收藏 举报  分类: Mat ...