如何更优雅地获取接收yield值的Python生成器返回值?
获取接收值的生成器返回值的替代方法
首先明确:我们讨论的是通过yield接收外部传入值的生成器,这类生成器和仅产出值的普通生成器逻辑不同。
原代码示例
生成器函数通过yield接收外部值,累积后返回结果:
def gen(): accumulator = [] # 循环接收传入值,直到收到None while (incoming := (yield)) is not None: accumulator.append(incoming) return accumulator
原调用方式(需捕获StopIteration获取返回值):
dataset = [1, 2, 3, 4] g = gen() next(g) # 预激生成器,使其进入接收状态 for item in dataset: g.send(item) # 发送None终止生成器,捕获异常获取返回值 try: g.send(None) except StopIteration as e: result = e.value print(result) # 输出: [1, 2, 3, 4]
更优雅的替代方法
方法1:利用yield from自动捕获返回值
Python 3.3+ 引入的yield from语法会自动处理生成器的StopIteration异常,并将返回值作为表达式结果返回。我们可以封装一个辅助函数来简化逻辑:
def run_accumulator_gen(gen_func, dataset): g = gen_func() next(g) # 预激生成器 try: # 发送所有数据到生成器 for item in dataset: g.send(item) # 通过yield from获取生成器返回值 return (yield from g) finally: g.close() # 确保生成器正确关闭 # 调用示例 dataset = [1, 2, 3, 4] # 包装为生成器执行以触发yield from def get_result(): return (yield from run_accumulator_gen(gen, dataset)) result = next(get_result()) print(result) # 输出: [1, 2, 3, 4]
方法2:简化异常捕获逻辑
如果不想引入额外辅助函数,可以简化原有的异常捕获代码,使其更紧凑:
dataset = [1, 2, 3, 4] g = gen() next(g) # 批量发送数据 for item in dataset: g.send(item) # 紧凑捕获返回值 result = None try: g.send(None) except StopIteration as e: result = e.value print(result) # 输出: [1, 2, 3, 4]
说明
- 预激生成器的步骤(
next(g))不可省略:生成器刚实例化时处于初始暂停状态,必须通过next()或g.send(None)启动,才能进入接收外部值的状态。 yield from是官方推荐的处理生成器协作与返回值的方式,在复杂逻辑场景下可读性更强。
内容的提问来源于stack exchange,提问作者pepoluan
相关产品推荐
相关产品推荐

