
python没有内置的“数组”类型来直接支持多维数组,但我们可以通过列表的嵌套来模拟二维数组。例如,一个3x3的二维列表可以表示为[[1, 2, 3], [4, 5, 6], [7, 8, 9]]。
许多开发者在尝试初始化一个指定大小的二维列表时,可能会直观地使用如下方式:
side = 5
arr_wrong = [[0] * side] * side
print("初始化的错误数组:", arr_wrong)这段代码的意图是创建一个 side 行 side 列,所有元素初始为0的二维列表。然而,这种初始化方式存在一个严重的缺陷。让我们通过一个例子来观察其行为:
side = 3
arr_wrong = [[0] * side] * side
print("初始化的错误数组 (3x3):", arr_wrong)
# 尝试修改 arr_wrong[0][0]
arr_wrong[0][0] = 99
print("修改 arr_wrong[0][0] 为 99 后:", arr_wrong)输出结果:
初始化的错误数组 (3x3): [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 修改 arr_wrong[0][0] 为 99 后: [[99, 0, 0], [99, 0, 0], [99, 0, 0]]
从输出可以看出,当我们修改 arr_wrong[0][0] 时,arr_wrong[1][0] 和 arr_wrong[2][0] 也随之改变了。这显然不是我们期望的结果。
立即学习“Python免费学习笔记(深入)”;
原因解析: 问题出在 [[0] * side] * side 这行代码的执行方式上。
简单来说,arr_wrong 中的所有子列表实际上都指向内存中的同一个列表对象。因此,当你修改其中一个子列表的元素时,你实际上是在修改那个唯一的共享列表,这会导致所有引用它的“子列表”都反映出相同的变化。这是一种典型的“浅拷贝”问题。
为了避免上述陷阱,我们应该确保每个子列表都是一个独立的列表对象。实现这一目标的最佳方式是使用列表推导式(List Comprehension):
side = 5
arr_correct = [[0] * side for _ in range(side)]
print("初始化的正确数组:", arr_correct)让我们再次通过一个例子来验证这种方法的行为:
side = 3
arr_correct = [[0] * side for _ in range(side)]
print("初始化的正确数组 (3x3):", arr_correct)
# 尝试修改 arr_correct[0][0]
arr_correct[0][0] = 99
print("修改 arr_correct[0][0] 为 99 后:", arr_correct)输出结果:
初始化的正确数组 (3x3): [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 修改 arr_correct[0][0] 为 99 后: [[99, 0, 0], [0, 0, 0], [0, 0, 0]]
这次,修改 arr_correct[0][0] 只影响了第一个子列表,其他子列表保持不变。这正是我们期望的正确行为。
原因解析: 列表推导式 [[0] * side for _ in range(side)] 的工作原理如下:
这里的 _ 是一个惯用的变量名,用于表示循环变量的值在循环体中不被使用,我们只关心循环的次数。
现在,我们结合一个实际场景,演示如何将用户输入(例如一行一个字符串)正确地填充到一个预先正确初始化的二维列表中。
side = 5 # 定义二维列表的边长,例如 5x5
# 1. 正确初始化一个 side x side 的二维列表
# 确保每个子列表都是独立的,初始值可以根据需要设定,这里用空字符串或None
arr = [[''] * side for _ in range(side)]
print(f"请按行输入 {side}x{side} 的数据。每行输入一个长度为 {side} 的字符串。")
input_lines = []
# 2. 接收用户输入,这里模拟了原问题中的输入方式
for r_idx in range(side):
# 提示用户输入,并确保输入长度符合要求
while True:
line_input = input(f"请输入第 {r_idx + 1} 行数据 (长度为 {side}): ")
if len(line_input) == side:
input_lines.append(line_input)
break
else:
print(f"输入长度不正确,请重新输入,需要 {side} 个字符。")
# 3. 将接收到的字符串数据填充到二维列表中
for r_idx in range(side): # 遍历行索引
current_row_str = input_lines[r_idx]
for c_idx in range(side): # 遍历列索引
arr[r_idx][c_idx] = current_row_str[c_idx] # 将字符串的每个字符赋给对应位置
print("\n最终生成的二维列表:")
for row in arr:
print(row)
# 4. 验证独立性:修改一个元素,检查是否会影响其他行
arr[0][0] = 'X' # 将 arr[0][0] 修改为 'X'
print("\n修改 arr[0][0] 为 'X' 后:")
for row in arr:
print(row)示例运行(假设用户输入):
请按行输入 5x5 的数据。每行输入一个长度为 5 的字符串。 请输入第 1 行数据 (长度为 5): ABCDE 请输入第 2 行数据 (长度为 5): FGHIJ 请输入第 3 行数据 (长度为 5): KLMNO 请输入第 4 行数据 (长度为 5): PQRST 请输入第 5 行数据 (长度为 5): UVWXY 最终生成的二维列表: ['A', 'B', 'C', 'D', 'E'] ['F', 'G', 'H', 'I', 'J'] ['K', 'L', 'M', 'N', 'O'] ['P', 'Q', 'R', 'S', 'T'] ['U', 'V', 'W', 'X', 'Y'] 修改 arr[0][0] 为 'X' 后: ['X', 'B', 'C', 'D', 'E'] ['F', 'G', 'H', 'I', 'J'] ['K', 'L', 'M', 'N', 'O'] ['P', 'Q', 'R', 'S', 'T'] ['U', 'V', 'W', 'X', 'Y']
可以看到,arr[0][0] 被成功修改为 'X',而其他行的对应列元素(如 arr[1][0]、arr[2][0] 等)并未受到影响,这证明了列表是独立且正确初始化的。
通过掌握正确的二维列表初始化方法,你可以避免常见的编程错误,确保数据结构的完整性,从而编写出更可靠、更易于维护的Python代码。
以上就是Python中二维列表(2D List)的正确初始化方法与常见陷阱解析的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号