让python迭代器倒退?

让python迭代器倒退?,python,list,iterator,Python,List,Iterator,有没有办法让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

有没有办法让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中的双向迭代器?

不,一般来说,不能让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()
class buffered:
    def __init__(self,it):
        self.it = iter(it)
        self.buf = []
    def __iter__(self): return self
    def __next__(self):
        if self.buf:
            return self.buf.pop()
        return next(self.it)
    def push(self,item): self.buf.append(item)

if __name__=="__main__":
    b = buffered([0,1,2,3,4,5,6,7])
    print(next(b)) # 0
    print(next(b)) # 1
    b.push(42)
    print(next(b)) # 42
    print(next(b)) # 2
然后,您可以随时在
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
类双向迭代器(对象): 定义初始化(自我,集合): self.collection=collection self.index=0 def next(自我): 尝试: 结果=自收集[自索引] 自索引+=1 除索引器外: 提出停止迭代 返回结果 def prev(自我): self.index-=1 如果自指数<0: 提出停止迭代 返回self.collection[self.index] 定义(自我): 回归自我
根据定义,迭代器是一个带有
next()
方法的对象——没有提到
prev()
。因此,您必须缓存结果,以便重新访问它们,或者重新实现迭代器,以便它按您希望的顺序返回结果。

我是否遗漏了一些内容,或者您不能使用

我知道这不会使迭代器倒退,但我很确定,一般来说,没有办法做到这一点。相反,编写一个迭代器,以相反的顺序遍历离散集合

编辑您还可以使用该函数为任何集合获取反向迭代器,这样您就不必编写自己的迭代器:

>>> it = reversed(['a', 1, 2, 3, 'c', 17])
>>> type(it)
<type 'listreverseiterator'>
>>> for each in it:
...  print each
... 
17
c
3
2
1
a
>it=reversed(['a',1,2,3',c',17])
>>>类型(it)
>>>对于其中的每一项:
...  打印每个
... 
17
C
3.
2.
1.
A.

根据你的问题,听起来你想要这样的东西:

def str(self, item):
    print item

    prev, current = None, self.__iter.next()
    while isinstance(current, int):
        print current
        prev, current = current, self.__iter.next()
class buffered:
    def __init__(self,it):
        self.it = iter(it)
        self.buf = []
    def __iter__(self): return self
    def __next__(self):
        if self.buf:
            return self.buf.pop()
        return next(self.it)
    def push(self,item): self.buf.append(item)

if __name__=="__main__":
    b = buffered([0,1,2,3,4,5,6,7])
    print(next(b)) # 0
    print(next(b)) # 1
    b.push(42)
    print(next(b)) # 42
    print(next(b)) # 2

