用于索引从 1 开始的 python 列表的自定义包装器
我想为 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
类的其他一些相关内置方法,例如 <代码>索引。
>>> len(p)
5
>>> p.index(p[-1])
5
请分享您关于我如何去做这样的事情的建议。我正在考虑是否只使用自定义类来完成它,但这似乎可能有点矫枉过正。我也欢迎任何关于有用的覆盖方法的建议。
编辑:后记
我只是想指出,这样做并不值得,我接受下面答案的原因并不是因为我试图以他的方式实现它描述,而是因为他帮助我意识到列表本身就足够好了。
I'd like to write a simple wrapper for the python list
type that forces it to start indexing at 1
instead of 0
. I've got a a fairly complex program based on some discrete probability distributions of duration data, with integer-length buckets, but I don't have any durations of less than 1. Anyway, it would greatly simplify a some significant portions of my code to be able to seamlessly index starting at 1. I was using a dict
at first but I found several properties of them to be too cumbersome.
I've never written a wrapper for a Python class before, much less a built-in type, but I feel like what I want to do is fairly simple. At the bare minimum, I should be able to do stuff like this:
>>> 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
However it would be good if I could overwrite some of the other relevant built-in methods of the list
class as well, such as index
.
>>> len(p)
5
>>> p.index(p[-1])
5
Please share your tips as to how I might go about doing something like this. I was considering whether or not to just do it with a custom class, but that seems like it might be overkill. I also welcome any recommendations as to useful methods to overwrite.
Edit: Afterword
I'd just like to note that it was not worth the trouble to do this, and the reason I've accepted the answer below is not because I tried to implement it in the way he describes, but because he helped me realize that lists are good enough on their own.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是一个完整的(我认为)基于 1 的列表的实现,正确处理切片(包括扩展切片)、索引、弹出等。正确处理这个问题比您想象的要稍微棘手一些,尤其是切片和负索引。事实上,我仍然不能 100% 确定它完全按照应有的方式工作,因此请注意编码器。
senderle 的
ExtraItemList
将会有更好的性能,因为它不'不需要不断调整索引,也不需要在您和数据之间有额外的(非 C!)方法调用层。希望我能想到这种方法;也许我可以将它与我的结合起来获利......Here's a complete (I think) implementation of a 1-based list, correctly handling slicing (including extended slices), indexing, popping, etc. It's slightly more tricky to get this right than you might think, especially the slicing and the negative indexes. In fact I'm still not 100% sure it works exactly as it should, so caveat coder.
senderle's
ExtraItemList
is going to have better performance, though, because it doesn't need to adjust the indices constantly nor does it have an extra layer of (non-C!) method calls between you and the data. Wish I'd thought of that approach; maybe I could profitably combine it with mine...好吧,看来你很有决心。正如我上面所说,你必须重写
__getitem__
、__setitem__
和__delitem__
。实际上,您还必须覆盖__getslice__
、__setslice__
、__delslice__
(否则切片像往常一样从 0 开始)。然后__add__
、__mul__
、__iadd__
、__imul__
也返回WonkyList
(否则串联将无法按照您想要的方式工作)。您必须覆盖index
因为它会返回错误的值(我测试过)。还有插入
、删除
和弹出
。这里有一些可以帮助您开始的东西:已测试:
以下是一些方法,除非您覆盖所有必要的方法,否则它会失败:
或者您可以尝试其他方法。例如,您是否考虑过...
这似乎可以解决您列出的问题,并且它仍然以基本上类似列表的方式运行,即使初始化程序有点奇怪。虽然说实话,看看你给出的例子,我开始觉得这甚至是一个丑陋的解决方案——你给出的函数都没有显示出从 1 开始索引的优点,它们只是显示了添加的坏影响列表开头的额外项目。根据这些示例,您应该只使用常规列表。
也许最好的方法是编写使用所需偏移量的自定义
get
和set
方法。这样列表就会正常运行,但在需要时您将有一个替代界面。Ok, well, you seem very determined. As I said above, you have to override
__getitem__
,__setitem__
, and__delitem__
. Actually you'll also have to override__getslice__
,__setslice__
,__delslice__
(otherwise slicing starts at 0 as usual). Then__add__
,__mul__
,__iadd__
,__imul__
to returnWonkyList
s as well (otherwise concatenation won't work the way you'd want). You'll have to overrideindex
because it will return a wrong value (I tested it). Alsoinsert
,remove
, andpop
. Here's something to get you started:Tested:
Here are some ways it will fail until you override all the necessary methods:
Or you could try something else. Have you considered, for example...
That seems to take care of the issues you list, and it still behaves in a basically list-like manner, even if the initializer is a little weird. Though to be honest, looking at the examples you gave, I'm starting to feel like even this is an ugly solution -- none of the functions you gave show the advantage of starting indexing from 1, they just show the bad effects of adding an extra item to the beginning of the list. Based on those examples, you should just use a regular list.
Perhaps the best approach would be to write custom
get
andset
methods that use the desired offset. That way the lists would behave normally, but you'd have an alternative interface when needed.这是一个可以帮助您入门的基本实现。我认为概括它会很好,这样您就可以拥有索引从您喜欢的任何整数开始的列表。这让我发现
__slots__
,所以谢谢为了问这个问题!您可能会发现您也想实现
__getslice__
、__setslice__
、__delslice__
,更不用说pop
和插入
。Here's a basic implementation to get you started. I thought it would be nice to generalize it, so you can have lists with indices starting at any integer you like. This led me to discover
__slots__
, so thank you for asking this question!You may find you want to implement
__getslice__
,__setslice__
,__delslice__
too, not to mentionpop
andinsert
.