生成器(constructor)

  生成器函数在Python中与迭代器协议的概念联系在一起。包含yield语句的函数会被特地编译成生成器 !!!

  当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。

  不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效

创建生成器方式有两种:

方法一:

s = ( x for x in range(5) )

方法二:

def foo():
print('OK')
yield 1

例子:

def g(n):
for i in range(n):
yield i **2 for i in g(5):
print(i)

要了解他的运行原理,我们来用next方法看看:

t = g(5)
print(t.__next__()) # 0
print(t.__next__()) # 1
print(t.__next__()) # 4
print(t.__next__()) # 9
print(t.__next__()) # 16
print(t.__next__()) Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

在运行完5次next之后,生成器抛出了一个StopIteration异常,迭代终止。

send(msg) 与 next()

了解了next()如何让包含yield的函数执行后,我们再来看另外一个非常重要的函数send(msg)。

其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做

c.next() 和 c.send(None) 作用是一样的。

def g(n):
for i in range(n):
ret = yield i **2
print(ret) t = g(5)
print(t.__next__())
print(t.send('Hello')) # 0 Hello 1

需要注意的是,第一次调用时,请使用next()语句或是send(None),不能使用send发送一个非None的值,否则会出错的,因为没有yield语句来接收这个值。

send(msg) 和 next()是有返回值的,它们的返回值很特殊,返回的是yield表达式的参数 !

执行顺序是:遇到yield 先返回值,等下次再进入时再用 msg 进行赋值!!!

再来看一个yield的例子,用生成器生成一个Fibonacci数列:

def fab(max):
a, b = 0, 1
while a < max:
yield a
a, b = b, a + b for i in fab(20):
print(i) # 0 1 1 2 3 5 8 13

另一个 yield 的例子来源于文件读取。

 def read_file(fpath):
BLOCK_SIZE = 1024
with open(fpath, 'rb') as f:
while True:
block = f.read(BLOCK_SIZE)
if block:
yield block
else:
return

  

迭代器(iterator)

  for循环可以用于Python中的任何类型,包括列表、元组等等,实际上,for循环可用于任何“可迭代对象”!

  迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。

  任何这类的对象在Python中都可以用for循环或其他遍历工具迭代,迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开。

  使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。

注意

  判断迭代器的条件是:

  1. 有__iter__ 方法

  2. 有__next__ 方法

  所有的生成器都是迭代器!

迭代器例子:

比如要逐行读取一个文件的内容,利用readlines()方法,我们可以这么写:

for line in open("test.txt").readlines():
print (line)

这样虽然可以工作,但不是最好的方法。因为他实际上是把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了。

利用file的迭代器,我们可以这样写:

for line in open("test.txt"):
print (line)

这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行。

for 循环实质

  1. 调用 __iter__ 方法将可迭代对象转换成迭代器

  2. 对迭代器对象不断调用 __next__ 方法

  3. 处理StopIteration 异常

class Fab(object):
def __init__(self, max):
self.max = max
self.n, self.a, self.b = 0, 0, 1 def __iter__(self):
return self def __next__(self):
if self.n < self.max:
r = self.b
self.a, self.b = self.b, self.a + self.b
self.n = self.n + 1
return r
raise StopIteration() '''
>>> for key in Fabs(5):
print key 1
1
2
3
5
'''

可迭代对象(iterable)

  判断条件:内部具有 __iter__ 方法

from collections import Iterable,Iterator
print(isinstance(range(1),Iterable))
print(isinstance(range(1),Iterator)) print(isinstance(list(),Iterable))
print(isinstance(list(),Iterator))

  

