为何Python函数未声明全局变量仍修改了原始列表?
为什么你的Python函数会意外修改原始列表?
你踩的这个坑其实是Python里**浅拷贝(shallow copy)**的典型问题,不少刚接触嵌套列表的开发者都会碰到!咱们一步步拆解原因:
问题根源:浅拷贝只复制外层引用
看你函数里的这行代码:
Ab = list(A)
这行是对列表A做了一个浅拷贝。对于普通一维列表来说,浅拷贝确实能生成独立的新列表,但你的A是嵌套列表(列表里装着列表)——浅拷贝只会复制外层列表的结构,里面的每个子列表(比如A[0]、A[1])其实还是和原始列表A共享同一个内存地址的引用。
换句话说,Ab[index]和A[index]指向的是同一个列表对象!所以当你在循环里执行:
Ab[index].append(b[index][0])
你其实是在修改那个共享的子列表,原始列表A里的对应子列表自然也会跟着变化,因为它们根本就是同一个东西。
怎么解决?用深拷贝或手动逐行复制
要让Ab和A完全独立,避免修改原始数据,有两种常用方法:
方法1:使用copy.deepcopy()做深拷贝
深拷贝会递归复制所有嵌套的可变对象,彻底切断和原始列表的关联:
import copy def make_Ab(A,b): n = len(A) Ab = copy.deepcopy(A) # 深拷贝所有层级 for index in range(n): Ab[index].append(b[index][0]) print(A) # 现在A不会被修改了 return Ab A = [[0.0, 1.0, 1.0, 2.0], [1.0, 3.0, 1.0, 5.0], [2.0, 0.0, 2.0, 4.0]] b = [[1],[2],[3]] print(A) Ab = make_Ab(A,b) print(A) # 输出和初始的A完全一致
方法2:手动逐行复制子列表
如果不想导入模块,可以用列表推导式逐个拷贝子列表,这样每个子列表都是独立的新对象:
def make_Ab(A,b): n = len(A) Ab = [row.copy() for row in A] # 逐个拷贝内层列表 for index in range(n): Ab[index].append(b[index][0]) print(A) return Ab A = [[0.0, 1.0, 1.0, 2.0], [1.0, 3.0, 1.0, 5.0], [2.0, 0.0, 2.0, 4.0]] b = [[1],[2],[3]] print(A) Ab = make_Ab(A,b) print(A)
总结一下
Python里的list(A)、A[:]这类操作都是浅拷贝,只处理外层结构;如果你的数据是嵌套的可变对象(比如列表套列表、字典套列表等),必须用深拷贝或者手动拷贝每一层,才能保证原始数据不被意外修改。
内容的提问来源于stack exchange,提问作者George Palasanu
相关产品推荐
相关产品推荐

