遇到的报错
W = tensor[np.ix_(p[i] for i in range(d))]
Traceback (most recent call last):
File “E:\Projects\PythonProjects\TuckerCross\tuckercross\DEIM_FS_Tucker.py”, line 206, in
S_F_iter, U_F_iter = deim_fs_iterative(tensor, r_f, r_f_star, max_iter=10, tol=1e-6)
File “E:\Projects\PythonProjects\TuckerCross\tuckercross\DEIM_FS_Tucker.py”, line 171, in deim_fs_iterative
S_F, U_F, V_F, p_new = deim_fs(tensor, U_hat, r_f, r_f_star, p)
File “E:\Projects\PythonProjects\TuckerCross\tuckercross\DEIM_FS_Tucker.py”, line 94, in deim_fs
W = tensor[np.ix_((p[i]) for i in range(d))]
File “D:\Program_Environment\Anaconda3\envs\pytorch\lib\site-packages\numpy\lib\index_tricks.py”, line 101, in ix_
raise ValueError(“Cross index must be 1 dimensional”)
ValueError: Cross index must be 1 dimensional
解决方案
p = [np.asarray(idx).flatten() for idx in p]
W = tensor[np.ix_(*p)] # 使用*p解包列表
详细解释:*p 解包列表(Unpacking List with *)
在 Python 中,* 运算符可以用于 解包(unpack) 可迭代对象(如列表、元组、生成器等),将其元素作为独立的参数传递给函数。
1. 基本概念
- 假设有一个列表
p = [a, b, c],其中a, b, c可能是数组、列表或其他对象。 - 如果直接调用
func(p),函数func会接收到 一个参数,即列表p。 - 但如果调用
func(*p),Python 会 解包p,相当于调用func(a, b, c),即 3 个独立参数。
2. 在 np.ix_ 中的应用
np.ix_ 的语法是:
np.ix_(row_indices, col_indices, depth_indices, ...)
即它接受 多个1维数组,每个数组代表一个维度的索引。
错误写法:
p = [row_idx, col_idx, depth_idx] # 假设 p 是包含3个索引数组的列表
W = tensor[np.ix_(p)] # ❌ 错误!np.ix_ 需要多个参数,但这里只传了1个(列表p)
正确写法(使用 * 解包):
p = [row_idx, col_idx, depth_idx] # 仍然是一个列表
W = tensor[np.ix_(*p)] # ✅ 相当于 np.ix_(row_idx, col_idx, depth_idx)
*p 把列表 p 拆解 成多个独立参数,符合 np.ix_ 的要求。
3. 为什么你的代码需要 *?
在你的原始代码:
W = tensor[np.ix_((p[i] for i in range(d)))] # ❌ 错误
(p[i] for i in range(d))是一个生成器,np.ix_会认为它是 1个参数(一个生成器对象),而不是d个独立的索引数组。- 使用
*解包后:
现在W = tensor[np.ix_(*[p[i] for i in range(d)])] # ✅ 正确[p[i] for i in range(d)]是一个列表,*将其拆解成d个参数,分别传给np.ix_。
4. 类似用法举例
-
普通函数调用:
def add(a, b, c): return a + b + c nums = [1, 2, 3] result = add(*nums) # 相当于 add(1, 2, 3) -
zip解包:names = ["Alice", "Bob"] scores = [85, 90] zipped = list(zip(*[names, scores])) # 相当于 zip(names, scores)
总结
| 情况 | 代码示例 | 是否可行 | 解释 |
|---|---|---|---|
| 直接传列表 | np.ix_(p) | ❌ | np.ix_ 只收到1个参数(列表 p) |
| 解包列表 | np.ix_(*p) | ✅ | *p 把 p 拆成多个参数,符合 np.ix_ 的要求 |
因此,在你的代码中,使用 *p 解包列表是 必须的,否则 np.ix_ 无法正确处理多维索引。

7022

被折叠的 条评论
为什么被折叠?



