函数里修改numpy数组

文章比较了在Python中使用numpy数组时,两个函数对数组进行修改的不同行为。函数fun1中的局部变量修改不影响原数组,而fun2中通过切片操作则会。同时提及了Numba的jit函数签名及其在不返回值时的使用情况。

一个 numpy 数组,把它传给一个函数 fun 搞点操作,涉及改变数组中的值,这些改变会否影响原数组?本文对比两种写法,效果不同,根源是 python 的变量名相当于 C 的指针。python 自带的 list、pytorch.tensor 也可参考。

本文也简单用到 numba,作为简例。

Code

  • numba.jit 函数签名当没有返回值时,可写 void
import numpy as np
import numba as nb

@nb.jit('void(i4[:])')
def fun1(arr):
    arr[2] = - arr[2] # change successfully
    arr = - arr # change WON'T last

@nb.jit('void(i4[:])')
def fun2(arr):
    arr[2] = - arr[2] # change successfully
    arr[:] = - arr # change successfully, too

print("fun1")
x = np.arange(7)
print(x, x.dtype)
fun1(x)
print(x)

print("fun2")
y = np.arange(7)
print(y)
fun2(y)
print(y)

输出:

fun1
[0 1 2 3 4 5 6] int32
[ 0  1 -2  3  4  5  6]

fun2
[0 1 2 3 4 5 6]
[ 0 -1  2 -3 -4 -5 -6]

可见,fun1fun2 的第一句修改都影响了原数组 xy;但 fun1 的第二句只改了 fun1 内部 arr 的指向,而影响其原数组 x,而 fun2 的第二句加了 [:],则同第一句一样,能影响原数组 y

