问题
I'm currently using something like
>> import itertools
>> ABC = [a, b, c]
>> abc = itertools.cycle( ABC )
>> next( abc )
a
>> next( abc )
b
>> next( abc )
c
I want my next call to be
>> previous( abc )
b
Is there a method in itertools that can accomplish this?
回答1:
No, there isn't.
Because of the way Python's iteration protocol works, it would be impossible to implement previous
without keeping the entire history of the generated values. Python doesn't do this, and given the memory requirements you probably wouldn't want it to.
回答2:
You can use deque
from collections
module and rotate
method,
for example:
from collections import deque
alist=['a','b','c']
d=deque(alist)
current = d[0]
print(current) # 'a'
d.rotate(1) # rotate one step to the right
current = d[0]
print(current) # 'c'
d.rotate(-1) # rotate one step to the left
current = d[0]
print(current) # 'a' again
回答3:
You can write your own class to emulate an iterable
object with next and previous. This is the simplest implementation:
class cycle:
def __init__(self, c):
self._c = c
self._index = -1
def __next__(self):
self._index += 1
if self._index>=len(self._c):
self._index = 0
return self._c[self._index]
def previous(self):
self._index -= 1
if self._index < 0:
self._index = len(self._c)-1
return self._c[self._index]
ABC = ['a', 'b', 'c']
abc = cycle(ABC)
print(next(abc))
print(next(abc))
print(next(abc))
print(abc.previous())
回答4:
Although deque
is the way to go, here's another example:
Code
import itertools as it
class Cycle:
"""Wrap cycle."""
def __init__(self, seq):
self._container = it.cycle(seq)
self._here = None
self.prev = None
def __iter__(self):
return self._container
def __next__(self):
self.prev = self._here
self._here = next(self._container)
return self._here
Demo
c = Cycle("abc")
next(c)
# 'a'
next(c)
# 'b'
c.prev
# 'a'
来源:https://stackoverflow.com/questions/44611890/itertools-previous-opposite-of-next-python