前言:本节主要讲解迭代器和生成器

迭代器&生成器

一、生成器(generator)

循环占用大部分的容量内存,如果只需要循环前面的几个结果那怎么样做呢,在python中有一种一边循环一边计算的机制,称为生成器:generator,就能解决这个问题。

生成器只有在调用的时候才会产生相应的数据,用__next()__方法调用(2.7版本里是next()),生成器只能记录当前的位置,不能后退也不能记录以后的数据。

实例:斐波那契数列中的生成器

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:qinjiaxi
def fib(max):
n, a, b = 0, 0, 1#初始化
while n < max:#循环
yield b
#print(b)#打印b
a, b = b, a + b
n += 1
return "done"#异常的时候打印的消息 #抓异常
g = fib(6)
while True:
try:
x = next(g)
print("g:", x)
except StopIteration as e:
print("Generator return value:", e.value)
break
#调用生成器
f = fib(10)
print(f)#打印生成器对象的内存地址
print(next(f))#取第一个值
print(f.__next__())#取第二个值
print(next(f))#取第三个值
print("---start loop---")
for i in f:#循环取剩下的数据
print(i)
#注:当用next()方法调用次数超过设定值时,会产生异常 #理解其中的a, b = b, a + b
t = (b, a + b)#实际有个临时变量t,t是一个元组
a = t[0]
b = t[1]
#t不会显式的出现在代码中

生成器实际工作中的应用:协程(单线程并行处理),异步io处理

yeild作用是保存当前状态并返回,无返回值(返回值是None)

next方法调用yield,send方法调用yield并给yield传值,yield后面加上一个变量,可以返回变量

协程1源码:

 #!/user/bin/env python
#-*-coding:utf-8 -*-
#Author: qinjiaxi
import time
def consumer(name):
print("%s准备吃包子了" % name)
while True:
baozi = yield
print("包子[%s]被%s吃了" % (baozi, name)) c = consumer('ql')
#next(c)#停在yield位置(中断,返回迭代值)
#c.__next__()#从yield下一句开始执行,由于默认没有给yield传递参数所以返回的是None,执行完后又回到yield这一行
#c.__next__()
#c.send("韭菜馅的")#send方法可以调用yield并且给yield传送参数 def producer(name):
c = consumer('A')
c1 = consumer('B')
c.__next__()#A准备吃包子了
c1.__next__()#B准备吃包子了
print("%s开始做包子了" % name)
for i in range(10):
time.sleep(1)
print("做了一个包子分两半")
c.send(i)#传递i到A的yield,给A的yield赋值
c1.send(i)#传递i到B的yield,给B的yield赋值
producer('qinlang')

协程2源码:

 #!/user/bin/env python
