Python递归生成器使用list()或append()时失效问题求助
问题原因及解决方案
核心问题
你的递归生成器存在两个关键问题,导致转成列表时结果全部一致:
- 可变默认参数的陷阱:Python中,可变默认参数(如
output={})会在函数定义阶段创建唯一的字典对象,所有递归调用共享这个字典,后续的修改都会覆盖之前的内容。 - yield引用而非副本:退出条件中
yield output返回的是字典的引用,而非独立副本,所有生成器产出的元素都指向同一个字典实例。
直接遍历打印时看似正常,是因为每次打印操作发生在字典被修改之前,你看到的是当前时刻的字典状态;但转成列表时,所有元素的引用都指向同一个字典,最终字典被修改为最后一组参数,所以列表中所有元素都显示最后结果。
修复后的代码
修改默认参数初始化逻辑,并在yield时返回字典副本:
def _recursive_nWay_generator(input: list, output=None): ''' Helper function; used to generate parameter-value pairs to submit to the model for the simulation. Parameters ---------- input : list of tuple every tuple of the list must be of the form: ``('name_of_parameter', iterable_of_values)`` output : dict, optional parameter used for recursion; allows for dict building across subgenerators Returns ------- Generator : Specifications used for simulation setup of the form: ``{'par1': val1, ...}`` ''' # 初始化新字典,避免共享同一可变对象 if output is None: output = {} # 退出条件:返回当前字典的副本,确保每个结果独立 if len(input) == 0: yield output.copy() # 递归逻辑 else: curr = input[0] par_name = curr[0] for par_value in curr[1]: output[par_name] = par_value yield from _recursive_nWay_generator(input[1:], output=output)
验证结果
运行测试代码:
testlist = [('a', (1, 2, 3)), ('b', (4, 5, 6)), ('c', (7, 8))] gen = _recursive_nWay_generator(testlist) print(list(gen))
会输出预期的所有参数组合,每个字典都是独立的实例,不会被后续修改覆盖。
内容的提问来源于stack exchange,提问作者XJiang
相关产品推荐
相关产品推荐

