学习笔记-Python基础17-迭代器、生成器、协成

# 迭代器
  - 可迭代(Iterable):直接作用域for循环的变量
  - 迭代器(Iterator):不但可以作用于for循环,还可以被next调用
  - isinstance()后跟第二个参数,可以判断这个变量是否是可迭代的或是迭代器
  - iterable和iterator可以转换
  - 通过iter函数

  

# 生成器
  - generator:一遍循环一遍计算下一个元素的机制/算法
  - 需要满足三个条件:
    - 1、每次调用都生产出for循环需要的下一个元素或者值
    - 2、如果达到最后一个后,需要StopIteration异常
    - 3、可以被next函数调用
  - 如何生成一个生成器
    - 直接使用
    - 如果函数中包含yield,则这个函数就叫生成器
      - 生成器用next函数调用,遇到yield返回

    

     

     

# 协成
  - 历史历程
    - 3.4引入协成,用yield实现
    - 3.5引入协成语法
    - 实现的协成比较好的包有asyncio、tornado、gevent
  - 定义:协成是为非抢占式多任务产生子程序的计算机程序组件,协成允许不同入口点在不同位置暂停或开始执行程序
  - 从技术角度讲,协成就是一个你可以暂停执行的函数,或者干脆把协成理解成生成器
  - 实现:
    - 1、yield返回
    - 2、generator.send()调用或者next(generator)预激

     

  

  - inspect.getgeneratorstate(...)函数确定,该函数会返回下述字符串中的一个(协成的四个状态):
    - 1、GEN_CREATED:等待开始执行
    - 2、GEN_RUNNING:解释器正在执行
    - 3、GEN_SUSPENED:在yield表达式处暂停
    - 4、GEN_CLOSED:执行结束
    - next预激(prime)

    

  

  - 协成终止
    - 协成中未处理的异常会向上冒泡,传给next函数或send方法的调用方(即触发协成的对象)
    - 终止协成的一种方式:发送某个哨符值,让协成退出。内置的None和Ellipsis等常量经常用作哨符值==

  - yield from
    - 调用协成为了得到返回值,协成必须正常终止
    - 在生成器正常终止会发出StopIteration异常,异常对象的value属性保存返回值
    - yield from从内部捕获StopIteration异常
    - 委派生产器:包含yield from表达式的生成器函数
      - 委派生产器在yield from表达式处暂停,调用方可以直接把数据发送给生成器
      - 子生成器再把产出的值发给调用方
      - 子生成器在最后,解释器会抛出StopIteration,并且把返回值附加到异常对象上

    

    

# 委派生成器
from collections import namedtuple
ResClass = namedtuple('Res', 'count average') #第一个参数元祖名称,第二个参数元祖元素依次的名称

# 子生成器
def averager():
    total = 0.0
    count = 0
    average = None
    
    while True:
        term = yield
        # None是哨符值
        if term is None:
            break
        total += total
        count += 1
        average = total / count
    # 返回元祖ResClass,里面的元素为数值的数量和所有数值的和
    return ResClass(count, average)
# 委派生成器
def grouper(storages, key):
    while True:
     # 获取averager返回值也就是Res元祖 storages[key]
= yield from averager() # 客户端代码 def client(): process_data = { 'boys_2':[1, 2, 3], 'boys_1':[9.8, 5.4, 3.2] } storages = {} for k, v in process_data.items(): print(k,"***",v) # 获得协成 coroutine = grouper(storages, k) # 预激协成 next(coroutine) # 发送数据到协成 for dt in v: coroutine.send(dt) # 终止协成 coroutine.send(None) print(storages) client()
原文地址:https://www.cnblogs.com/Cloudloong/p/9798987.html