Python中的生成器与迭代器

86 阅读2分钟

在开始之前,首先我们要了解他们的作用:

  1. 节省内存,相比列表,每次生成一个元素,而不是直接计算所有元素
  2. 提速,因为占用的内存更小
  3. 节省代码长度

常见的使用场景:

  1. 异步调用,可以查看 fastapi yield 教程
  2. 读取大文件,每次读取固定字节
  3. 流式响应,详见 chatGPT API
  4. ......

迭代器

可迭代对象:str, list, tuple, set, dict,自定义类;

迭代器可以按顺序,依次返回变量中的元素

自定义类

如果使用自定义类定义迭代器,迭代器的两个关键函数:__iter__, __next__,它们是必须的 E.g.:

class MyNumbers:
  def __init__(self):
    self.a = 1
    
  def __iter__(self): 
    return self 
  
  def __next__(self): 
    x = self.a 
    self.a += 1
    return x
    
myclass = MyNumbers()

迭代器生成

iter() 函数:直接将可迭代的对象变成迭代器:E.g.:

i = iter('hello')
j = iter(myclass)

迭代对象

next() 函数:依次迭代对象

next(i)
# 'h'
next(i)
# 'e'
...

生成器

生成器本质是迭代器中元素的生成方式,有两种:

1:生成表达式

E.g.:

(i * 2 for i in range(10))

注意,必须使用 ( ), 而不是 [ ],使用 ( ) 则会将表达式转换为生成器,而使用 [ ] 则直接转化列表

区别在于:

( ) 会依次执行 i * 2 的动作,然后被 for 取出

[ ] 会直接一下执行完 i * 2 的动作,然后被 for 取出

2:生成函数

通过 yield 关键字创建,E.g.:

def dd(n):
  a, b = 0, 1
  for i in range(n):
      yield a
      a, b = b, a+b
      
for i, j in enumerate(dd(10))
    print(i, e)

yield 也是返回,但与 return 有很大不同,return 会直接返回并结束函数执行,yeild 会返回并挂起函数执行,直到下次 next() 时,从挂起的地方再次开始执行