Iterators created by zip
cannot be reversed because zip
can accept any sort of iterable - including iterators where the iterated elements will be determined on-demand, and might be unlimited. (Recall that in Python, an iterator is a type of iterable.)
Thus, reverse iteration over the inputs isn't necessarily possible at all; and if it is possible, zip
has no way to know "where to start" (for example, given a list iterator, there is no easy way to access the original list, even though the iterator presumably holds a reference internally).
However, if the inputs are known to be reversible, we can simply reverse each before zipping:
>>> lst = ["Namaste", "Hello", "Ciao", "Salut"]
>>> for curr, nxt in zip(reversed(lst[:-1]), reversed(lst)):
... print(f'{curr}, {nxt}')
...
Ciao, Salut
Hello, Ciao
Namaste, Hello
Notice the slicing is different from the forwards-iterating version: for the curr
iterator we must skip the last element of the list explicitly, since iteration will start at the end, but the next
iterator can be made with the original list - we don't need to trim off the first element of the list, because it won't pair up. This is the opposite of how it works when iterating forwards.
Similarly, if we are starting with actual sequences, we can create reversed sequences and iterate over those. The simplest way is by slicing, and the simplest way to get "offset" iterators is to slice the offset one twice rather than doing the offset math:
>>> for curr, nxt in zip(lst[::-1][1:], lst[::-1]):
... print(f'{curr}, {nxt}')
...
Ciao, Salut
Hello, Ciao
Namaste, Hello
Again, because we iterate in reverse, it's the first input that needs to be offset.