Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于索引从1开始的python列表的自定义包装器_Python_List_Types_Operator Overloading_Wrapper - Fatal编程技术网

用于索引从1开始的python列表的自定义包装器

用于索引从1开始的python列表的自定义包装器,python,list,types,operator-overloading,wrapper,Python,List,Types,Operator Overloading,Wrapper,我想为pythonlist类型编写一个简单的包装器,强制它从1开始索引,而不是0。我有一个相当复杂的程序,基于持续时间数据的离散概率分布,有整数长度的桶,但我没有任何持续时间小于1。无论如何,它将大大简化我的代码中的一些重要部分,以便能够从1开始无缝索引。起初我使用的是dict,但我发现它们的几个属性太麻烦了 我以前从未为Python类编写过包装器,更不用说内置类型了,但我觉得我想做的事情相当简单。至少,我应该能够做这样的事情: >>> p = one_list([1,2,3,

我想为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
但是,如果我也可以覆盖
列表
类的其他相关内置方法,例如
索引
,那就太好了

>>> len(p)
5
>>> p.index(p[-1])
5
请分享你的建议,告诉我如何做这样的事情。我在考虑是否只使用自定义类来实现它,但这似乎有点过头了。我也欢迎任何关于覆盖有用方法的建议

编辑:后记


我只想指出,这样做是不值得的,我之所以接受下面的答案,并不是因为我试图按照他所描述的方式来实施,而是因为他帮助我意识到列表本身就足够好了。

好吧,好吧,你看起来很有决心。正如我上面所说的,你必须覆盖,并且。实际上,您还必须重写
\uuuu getslice\uuuuuuu
\uuuuuu setslice\uuuuu
\uuu delslice\uuuuuu
(否则切片通常从0开始)。然后
\uuuu add\uuuu
\uuu mul\uuuu
\uu iadd\uuuu
\uuu imul\uuuuu
也返回
WonkyList
以返回
WonkyList
。您必须重写
索引
,因为它将返回错误的值(我测试了它)。另外还有
插入
删除
弹出
。以下是一些让您开始学习的内容:

class WonkyList(list):
    def __getitem__(self, index):
        return super(WonkyList, self).__getitem__(index - 1)
    def __setitem__(self, index, val):
        super(WonkyList, self).__setitem__(index - 1, val)
    def __delitem__(self, index):
        super(WonkyList, self).__delitem__(index - 1)
测试:

>>> w = WonkyList(range(10))
>>> w[1]
0
>>> del w[5]
>>> w
[0, 1, 2, 3, 5, 6, 7, 8, 9]
>>> w[1] = 10
>>> w
[10, 1, 2, 3, 5, 6, 7, 8, 9]
以下是在覆盖所有必要方法之前它将失败的一些方法:

>>> w
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> w[5]
4
>>> w.pop(5)
5
>>> w.insert(5, 5)
>>> w
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del w[2:4]
>>> w
[0, 1, 4, 5, 6, 7, 8, 9]
>>> 
>>> w.index(1)
1

或者你可以试试别的。例如,你有没有考虑过

def ExtraItemList(list):
    def __init__(self, seq):
        self[0] = 0
        self[1:] = seq
    def n_items(self):
        return len(self) - 1
这似乎解决了您列出的问题,并且它仍然以基本类似于列表的方式运行,即使初始值设定项有点奇怪。尽管说实话,看看你给出的例子,我开始觉得即使这是一个丑陋的解决方案——你给出的函数都没有显示从1开始索引的优势,它们只是显示了在列表开头添加额外项的不良影响。基于这些示例,您应该只使用常规列表


也许最好的方法是编写使用所需偏移量的自定义
get
set
方法。这样列表将正常运行,但在需要时,您将有一个替代接口

下面是一个基本的实现,让您开始。我认为推广它会很好,这样你就可以有索引从你喜欢的任何整数开始的列表。这让我发现,谢谢你提出这个问题

class OffsetList(list):
    __slots__ = 'offset'
    def __init__(self, init=[], offset=-1):
        super(OffsetList, self).__init__(init)
        self.offset = offset
    def __getitem__(self, key):
        return super(OffsetList, self).__getitem__(key + self.offset)
    def __setitem__(self, key, value):
        return super(OffsetList, self).__setitem__(key + self.offset, value)
    def __delitem__(self, key):
        return super(OffsetList, self).__delitem__(key + self.offset)
    def index(self, *args):
        return super(OffsetList, self).index(*args) - self.offset

>>> a = OffsetList([1,2,3])
>>> a
[1, 2, 3]
>>> a[1]
1
>>> a.index(2)
2
你可能会发现你也想实现
\uuuu getslice\uuuuuuuuuuuuuuuu
\uuuuuuu delslice\uuuuuuuuu
,更不用说
pop
insert

这是一个完整的(我认为)基于1的列表实现,正确处理切片(包括扩展切片)、索引、弹出、,等等。要想正确处理这个问题比你想象的要稍微复杂一些,尤其是切片和负索引。事实上,我仍然不能100%确定它是否能正常工作,所以请注意编码器

类列表1(列表):
“”“基于一个版本的列表。”“”
基于零的定义(自我,i):
如果类型(i)为切片:
返回片(自零基(即开始),
自。_基于零的(i.stop),i.step)
其他:
如果i为无或i<0:
返回i
如果不是我:
raise索引器(“基于1的列表中不存在元素0”)
返回i-1
定义获取项目(自我,i):
返回列表。\uuuu getitem(self,self.\u基于零的(i))
定义设置项(自身、i、值):
列表。设置项(自,自。基于零的(i),值)
定义(自我,i):
列表.uuu delitem(self,self.u零基(i))
定义获取切片(self,i,j):
打印i,j
返回列表。获取切片(self,self.\u基于零的(i或1),
自校正(零基(j))
def_uu设置许可证(self,i,j,value):
列表。设置许可证(自、自、基于零(i或1),
自。_零基(j),值)
def索引(self、value、start=1、stop=-1):
返回列表.索引(self,value,self.\u零基(start),
自零点(停止))+1
def pop(自我,i):
返回列表.pop(self,self.\u零基(i))

senderle的
ExtraItemList
将具有更好的性能,因为它不需要不断调整索引,也不需要在您和数据之间有额外的(非C!)方法调用层。但愿我想到了那种方法;也许我可以把它和我的结合起来……不要。您的代码将不可能由其他任何人维护。你为什么要这样做?@吉姆:我不同意。这是一种非常直观的方式来查看和索引我的数据,我在上面解释过。我可能会将这个类的使用限制在我的文件空间中的1到2个模块内,并且我会非常清楚地给出如何使用它的注释。我认为在直观的代码可读性/可写性方面进行权衡是值得的。这看起来更合适。好吧,这就像覆盖一样简单,而且——但我必须同意吉姆·加里森的观点,可能有更好更合适的方法
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))