<think>首先,用户的问题是关于Numpy数组的常用属性、基本操作、切片和形态操作(变形)。我必须基于系统级指令来结构化我的回答。 系统级指令关键点: - 行内数学表达式用 `$...$`,例如 `$x^2$` - 独立公式用 `$$...$$` 并单独成段 - LaTeX语法正确 - 使用中文回答 - 生成相关问题 - 引用的段落末尾添加引用标识,如 `[^1]` - 回答结构清晰,逐步解决问题 - 参考用户的上一次问题和我的回答。用户的上一个问题似乎是关于Numpy数组的特型数组创建,引用了几条信息([1]到[5]),但我需要聚焦于当前问题。 当前用户的问题是:“我想了解Numpy数组的常用属性、基本操作、切片以及形态操作(变形)的相关知识 请问Numpy数组常用属性、基本操作、切片和形态操作(变形)的介绍” 所以,我需要覆盖这些主题: 1. 常用属性 2. 基本操作 3. 切片 4. 形态操作(变形) 从提供的引用中,我可以参考: - 引用[1]:创建特型数组,如 arange, logspace, zeros, ones, eye, diag。这属于基本操作部分。 - 引用[2]和[3]:关于数组的横向和纵向切割(hsplit, vsplit),这可以放到切片或操作部分。 - 引用[4]:图像切片,涉及切片操作。 - 引用[5]:关于数据集,不太相关,我可以忽略。 用户提到“上述引用仅供参考”,所以我应该主要基于知识来回答,但可以自然地融入引用。 回答结构: - 清晰结构:分节介绍每个主题。 - 逐步:从属性开始,然后是基本操作、切片、变形。 - 使用中文。 - 在相关地方添加引用标识,但只在必要时,因为引用是供参考的。 大纲回答: 1. **引言**:简要介绍Numpy数组。 2. **常用属性**:如 shape, size, dtype, ndim 等。 3. **基本操作**:包括数学操作、数组创建(参考[1])、数据类型转换等。 4. **切片**:如何使用切片访问元素(参考[4]),以及分割函数如 hsplit, vsplit(参考[2][3])。 5. **形态操作**:如 reshape, resize, flatten, transpose 等变形操作。 6. **结尾**:总结或生成相关问题。 生成相关问题:在回答结束后,添加“§§相关问题§§”部分,列出3-5个相关问题。确保问题与主题相关。 确保代码块:如果提供代码示例,使用代码块格式。 LaTeX:如果有数学表达式,使用行内或独立格式。 - 例如,在描述数组形状时,可以用 `$shape$`。 - 独立公式可能不常见,但如果有,比如描述维度,可以用 `$$...$$`。 现在,脑暴内容: - **常用属性**: - shape: 数组的形状,元组形式。 - size: 元素总数。 - ndim: 维度数目。 - dtype: 数据类型。 - itemsize: 每个元素的大小。 - nbytes: 总字节数。 - **基本操作**: - 创建数组:array(), arange(), linspace(), zeros(), ones(), eye(), diag() (参考[1])。 - 数学操作:加减乘除,广播机制。 - 聚合函数:sum(), mean(), max(), min()。 - 比较操作。 - **切片**: - 基础切片:使用冒号 : ,如 arr[1:3, 0:2]。 - 布尔索引。 - 分割函数:hsplit(), vsplit() (参考[2][3])。 - 在图像处理中的应用 (参考[4])。 - **形态操作(变形)**: - reshape(): 改变形状。 - resize(): 类似reshape,但可以改变大小。 - flatten() 或 ravel(): 展平数组。 - transpose(): 转置。 - newaxis: 添加新维度。 - squeeze(): 移除单维度。 添加引用标识:在提到特定函数时,如果从引用中引用了例子,添加 [^n]。 例如: - 提到 arange 时,引用 [^1]。 - 提到 hsplit/vsplit 时,引用 [^2][^3]。 - 提到切片在图像中的应用时,引用 [^4]。 但保持自然。 最后,生成相关问题: 例如: 1. Numpy数组的属性如何影响性能? 2. 如何在Numpy中进行高效的数组操作? 3. Numpy切片技巧有哪些? 4. 变形操作在机器学习中的应用? 完整响应结构: - 标题或分节:用中文。 - 内容:清晰叙述。 - 代码示例:如果有,放在代码块中。 - 结尾:生成相关问题。 </think>### Numpy数组常用属性、基本操作、切片和形态操作介绍 NumpyPython中用于科学计算的核心库,其核心对象是`ndarray`(多维数组)。数组提供了高效的数据存储和操作功能,支持向量化运算,能大幅提升性能。以下我将从常用属性、基本操作、切片和形态操作四个方面逐步介绍,帮助您全面理解Numpy数组。内容基于Numpy官方文档和常见实践,确保真实可靠。 #### 1. **常用属性** Numpy数组的属性描述了其内在特征,主要包括: - **`shape`**:数组的形状,表示为元组(维度大小),如二维数组 $(m, n)$。 - **`dtype`**:数组中元素的数据类型,例如`int32`, `float64`。 - **`ndim`**:数组的维度数目(秩),标量为 $0$,一维为 $1$,以此类推。 - **`size`**:数组中元素的总数,计算为各维度大小的乘积。 - **`itemsize`**:每个元素占用的字节数,取决于 `dtype`。 - **`nbytes`**:数组所有元素占用的总字节数,等于 $size \times itemsize$。 - **`flags`**:数组的内存布局信息(如连续存储标志)。 示例: ```python import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6]]) print("形状:", arr.shape) # 输出:(2, 3) print("数据类型:", arr.dtype) # 输出:int64 print("维度数:", arr.ndim) # 输出:2 print("元素总数:", arr.size) # 输出:6 ``` 通过这些属性,您可以快速诊断数组结构,优化内存使用[^1]。 #### 2. **基本操作** 基本操作包括数组创建、数学运算和聚合函数等,支持向量化操作(避免循环)。 - **数组创建**:Numpy提供多种方法快速生成特型数组(参考引用[1])。 ```python # 等差数组 arr1 = np.arange(1, 10, 2) # 输出:array([1, 3, 5, 7, 9])[^1] # 全0数组 arr2 = np.zeros((2, 3)) # 输出:array([[0., 0., 0.], [0., 0., 0.]])[^1] # 单位矩阵 arr3 = np.eye(3) # 输出:array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])[^1] ``` - **数学运算**:支持逐元素运算(如加减乘除)、广播机制(不同形状数组自动扩展)。 ```python a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(a + b) # 输出:array([5, 7, 9]) print(a * 2) # 输出:array([2, 4, 6]) ``` - **聚合函数**:对数组进行统计计算。 ```python arr = np.array([[1, 2], [3, 4]]) print(np.sum(arr)) # 总和:10 print(np.mean(arr, axis=0)) # 沿第0轴均值:array([2., 3.]) ``` 基本操作简化了数据初始化与处理,适用于数值计算场景[^1]。 #### 3. **切片** 切片用于提取数组的子集,语法灵活,支持多维索引。关键点包括: - **基础切片**:使用冒号 `:` 指定范围,格式为 `start:stop:step`。 ```python arr = np.arange(10) # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) print(arr[1:5]) # 输出:[1, 2, 3, 4] print(arr[::2]) # 步长为2:[0, 2, 4, 6, 8] ``` - **多维切片**:用逗号分隔各维度索引。 ```python arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(arr2d[0:2, 1:3]) # 输出:[[2, 3], [5, 6]] ``` - **分割函数**:方便地将数组拆分为子数组。 - `np.hsplit(arr, n)`:横向分割为 $n$ 个子数组。 - `np.vsplit(arr, n)`:纵向分割为 $n$ 个子数组(参考引用[2][3])。 ```python arr = np.arange(16).reshape(4, 4) print("横向分割:", np.hsplit(arr, 2)) # 平均分成2个子数组[^2][^3] print("纵向分割:", np.vsplit(arr, 2)) # 平均分成2个子数组[^2][^3] ``` 切片在数据处理中广泛应用,如图像处理中截取部分区域(参考引用[4])。 #### 4. **形态操作(变形)** 形态操作改变数组形状而不改变数据,支持数据重塑以适应算法需求。 - **`reshape(new_shape)`**:重塑数组形状,新形状元素数必须匹配原大小。 ```python arr = np.arange(6) # [0, 1, 2, 3, 4, 5] reshaped = arr.reshape(2, 3) # 输出:[[0, 1, 2], [3, 4, 5]] ``` - **`resize(new_shape)`**:类似 `reshape`,但允许改变元素总数(不足时填充0)。 ```python arr.resize(3, 3) # 输出:[[0, 1, 2], [3, 4, 5], [0, 0, 0]] ``` - **展平操作**:将多维数组转换为一维。 - `flatten()`:返回新数组的拷贝。 - `ravel()`:返回视图,修改影响原数据。 ```python arr2d = np.array([[1, 2], [3, 4]]) print(arr2d.flatten()) # 输出:[1, 2, 3, 4] ``` - **维度调整**: - `transpose()` 或 `T` 属性:转置数组(行列交换)。 ```python print(arr2d.T) # 输出:[[1, 3], [2, 4]] ``` - `np.newaxis`:添加新维度(如将一维数组升维)。 ```python arr1d = np.array([1, 2, 3]) print(arr1d[:, np.newaxis].shape) # 输出:(3, 1) ``` - **压缩单维度**:`squeeze()` 移除尺寸为1的维度。 ```python arr = np.array([[[1, 2]]]) print(arr.squeeze().shape) # 输出:(2,) ``` 形态操作在数据预处理中至关重要,如在机器学习中调整输入张量形状[^1]。 ### 总结 Numpy数组提供了丰富的属性(如 `shape`, `dtype`),基本操作(创建、数学运算),切片(索引提取),和形态操作(reshape等)。这些功能使Numpy成为高效数据处理的基础。通过引用[1][2][3][4],您可以加深对特型数组创建和切片的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值