NumPy 数组复制有多种方法,主要分为 浅拷贝(视图) 和 深拷贝(副本) 两类。以下是主要的实现方法:
1. 浅拷贝(视图,共享内存)
a) 切片操作
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
arr_view = arr[:] # 创建视图
arr_view[0] = 100 # 修改视图会影响原始数组
print(arr) # [100 2 3 4 5]
b) view() 方法
arr = np.array([1, 2, 3, 4, 5])
arr_view = arr.view()
arr_view[1] = 200 # 修改会影响原始数组
2. 深拷贝(副本,独立内存)
a) copy() 方法(最常用)
arr = np.array([1, 2, 3, 4, 5])
arr_copy = arr.copy()
arr_copy[0] = 100 # 修改副本不会影响原始数组
print(arr) # [1 2 3 4 5]
b) np.copy() 函数
arr = np.array([1, 2, 3, 4, 5])
arr_copy = np.copy(arr)
c) np.array() 构造函数
arr = np.array([1, 2, 3, 4, 5])
arr_copy = np.array(arr, copy=True) # copy=True 是默认值
# 或者简写
arr_copy = np.array(arr)
d) 切片 + copy()(复杂切片时)
arr = np.array([[1, 2], [3, 4]])
# 如果只做切片,仍然是视图
arr_slice_view = arr[0:2, 0:2]
# 需要复制切片结果
arr_slice_copy = arr[0:2, 0:2].copy()
3. 特殊情况的复制
a) 结构化数组的复制
# 结构化数组
dtype = [('name', 'U10'), ('age', 'i4')]
arr = np.array([('Alice', 25), ('Bob', 30)], dtype=dtype)
arr_copy = arr.copy() # 会复制所有字段
b) 内存布局转换时的复制
arr = np.array([[1, 2], [3, 4]], order='C')
arr_fortran = np.asfortranarray(arr) # 转换为 Fortran 顺序,通常会产生复制
4. 验证复制类型的方法
def check_copy_type(original, new_array):
print("数据相同:", np.array_equal(original, new_array))
print("共享内存:", np.shares_memory(original, new_array))
print("内存地址相同:", original.__array_interface__['data'][0] ==
new_array.__array_interface__['data'][0])
5. 性能比较和建议
| 方法 |
内存使用 |
速度 |
适用场景 |
|---|
view()/切片 |
低(共享) |
快 |
需要观察数据而不修改 |
copy() |
高(独立) |
慢 |
需要修改且不影响原数据 |
np.array() |
高(独立) |
中等 |
从其他数组创建新数组 |
使用建议:
默认使用 copy() - 最安全,避免意外的副作用
大数据集考虑内存 - 如果数据很大且只读,使用视图节省内存
链式操作注意 - 多个操作组合时可能产生不必要的复制
# 不好的写法:产生中间副本
result = arr.copy().reshape(10, 10).T.copy()
# 好的写法:尽量减少复制
result = arr.reshape(10, 10).T.copy()
选择哪种方法取决于具体需求:如果需要独立修改数据,使用深拷贝(copy());如果只是查看或临时计算,使用浅拷贝可以节省内存。