二维数据结构:列表与数组对比学习¶
(date: 2025-11-13)
1. Python 二维列表¶
什么是二维列表?¶
二维列表是列表的列表,用于存储表格状数据。
创建二维列表¶
# 直接创建
matrix_2d = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 动态创建 3x3 矩阵
rows, cols = 3, 3
matrix = [[0 for _ in range(cols)] for _ in range(rows)]
print(matrix) # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
基本操作¶
# 访问元素
print(matrix_2d[0][1]) # 2 (第1行第2列)
print(matrix_2d[1][0]) # 4 (第2行第1列)
# 修改元素
matrix_2d[0][1] = 10 # 修改单个元素
matrix_2d[1] = [40, 50, 60] # 修改整行
# 遍历
for row in matrix_2d:
for element in row:
print(element, end=' ')
print()
列表运算的限制¶
# 尝试向量运算会出错
a = [[1, 2], [3, 4]]
b = [[5, 6], [7, 8]]
# 以下操作都不支持!
# result = a + 10 # 错误!
# result = a * 2 # 错误!
# result = a + b # 这不是矩阵加法!
# 必须手动实现
result = []
for i in range(len(a)):
row = []
for j in range(len(a[i])):
row.append(a[i][j] + b[i][j])
result.append(row)
print(result) # [[6, 8], [10, 12]]
2 NumPy 二维数组¶
为什么需要 NumPy?¶
解决二维列表在数值计算中的局限性。
创建二维数组¶
import numpy as np
# 从列表转换
lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(lst)
print(arr)
# 输出:
# [[1 2 3]
# [4 5 6]
# [7 8 9]]
# 专用创建方法
zeros_arr = np.zeros((3, 3)) # 全零数组
ones_arr = np.ones((2, 4)) # 全一数组
range_arr = np.arange(9).reshape(3, 3) # 范围数组
基本操作对比¶
# 访问元素对比
print("列表访问:", lst[0][1]) # 需要两个括号
print("数组访问:", arr[0, 1]) # 一个括号,逗号分隔
# 修改元素对比
lst[0][1] = 10 # 列表修改
arr[0, 1] = 10 # 数组修改
# 切片操作对比
print("列表切片:", [row[1:] for row in lst]) # 复杂
print("数组切片:", arr[:, 1:]) # 简洁
强大的向量化运算¶
# 创建测试数据
lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(lst)
# 标量运算 - 一行搞定!
print("数组标量运算:")
print(arr + 10) # 每个元素加10
print(arr * 2) # 每个元素乘2
print(arr ** 2) # 每个元素平方
# 矩阵运算
print("转置:\n", arr.T)
print("求和:", arr.sum())
print("均值:", arr.mean())
# 矩阵乘法
b = np.array([[2, 0, 1], [1, 2, 3], [0, 1, 2]])
print("矩阵乘法:\n", arr @ b) # 矩阵乘法运算符
3 对比分析¶
核心差异总结¶
特性 |
二维列表 |
NumPy 二维数组 |
|---|---|---|
创建语法 |
|
|
元素访问 |
|
|
内存效率 |
存储对象引用,开销大 |
紧凑存储,效率高 |
数据类型 |
可混合类型 |
要求统一类型 |
运算支持 |
需手动循环实现 |
内置向量化运算 |
功能扩展 |
基础操作 |
丰富数学函数库 |
性能对比测试¶
import numpy as np
import time
# 大规模数据测试
size = 1000
data = [[i + j for j in range(size)] for i in range(size)]
# 列表运算时间
start = time.time()
result_list = [[x * 2 for x in row] for row in data]
list_time = time.time() - start
# NumPy 运算时间
arr = np.array(data)
start = time.time()
result_arr = arr * 2
numpy_time = time.time() - start
print(f"1000x1000 矩阵标量乘法:")
print(f"二维列表: {list_time:.4f} 秒")
print(f"NumPy数组: {numpy_time:.4f} 秒")
print(f"性能提升: {list_time/numpy_time:.1f} 倍")
适用场景指南¶
使用二维列表的情况:
# 混合数据类型
mixed_data = [
["Alice", 25, "Engineer"],
["Bob", 30, "Designer"],
["Charlie", 35, "Manager"]
]
# 不规则结构
irregular = [
[1, 2],
[3, 4, 5],
[6, 7, 8, 9]
]
使用 NumPy 数组的情况:
# 数值计算
matrix_ops = arr1 @ arr2 + arr3 * 2
# 科学计算
result = np.sin(arr) + np.log(arr + 1)
# 数据处理
filtered = arr[arr > 5] # 条件筛选
相互转换¶
# 列表 → 数组
python_list = [[1, 2, 3], [4, 5, 6]]
numpy_array = np.array(python_list)
# 数组 → 列表
back_to_list = numpy_array.tolist()
print("原始列表:", python_list)
print("NumPy数组:\n", numpy_array)
print("转换回列表:", back_to_list)
4. 练习¶
练习1:性能测试实践¶
创建一个 100x100 的随机数矩阵,比较两种结构的运算性能。
import random
import numpy as np
import time
# 生成 100x100 的随机数据
data = [[random.randint(1, 100) for _ in range(100)] for _ in range(100)]
任务要求:
分别使用二维列表和 NumPy 数组实现矩阵的标量乘法(乘以 5)
测量并比较两种方法的执行时间
分析性能差异的原因
要点:
NumPy 通常快 10-100 倍
原因:向量化运算、C语言底层实现、内存连续存储
练习2:实际应用场景¶
学生成绩管理系统中有以下数据:
# 学生成绩数据(姓名, 数学, 英语, 物理)
students_list = [
["Alice", 85, 92, 78],
["Bob", 76, 88, 90],
["Charlie", 92, 85, 88],
["Diana", 68, 72, 80]
]
任务要求:
分析这种数据结构适合用二维列表还是 NumPy 数组?为什么?
如果需要计算每个学生的平均分,你会选择哪种结构?请实现
如果只需要处理数值成绩(不含姓名),哪种结构更合适?请转换并计算各科平均分
要点:
混合数据类型适合用二维列表
纯数值计算适合用 NumPy 数组
练习3:图像处理综合应用¶
图像处理中经常使用二维数组。假设我们有一个简单的 4x4 灰度图像:
# 图像像素数据(0-255 表示灰度值)
image_list = [
[100, 120, 130, 110],
[115, 125, 135, 105],
[105, 115, 140, 120],
[125, 135, 125, 115]
]
任务要求:
将数据转换为 NumPy 数组
实现图像亮度调整:将所有像素值增加 50(注意不能超过 255)
实现图像对比度调整:将所有像素值乘以 1.2(注意边界处理)
提取图像的中央 2x2 区域
计算图像的平均亮度
提示:使用 np.clip 处理边界,np.mean 计算平均值等
图像可视化方法1: imshow()¶
import numpy as np
import matplotlib.pyplot as plt
img = ...
plt.imshow(img, cmap='gray')
plt.show()
plt.imshow(img + 50, cmap='gray')
plt.show()
plt.imshow(img * 1.2, cmap='gray')
plt.show()
图像可视化方法2: subplot()¶
import numpy as np
import matplotlib.pyplot as plt
# 原始图像数据
image_arr = ...
# 图像处理
brightened = image_arr + 50
contrasted = image_arr * 1.2
# 最简单的可视化
plt.figure(figsize=(10, 3))
plt.subplot(1, 3, 1)
plt.imshow(image_arr, cmap='gray')
plt.title('Original')
plt.subplot(1, 3, 2)
plt.imshow(brightened, cmap='gray')
plt.title('Brightness +50')
plt.subplot(1, 3, 3)
plt.imshow(contrasted, cmap='gray')
plt.title('Contrast ×1.2')
plt.show()