为何修改切片列表directors会影响原voting_records列表?
问题:修改衍生列表时原列表同步被修改的原因
原代码与问题场景
首先定义嵌套列表:
voting_records = [['1.', 'DIRECTOR', 'Management'], ['1', 'Allison Grant Williams', 'For'], ['2', 'Sheila Hartnett-Devlin', 'For'], ['3', 'James Jessee', 'For'], ['4', 'Teresa Polley', 'For'], ['5', 'Ashley T. Rabun', 'For'], ['6', 'James E. Ross', 'For'], ['7', 'Rory Tobin', 'For']]
通过列表推导式创建衍生列表voting_records_short:
cnames = ["Record","Proposal","Sponsor","VoteCast"] voting_records_short = [record for record in voting_records if len(record) < len(cnames)]
随后对voting_records_short切片得到directors并修改:
if len(voting_records_short) == 0: pass else: ifdirector = ["DIRECTOR" in record for record in voting_records_short] if True in ifdirector: directorindx = int(ifdirector.index(True)) directorline = [voting_records_short[directorindx]] directors = voting_records_short[directorindx+1:] sponsoridx = cnames.index("Sponsor") for ls in range(len(directors)): directors[ls][0] = directorline[0][0] + directors[ls][0] directors[ls][1] = directorline[0][1] + " " +directors[ls][1] directors[ls].insert(sponsoridx,directorline[0][-1])
意外结果
修改directors后,原列表voting_records和voting_records_short也同步被修改:
In [2]: voting_records Out[2]: [['1.', 'DIRECTOR', 'Management'], ['1.1', 'DIRECTOR Allison Grant Williams', 'Management', 'For'], ['1.2', 'DIRECTOR Sheila Hartnett-Devlin', 'Management', 'For'], ['1.3', 'DIRECTOR James Jessee', 'Management', 'For'], ['1.4', 'DIRECTOR Teresa Polley', 'Management', 'For'], ['1.5', 'DIRECTOR Ashley T. Rabun', 'Management', 'For'], ['1.6', 'DIRECTOR James E. Ross', 'Management', 'For'], ['1.7', 'DIRECTOR Rory Tobin', 'Management', 'For']] In [9]: voting_records_short Out[9]: [['1.', 'DIRECTOR', 'Management'], ['1.1', 'DIRECTOR Allison Grant Williams', 'Management', 'For'], ['1.2', 'DIRECTOR Sheila Hartnett-Devlin', 'Management', 'For'], ['1.3', 'DIRECTOR James Jessee', 'Management', 'For'], ['1.4', 'DIRECTOR Teresa Polley', 'Management', 'For'], ['1.5', 'DIRECTOR Ashley T. Rabun', 'Management', 'For'], ['1.6', 'DIRECTOR James E. Ross', 'Management', 'For'], ['1.7', 'DIRECTOR Rory Tobin', 'Management', 'For']]
原因分析
核心问题在于Python嵌套列表的引用机制:
- 你用列表推导式创建
voting_records_short时,只是把voting_records里的每个子列表的引用直接复制过来,并没有生成新的子列表对象。也就是说,voting_records_short中的子列表和voting_records里的对应子列表是同一个内存对象。 - 后续切片
directors = voting_records_short[directorindx+1:]同样只是复制子列表的引用,directors里的元素还是指向原列表的子列表。 - 当你在循环中修改
directors[ls][0]、directors[ls][1]或调用insert方法时,都是直接修改了这个共享的子列表对象本身,因此所有引用该对象的列表(voting_records、voting_records_short、directors)都会同步看到修改结果。
解决办法
需要为每个子列表创建独立的副本,避免共享引用:
- 浅拷贝(适用于子列表元素都是不可变类型如字符串):
在列表推导式中对子列表做切片生成副本:
voting_records_short = [record[:] for record in voting_records if len(record) < len(cnames)]
- 深拷贝(适用于子列表中还有可变对象的场景):
使用copy模块的deepcopy函数:
import copy voting_records_short = [copy.deepcopy(record) for record in voting_records if len(record) < len(cnames)]
这样修改directors时,只会影响自身的子列表,不会波及原列表voting_records和voting_records_short。
内容的提问来源于stack exchange,提问作者Segun Ojo
相关产品推荐
相关产品推荐

