所以在与@kkasra12 讨论之后,我最终实现了 Python 的伪列表对象(没有进行所有必要的检查)来模仿它的行为,我只专注于 reverse() 操作。这是我的课:
class MyList:
def __init__(self, n):
self.length = n
self._seq = list(range(n))
@property
def seq(self):
return self._seq
def __len__(self):
return self.length
def __getitem__(self, item):
return self._seq[item]
def __setitem__(self, idx, value):
self._seq[idx] = value
def __reversed__(self):
return ReverseIterator(self)
def __str__(self):
return str(self._seq)
def append(self, v):
self._seq.append(v)
self.length += 1
def remove(self, v):
self._seq.remove(v)
self.length -= 1
还有我的ReverseIterator:
class ReverseIterator:
def __init__(self, org):
self.org = org
self._index = org.length
def __iter__(self):
return self
def __next__(self):
if 0 < self._index:
try:
item = self.org.seq[self._index - 1]
self._index -= 1
return item
except IndexError:
raise StopIteration()
else:
raise StopIteration()
结果:
obj = MyList(6)
iter_obj = iter(obj)
obj.remove(2)
print(list(iter_obj))
print('-----------------------')
obj = MyList(6)
rev_iter_obj = reversed(obj)
obj.remove(2)
print(list(rev_iter_obj))
输出:
[0, 1, 3, 4, 5]
-----------------------
[]
通过注释上面的remove 语句,我们可以看到它的工作方式与原始list 对象一样。
然后我创建了新的 SmartReverseIterator 迭代器,它可以处理从原始对象中删除项目的情况,并且可以动态生成值,就像iter() 在 OP 中的列表中工作一样。
唯一应该考虑的是,如果删除了一个项目(self._index 将小于原始对象的长度),则应重置 self._index。
class SmartReverseIterator:
def __init__(self, org):
self.org = org
self._index = org.length
def __iter__(self):
return self
def __next__(self):
if 0 < self._index:
try:
item = self.org.seq[self._index - 1]
return item
except IndexError:
self._index = self.org.length
item = self.org.seq[self._index - 1]
return item
finally:
self._index -= 1
else:
raise StopIteration()
通过更改MyList 上的__reversed__ 方法以返回这个新的迭代器,结果将是:
obj = MyList(6)
iter_obj = iter(obj)
obj.remove(2)
print(list(iter_obj))
print('-----------------------')
obj = MyList(6)
rev_iter_obj = reversed(obj)
obj.remove(2)
print(list(rev_iter_obj))
输出:
[0, 1, 3, 4, 5]
-----------------------
[5, 4, 3, 1, 0]
我想知道这是否有任何缺点,或者换句话说,为什么 python 决定不对这样的 list 对象实现 __reversed__ 方法,以确切地导致 iter() 如果项目是删除。
在什么情况下我们会看到问题?