JokerShame 发表于 2022-3-31 23:58

Python基础教程总结分享——迭代器和生成器

本帖最后由 JokerShame 于 2022-4-1 08:30 编辑

可迭代对象:实现了方法__iter__的对象
迭代器:既有方法__iter__,又有方法__next__。
方法__iter__返回一个迭代器
调用方法__next__时,迭代器返回其下一个值。当迭代器没有可供返回的值时,再次调用方法__next__,会引发StopIteration异常。
注:有内置的函数iter()和next(),next(it)与it.__next__()等效。

迭代是一个重复的过程,并且每一次的重复都基于上一次的结果而来,迭代器是一种可以不依赖于索引做到迭代取值的工具。
可迭代对象:字符串、列表、元组、字典、集合、文件。

调用可迭代对象的__iter__方法得到的是迭代器,调用迭代器的__iter__方法,得到的还是迭代器本身,for循环就是利用这个原理产生的。
for循环可以做到如下三点:
1、将可迭代对象变成迭代器。2、能够自己获取迭代器的next值。3、返回完迭代器的最后一个值之后停止迭代。
for循环的底层工作原理:
1、先调用in后面那个对象的__iter__方法,将其变成一个迭代器。
2、调用__next__方法,将得到的返回值赋给变量名i。
3、循环往复直到__next__方法抛出异常StopIteration,for循环自动捕捉异常并结束循环。

关于迭代器应用的例子:
迭代器创建斐波那契数列:
class Fibs:
    def __init__(self):
      self.a = 0
      self.b = 1

    def __next__(self):
      self.a, self.b = self.b, self.a + self.b
      return self.a

    def __iter__(self):
      return self


fibs = Fibs()
for i in fibs:
    while i < 15:
      print(i)
      break
    else:
      break

上面得到的结果为:
1
1
2
3
5
8
13

===============================分割线****生成器========================================
生成器就是一种自定义的迭代器,本质就是一种迭代器。包含yield语句的函数都被称为生成器,还有种说法时,当函数内有yield关键字时,调用函数就不会执行函数体代码,而是会获得一个返回值,这个返回值就是生成器。
def func():
    print("=====1")
    yield 1
    print("=====2")
    yield 2
    print("=====3")

>>>g = func()
>>>print(next(g))
# 在生成器中,next方法会触发函数的执行,直到碰到一个yield停下来,并且将yield后的值当作本次next的结果返回。
=====1
1
# 如果我继续执行next(g),函数会继续往下执行,遇到yield停止,但是若不打印next(g)的返回值,就不会打印yield后面的值。
>>>next(g)
=====2

yield对比return:
相同点:都可以返回值,值的类型与个数都没有限制。
不同点:yield可以返回多次值,而return返回一次值之后,函数就会结束。

再举一个关于生成器的例子,还拿斐波那契数列来说:
例:定义一个生成器,这个生成器可以生成10为斐波那契数列
def Fibs(n):
    i, a, b = 0, 1, 1
    while i < n:
      yield a
      a, b = b, a + b
      i += 1


>>>fibs = Fibs(10)
>>>print(list(fibs))


递归式生成器:
创建一个将任意层嵌套列表展开的函数,在不知道有多少层嵌套的情况下,可使用递归的方式进行拆分:
def flatten(nested):
    try:
      for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
      yield nested
调用flatten时,有两种可能性(处理递归时都如此):基线条件和递归条件。在基线条件下,要求这个函数展开的对象是单个元素,在这种情况下for循环将引发TypeError异常(因为一个数已经无法再次展开了),那么直接生成被展开的那个对象;如果要展开的是个列表(或其他任何可迭代对象),就需要有如下步骤:遍历所有的子列表,然后对子列表重复上面的两步(如果无法拆开了就返回不能拆开的那个元素,如果还能拆开就继续拆开,直到最后不能拆开),由于yield后面的结果是生成器,又由于生成器就是一种迭代器,而in后面是会自动调用__init__和__next__方法的,所以flatten(sublist)最后还是一个迭代器(在这里,它是列表),而它里面的元素是可以确保到最后都是些无法再次被拆分的单个元素。

没事好好 发表于 2022-4-1 07:05

自己得到的经验

jffwoo 发表于 2022-4-1 08:21

细致学习的话还有很多内容的

mmnn123 发表于 2022-4-1 10:40

{:1_921:}感谢分享!
页: [1]
查看完整版本: Python基础教程总结分享——迭代器和生成器