python基础—迭代器、生成器
python基础—迭代器、生成器
1 迭代器定义
迭代的意思是重复做一些事很多次,就像在循环中做的那样。
只要该对象可以实现__iter__方法,就可以进行迭代。
迭代对象调用__iter__方法会返回一个迭代器,所谓的迭代器就是具有next方法的对象。(在调用next方法时不需要任何参数)。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopITeration异常。
一个实现了__iter__方法的对象是可迭代的,一个实现了next方法的对象是迭代器。
迭代器也有__iter__方法。
2 迭代器特性
优点:
1 迭代器提供了一种不依赖索引的取值方式,这样就可以遍历那些没有索引的可迭代对象了(字典,集合,文件)
2 迭代器与列表比较,迭代器是惰性计算的,更节省内存
缺点:
1 无法获取迭代器的长度,使用不如列表索引取值灵活
2 一次性的,只能往后取值,不能倒着取值
迭代规则的关键是?为什么不是使用列表?
1 如果有一个函数,可以一个接一个地计算值,那么在使用时可能是计算一个值时获取一个值,而不是像列表一样获取所有的值。如果有很多值,列表会占用太多的内存。
2 使用迭代器更通用,更简单,更优雅
3 迭代器代码
(1)索引方式循环
l=['a','b','c','d']
i=0
while i<len(l):
print(l[i])
i+=1
for i in range(len(l)):
print(l[i])
(2)只要被内置了__iter__方法就是可迭代对象
可迭代的:只要对象本身有__iter__方法,那他就是可迭代的
l=['a','b','c','d']
l.__iter__() #相当于iter(l)
iter(l)
i=iter(l)
i 就是迭代器,i 就是列表l的迭代器
(3)迭代器的__next__方法
迭代器使用__next__方法,可以不依赖下标取值,超出字典长度会有结束报错。
调用__next__方法必须是迭代器,也只有迭代器才有__next__方法。
l=['a','b','c','d']
i=iter(l)
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
输出结果:
a
b
c
d
StopIteration #报错
(4)while循环与迭代器
d={'a':1,'b':2,'c':3,'d':4}
i=iter(d)
while True:
try:
print(next(i))
except StopIteration:
break
输出结果:
b
c
a
d

(5)for循环与迭代器
在这里for就是使用可迭代对象的__iter__方法返回此可迭代对象的迭代器,并且执行此迭代器的next方法,并且出现StopITeration报错就结束
For循环与列表
d={'a':1,'b':2,'c':3,'d':4}
for i in d:
print(i)
For循环与文件
with open('a.txt','r') as f:
for line in f:
print(line.strip())
(6)迭代器也有__iter__方法
f 的迭代器也有__iter__方法,并且指向f这个迭代器本身

