1> 迭代器

	迭代的意思类似递归一般,不断地对一个对象做重复的操作。来看个例子:
    class Fibs:
def __init__(self):
self.last = self.now = 1
def __iter__(self): # __iter__定义用来返回一个包含__next_方法的对象。
return self
def __next__(self): # __next__定义返回迭代后的数据,并迭代到下一个
self.last, self.now = self.now, self.last + self.now
if self.last>10:
raise StopIteration #当没有任何元素时,__next__() 将产生StopIteration异常来告诉 for 语句停止迭代。
return self.last
>>> for i in Fibs():
print(i)
1
2
3
5
8
>>> a = Fibs()
>>> next(a)
1
>>> next(a)
2
>>> list(Fibs())
[1, 2, 3, 5, 8]
	准确的说,一个实现了__iter__方法的对象是可迭代的,一个实现了__next__方法的对象则是迭代器。
定义一个__iter__()方法返回一个具有 __next__() 的对象,如果这个类定义了 __next__() , 那么 __iter__() 仅需要返回 self:
通过这样的对__iter__方法和__next__方法的操作,我们完全可以实现个人的Range()的迭代器。
    >>> class Range:
def __init__(self, times):
self.count = 0
self.times = times
def __iter__(self):
return self
def __next__(self):
if self.count+1 > self.times:
raise StopIteration
self.count += 1
return self.count-1
>>> for i in Range(3):
print(i)
0
1
2

2> 生成器(generator)——用来创建迭代器的一个方便的工具

	简单来讲,通过yield能将函数变成生成器函数(generator),python解释器会将其视为generator,在运行的过程中,在每次遇到yield时函数暂停并保存函数所有当前运行信息,返回yield的值。并在下一次__next__方法时从当前位置继续运行。

	一个简单例子:
    >>> def rev():
yield 1
yield 2
>>> a = rev()
>>> next(a)
1
>>> next(a)
2
>>> next(a)
StopIteration # for会将StopIteration作为循环结束标志
	执行过程:
1. 调用生成器函数rev将返回一个生成器
2. 第一次调用__next__方法时,函数将在yield 1位置停止,并保存运行的位置及状态,返回1
3. 第二次调用__next__方法时,函数从yield 1位置开始运行,再次在yield 2位置停止,并保存运行位置及状态,返回2
4. 第三次调用__next__方法时,函数从yield 2位置开始执行,函数结束,不返回值,出现StopIteration错误 来看一个复杂点的例子:
    >>> def Reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for i in Reverse('golf'):
print(i, end='')
flog
>>> Reverse('golf')
<generator object Reverse at 0x0000000003EC2FC0>
>>> rev = Reverse('golf')
>>> next(rev)
'f'
>>> next(rev)
'l'
	对于上面中用for来遍历这个生成器来说,执行步骤大概是这样的:
1. 调用生成器函数将返回一个生成器
2. 第一次调用__next__方法时,生成器开始执行,直到遇到yield时暂停,保存生成器函数中的所有执行及状态(对于这个例子来说,生成器函数将会在while循环中暂停,并且保存while执行状态,在下次调用时从当前状态开始执行),并将yield的参数作为返回值。
3. 之后再调用__next__方法时,生成器将在上次暂停的地方继续执行。
4. 不断循环重复上述两步骤。
5. 当调用__next__方法生成器产生StopIteration异常时,for循环结束。 一个更复杂的例子:(利用递归将多重的列表展开)
    >>> def flat(s):
try:
try:
s+'' # 判断是否为字符串
except TypeError:
pass
else:
raise TypeError
for sub in s:
for element in flat(sub):
yield element
except TypeError: # 是字符串直接返回
yield s
>>> list(flat(['a',[['b'],['c']]]))
['a', 'b', 'c']
>>> list(flat([1,[[''],3]]))
[1, '', 3]
>>> list(flat([1,[[2],3]]))
[1, 2, 3]
>>> list(flat([['Sun', ['Moon']],'god']))
['Sun', 'Moon', 'god']

  

