How to inherit and extend a list object in Python?

后端 未结 4 1694
盖世英雄少女心
盖世英雄少女心 2020-12-05 04:14

I am interested in using the python list object, but with slightly altered functionality. In particular, I would like the list to be 1-indexed instead of 0-indexed. E.g.:

4条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-05 04:26

    You can avoid violating the Liskov Substitution principle by creating a class that inherits from collections.MutableSequence, which is an abstract class. It would look something like this:

    class MyList(collections.MutableSequence):
    def __init__(self, l=[]):
        if type(l) is not list:
            raise ValueError()
    
        self._inner_list = l
    
    def __len__(self):
        return len(self._inner_list)
    
    def __delitem__(self, index):
        self._inner_list.__delitem__(index - 1)
    
    def insert(self, index, value):
        self._inner_list.insert(index - 1, value)
    
    def __setitem__(self, index, value):
        self._inner_list.__setitem__(index - 1, value)
    
    def __getitem__(self, index):
        return self._inner_list.__getitem__(index - 1)
    

    There is one problem here (though there might be more). If you index your new list like this:

    l = MyList()
    l[0]
    

    you will actually call:

    self._inner_list[-1]
    

    which will get you the last element. So you must do additional checking in the methods and make sure you keep the reverse indexing, if you want to have that feature for your list.

    EDIT:

    Here is the new code, which I believe should not have any problems.

    def indexing_decorator(func):
    
        def decorated(self, index, *args):
            if index == 0:
                raise IndexError('Indices start from 1')
            elif index > 0:
                index -= 1
    
            return func(self, index, *args)
    
        return decorated
    
    
    class MyList(collections.MutableSequence):
        def __init__(self):
            self._inner_list = list()
    
        def __len__(self):
            return len(self._inner_list)
    
        @indexing_decorator
        def __delitem__(self, index):
            self._inner_list.__delitem__(index)
    
        @indexing_decorator
        def insert(self, index, value):
            self._inner_list.insert(index, value)
    
        @indexing_decorator
        def __setitem__(self, index, value):
            self._inner_list.__setitem__(index, value)
    
        @indexing_decorator
        def __getitem__(self, index):
            return self._inner_list.__getitem__(index)
    
        def append(self, value):
            self.insert(len(self) + 1, value)
    

提交回复
热议问题