(7)迭代器是一次性的
只能往后取值,不能倒着取值
可迭代对象不是一次性的。
d={'a':1,'b':2,'c':3,'d':4}
i=iter(d)
print(next(i))
print(next(i))
print(next(i))
print(next(i))
for x in i: #迭代器i已经将上面的值取完,for循环在这里没有值可取
print(x)
输出结果:
d
a
b
c
(8)isinstance判断对象是否是可迭代对象和迭代器对象
Isinstance使用例子:
print(type('ssssss') is str)
print(isinstance("ssssss",str))
输出结果:
True
True
用isinstance判断是不是可迭代对象与迭代器对象
#查看可迭代对象和迭代器对象
from collections import Iterable,Iterator
str1='hello'
list1=[1,2,3]
tuple1=(1,2,3)
dict1={"a":1,"b":2,"c":3}
set1={1,2,3,4}
f1=open('a.txt')
#都是可迭代的
str1.__iter__()
list1.__iter__()
tuple1.__iter__()
dict1.__iter__()
set1.__iter__()
f1.__iter__()
print(isinstance(str1,Iterable)) #True
print(isinstance(list1,Iterable)) #True
print(isinstance(tuple1,Iterable)) #True
print(isinstance(dict1,Iterable)) #True
print(isinstance(set1,Iterable)) #True
print(isinstance(f1,Iterable)) #True
#查看是否是迭代器
print(isinstance(str1,Iterator)) #False
print(isinstance(list1,Iterator)) #Flase
print(isinstance(tuple1,Iterator)) #Flase
print(isinstance(dict1,Iterator)) #Flase
print(isinstance(set1,Iterator)) #Flase
print(isinstance(f1,Iterator)) #Flase
4、生成器
4.1 生成器函数定义
生成器就是一个函数,这个函数内包含有yield这个关键字
返回一个生成器对象。生成器本质就是迭代器
生成器是一个包含yield关键字的函数。当它被调用时,在函数体中的代码不会被执行,而会返回一个迭代器。每次请求一个值,就会请求生成器中的代码,直到遇到一个yield或者return语句。Yield语句意味着生成一个值。Return语句意味着生成器要停止执行。
生成器是由两部分组成的:生成器的函数和生成器的迭代器。生成器的函数是有def语句定义的,包含yield部分。生成器的迭代器是这个函数返回的部分。生成器函数返回的迭代器可以像其他迭代器那样使用。
4.2 yield作用
生成器与return有何区别?
Return只能返回一次函数就彻底结束了,而yield返回多次值
yield到底干了什么事情?
1 yield把函数变成生成器-,生成器实质就是迭代器。 相当于把__iter__和__next__方法封装到函数内部。
2 用return返回值能返回一次,而yield返回多次
3 函数在暂停以及继续下一次运行时的状态是由yield保存
任何包含yield语句的函数称为生成器。Yield不是像return那样返回值,而是每次产生多个值。生成器每次产生一个值(使用yield语句),函数就会被冻结:即函数停在那点等待被重新唤醒。函数被重新唤醒之后就从停止的那点开始。
4.3 生成器运行详解
Test函数中yield返回给g一个生成器,实质就是迭代器,通过next方法取值,并且在取值时会执行test函数和取yield的返回值。即next函数会触发生成器函数g的运行,遇到yield停止
from collections import Iterable,Iterator
def test():
print("first")
yield 1
g=test()
print(g)
print(next(g))
print(isinstance(g,Iterable))
print(isinstance(g,Iterator))
输出结果:
<generator object test at 0x000000E8CBDE5360>
first
1
True
True
def test():
print("one")
yield 1
print("two")
yield 2
print("three")
yield 3
g=test()
res=next(g)
print(res)
res=next(g)
print(res)
res=next(g)
print(res)
res=next(g)
print(res)
输出结果:
one
1
two
2
three
3
StopIteration #报错
def test():
print("one")
yield 1
print("two")
yield 2
print("three")
yield 3
g=test()
for i in g:
print(i)
输出结果:
one
1
two
2
three
3
一个yield可以返回多个值,接收的类型是元组
yield可以返会任何类型的值
def test():
yield 1,2,3,4
g=test()
print(next(g))
输出结果:
(1,2,3,4)
生成器与return有何区别?
Return只能返回一次函数就彻底结束了,而yield返回多次值
yield到底干了什么事情?
1 yield把函数变成生成器--->迭代器
2 用return返回值能返回一次,而yield返回多次
3 函数在暂停以及继续下一次运行时的状态是由yield保存
例子:
def countdown(n):
print("start countnum")
while n>0:
yield n
n-=1
print('done')
g=countdown(5)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
try:
print(next(g)) #这一次next函数应用没有yield返回,会报错StopIteration,需要try检测
except StopIteration:
pass
g=countdown(5)
print(next(g))
for i in g: #for会将g变成迭代器:iter(g),执行next取值,并捕捉next出现的异常
print(i)
输出结果:
start countnum
5
4
3
2
1
done
start countnum
5
4
3
2
1
done
4.4 用生成器模拟管道
tailf命令的实现
1 普通函数实现
#/usr/bin/env python
import time
def tail(file_path):
with open(file_path,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if not line:
time.sleep(0.3)
continue
else:
print(line,end="") tail("/tmp/a.txt")
2 生成器函数实现
#/usr/bin/env python
import time
def tail(file_path):
with open(file_path,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if not line:
time.sleep(0.3)
continue
else:
yield line
g=tail("/tmp/a.txt")
print(g)
for line in g:
print(line)
tail -f |grep “error” 实现
#/usr/bin/env python
import time
#定义阶段:定义两个生成器函数
def tail(file_path):
with open(file_path,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if not line:
time.sleep(0.3)
continue
else:
yield line
def grep(pattern,lines):
for line in lines:
if pattern in line:
yield line
#调用阶段:得到两生成器对象
g=tail("/tmp/a.txt")
gg=grep("error",g)
#next触发执行gg生成器函数
for line in gg:
print(line)
1 迭代器的应用
文件名:a.txt 文件内容如下:
apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3
实现功能:cat a.txt|grep apple
要求1:定义迭代器函数cat
要求2:定义迭代器函数grep
要求3:模拟管道的功能,将cat的处理结果作为grep的输入
def cat(file_auth):
with open(file_auth,"r") as f:
f.seek(0)
for line in f:
yield line
def grep(pattern,lines):
for line in lines:
if pattern in line:
yield line
cat_func=cat("/tmp/a.txt")
grep_func=grep("apple",cat_func)
for line in grep_func:
print(line)
5、协程函数
5.1 协程函数定义
如果在一个函数内部yield的使用方式是表达式形式的话,如x=yield,那么该函数成为协程函数。
yield是表达式方式使用,则必须用send方法进行传值。
协程函数=生成器+yield表达式+send方法
5.2 e.send与next(e)的区别
e.send与next(e)的区别
1 如果函数内yield是表达式形式,那么必须先next(e)
使用send方法只有在生成器挂起之后才有意义(也就是在yield函数第一次被执行之后),因此要用send方式时需要用next方法初始化生成器。
用next(e)初始化 相当于 e.send(None) ,可以用装饰器解决初始化问题
2 二者的共同之处是都可以让函数在上次暂停的位置继续运行,不一样的地方在于send在触发下一次代码的执行时,会顺便给yield传一个值。
end可以传多个值,但是必须是元组类型

5.3协程函数举例
def eater(name):
print("%s start to eat food"%name)
while True:
food=yield
print("%s get %s,to start eat"%(name,food))
print("done")
e=eater("people")
print(e)
next(e)
e.send("apple")
e.send("fruit")
e.send("beef")
e.send("meet")
输出结果:
<generator object eater at 0x000000F944583D00>
people start to eat food
people get apple,to start eat
people get fruit,to start eat
people get beef,to start eat
people get meet,to start eat
def eater(name):
print("%s start to eat food"%name)
food_list=[]
while True:
food=yield food_list
print("%s get %s,to start eat"%(name,food))
food_list.append(food)
print("done")
e=eater("people")
print(e)
next(e) print(e.send("apple"))
print(e.send("fruit"))
print(e.send("beef"))
print(e.send("meet"))
输出结果:
<generator object eater at 0x0000006F92D83D00>
people start to eat food
people get apple,to start eat
['apple']
people get fruit,to start eat
['apple', 'fruit']
people get beef,to start eat
['apple', 'fruit', 'beef']
people get meet,to start eat
['apple', 'fruit', 'beef', 'meet']
2 生成器的应用
把下述函数改成生成器的形式,执行生成器函数的到一个生成器g,
然后g.send(url),打印页面的内容,利用g可以无限send
from urllib.request import urlopen
def get(url):
while True:
def index():
print(url)
print(urlopen(url).read())
url=yield index g=get("http://www.baidu.com")
next(g)
baidu=g.send("http://www.baidu.com")
baidu()

5.4 协程函数用装饰器初始化
协程函数使用装饰器完成初始化
def auth(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
next(res)
return res
return wrapper
@auth
def eater(name):
print("%s start to eat food"%name)
food_list=[]
while True:
food=yield food_list
print("%s get %s,to start eat"%(name,food))
food_list.append(food)
print("done") e=eater("people")
e.send("123")

python基础—迭代器、生成器的更多相关文章
- Python基础-迭代器&生成器&装饰器
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
- python基础——迭代器
python基础——迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器 ...
- 十三. Python基础(13)--生成器进阶
十三. Python基础(13)--生成器进阶 1 ● send()方法 generator.send(value) Resumes the execution, and "sends&qu ...
- 十二. Python基础(12)--生成器
十二. Python基础(12)--生成器 1 ● 可迭代对象(iterable) An object capable of returning its members one at a time. ...
- python函数-迭代器&生成器
python函数-迭代器&生成器 一.迭代器 1 可迭代协议 迭代:就是类似for循环,将某个数据集内的数据可以“一个挨着一个取出来” 可迭代协议: ① 协议内容:内部实现__iter__方法 ...
- python基础--迭代器、生成器
(1)迭代器 可迭代对象和迭代器的解释如下: ''' 什么是对象?Python中一切皆对象,之前我们讲过的一个变量,一个列表,一个字符串,文件句柄,函数名等等都可称作一个对象,其实一个对象就是一个实例 ...
- 【python】迭代器&生成器
源Link:http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素 ...
- python基础-迭代器和生成器
一.递归和迭代 1.递归:(问路示例) 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 2.迭代:简单理 ...
- python基础(八)生成器,迭代器,装饰器,递归
生成器 在函数中使用yield关键字就会将一个普通的函数变成一个生成器(generator),普通的函数只能使用return来退出函数,而不执行return之后的代码.而生成器可以使用调用一个next ...
随机推荐
- Xcode9的xib只支持iOS7.0及以上版本
Xcode升级到9以后,对xib的最低编译版本有了限制,以前未指定版本的xib会报错,如下 遇到这个情况,根据错误提示很明显提示的是ib文件支持的最低版本是iOS7,所以我就将该xib的版本设为iOS ...
- es6学习笔记--新数据结构Set,Map以及WeakSet,WeakMap
在javascript中,存储数据的方式大部分就是以数组或者对象形式存储的,es6出现了4种新集合Set,Map,WeakSet,WeakMap来存储数据,简化了编程. 集合--Set 类似于数组,但 ...
- IMLite轻量级即时通信工具开发指南
花了一周时间开发了一个简单的即时通信工具,勉强算是程序原型.现在我把开发流程和一些个人的想法记录下来.本文首先介绍程序架构和通信接口,之后会聚焦到服务器的信号槽设计原则,接下来将解释有关TCP通信的粘 ...
- python 一篇就能理解函数基础
一,函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过 ...
- Java注解学习笔记
我们平常写Java代码,对其中的注解并不是很陌生,比如说写继承关系的时候经常用到@Override来修饰方法.但是@Override是用来做什么的,为什么写继承方法的时候要加上它,不加行不行.如果对J ...
- docker环境下使用xdebug进行断点调试
最近把本地环境切换成了docker的环境,便于快速运行和开发,确实比较给力,但是也遇到了问题,以前的本地xdebug断点调试都用不了,弄了几个小时终于搞定了 docker还是坑多,绕,下面把docke ...
- 新手立体四子棋AI教程(3)——极值搜索与Alpha-Beta剪枝
上一篇我们讲了评估函数,这一篇我们来讲讲立体四子棋的搜索函数. 一.极值搜索 极值搜索是game playing领域里非常经典的算法,它使用深度优先搜索(因为限制最大层数,所以也可以称为迭代加深搜索) ...
- 利用CSS3制作网页动画
如何在网页中实现动画效果动态图片 flashjavascriptcss3变形是一些效果的集合如平移 旋转 缩放 倾斜效果每个效果都可以称为变形(transfrom) 它们可以分别操控元素发生平移.旋转 ...
- IDEA的快捷键的使用
1.配置Intellij Idea的配置文件从默认c盘转移到其他盘符 找到Intellij idea的安装文件,在bin目录下找到idea.properties配置文件,如下把Idea的配置文件夹和I ...
- JS常见操作,日期操作,字符串操作,表单验证等
复制代码 //第一篇博文,希望大家多多支持 /***** BasePage.js 公共的 脚本文件 部分方法需引用jquery库 *****/ //#region 日期操作 //字符串转化为时间. f ...