我想这会帮助你解决你的问题

    class TestIterator():
        def __init__(self):`
            self.data = ["MyData", "is", "here","done"]
            self.index = -1
            #self.index=len(self.data)-1
    def __iter__(self):
        return self

    def next(self):
        self.index += 1
        if self.index >= len(self.data):
            raise StopIteration
        return self.data[self.index]

    def __reversed__(self):
        self.index = -1
        if self.index >= len(self.data):
            raise StopIteration
        return self.data[self.index]

r = TestIterator()
itr=iter(r)
print (next(itr))
print (reversed(itr))

您可以将迭代器包装在迭代器帮助器中,使其能够向后运行。它将迭代的值存储在一个集合中,并在返回时重用它们

class MemoryIterator:
    def __init__(self, iterator : Iterator):
        self._iterator : Iterator = iterator
        self._array = []
        self._isComplete = False
        self._pointer = 0

    def __next__(self):
        if self._isComplete or self._pointer < len(self._array):
            if self._isComplete and self._pointer >= len(self._array):
                raise StopIteration

            value = self._array[self._pointer]
            self._pointer = self._pointer + 1
            return value

        try:
            value = next(self._iterator)
            self._pointer = self._pointer + 1
            self._array.append(value)
            return value
        except StopIteration:
            self._isComplete = True

    def prev(self):        
        if self._pointer - 2 < 0:
            raise StopIteration

        self._pointer = self._pointer - 1
        return self._array[self._pointer - 1]

其中direct是反向的
-1
,或普通的
1

Python您可以使用列表和索引来模拟迭代器:

a=[1,2,3]
电流=1
def get_下一步(a):
电流=a[a.指数(电流)+1%长度(a)]
回流
def get_last(a):
电流=a[a.指数(电流)-1]
返回电流#a[-1]>>>3(负安全)
如果列表中包含重复项,则必须单独跟踪索引:

a =[1,2,3]
index = 0

def get_next(a):
  index = index+1 % len(a)
  current = a[index]
  return current
def get_last(a):
  index = index-1 % len(a)
  current = a[index-1]
  return current # a[-1] >>> 3 (negative safe)

请参阅Morten Piibeleht制作的此函数。它为iterable的每个元素生成一个(上一个、当前个、下一个)元组


您可以通过以下代码使迭代器向后移动

class EnableBackwardIterator:
    def __init__(self, iterator):
        self.iterator = iterator
        self.history = [None, ]
        self.i = 0

    def next(self):
        self.i += 1
        if self.i < len(self.history):
            return self.history[self.i]
        else:
            elem = next(self.iterator)
            self.history.append(elem)
            return elem

    def prev(self):
        self.i -= 1
        if self.i == 0:
            raise StopIteration
        else:
            return self.history[self.i]
class EnableBackardificator:
定义初始化(self,迭代器):
self.iterator=迭代器
self.history=[None,]
self.i=0
def next(自我):
self.i+=1
如果self.i
用法:

>>> prev = lambda obj: obj.prev()  # A syntactic sugar.
>>> 
>>> a = EnableBackwardIterator(iter([1,2,3,4,5,6]))
>>> 
>>> next(a)
1
>>> next(a)
2
>>> a.next()  # The same as `next(a)`.
3
>>> prev(a)
2
>>> a.prev()  # The same as `prev(a)`.
1
>>> next(a)
2
>>> next(a)
3
>>> next(a)
4
>>> next(a)
5
>>> next(a)
6
>>> prev(a)
5
>>> prev(a)
4
>>> next(a)
5
>>> next(a)
6
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
prev=lambda obj:obj.prev()#语法糖。 >>> >>>a=使能反向计数器(iter([1,2,3,4,5,6])) >>> >>>下一(a) 1. >>>下一(a) 2. >>>与“next(a)”相同。 3. >>>上(a) 2. >>>a.prev()#与“prev(a)”相同。 1. >>>下一(a) 2. >>>下一(a) 3. >>>下一(a) 4. >>>下一(a) 5. >>>下一(a) 6. >>>上(a) 5. >>>上(a) 4. >>>下一(a) 5. >>>下一(a) 6. >>>下一(a) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 停止迭代
按相反顺序访问列表元素的迭代器:

class ReverseIterator:
    def __init__(self,ls):
        self.ls=ls
        self.index=len(ls)-1

    def __iter__(self):
        return self
    def __next__(self):
        if self.index<0:
            raise StopIteration
        result = self.ls[self.index]
        self.index -= 1
        return result
类反转器:
定义初始化(自我,ls):
self.ls=ls
自索引=len(ls)-1
定义(自我):
回归自我
定义下一个(自我):

如果self.index我来这里寻找一个双向迭代器。不确定这是否是OP所寻找的,但这是一种生成双向迭代器的方法,方法是为其提供一个属性,以指示下一步的方向:

class BidirectionalCounter:
    """An iterator that can count in two directions (up
    and down).
    """

    def __init__(self, start):
        self.forward = True
        # Code to initialize the sequence
        self.x = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.forward:
            return self.next()
        else:
            return self.prev()
    
    def reverse(self):
        self.forward = not self.forward
        
    def next(self):
        """Compute and return next value in sequence.
        """
        # Code to go forward
        self.x += 1
        return self.x
    
    def prev(self):
        """Compute and return previous value in sequence.
        """
        # Code to go backward
        self.x -= 1
        return self.x
演示:

输出:

11
12
11
10

是的,我试图避免这种情况,但是,因为这会增加相当多的恼人的开销:/在上面添加了一个
双向迭代器
示例,因为我已经看到您更新了您的问题,但是这可能会比我的第一个解决方案引入更多的开销。请注意,此类不会生成适当的迭代器。您可以在其实例上手动调用.next()和.prev(),但不能利用迭代器的功能,比如在
for
循环或列表理解中传递它。这将引发一个
TypeError:iter()返回了类型为“双向迭代器”的非迭代器。
。奇怪的是,它适合我(Python 2.7.1,Mac OS X)。在Python中,迭代器只需要一个
next()
方法和一个返回自身的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
。@etuardu:您使用的是Python 3吗?iirc
next
已重命名为
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?你明确地想要能够倒退,还是仅仅想要结果倒退?哦。。。。是否要停止中间迭代并进行备份?您可能需要缓存已遍历的列表部分,并使用
reversed()遍历它
my_counter = BidirectionalCounter(10)
print(next(my_counter))
print(next(my_counter))
my_counter.reverse()
print(next(my_counter))
print(next(my_counter))
11
12
11
10