Python中二维列表深拷贝的正确实现方法

3次阅读

Python中二维列表深拷贝的正确实现方法

本文详解python二维列表赋值时因浅拷贝导致的“所有行同步修改”问题,揭示[[0]*3]*3的陷阱,并提供安全创建独立子列表的多种解决方案。

本文详解python二维列表赋值时因浅拷贝导致的“所有行同步修改”问题,揭示[[0]*3]*3的陷阱,并提供安全创建独立子列表的多种解决方案。

在Python中,初学者常误以为 R = [[0] * 3] * 3 能创建一个 3×3 的二维列表,但实际上它生成的是三个指向同一内层列表对象的引用。这意味着:对 R[0][j]、R[1][j] 或 R[2][j] 的任意修改,都会作用于同一个底层列表 [0, 0, 0] —— 这正是你观察到“所有行最终都变成最后一行值”的根本原因。

我们来复现问题:

R = [[0] * 3] * 3 print("初始R:", R)  # [[0, 0, 0], [0, 0, 0], [0, 0, 0]] R[0][0] = 99 print("修改R[0][0]后:", R)  # [[99, 0, 0], [99, 0, 0], [99, 0, 0]] ← 所有行都被改变!

这是因为 [[0]*3] * 3 先构造一个列表 [0,0,0],再将其引用复制三次,而非创建三个独立副本。

✅ 正确做法:确保每行都是全新的、相互独立的列表对象。推荐以下三种方式(按优先级排序):

立即学习Python免费学习笔记(深入)”;

✅ 方式1:列表推导式(最推荐)

R = [[0 for _ in range(3)] for _ in range(3)] # 或等价写法(更简洁) R = [[0] * 3 for _ in range(3)]

该写法每次迭代都执行一次 [0] * 3,生成全新的子列表,彻底避免共享引用。

✅ 方式2:嵌套循环显式构建

R = [] for i in range(3):     R.append([0, 0, 0])  # 每次append都创建新列表

✅ 方式3:使用 copy.deepcopy()(适用于复杂嵌套结构)

import copy R = [[0] * 3] * 3 R_safe = copy.deepcopy(R)  # 完全独立的深拷贝

⚠️ 注意:deepcopy 开销较大,仅在动态结构或含可变对象(如嵌套字典、自定义类实例)时必要;对纯数字二维列表,列表推导式更高效、更Pythonic。

回到你的原始代码,修正版如下:

# ✅ 正确初始化:每行独立 R = [[0] * 3 for _ in range(3)] p = [[1, 0.25, 0.14], [0.25, 1, 0.1], [0.14, 0.1, 1]]  # 复制数值(也可直接用 R = [row[:] for row in p] 实现浅拷贝) for i in range(3):     for j in range(3):         R[i][j] = p[i][j]  print(R) # 输出: [[1, 0.25, 0.14], [0.25, 1, 0.1], [0.14, 0.1, 1]] ✅

? 关键总结

  • * 对列表操作是引用复制,不是对象复制;
  • 创建多维容器时,务必使用列表推导式或显式循环确保子对象独立;
  • 验证是否真正独立:id(R[0]) != id(R[1]) 且 R[0] is not R[1] 应为 True;
  • 若需复制已有二维列表(如 p),推荐 R = [row.copy() for row in p] 或 R = [row[:] for row in p],二者均对每行做浅拷贝,安全高效。

text=ZqhQzanResources