2 回答
TA贡献1784条经验 获得超8个赞
list您可以通过使用适当的方法实现对其进行子类化来自定义行为,remove当被删除的索引小于当前迭代器索引时,该方法会减少迭代器指向的索引:
from weakref import WeakSet
class IterList:
def __init__(self, lst):
self.list = lst
self.index = 0
def __next__(self):
if self.index == len(self.list):
raise StopIteration
value = self.list[self.index]
self.index += 1
return value
class List(list):
iterators = WeakSet()
def __iter__(self):
iterator = IterList(self)
self.iterators.add(iterator)
return iterator
def remove(self, item):
index = super().index(item)
for iterator in self.iterators:
if index < iterator.index:
iterator.index -= 1
del self[index]
以便:
container = List((1, 2, 3, 4))
for i in container:
if i == 2:
container.remove(1)
for j in container:
print(i, j)
输出:
1 1
1 2
1 3
1 4
2 2
2 3
2 4
3 2
3 3
3 4
4 2
4 3
4 4
TA贡献1805条经验 获得超10个赞
您要询问的行为是所涉及的迭代器的实现细节。正如您所注意到的,该list_iterator类型使用内部索引,因此删除已访问的元素会导致问题,因为它会更改列表中所有后续值的索引。
我的建议是您实际上并没有从列表中删除任何值。相反,将它们添加到另一个容器中,也许是一个set(如果它们是可散列的)。这假设值是唯一的。但如果不是,您可能会在使用任何方法从列表中删除它们时遇到问题。
container = [1, 2, 3, 4]
removed = set()
for i in container:
if i not in removed: # skip values that have been "removed"
print(i)
if i == 2:
removed.add(1) # since we've already visited 1, this has no real effect
removed.add(3) # this does work though, we won't print the 3
container.append(8) # additions of new elements work as normal
正如评论所暗示的那样,该循环带有 print out 1、2、4和8.
添加回答
举报