ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

慢就是快13-5 生成器

慢就是快13-5 生成器

1.生成器函数:函数体中如果出现了yield关键字,那该函数是『生成器函数』

2.生成器对象:调用『生成器函数』时,其函数体不会立刻执行,而是返回一个『生成器对象』

备注:不管能否执行到yield所在的位置,只要函数中有yield关键字,那该函数,就是『生成器函数』

# generator:生成器 def demo(): print('哈哈哈') print(100) yield a=200 print(a) d=demo() print(d)

写在『生成器函数』中的代码,需要通过『生成器对象』来执行:

1.调用『生成器对象』的__next__方法,会让『生成器函数』中的代码开始执行。

2.当『生成器函数』中的代码开始执行后,遇到yield会“暂停”执行,并且其内部会记录“暂停”的位置。

3.后续调用__next_ 方法时,都会从上一次“暂停”的位置,继续运行,直到再次遇到yield。

4.遇到return 会抛出 StopIteration异常,并将 return后面的表达式,作为异常信息。

5.yield后面所写的表达式,会作为本次__next__方法的返回值。

def demo(): print('哈哈哈') print(100) yield '我是1' a=200 print(a) yield '我是2' b=300 print(b) return '哒哒哒' d=demo() # print(hasattr(d,'__iter__')) # print(hasattr(d,'__next__')) # r0=iter(d) # print(r0==d) # # r=next(d) # print(r) # r1=next(d) # print(r1) # try: # next(d) # except StopIteration as e: # print(e) for item in d: print(item)
  • 生成器对象是一种特殊的迭代器(本质是通过yield自动实现了迭代器协议)
  • yield也能写在循环里
  • yield from 能把一个『可迭代对象』里的东西依次yield 出去。(替代:for+yield)
    def demo(): nums=[10,20,30,40] yield from nums # region d=demo() r=next(d) print(r) for item in d: print(item) # endregion
  • 使用:生成器.send(值)可以让生成器继续执行的同时,给上一次yield传值。
    • 备注1:next只能取值,send既能取值,也能送值
    • 备注2:第一次启动生成器,不能传值!
      def demo(): print('demo函数开始执行了') print(100) a = yield '我是第1个yield所返回的数据' print(a) b = yield '我是第2个yield所返回的数据' print(b) return '尚硅谷' d=demo() r=next(d) print(r) r1=d.send(666) print(r1) # r2=d.send(888) # print(r2) try: d.send(888) except StopIteration as e: print(e) # for item in d: # print(item)

用生成器实现遍历Person类的实例对象

class Person: def __init__(self, name, age, gender, address): self.name = name self.age = age self.gender = gender self.address = address def __iter__(self): yield self.name yield self.age yield self.gender yield self.address p1=Person('张三',18,'男','北京昌平') #目标: for attr in p1: print(attr)

无论是迭代器,还是生成器对象,都可以用1ist、tuple、set等直接拿到其里面的所有内容(注意:容易挤爆内存)

def fibo(total): pre=1 cur=1 for index in range(total): if index<2: yield 1 else: value=pre+cur pre=cur cur=value yield value f1=fibo(10) for item in f1: print(item) # result=list(f1)

生成器表达式:一种类似列表推导式的语法,快速创建生成器对象的方式

语法格式:(表达式 for 变量 in 可迭代对象)

什么时候适合用生成器表达式? 当“每个结果,只依赖当前这一个元素”时。

nums=[10,20,30,40] # 列表推导式 r1=[n*2 for n in nums] print(r1) # 生成器表达式 r2=(n*2 for n in nums) for item in r2: print(item)
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进