Python列表/数组:禁用索引负环绕在片 [英] Python lists/arrays: disable negative indexing wrap-around in slices

查看:258
本文介绍了Python列表/数组:禁用索引负环绕在片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然我觉得回绕负数(即 A [-2] 索引第二到最后一个元素)在许多情况下是非常有用的,当它发生内切片它通常是一个多有用的功能一个烦恼,我常常希望换一种方式来禁用特定的行为。

While I find the negative number wraparound (i.e. A[-2] indexing the second-to-last element) extremely useful in many cases, when it happens inside a slice it is usually more of an annoyance than a helpful feature, and I often wish for a way to disable that particular behaviour.

下面是低于罐装2D例子,但我有同样的忌讳几次与其他数据结构和尺寸的其他号码。

Here is a canned 2D example below, but I have had the same peeve a few times with other data structures and in other numbers of dimensions.

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

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()

在切片以上我宁愿任何负数的切片将被视为相同是,而不是包装到阵列的另一端。

In the slice above I would rather that any negative number to the slice would be treated the same as None is, rather than wrapping to the other end of the array.

由于包装的,否则在执行好看上面给出的边界条件不正确的结果和需要某种像补丁的:

Because of the wrapping, the otherwise nice implementation above gives incorrect results at boundary conditions and requires some sort of patch like:

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()

我也尝试零填充的数组或列表,但它仍然是不雅(需要相应地调整位置查找索引)和低效(需要复制数组)。

I have also tried zero-padding the array or list, but it is still inelegant (requires adjusting the lookup locations indices accordingly) and inefficient (requires copying the array).

我缺少一些标准的伎俩,或优雅的解决方案可以用来处理这个样子?我注意到,Python和numpy的已处理其中指定得大一些很好的情况下 - 也就是说,如果指数比数组的形状越大它的行为一样,如果它是

Am I missing some standard trick or elegant solution for slicing like this? I noticed that python and numpy already handle the case where you specify too large a number nicely - that is, if the index is greater than the shape of the array it behaves the same as if it were None.

推荐答案

我的猜测是,你必须创建一个围绕期望的对象自己的子类包装和重新实施 __的GetItem __()负键转换为,然后调用父类 __ __的GetItem

My guess is that you would have to create your own subclass wrapper around the desired objects and re-implement __getitem__() to convert negative keys to None, and then call the superclass __getitem__

请注意,我的建议是继承现有的自定义类,但不是内建像列表字典。这仅仅是做一个实用围绕另一个类,不要混淆一个列表的正常预期的操作类型。这将是你会想你的,直到操作完成一定的上下文中使用了一段时间的东西。最好是避免全球不同的变化,这将混淆你的code的用户。

Note, what I am suggesting is to subclass existing custom classes, but NOT builtins like list or dict. This is simply to make a utility around another class, not to confuse the normal expected operations of a list type. It would be something you would want to use within a certain context for a period of time until your operations are complete. It is best to avoid making a globally different change that will confuse users of your code.

数据模型

对象。的GetItem (自我,键)结果
  所谓实行评价
  自[关键]。对于序列类型,可接受的键应该是整数
  和切片对象。需要注意的是负面的特殊间pretation
  索引(如果类希望模拟序列类型)是至
  的GetItem ()方法。如果关键是不合适的类型的,类型错误可能会提高;如果设定为索引以外的值的
  序列(负值的任何特殊间pretation后)
  IndexError应该提高。对于映射类型,如果钥匙丢失(不
  在容器中),KeyError异常应提高

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.

您甚至可以创建一个包装,仅仅需要一个实例作为ARG,只是推迟所有的 __的GetItem __()调用私有成员,而转换键,情况下,你不能或不愿继承一个类型,而是只想任何序列对象的实用工具的包装。

You could even create a wrapper that simply takes an instance as an arg, and just defers all __getitem__() calls to that private member, while converting the key, for cases where you can't or don't want to subclass a type, and instead just want a utility wrapper for any sequence object.

后者的建议简单的例子:

Quick example of the latter suggestion:

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列表/数组:禁用索引负环绕在片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