08-Python迭代器与生成器

迭代器

什么是迭代器
  • 迭代是Python最强大的功能之一,是访问序列中元素的一种方式。
  • 迭代器是一个可以记住遍历的位置的对象。
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
  • 迭代器有两个基本的方法:iter() 和 next()。
可迭代对象
  • 字符串、列表、元组对象等都是可迭代对象
  • 字符串、列表、元组对象等都可以创建迭代器

也就是说:

字符串、列表、元组对象等暂时不是迭代器,暂时不能被迭代。但是,它们成为迭代器之后就可以被迭代了,如for循环。

利用可迭代对象Iterable创建迭代器Iterator
l=[1,2,3,4]     #l:可迭代对象
i=iter(l)       #i:迭代器
print(next(i))     #输出1
print(next(i))     #输出2
print(i.__next__())     #输出3

解释:

  • iter()函数可以将可迭代对象创建为迭代器
  • 利用next函数可以得到下一个元素值
  • 迭代器能够记住遍历的位置,所以可以依次调用next()
  • 可迭代对象:Iterable
  • 迭代器:Iterator
  • 可迭代对象不能被迭代,不能调用next()。成为迭代器之后才可以。

注意:

遍历完毕后,若再次调用next()函数,则会抛出异常:StopIteration,处理此异常即可。

处理StopIteration异常
try:
    l=[1,2]
    i=iter(l)
    print(next(i))     #输出1
    print(next(i))     #输出2
    print(next(i))     #抛出异常
except StopIteration as stopIteration:
    print("遍历完成") 
刨析for循环

for循环实现了序列的遍历,那它怎么实现的呢?

for循环做的三件事:

  1. 创建迭代器
  2. 调用next方法
  3. 处理StopIteration异常

模拟for循环:

a=[100,200,300,400,500]
j=None
i=iter(a)   #1.创建迭代器
while(True):
    try:
        j=next(i)    #2.调用next方法
    except StopIteration as stopIteration:      #3.处理StopIteration异常
        break
    print(j)

结果:

100
200
300
400
500

生成器

什么是生成器?
  • 生成器是一种特殊的迭代器。
  • 普通的迭代器将所有数据存放在内存中,极其占用内存空间。
  • 生成器不将数据存入内存,而是通过计算得到数据
生成式生成器
a=(x*x for x in range(4))
print(next(a))     #输出0
print("---------------------")
for i in a:         #输出1、4、9
    print(i)

解释:

  • 生成式生成器的语法与列表生成式相似,但用小括号( )包裹。列表生成式用[ ]包裹。
  • 数据不会存放在内存中,每一个调用next函数,就会计算一次数据。
  • 使用生成器的好处是:节约内存空间。
函数生成器
  • 函数生成器使用关键字yield来产生数据。
  • 通过next()来得到yield产生的数据
def get():
    yield 1     
    yield 2
g=get()
print(next(g))  #输出1
print(next(g))  #输出2

解释:

  • 依次产生1和2,第三次调用next()则报错
  • 运行yield语句后,python立即设置断点,停止运行此函数,等待下一次调用next()
  • 每次运行,将从上一次的断点处(即上一个yield后)开始运行。
函数生成器-send
  • 通过send函数得到下一个值
  • send函数还可以传入一个值,这个值将被yield接收到
def func():
    count1 = yield 1
    print("count1=" , count1)
    count2 = yield 2
    print("count2=" , count2)
    yield 3
g = func()
print(g.send(None))
print(g.send(2))

结果:

1
count1= 2
2

解释:

  • count1 = yield 1是赋值语句,先执行等号右边。
  • 运行yield语句后,暂停运行此函数,所以第一次并没有接收值。所以第一次通过send得到值需要用send(None)。
  • 此处的知识可以运用到协程上。

应用-斐波那契序列

可以得到无限多个斐波那契序列中的元素:

def fib():
    a=1
    b=1
    yield a
    yield b
    while(True):
        yield a+b
        temp=a+b
        a=b
        b=temp
f = fib()
for i in range(10):
    print(next(f),end=" ")

结果:

1 1 2 3 5 8 13 21 34 55 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章