我想为 python list
类型编写一个简单的包装器,强制它从 1
而不是 0
开始索引。我有一个相当复杂的程序,它基于持续时间数据的一些离散概率分布,具有整数长度的桶,但我没有任何小于 1 的持续时间。无论如何,它会大大简化我代码的一些重要部分能够从 1 开始无缝索引。起初我使用的是 dict
,但我发现它们的几个属性太麻烦了。
我以前从未为 Python 类编写过包装器,更不用说内置类型了,但我觉得我想做的事情相当简单。至少,我应该能够做这样的事情:
>>> p = one_list([1,2,3,4,5])
>>> for i in range(1,6):
print i, p[i]
1 1
2 2
3 3
4 4
5 5
>>> len(p)
5
但是,如果我也可以覆盖 list
类的一些其他相关内置方法,例如 index
,那就太好了。
>>> len(p)
5
>>> p.index(p[-1])
5
请分享您的技巧,告诉我如何去做这样的事情。我在考虑是否只用自定义类来做,但这似乎有点过头了。我也欢迎任何关于有用的覆盖方法的建议。
编辑:后记
我只是想指出这样做是不值得的,我接受下面答案的原因不是因为我试图按照他描述的方式实现它,而是因为他帮助了我意识到列表本身就足够了。
最佳答案
这是一个完整的(我认为)基于 1 的列表的实现,正确处理切片(包括扩展切片)、索引、弹出等。要做到这一点比你想象的要复杂一些,尤其是切片和负面指标。事实上,我仍然不能 100% 确定它能正常工作,所以警告编码员。
class list1(list):
"""One-based version of list."""
def _zerobased(self, i):
if type(i) is slice:
return slice(self._zerobased(i.start),
self._zerobased(i.stop), i.step)
else:
if i is None or i < 0:
return i
elif not i:
raise IndexError("element 0 does not exist in 1-based list")
return i - 1
def __getitem__(self, i):
return list.__getitem__(self, self._zerobased(i))
def __setitem__(self, i, value):
list.__setitem__(self, self._zerobased(i), value)
def __delitem__(self, i):
list.__delitem__(self, self._zerobased(i))
def __getslice__(self, i, j):
print i,j
return list.__getslice__(self, self._zerobased(i or 1),
self._zerobased(j))
def __setslice__(self, i, j, value):
list.__setslice__(self, self._zerobased(i or 1),
self._zerobased(j), value)
def index(self, value, start=1, stop=-1):
return list.index(self, value, self._zerobased(start),
self._zerobased(stop)) + 1
def pop(self, i):
return list.pop(self, self._zerobased(i))
不过,senderle 的 ExtraItemList
将具有更好的性能,因为它不需要不断调整索引,也不需要额外的层(非 C!)方法调用和数据。希望我能想到这种方法;也许我可以将它与我的...结合起来获利...
关于python - 用于从 1 开始索引 python 列表的自定义包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6713463/