Python中*号解包列表中的参数

遇到的报错

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) *pp 拆成多个参数,符合 np.ix_ 的要求

因此,在你的代码中,使用 *p 解包列表是 必须的,否则 np.ix_ 无法正确处理多维索引。

你可能感兴趣的:(Python学习,编程问题专栏,python,开发语言)