This rule raises an issue when an object that does not support reverse iteration is passed to the built-in reversed() function.
The built-in reversed() function returns a reverse iterator over the values of a sequence. For an object to be reversible, it must
either:
__reversed__ method, or__len__ and __getitem__.Passing an object that satisfies none of these requirements, such as a set, a generator, or a custom class that does not implement the
required methods, raises a TypeError at runtime and interrupts the program.
Make sure the argument passed to reversed() supports reverse iteration.
list, tuple, str, or range.set, convert it to a sequence first, for example with
sorted() or list().__reversed__, or both __len__ and __getitem__.
for value in reversed({1, 2, 3, 4}): # Noncompliant: a set does not support reverse iteration
print(value)
for value in reversed([1, 2, 3, 4]):
print(value)
class Deck:
def __init__(self, cards):
self._cards = cards
for card in reversed(Deck(["Ace", "King", "Queen"])): # Noncompliant: "Deck" does not support reverse iteration
print(card)
class Deck:
def __init__(self, cards):
self._cards = cards
def __reversed__(self):
return reversed(self._cards)
for card in reversed(Deck(["Ace", "King", "Queen"])):
print(card)
For a custom class, inheriting from collections.abc.Sequence is a more robust option than implementing the methods directly. Because
it is an abstract base class, Python refuses to instantiate a subclass until both __len__ and __getitem__ are defined. In
return, the class inherits __reversed__, along with other sequence behaviors such as __iter__, __contains__,
index, and count.
from collections.abc import Sequence
class Deck(Sequence):
def __init__(self, cards):
self._cards = cards
def __getitem__(self, index):
return self._cards[index]
def __len__(self):
return len(self._cards)
for card in reversed(Deck(["Ace", "King", "Queen"])):
print(card)
reversedobject.__reversed__collections.abc.Sequence