Python递归场景下yield是否会沿调用栈向上传递?
输出差异的核心原因
你观察到的交替输出本质是Python生成器的惰性求值特性导致的,和递归栈的展开逻辑无关,具体执行流程如下:
- 当外层
flatten遍历到元素[3,4,5]时,进入for subitem in flatten(item):循环,这里的flatten(item)会返回一个生成器对象,不会立刻执行内层函数的代码 - 生成器每次迭代只会执行到下一个
yield语句就暂停,返回当前值,下次迭代时从暂停位置继续执行,所以实际执行顺序是:- 第一次迭代内层生成器:内层
flatten处理元素3,匹配非列表分支,打印yield2 3,yield返回3,内层函数暂停 - 外层循环拿到subitem=3,执行
print('yield1 ', 3),yield返回3 - 触发第二次迭代内层生成器:内层函数从暂停位置恢复,处理下一个元素4,匹配非列表分支,打印
yield2 4,yield返回4,内层函数暂停 - 外层循环拿到subitem=4,执行
print('yield1 ', 4),yield返回4 - 后续元素以此类推,就会出现
yield2和yield1交替打印的结果
- 第一次迭代内层生成器:内层
递归+yield的栈逻辑
递归场景下的yield完全遵循普通递归的栈规则,没有特殊的提前栈展开行为:每次内层函数yield返回值时,当前递归栈的所有状态都会被保存,直到下次迭代生成器时,再从当前暂停的栈位置继续执行。
符合你预期的修改方案
如果你想让内层生成器先执行完所有逻辑(打印所有yield2),再处理外层的打印逻辑,可以主动把内层生成器转为列表,强制它一次性执行完毕:
def flatten(lol): for item in lol: if isinstance(item, list): # 转list会一次性消耗内层生成器,打印所有内层yield2 for subitem in list(flatten(item)): print('yield1 ', subitem) yield subitem else: print('yield2 ', item) yield item
内容的提问来源于stack exchange,提问作者dragor0123
相关产品推荐
相关产品推荐

