当前位置: 首页 > news >正文

Python列表初始化的陷阱:重复引用的坑

Python列表初始化的"陷阱":重复引用的坑

# 当时的"聪明"代码
matrix = [[0] * 3] * 3  # 创建3x3矩阵,看起来很优雅对吧?# 修改第一个元素
matrix[0][0] = 1
print(matrix)
# [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
# 卧槽!为什么都变了?

这个例子展示了Python中列表初始化时一个非常经典的"坑",看似优雅的代码却产生了意外结果。让我们来深入分析:

问题现象

当我们用[[0] * 3] * 3创建矩阵并修改其中一个元素时,所有子列表的对应位置都被修改了:

matrix = [[0] * 3] * 3  # 看起来像创建3x3矩阵
matrix[0][0] = 1
print(matrix)
# 输出: [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
# 预期: [[1, 0, 0], [0, 0, 0], [0, 0, 0]]

问题根源:列表是可变对象,乘法创建的是引用副本

[[0] * 3] * 3的执行过程是:

  1. 首先创建内部列表[0] * 3,得到[0, 0, 0]
  2. 然后用* 3复制这个列表,但复制的是引用(内存地址)而非创建新列表

这意味着:

  • 矩阵中的三个子列表实际上是同一个列表对象的三个引用
  • 当你修改matrix[0][0]时,其实是修改了那个唯一的子列表对象
  • 由于三个子列表引用的是同一个对象,所以看起来"都变了"

验证:三个子列表是同一个对象

我们可以通过is运算符验证这一点:

matrix = [[0] * 3] * 3
print(matrix[0] is matrix[1])  # True
print(matrix[1] is matrix[2])  # True
# 证明三个子列表是同一个对象

正确的矩阵创建方式

方法1:使用列表推导式(推荐)

matrix = [[0] * 3 for _ in range(3)]
matrix[0][0] = 1
print(matrix)  # [[1, 0, 0], [0, 0, 0], [0, 0, 0]] ✅

方法2:显式创建每个子列表

matrix = []
for _ in range(3):row = [0] * 3  # 每次循环创建新列表matrix.append(row)

这两种方法的关键是:每次都创建新的子列表对象,而不是复制已有列表的引用。

扩展:其他可变对象的类似问题

不只是列表,所有可变对象(字典、集合等)都会有类似问题:

# 字典的错误初始化
dicts = [{}] * 3
dicts[0]['name'] = 'Alice'
print(dicts)  # [{'name': 'Alice'}, {'name': 'Alice'}, {'name': 'Alice'}] ❌# 正确方式
dicts = [{} for _ in range(3)]
dicts[0]['name'] = 'Alice'
print(dicts)  # [{'name': 'Alice'}, {}, {}] ✅

总结:避免陷阱的原则

当使用*运算符初始化包含可变对象的容器时要特别小心:

  1. *对于不可变对象(如数字、字符串)是安全的:[0] * 3是安全的
  2. *对于可变对象(如列表、字典)会创建引用副本,可能导致意外
  3. 初始化包含可变对象的容器时,推荐使用列表推导式,确保每次创建新对象

记住:可变对象的复制通常是引用复制,而非值复制,这是Python中许多"坑"的根源!

http://www.hskmm.com/?act=detail&tid=25548

相关文章:

  • MongoDB
  • 实用指南:第三十三天打卡复习
  • 实用指南:Hardening fixes lead to hard questions
  • 赛前训练6 状压
  • 排序综合
  • NKOJ全TJ计划——NP11745
  • InfinityFree教程 ——免费搭建属于你的网站
  • 关于调和级数估算前n项的和
  • 10.6 模考 T4(QOJ 1836)
  • 实用指南:【Node.js 深度解析】npm install 遭遇:npm ERR! code CERT_HAS_EXPIRED 错误的终极解决方案
  • 顺序结构
  • Windows漏洞利用技巧:虚拟内存访问陷阱(2025更新)
  • Python编译期优化:隐藏在代码背后的效率魔法
  • 一篇文章带你了解 WGCLOUD运维监控系统的部署与应用
  • 选择结构
  • Python函数默认参数陷阱:可变对象的共享问题深度解析
  • 无需安装的Photoshop:网页版完整使用指南与在线图片编辑技巧
  • 求阶
  • gin 框架 - 教程
  • 赛前训练 5 树形 dp
  • 递推求解逆元
  • 一些做题记录(2025 2-3)
  • 智慧决策的透明化路径:“空白金兰契”架构下的“悟空备案制”研究
  • 笔记:寻找适合自己的简历工具(YAMLResume)
  • 实用指南:Linux 权限管理入门:从基础到实践
  • vue插槽
  • Magnet Axiom 9.6 新增功能概览 - 数字取证与分析
  • Windows 11 24H2 中文版、英文版 (x64、ARM64) 下载 (2025 年 9 月发布)
  • Windows 11 25H2 正式版发布,新增功能简介
  • 无法定时发送