Skip to main content
 首页 » 编程设计

python / NumPy : negate or complement a slice

2025年05月04日10jackei

我有一些功能,大型分析软件的一部分,需要 bool 掩码将数组项分成两组。这些函数是这样的:

def process(data, a_mask): 
    b_mask = -a_mask 
    res_a = func_a(data[a_mask]) 
    res_b = func_b(data[b_mask]) 
    return res_a, res_b 

现在,我需要将这些函数(未经修改)用于一个只有“a”类项目的大数组,但我想节省 RAM 并且不传递所有 True 的 bool 掩码。例如,我可以传递像 slice(None, None) 这样的切片。

问题是如果 a_mask 是一个切片,行 b_mask = -a_mask 将失败。理想情况下,-a_mask 应该提供 0 项选择。

我正在考虑创建一个“修改过的”切片对象,将 __neg__() 方法实现为空切片(例如 slice(0, 0))。我不知道这是否可能。

允许不修改 process() 函数但同时避免分配全真 bool 数组的其他解决方案也将被接受。

请您参考如下方法:

不幸的是,我们无法将 __neg__() 方法添加到 slice,因为它 cannot be subclassed .但是,tuple 可以被子类化,我们可以用它来保存单个 slice 对象。

这让我想到了一个非常非常非常的讨厌的 hack,它应该对你有用:

class NegTuple(tuple): 
    def __neg__(self): 
        return slice(0) 

我们可以创建一个包含单个切片对象的 NegTuple:

nt = NegTuple((slice(None),)) 

这可以用作索引,将它取反会产生一个空切片,导致索引长度为 0 的数组:

a = np.arange(5) 
print a[nt] 
# [0 1 2 3 4] 
print a[-nt] 
# [] 

不过,你必须非常绝望地求助于这样的事情。像这样修改 process 是完全不可能的吗?

def process(data, a_mask=None): 
    if a_mask is None: 
        a_mask = slice(None)  # every element 
        b_mask = slice(0)     # no elements 
    else: 
        b_mask = -a_mask 
    res_a = func_a(data[a_mask]) 
    res_b = func_b(data[b_mask]) 
    return res_a, res_b 

这是更明确的方式,应该不会对其当前用例的行为产生任何影响。