Python列表/数组:禁用负向索引换行
虽然我发现在很多情况下,负片数环绕(即A[-2]
索引倒数第二个元素)非常有用,但当它发生在片内时,通常比有用的功能更麻烦,而且我经常希望有一种方法来禁用该特定行为。
下面是一个2D的封装示例,但是我已经和其他数据结构以及其他维度数量相同。
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()
在上面的片段中,我宁愿片的任何负数将被视为与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
,然后调用超类__getitem__
请注意,我所建议的是将现有的自定义类进行子类化,而不是像list
或dict
一样dict
。 这只是为了围绕另一个类创建实用程序,而不是混淆list
类型的正常预期操作。 这将是你想在特定环境中使用一段时间直到你的操作完成。 最好避免进行全球不同的更改,这会使代码的用户感到困惑。
数据模型
目的。 getitem (自我,关键)
被称为实施自我评估[关键]。 对于序列类型,接受的键应该是整数和切片对象。 请注意,负指数的特殊解释(如果类希望模拟序列类型)取决于getitem ()方法。 如果密钥的类型不合适,则可能会引发TypeError; 如果对于序列的索引集合之外的值(在负值的任何特殊解释之后),应该引发IndexError。 对于映射类型,如果键缺失(不在容器中),应该引发KeyError。
你甚至可以创建一个简单的实例作为arg,并且只是将所有__getitem__()
调用都推迟到该私有成员,同时转换密钥(对于不能或不想要子类型的情况)而只需要一个用于任何序列对象的实用包装。
后一个建议的简单例子:
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
虽然你可以像jdi所建议的那样list
子list
,但是Python的切片行为并不是任何人希望你沉溺的东西。
改变它可能会导致其他人在使用你的代码时发生一些严重的头疼,当它不像预期的那样行事时 - 并且可能需要一段时间,然后才会查看你的子类的特殊方法,以查看实际发生的事情上。
请参阅:在远处采取行动
我认为这不足以证明新课程和包装事物的合理性。 然后再次它是你的代码。
def foo(i, j, r=2):
'''sum of neighbours within r steps of A[i,j]'''
return A[i-r:abs(i+r+1), j-r:abs(j+r+1)].sum() # ugly, but works?
(Downvoting很有趣,所以我增加了一些选项)
我发现了一些非常意想不到的事情(对我来说): __getslice__(i,j)
不包装! 相反,负指数被忽略,所以:
lst[1:3] == lst.__getslice__(1,3)
lst[-3:-1] == 2 next to last items
lst.__getslice__(-3,-1) == []
lst[-3:-1] == 2 next to last items
但是lst.__getslice__(-3,-1) == []
最后:
lst[-2:1] == []
,但是lst.__getslice__(-2,1) == lst[0:1]
令人惊讶,有趣,完全无用。
链接地址: http://www.djcxy.com/p/26753.html