This rule raises an issue when an object that does not support reverse iteration is passed to the built-in reversed() function.

Why is this an issue?

The built-in reversed() function returns a reverse iterator over the values of a sequence. For an object to be reversible, it must either:

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.

How to fix it

Make sure the argument passed to reversed() supports reverse iteration.

Code examples

Noncompliant code example

for value in reversed({1, 2, 3, 4}):  # Noncompliant: a set does not support reverse iteration
    print(value)

Compliant solution

for value in reversed([1, 2, 3, 4]):
    print(value)

Noncompliant code example

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)

Compliant solution

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)

Going the extra mile

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)

Resources

Documentation