Python数组索引中冒号与其他运算符的优先级及切片赋值疑问
关于NumPy切片中表达式优先级与执行逻辑的清晰解释
嘿,这个问题太常见了!刚上手NumPy分块赋值的时候,很容易对切片里的表达式执行顺序产生疑惑,我来给你讲得明明白白~
首先直接给你结论:算术运算(乘法*、加法+)的优先级远高于切片的冒号语法,所以冒号两侧的所有运算会先被完全计算,再用计算后的结果作为切片的起始/结束索引。
针对你的代码具体拆解
看这段代码:
output_r[output_qr_dim * i:output_qr_dim * i + output_qr_dim, output_qr_dim * j:output_qr_dim * j + output_qr_dim] = ra
执行逻辑是分两步走的:
先计算所有切片边界的数值
Python会先把每个冒号左右的算术表达式都算出来:- 第一个维度的起始索引:
output_qr_dim * i - 第一个维度的结束索引:
output_qr_dim * i + output_qr_dim(其实等价于output_qr_dim * (i + 1)) - 第二个维度的起始索引:
output_qr_dim * j - 第二个维度的结束索引:
output_qr_dim * j + output_qr_dim
举个实际数值的例子:假设
output_qr_dim=3,i=1,j=2,那计算后就是:第一个切片是3:6,第二个切片是6:9。- 第一个维度的起始索引:
用计算后的索引执行切片赋值
当所有边界数值都确定后,NumPy会在output_r数组中定位出一个output_qr_dim × output_qr_dim的子矩阵区域,然后把ra的值整体赋值到这个区域里——这通常是在做分块矩阵的拼接或更新操作。
关键误区澄清
你之前的初始理解是对的!切片的冒号只是语法标记,用来分隔切片的「起始」「结束」「步长」三个参数,它本身不参与运算优先级的竞争。Python会先把冒号两侧的所有表达式求值完毕,再构建切片对象去索引数组。
直观验证示例
可以跑一段小代码来验证这个逻辑:
import numpy as np # 初始化参数 output_qr_dim = 2 i = 1 j = 0 output_r = np.zeros((4, 4)) # 4x4的全零矩阵 ra = np.ones((2, 2)) # 2x2的全一矩阵 # 执行你的赋值代码 output_r[output_qr_dim*i : output_qr_dim*i + output_qr_dim, output_qr_dim*j : output_qr_dim*j + output_qr_dim] = ra print(output_r)
运行后输出的矩阵会是:
[[0. 0. 0. 0.] [0. 0. 0. 0.] [1. 1. 0. 0.] [1. 1. 0. 0.]]
完全符合预期:第一个维度取2:4(第3、4行),第二个维度取0:2(第1、2列),把这个2x2区域赋值为1。
内容的提问来源于stack exchange,提问作者MigfibOri
相关产品推荐
相关产品推荐

