如何在Python中继承和扩展列表对象?

如何在Python中继承和扩展列表对象?,python,list,inheritance,Python,List,Inheritance,我对使用pythonlist对象感兴趣,但功能稍有改动。特别是,我希望列表是1索引的,而不是0索引的。例如: >> mylist = MyList() >> mylist.extend([1,2,3,4,5]) >> print mylist[1] 输出应为:1 但是,当我更改\uuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

我对使用pythonlist对象感兴趣,但功能稍有改动。特别是,我希望列表是1索引的,而不是0索引的。例如:

>> mylist = MyList()
>> mylist.extend([1,2,3,4,5])
>> print mylist[1]
输出应为:1

但是,当我更改
\uuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我对这些方法做了很多修改,但这基本上就是我在那里所做的:

class MyList(list):
    def __getitem__(self, key):
        return self[key-1]
    def __setitem__(self, key, item):
        self[key-1] = item
我想问题在于,
self[key-1]
本身正在调用它定义的相同方法。如果是这样,我如何使它使用
list()
方法而不是
MyList()
方法?我尝试使用
super[key-1]
而不是
self[key-1]
,但这导致投诉
TypeError:“type”对象不可订阅

有什么想法吗?如果你能给我一个很好的教程,那就太好了

谢谢

使用
super()
函数调用基类的方法,或直接调用该方法:

class MyList(list):
    def __getitem__(self, key):
        return list.__getitem__(self, key-1)

但是,这不会改变其他列表方法的行为。例如,索引保持不变,这可能导致意外结果:

numbers = MyList()
numbers.append("one")
numbers.append("two")

print numbers.index('one')
>>> 1

print numbers[numbers.index('one')]
>>> 'two'

相反,子类integer使用相同的方法将所有数字定义为设置为负1。瞧


对不起,我不得不这么做。这就像微软将dark定义为标准的笑话。

通过创建一个继承自collections.MutableSequence(抽象类)的类,可以避免违反Liskov替换原则。它看起来像这样:

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)
l = MyList()
l[0]
这里有一个问题(尽管可能还有更多)。如果您像这样为新列表编制索引:

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)
l = MyList()
l[0]
您将实际调用:

self._inner_list[-1]
这将得到最后一个元素。因此,如果您想在列表中使用反向索引功能,您必须在方法中进行额外的检查,并确保保留反向索引

编辑:

这是新的代码,我相信它不会有任何问题

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)

另外,要小心其他列表方法的破坏,因为您正在更改索引的行为,这是列表对象的一个基本部分。如果您注意到递归发生的原因,我将+1。你给出的解决方案没有解释问题。递归发生的原因在问题中解释得很好。这里还有一个问题需要指出:你可能认为super(MyList,self)[key-1]会起作用,但它不会。super()显式地不处理任何像[]而不是getitem这样的“隐式查找”。当心其他列表方法的破坏“这些方法不应该在内部使用
\uuuuuuGetItem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和
\uuuuuuuuuuuuuuuuuuuuuuuuuuu。如果您不能在任何需要
列表
的地方实际使用它,那么子类化
列表
可能没有多大价值。也许在这种情况下,构图是更合适的策略?我不太明白;你说的“作文”是什么意思?此外,我们如何确保不能用MyList代替标准列表?有什么好办法告诉你吗?例如,如果内部方法使用
\u getitem\u
\u setitem\u
那么会有问题吗?Mindsteep:--如果您更改
列表的现有接口(即,您在这里要求的内容),则不能用
MyList
替换
列表。即使是像
x[0]
这样的基本功能也不会起作用;x、 追加(4);y=MyList();打印(y)
试试看。你会得到有趣的结果…就快到了。您不应该调整
insert
的索引。另外,尝试处理index==0的情况。是的,您是对的。但这样索引就不一致了。我对答案中的代码做了一些修改。我认为它现在应该可以正常工作了。如果从collections.UserList继承,它会违反Liskov替换原则吗?e、 g.class MyList(collections.UserList):微软将黑暗定义为标准的笑话是什么?编辑:nvm,:“问:更换一个灯泡需要多少微软硬件工程师?答:没有,他们把黑暗作为行业标准。”