All the provided answers creating a list
of all the Enum members, but you actually can avoid it by using the itertools.cycle
:
from itertools import cycle
class Days(Enum):
SUNDAY = 'Su'
MONDAY = 'Mo'
TUESDAY = 'Tu'
WEDNSDAY = 'We'
THURSDAY = 'Th'
FRIDAY = 'Fr'
SATURDAY = 'Sa'
def next(self):
iterator = cycle(self)
for member in iterator:
if member is self:
# We have found the current member, so we want to
# return the next member
return next(iterator)
# Call it:
tomorrow = DAY.SUNDAY.next()
Note that in this approach, if current member is the last one in your enum, then it will return the first member, because cycle()
is cycling your iterable forever.
With the functools.cached_property
decorator we can also easily save the result for further reuse:
@chached_property
def next(self):
# The rest of the code is the same.
# Call it:
tomorrow = DAY.SUNDAY.next # Without parenthesis
To get previous member in same style you can use the reversed()
generator:
@cached_property
def prev(self):
# The only change is in the following line: we cycling in the revert order.
iterator = cycle(reversed(self))
for member in iterator:
if member is self:
# We have found the current member, so we want to
# return the next member
return next(iterator)
UPDATE:
As @EthanFurman states in the comment, the cycle()
saves the objects that it returns (to be able to return them in future cycles). so if you want to avoid this overhead as well, you can just iter(self)
on your enum
def next(self):
iterator = iter(self)
for member in iterator:
if member is self:
try:
return next(iterator)
except StopIteration:
# Create a new iterator of the enum and return the
# first object in it.
return next(iter(self))