【Python之路】特别篇--生成器(constructor)、迭代器(iterator)、可迭代对象(iterable)的更多相关文章

  1. Python的容器、生成器、迭代器、可迭代对象的家谱

    前言 之前虽然写Python,但是对Python的这些概念也是模模糊糊,知道有一天,看到了一篇文章,讲的透彻,所以就写这篇作为对于这篇高文的读书笔记吧 致谢,该文作者,完全理解Python迭代对象.迭 ...

  2. python的生成器与迭代器和可迭代对象

    来简单的说下python中的生成器和可迭代对象以及迭代器的问题.只是简单地记录一下并不涉及太深入的内容. 首先来说一下什么是生成器,先看下面的代码: #_*_ coding:utf-8 _*_ res ...

  3. Python生成器、迭代器、可迭代对象

    把一个列表[]改成()就创建了一个生成器:generator,generator保存的是算法. 可以用于for循环的数据类型:1.集合类型:list tuple dict set str2.gener ...

  4. Python 生成器 (generator) & 迭代器 (iterator)

    python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...

  5. Python 第四篇:生成器、迭代器、装饰器、递归函数与正则表达式

    一:生成器:Generator,可以理解为是一种一个函数产生一个迭代器,而迭代器里面的数据是可以通过for循环获取的,那么这个函数就是一个生成器,即生成器是有函数生成的,创建生成器使用()表示,比如g ...

  6. python的语法小结之生成器和迭代器

    生成器: 首先介绍一下列表生成式:a=[x for x in range(10)]               >>>>>>[0, 1, 2, 3, 4, 5, 6 ...

  7. python基础-装饰器,生成器和迭代器

    学习内容 1.装饰器 2.生成器 3.迭代器 4.软件目录结构规范 一:装饰器(decorator) 1.装饰器定义:本质就是函数,用来装饰其他函数,即为其他函数添加附加功能. 2.装饰器原则:1)不 ...

  8. 搞清楚 Python 的迭代器、可迭代对象、生成器

    很多伙伴对 Python 的迭代器.可迭代对象.生成器这几个概念有点搞不清楚,我来说说我的理解,希望对需要的朋友有所帮助. 1 迭代器协议 迭代器协议是核心,搞懂了这个,上面的几个概念也就很好理解了. ...

  9. 『Python』列表生成式、生成器与迭代器

    1. 迭代 在 Python中, 迭代是通过 for ... in 来完成的, 而很多语言比如 C 语言, 迭代 list 是通过下标完成的. Python 的 for 循环抽象程度要高于 C 的 f ...

随机推荐

  1. Jenkins+SVN持续环境搭建

    需要三台不同环境的服务器,SVN.Jenkins.Tomcat 1.SVN搭建 1.Subversion服务器(SVN服务器) 2.项目对应的版本库 3.版本库中钩子程序(用于触发构建命令) 在我以前 ...

  2. 在使用selenium时出现FileNotFoundError: [WinError 2] 系统找不到指定的文件。

    今天在使用selenium出现这样的错: Traceback (most recent call last): File "E:\python\lib\site-packages\selen ...

  3. Python基础(九)--函数

    函数的作用 减少重复代码 程序易于维护 程序易于扩展 函数的定义 >>> def calculate(x,y): #定义函数名为calculate,参数为x和y result = x ...

  4. T100——r类 凭证报表 打印

    报表开发流程:1.建立入口程序 如r类的作业:cxmr500步骤: azzi900中建立程序代号 azzi910中建立作业代号 设计器--规格--签出 设计器--程序--签出 adzp168(r.a) ...

  5. 《深入实践C++模板编程》之五——容器与迭代器

    1.容器的定义 容器:专门用于某种形式组织及存储数据的类称为“容器”.   2.容器与迭代器 迭代器:封装了对容器虚拟数据序列的操作并按约定提供统一界面以遍历容器内容的代理类即为迭代器.   举例理解 ...

  6. C#文本_文件夹操作

    1我们常用的File类 可以用来对文件的一些操作 下面看代码. using System;using System.Collections.Generic;using System.IO;using ...

  7. B-Tree和 B+Tree的数据存储结构

    B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引.B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的.在讲B ...

  8. [Scala] java使用scala的jar包问题:Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Short

    场景 刚写的scala处理bmp文件的实验, 打了jar包让java调用一下, 结果发生这个错误. package org.tanglizi.bmp.demo; import org.tanglizi ...

  9. Delphi 10.3.2试用报告

    感谢朋友们,如此之快就发了注册机,209321818群里有下载,感兴趣可以去. 安装前,需要先卸载Delphi 10.3.1,然后就是正常的安装过程,非常顺利,现在差不多半小时就安装完成. 安装后,启 ...

  10. Ceph自动化部署----Ceph-ansible

    目录 Ceph自动化部署----Ceph-ansible 一.前言--Ceph的几种不同的部署方式 二.使用Ceph-ansible部署Ceph Ceph自动化部署----Ceph-ansible 一 ...