Python3 学习第六弹: 迭代器与生成器的更多相关文章

  1. python cookbook第三版学习笔记六:迭代器与生成器

    假如我们有一个列表 items=[1,2,3].我们要遍历这个列表我们会用下面的方式 For i in items:   Print i 首先介绍几个概念:容器,可迭代对象,迭代器 容器是一种存储数据 ...

  2. 前端学习 第六弹: javascript中的函数与闭包

    前端学习 第六弹:  javascript中的函数与闭包 当function里嵌套function时,内部的function可以访问外部function里的变量 function foo(x) {   ...

  3. Python3基础教程(十六)—— 迭代器、生成器、装饰器

    在这个实验里我们学习迭代器.生成器.装饰器有关知识. 这几个概念是 Python 中不容易理解透彻的概念,务必把所有的实验代码都完整的输入并理解清楚其中每一行的意思. 迭代器 Python 迭代器(I ...

  4. python_魔法方法(六):迭代器和生成器

    迭代器 自始至终,都有一个概念一直在用,但是我们却没来都没有人在的深入剖析它.这个概念就是迭代. 迭代的意思有点类似循环,每一次的重复的过程被称为迭代的过程,而每一次迭代得到的结果会被用来作为下一次迭 ...

  5. Python学习笔记 (4) :迭代器、生成器、装饰器、递归、正则表达式等

    迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大优点是 ...

  6. python学习笔记之八:迭代器和生成器

    一. 迭代器 在前面的笔记中,已经提到过迭代器(和可迭代),这里会对此进行深入讨论.只讨论一个特殊方法---__iter__,这个方法是迭代器规则的基础. 1.1 迭代器规则 迭代的意思是重复做一些事 ...

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

    生成器 如果创建一个有很多元素的列表,但是只需要访问前几个元素,后面的元素占着的空间就白白浪费了 在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间. 在Pytho ...

  8. Python3 学习第五弹:类与面向对象

    对于面向对象总是要提到,万物皆对象.好似博大精深的感觉. 接下来一起看看python的面向对象的例子 创建一个对象 class Person: type = 'person' def __init__ ...

  9. Python3 学习第四弹:编码问题(转载)

    关于python的编码问题一直以来不得解,终于在今天从这篇博文中明白了. 原文地址: http://nedbatchelder.com/text/unipain.html 译文地址:http://py ...

随机推荐

  1. 拆分Sql列中内容的拆分

    拆分Sql列中内容的拆分. /*按照符号分割字符串*/ create function [dbo].[m_split](@c varchar(2000),@split varchar(2)) retu ...

  2. HDOJ 3183 A Magic Lamp

    A Magic Lamp Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  3. 使用命令行编译、打包、运行WordCount--不用eclipse

    1)首先创建WordCount1023文件夹,然后在此目录下使用编辑器,例如vim编写WordCount源文件,并保存为WordCount.java文件 /** * Licensed under th ...

  4. 游戏引擎网络开发者的64做与不做(二A):协议与API

    [编者按]在这个系列之前的文章"游戏引擎网络开发者的64做与不做(一):客户端方面"中,Sergey介绍了游戏引擎添加网络支持时在客户端方面的注意点.本文,Sergey则将结合实战 ...

  5. POJ 1006 Biorhythms (中国剩余定理)

    在POJ上有译文(原文右上角),选择语言:简体中文 求解同余方程组:x=ai(mod mi) i=1~r, m1,m2,...,mr互质利用中国剩余定理令M=m1*m2*...*mr,Mi=M/mi因 ...

  6. HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)

    做这道题之前,建议先做POJ 1151  Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...

  7. .NET Framework 框架简述01

    NET技术可以以规范和实现两部分来划分.   规范:   公共语言架构(Common Language Infrastructure, CLI),主要包括 1.通用类型系统(Common Type S ...

  8. C#中的 序列化和反序列化

    什么是序列化和反序列化? 序列化就是把一个对象保存到一个文件或数据库字段中去,反序列化就是在适当的时候把这个文件再转化成原来的对象使用. 我想最主要的作用有: 1.在进程下次启动时读取上次保存的对象的 ...

  9. 14.spark RDD解密

    开篇:spark各种库,sparksql,sparkmachicelearning,等这么多库底层都是封装的RDD.意味着 1:RDD本身提供了通用的抽象, 2:spark现在有5个子框架,sql,S ...

  10. Linux zip解压/压缩并指定目录

    方法如下: 压缩并指定目录举例:zip -r /home/kms/kms.zip /home/kms/server/kms 解压并指定目录 举例:unzip /home/kms/kms.zip -d ...