嵌套dict/list/tuple结构递归原地更新时tuple元素修改方案
嵌套结构tuple元素更新解决方案
方案1:利用numpy数组原地修改(最推荐,改动极小)
因为所有叶子节点都是numpy数组,而tuple仅存储数组的引用,不需要修改tuple本身的元素,直接修改数组对象的内容即可避开tuple不可变的限制。
仅需修改原函数的更新逻辑,无需调整其他部分:
def walk(x, update=False): for i, key in enumerate(x): value = x[key] if isinstance(x, dict) else key if isinstance(value, (dict, list, tuple)): yield from walk(value, update=update) else: result = yield value if update: # 直接原地修改numpy数组内容,不修改外层容器的元素引用 target = x[key] if isinstance(x, dict) else x[i] target[:] = result
注意事项
- 要求传入的新数组
result和原数组形状、数据类型兼容,否则切片赋值会抛出错误 - 该方案不会改变任何容器的内存地址,完全符合原地更新的需求
方案2:tuple转list处理(适用于需要替换整个数组对象的场景)
如果更新逻辑需要改变数组的形状、数据类型,必须替换整个数组对象,可以在递归时将tuple临时转为list处理,完成更新后再转回tuple返回给上层容器更新:
def walk(x, update=False): is_tuple = isinstance(x, tuple) # tuple临时转list处理 if is_tuple: x = list(x) for i, key in enumerate(x): value = x[key] if isinstance(x, dict) else key if isinstance(value, (dict, list, tuple)): # 接收递归返回的处理后容器 new_val = yield from walk(value, update=update) if update: x[key if isinstance(x, dict) else i] = new_val else: result = yield value if update: x[key if isinstance(x, dict) else i] = result # 处理完转回到tuple返回 if is_tuple: x = tuple(x) return x
使用说明
- 调用该函数时需要接收返回的新根容器,替换原来的根对象即可
- 所有tuple会生成新的对象,上层可变容器(list、dict)会原地更新对应位置的tuple元素
内容的提问来源于stack exchange,提问作者Gerges
相关产品推荐
相关产品推荐

