Python迭代器和生成器

迭代器:

列表,元组,字典,集合,字符串,文件都为迭代器

迭代:每次重复的过程成为迭代的过程,每次迭代得到的结果,回作为下次迭代的初始值
迭代器:可以被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

补充:

  • 凡是可作用于for循环的对象都是Iterable类型;
  • 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
  • 集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

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

你可能感兴趣的:(python)