如何让Python迭代器反向遍历?
有没有办法让Python的列表迭代器向后走呢?
基本上,我有这个
class IterTest(object):
def __init__(self, data):
self.data = data
self.__iter = None
def all(self):
self.__iter = iter(self.data)
for each in self.__iter:
mtd = getattr(self, type(each).__name__)
mtd(each)
def str(self, item):
print item
next = self.__iter.next()
while isinstance(next, int):
print next
next = self.__iter.next()
def int(self, item):
print "Crap i skipped C"
if __name__ == '__main__':
test = IterTest(['a', 1, 2,3,'c', 17])
test.all()
运行这段代码会得到这样的输出:
a
1
2
3
Crap i skipped C
我知道为什么会得到这个输出,不过我想知道有没有办法在str()方法中,向后走一步?
编辑
好吧,也许我可以更清楚地说明一下。我并不想完全反转,基本上我想知道有没有简单的方法可以在Python中实现一个双向迭代器?
14 个回答
3
迭代器的定义是一个有 next()
方法的对象——这里没有提到 prev()
方法。因此,你要么需要保存你的结果,以便可以重新访问它们,要么就得重新实现你的迭代器,让它按照你想要的顺序返回结果。
10
我是不是漏掉了什么,或者说你不能用Python教程中迭代器部分提到的方法吗?
>>> class reverse_iterator:
... def __init__(self, collection):
... self.data = collection
... self.index = len(self.data)
... def __iter__(self):
... return self
... def next(self):
... if self.index == 0:
... raise StopIteration
... self.index = self.index - 1
... return self.data[self.index]
...
>>> for each in reverse_iterator(['a', 1, 2, 3, 'c', 17]):
... print each
...
17
c
3
2
1
a
我知道这样做并不能让迭代器反向遍历,但我很确定一般来说是没有办法做到这一点的。相反,你可以写一个迭代器,让它以相反的顺序遍历一个具体的集合。
补充 你还可以使用reversed()
这个函数来获取任何集合的反向迭代器,这样你就不需要自己写了:
>>> it = reversed(['a', 1, 2, 3, 'c', 17])
>>> type(it)
<type 'listreverseiterator'>
>>> for each in it:
... print each
...
17
c
3
2
1
a
36
不,一般来说,你不能让Python的迭代器向后走。不过,如果你只想退回一步,可以试试下面这个方法:
def str(self, item):
print item
prev, current = None, self.__iter.next()
while isinstance(current, int):
print current
prev, current = current, self.__iter.next()
这样的话,你就可以随时在prev
中访问到前一个元素。
如果你真的需要一个可以双向移动的迭代器,你可以自己实现一个,但这样做可能会比上面的解决方案更复杂,开销也会更大:
class bidirectional_iterator(object):
def __init__(self, collection):
self.collection = collection
self.index = 0
def next(self):
try:
result = self.collection[self.index]
self.index += 1
except IndexError:
raise StopIteration
return result
def prev(self):
self.index -= 1
if self.index < 0:
raise StopIteration
return self.collection[self.index]
def __iter__(self):
return self