Python多维列表填充时原列表被修改的问题及解决
Python嵌套列表填充时原列表被意外修改的问题解析与修复
问题场景
你正在处理一个三层嵌套的列表(结构为[序列集合, 序列长度, 独热编码]),想要把所有子序列填充到最大长度,但运行代码后发现原列表lst和新生成的new_lst完全一样,原列表被意外修改了。你的原始代码如下:
lst = [[[0,1],[0,1],[0,1],[0,1]], [[0,1],[0,1],[0,1]], [[0,1],[0,1],[0,1],[0,1],[0,1]]] def pad_sequence(list_to_pad): padded_lst = list_to_pad.copy() # Define length of alphabet (len_alphabet: Integer) len_alphabet = len(padded_lst[0][0]) # Find max length of a seq (max_len: Integer) max_len = 0 for seq in padded_lst: if len(seq) > max_len: max_len = len(seq) # Define vector to append (pad: list) pad = [0 for _ in range(len_alphabet)] # Add padding to all sequences for idx, seq in enumerate(padded_lst): length = max_len - len(seq) for _ in range(length): padded_lst[idx].append(pad) return padded_lst new_lst = pad_sequence(lst) print(lst) print(new_lst)
问题根源:浅拷贝的局限性
你用list_to_pad.copy()创建的是浅拷贝(shallow copy):
- 浅拷贝只会复制外层列表的结构,但里面的子列表(也就是那些长度不同的序列)依然是原列表中对象的引用。
- 当你执行
padded_lst[idx].append(pad)时,你其实是在直接修改原列表lst里的子序列对象——因为padded_lst里的子列表和lst里的是同一个东西!
打个比方:浅拷贝就像复制了一个文件夹的快捷方式,你打开这个快捷方式修改里面的文件,原文件夹里的文件也会跟着变。
修复方案:用深拷贝完全隔离副本
要让新列表和原列表彻底独立,你需要使用copy模块的deepcopy函数,它会递归复制所有嵌套层级的对象,连最内层的独热编码列表都会被复制,完全不会影响原列表。
修正后的函数如下:
def pad_sequence(list_to_pad): from copy import deepcopy # Deepcopy list padded_lst = deepcopy(list_to_pad) # Define length of alphabet (len_alphabet: Integer) len_alphabet = len(padded_lst[0][0]) # Find max length of a seq (max_len: Integer) max_len = 0 for seq in padded_lst: if len(seq) > max_len: max_len = len(seq) # Define vector to append (pad: list) pad = [0 for _ in range(len_alphabet)] # Add padding to all sequences for idx, seq in enumerate(padded_lst): length = max_len - len(seq) for _ in range(length): padded_lst[idx].append(pad) return padded_lst
现在运行代码,原列表lst会保持原样,new_lst是填充后的独立副本。
内容的提问来源于stack exchange,提问作者Mathias Byskov
相关产品推荐
相关产品推荐

