如何在Python中继承和扩展列表对象?
我对使用pythonlist对象感兴趣,但功能稍有改动。特别是,我希望列表是1索引的,而不是0索引的。例如:如何在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
>> 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,:“问:更换一个灯泡需要多少微软硬件工程师?答:没有,他们把黑暗作为行业标准。”