#-*-coding:utf-8 -*-
#Author: qinjiaxi
import time
def consumer():
r = ''#初始化r
while True:
n = yield r#将值传给n,然后执行下一句,碰到r变量再返还r给producer函数
print("[consumer] is consuming %s " % n)
r = '200 is ok' def producer(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
time.sleep(1)
print("[producer] is producting %s" % n)
r = c.send(n)
print("[producer] cousumer return %s" % r)
# for i in range(6):
# time.sleep(1)
# print('[producer] is producing %s ' % i)
# r = c.send(i)#传n值给生成器yield
# print('[producer] consumer return %s' % r)
c.close()#关闭生成器
c = consumer()
producer(c)

结论:

一个带有yield的函数就是一个generator,它和普通函数不一样,生成器generator看起来像函数,其实不会执行任何函数代码,直到对其调用next()方法(在for循环中会自动调用next()方法)才会执行。虽然执行仍然像函数一样执行,其实当执行到yield时候就会中断并返回一个迭代值,当再次调用next()方法时从yield下一句开始执行。看起来就好像一个函数在正常执行的时候被yield中断了数次,每次中断都会通过yield返回迭代值。

二、迭代器(Iterator)

我们知道能直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如list、tuple、str、set、dict

一类是generator,包括生成器和带yield的generator function

*这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

可以使用isinstance()来判断一个对象是否是iterable对象:

 >>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance((i for i in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

生成器不但可以作用于for循环,还可以被next()函数不断的调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值。

*可以被next()函数调用并且不断返回下一个值的对象称为迭代器:Iterator

可以使用isinstance()来判断一个对象是否是interator对象:

 >>> from collections import Iterator
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance((i for i in range(10)), Iterator)
True

由上可知生成器都是Iterator对象,但list、dict、str虽然是Iterable但不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

 >>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
>>> isinstance(iter({}), Iterator)
True

为什么list、dict、str等数据不是Iterator?

因为python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断的返回下一个数据,直到没有数据时抛出StopIteration错误。可以把数据流看做是一个有序序列,但是我们提前并不知道序列的长度,只有通过next()函数按需继续下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据的时候才计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。但是list是永远不可能村粗全体自然数的。

小结:

凡是可作用于for循环的对象都是Iterable类型(可迭代类型);

凡是可以作用于next()函数的对象都是Iterator类型(迭代器类型),它们表示一个惰性的计算序列;

集合数据类型例如list、dict、str等都是Iterable(可迭代对象)但不是Iterator(迭代器),可以通过iter()函数获得一个迭代对象。

Python的for循环的本质就是不断的通过调用next()函数实现的。

python3.0中range(10)其实是一个迭代器

python2.x中xrange(10)是迭代器

ql的python学习之路-day10的更多相关文章

  1. ql的python学习之路-day15

    前言:本节主要讲解的是文件路径 在实际的软件开发中会设计一个项目的文件目录,按照执行包bin.配置包config.核心包core等来设计,在执行包里面要运行核心包里的主程序mian,由于不在同一级的目 ...

  2. ql的python学习之路-day14

    前言:本节主要学习时间模块time.datetime python中的几种时间表示:1)时间戳  2)格式化的字符串时间 3)struct_time元组格式的时间 time.datetime模块源码: ...

  3. ql的python学习之路-day13

    前言:本节主要学习模块 一.模块的定义 模块:本质是.py结尾的python文件(文件名:test.py,对应的模块是:test),用来从逻辑上组织python代码(变量.函数.类.逻辑,本质是实现一 ...

  4. ql的python学习之路-day12

    前言:这一节主要学习json和pickle 背景: 相信大家在日常生活中都有接触大型的网络游戏,打游戏的时候都是自己在电脑上操作,自己刷怪升级:当然也会碰到中午去吃饭然后挂机的情况,让电脑自动的刷怪, ...

  5. ql的python学习之路-day11

    前言:本节主要学习python内置的方法 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:qinjiaxi from collections ...

  6. ql的python学习之路-day9

    前言:本节主要学习装饰器 一.装饰器 定义:本质上是个函数,用来装饰其他函数:(就是为其他函数添加附加功能) 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 以上两点可以总 ...

  7. ql的python学习之路-day8

    前言:本节主要学习的是函数的全局变量和局部变量以及递归 一.全局变量和局部变量 定义在函数外并且在函数头部的变量,叫做全局变量,全局变量在整个代码中都生效. 局部变量只在函数里生效,这个函数就叫做这个 ...

  8. ql的python学习之路-day7

    函数与函数式编程 一.编程模式分为三种: 1.面向对象编程:类----->关键字class 2.面向过程编程:过程----->关键字def,没有return 3.函数式编程:函数----- ...

  9. ql的python学习之路-day6

    字节编码: 这一节主要学习的是各种编码模式的相互转换,另外插两句话,今天的心情不是特别好,又没控制好自己的情绪,以后要心存阳光,好好的对待生活和身边的人. 废话不多说了直接贴码: #!/usr/bin ...

随机推荐

  1. XSS Cheat Sheet(basics and advanced)

    XSS Cheat Sheet BASICS HTML注入 当输入位于HTML标记的属性值内或标记的外部(下一种情况中描述的标记除外)时使用.如果输入在HTML注释中,则在payload前加上&quo ...

  2. 0day堆(1)堆的管理策略

    基本概念 堆块:堆区内存的基本单位 包括两个部分:块首,块身 块首:标识这个堆块自身的信息:如大小,是否被占用等 块身:分配给用户使用的数据区 堆表:一般位于堆区的起始位置,用于索引堆区所有堆块的信息 ...

  3. LaTex中文article模板(支持代码、数学、TikZ)

    代码 请使用XeLatex编译 main.tex \documentclass{article} \usepackage{ctex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...

  4. CSS样式1

    编写CSS样式: 1.标签的style属性 如:<div style="width:980px;"></div> 2.写在head里面,style标签中写样 ...

  5. mysql备份及恢复

    第四章:MySQL数据库的备份与恢复                            2016-09-30 00:58:05 标签:数据库备份 工作原理 数据库表 mysql source 原创 ...

  6. Codeforces Round #530 (Div. 1) 1098A Sum in the tree

    A. Sum in the tree Mitya has a rooted tree with nn vertices indexed from 11 to nn, where the root ha ...

  7. PyCharm 集成 SVN,检出、提交代码

    1.安装 SVN,解决 SVN 目录中没有 svn.exe 问题 重新打开 TortoiseSVN 安装文件 选择 Modify 后在command line client tools 选项修改为 W ...

  8. 数据库SQL---实体-联系模型(E-R模型)

    1.E-R模型的基本概念与表示 1)实体与实体集 (1)实体:可以是有形的.实在的事物(如每个员工),可以是抽象的.概念上存在的事物(如一个部门). (2)实体的特征:独立存在.可区别于其他实体. ( ...

  9. uiautomatorviewer 出现安卓8.0级以上无法打开的解决方法

    一..本人在使用Android自带的uiautomatorviewer工具来进行app元素定位时,出现了Android 9.0打开不了.出现了如下图错误提示: 经过网上的查阅,总结了几个解决的方法. ...

  10. 将A页面提交的数据id传递到B页面

    A页面 在A页面跳转到B页面的时候,在url后面可以拼接参数 例如: window.location.href = './B.html?' + id; 跳转到B页面之后,可以通过url地址获取到从A页 ...