Python 列表/数组 : disable negative indexing wrap-around in slices

标签 python arrays list numpy slice

虽然我发现负数环绕(即 A[-2] 索引倒数第二个元素)在许多情况下非常有用,但当它发生在切片内部时,它通常更多与其说是有用的功能,不如说是一种烦恼,我经常希望有一种方法来禁用该特定行为。

下面是一个固定的 2D 示例,但我对其他数据结构和其他维数也有过几次同样的不满。

import numpy as np
A = np.random.randint(0, 2, (5, 10))

enter image description here

def foo(i, j, r=2):
  '''sum of neighbours within r steps of A[i,j]'''
  return A[i-r:i+r+1, j-r:j+r+1].sum()

在上面的切片中,我宁愿切片的任何负数都被视为与 None 相同,而不是换行到数组的另一端。

由于包装,上面其他方面不错的实现在边界条件下给出了错误的结果,并且需要某种补丁,例如:

def ugly_foo(i, j, r=2):
  def thing(n):
    return None if n < 0 else n
  return A[thing(i-r):i+r+1, thing(j-r):j+r+1].sum()

我也尝试过对数组或列表进行零填充,但它仍然不够优雅(需要相应地调整查找位置索引)并且效率低下(需要复制数组)。

我是否遗漏了一些标准技巧或优雅的切片解决方案?我注意到 python 和 numpy 已经很好地处理了您指定的数字太大的情况 - 也就是说,如果索引大于数组的形状,它的行为就好像它是 None 一样。

最佳答案

我的猜测是,您必须围绕所需对象创建自己的子类包装器并重新实现 __getitem__() 以将否定键转换为 None,然后调用父类(super class) __getitem__

请注意,我的建议是对现有自定义类进行子类化,而不是像 listdict 这样的内置类。这只是为了围绕另一个类创建实用程序,而不是混淆 list 类型的正常预期操作。这将是您希望在特定上下文中使用一段时间直到您的操作完成的东西。最好避免进行全局不同的更改,否则会使您的代码用户感到困惑。

Datamodel

object.getitem(self, key)
Called to implement evaluation of self[key]. For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the getitem() method. If key is of an inappropriate type, TypeError may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), IndexError should be raised. For mapping types, if key is missing (not in the container), KeyError should be raised.

你甚至可以创建一个包装器,它只需要一个实例作为参数,并且只是将所有 __getitem__() 调用推迟到那个私有(private)成员,同时转换 key ,以防你不能或者不想子类化一个类型,而只是想要一个用于任何序列对象的实用程序包装器。

后一个建议的简单示例:

class NoWrap(object):

    def __init__(self, obj, default=None):
        self._obj = obj 
        self._default = default

    def __getitem__(self, key):
        if isinstance(key, int):
            if key < 0:
                return self._default

        return self._obj.__getitem__(key)

In [12]: x = range(-10,10)
In [13]: x_wrapped = NoWrap(x)
In [14]: print x_wrapped[5]
-5
In [15]: print x_wrapped[-1]
None 
In [16]: x_wrapped = NoWrap(x, 'FOO')
In [17]: print x_wrapped[-1]
FOO

关于Python 列表/数组 : disable negative indexing wrap-around in slices,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13410615/

相关文章:

python - 查找列表中整数之间的差异

python - 如何使用独立的 stdout、stderr 和 stdin fork 一个新进程?

javascript - 如何延迟解析数组并在循环遍历时修改它?

arrays - 对先递增后递减的数组进行排序

c# - 识别List中的common Lists并返回List中的Distinct Lists

python - 将两个字典以及具有相同键的项目添加到一起

c# - 通过python脚本将值返回给c#程序

javascript - 将数组项打印到列表项中的更简单方法 (JavaScript)

python - 使用列表列表过滤列表列表

python - 转置/解压缩功能(zip的倒数)?