列表,元组,字典,集合,字符串,文件都为迭代器
迭代:每次重复的过程成为迭代的过程,每次迭代得到的结果,回作为下次迭代的初始值
迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器
它只是实现了__next__()方法的对象,并不是容器
相关函数
Iter()(iteration)
next()
迭代器魔法方法:
__iter__() 返回对象本身:self
__next_()
1如何判断一个容器是否有迭代功能?
查看该容器是否具有__next__()和__iter__()
2 for语句如何判断迭器里面已经取空了?
迭代器每次通过__next__()方法返回一个元素,并指向下一个元素,如果当前位置已无元素,通过抛出StopIteration异常表示
3 python原生数据结构中,只有集合只能用迭代器进行访问 。
生成器是一个特殊的迭代器
生成器的出现使python模仿协同程序的概念能够实现
协同程序:可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始
注解:
1.如果函数中出现yield时,则这个函数被定义成生成器
2.yield 相当与函数中的return语句,不同的时候,yield是被暂停,程序能继续进行执行
注意:
1生成器都是Iterator对象,但list、dict、str虽然是Iterable(可迭代对象),却不是Iterator(迭代器)。
2以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list,tuple,dict,set,str等
一类是generator,包括生成器和带yield的generator function
统称为可迭代对象:Iterable
3为什么list、dict、str等数据类型不是Iterator
这是因为Python的Iterator
对象表示的是一个数据流,Iterator对象可以被next()
函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration
错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()
函数实现按需计算下一个数据,所以Iterator
的计算是惰性的,只有在需要返回下一个数据时它才会计算。
4判断一个对象是否是可迭代,迭代器
from collections import Iterator #迭代器
from collections import Iterable #可迭代对象
print(isinstance(s,Iterator)) #判断是不是迭代器
print(isinstance(s,Iterable)) #判断是不是可迭代对象
5可迭代对象通过iter转成迭代器对象
6
补充:
7 send()和next()的区别就在于send可传递参数给yield表达式,这时候传递的参数就会作为yield表达式的值,而yield的参数是返回给调用者的值,也就是说send可以强行修改上一个yield表达式值。
8 send()和next()都有返回值,他们的返回值是当前迭代遇到的yield的时候,yield后面表达式的值,其实就是当前迭代yield后面的参数。
9 第一次调用时候必须先next()后send(),否则会报错,send后之所以为None是因为这时候没有上一个yield,所以也可以认为next()等同于send(None),(send是给上一个yield复制对象进行复制)
10不管是send还是next都是跑到下一个yield进行操作,并把yield之后的值返回来
EG1:
def A():
x = yield "这是第一次yield"
print("第一个yield和第二个yield之间,第一个x是:{}".format(x))
x = yield "这是第二次yield"
print("第二个yield和第三个yield之间,第二个x是:{}".format(x))
x = yield "这是第三次yield"
a = A()
# print(a)
# print(type(a))
print(a.__next__())
print(a.__next__())
print(a.send("第一次使用send"))
实行结果:
这是第一次yield
第一个yield和第二个yield之间,第一个x是:None
这是第二次yield
第二个yield和第三个yield之间,第二个x是:第一次使用send
这是第三次yield
EG2:
# 利用yield求出指定数字开始,指定个数的素数
def is_p(number):
while True:
if number == 1:
number += 1
continue
elif number == 2:
yield number
number += 1
else:
number > 1
for i in range(2, number):
if not number % i:
number += 1
break
else:
yield number
number += 1
#第一个参数是指定开始数字,第二个参数是打印多少个参数
def get_p(number, count):
t = is_p(number)
for i in range(count):
print(t.__next__())
get_p(2, 10)
实行结果:
2
3
5
7
11
13
17
19
23
29
EG3:
# 题目:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。
sum = 0
def get_sum():
molecule = 2
denominator = 1
global sum
while True:
sum += molecule / denominator
yield sum
temp = denominator + molecule
molecule, denominator = temp, molecule
a = get_sum()
for i in range(20):
a.__next__()
print(sum)
实行结果:
32.66026079864164