reversed in python , a tutorial

What is reversed?

The reversed class is used to create a reverse iterator from an object .

This object , must either implement the __getitem__ and the __len__ special methods . In this case reverse will create an iterator from this object . Or the object must implement the __reversed__ method , and the __reversed__ method must return an iterator .

reversed can be used with python builtin types , that implements the __reversed__ method . It can also be used with python built in types , that implement the sequence protocol , like the list , which implements the : __getitem__ and __len__ methods .

reversed can also be used with custom created types , that implement the __getitem__ and __len__ methods , or that implement the __reversed__ method , which must return an iterator .

Using reverse with built-in python types

# #### example one : reversed with built-in types  ####
    
>>> _printList = ['_oo_', '|__|', '(^|^)']
>>> print(list(reversed(_printList)))
# list implements the sequence protocol 
# get a reverse iterator from _printList using 
# reversed
# create a list
# print the reversed list 
['(^|^)', '|__|', '_oo_']


>>> work = "eciohc fo rewop ehT"
>>> print(''.join(reversed(work)))
# string implements the sequence protocol
# get a reverse iterator from work string
# using reverse .
# join the iterator using the empty string 
# the result is 
The power of choice


>>> list(filter(lambda word: set(word) & {'a', 'e', 'i', 'o', 'u'}, reversed(
    ["flavors", "ft",  "kg", "blink", "cash", "food", "eggs"])))
# reverse the list
# filter it using a lambda function 
# return true if the word contain a vowel
# create a list from the resulting iterator
# result 
['eggs', 'food', 'cash', 'blink', 'flavors']



>>> temperatures = [0, 12, 23, 34]
for temperature in reversed(temperatures):
    print(temperature, end=';')  
# reverse the temperature in a list and print them 
# output : 
34;23;12;0;




# a useful example of reverse is to test for the 
# associativity of  an operation
# let us say  we want to test if the addition of two 
# strings is associative

>>> data = ["a", "b"]
# data 

>>> sum_left_to_right = ''
>>> sum_right_to_left = ''
# sums from left to right and from right to left = ''

for _data in data:
    sum_left_to_right += _data
# sum the data from left to right 

for _data in reversed(data):
    sum_right_to_left += _data
# sum the data from right to left

if sum_left_to_right == sum_right_to_left:
    print("The sum of strings is associative")
else:
    print("The sum of strings is not associative")

# output 
The sum of strings is not associative



>>> _dict = {'g':'e' , 1:2}
>>> reversed(_dict)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: 'dict' object is not reversible
# dictionaries do not implement the 
# __reverse__ method  or the sequence 
# protocol , trying to  reverse a 
# dictionary  will raise a TypeError

Using reversed with custom types that implement __getitem__ and __len__

# example two : reversed with custom types that implements _getitem__ and __len__
    
    
class Bar:
    ''' Bar class implements __getitem__  , __len__
        Show how to use reverse function with a type that implements __getitem__ __len__ 
        default bar is iterated from start to stop  -> the bar is filled
        reverse iterate the bar from stop to start   -> the bar is emptied 
    '''
    def __init__(self, start=0, stop=15):
        '''
            bar [|||||||||||||||]
                start:0          stop:15
        '''
        self.start = start
        self.stop = stop
    def __getitem__(self, barIndex):  
        if barIndex < self.start or barIndex >= self.stop:
            raise IndexError  
            # barIndex must be between [start and stop)
        return barIndex - self.start
    def __len__(self): 
        return self.stop - self.start


>>> bar = Bar()
>>> list(bar)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

>>> list(reversed(bar))
[14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    

Using reversed with custom types that implements __reversed__ , __reversed__ returns a class that implements __iter__ and __next__

class Problems:
    ''' Contains problems that we want to check.
        We want to be able to check the problems from the
        first that was inserted to the last that was inserted.
        We also want to be able to check the problems from the last
        that was inserted to the first that was inserted.
        We can implement the __reversed__ method that must return
        an iterator.
    '''
    def __init__(self):
        self.problems = ['undefined', 'check', 'unexpected', 'indent']
    def __iter__(self):
        ''' returns an iterator , that 
            iterates through the problems from 
            first to last .  
        '''
        return iter(self.problems)
    def __reversed__(self):
        '''__reversed__ creates an instance of the
        ProblemsReversed class which implements the
        __iter__ and __next__ methods
        '''
        class ProblemsReversed:
            def __init__(self, problems):
                self.problems = problems
                self.counter = len(self.problems)
            def __iter__(self):
                ''' ProblemsReverseIterator is iterable.
                it returns an iterator , it implements
                __next__ ,as such it can return itself
                '''
                return self
            def __next__(self):
                ''' iterate through the problems
                    from [length-1 , 0 ]
                '''
                if self.counter > 0:
                    self.counter -= 1
                    return self.problems[self.counter]
                raise StopIteration
        return ProblemsReversed(self.problems)

        


>>> problems = Problems() 
>>> list(problems)
# list the problems from first to last
['undefined', 'check', 'unexpected', 'indent']

>>> list(reversed(problems))
# list the problems from last to first
['indent', 'unexpected', 'check', 'undefined']

Using reversed with custom types that implements __reversed__ , __reversed__ returns a generator

class Print:
    '''
        iterate through a string , from
        start till end , and from end till start
    '''
    def __init__(self, string='''
0 : 0
    0  
    |  
'''):
        self.string = string
    def __iter__(self):
        ''' returns an iterator  , that iterates 
            through a string from start till end
        '''
        return iter(self.string)
    def __reversed__(self): 
        ''' returns a generator object , that  iterates
            through  a string , from  end to 
            start
        '''
        string = self.string
        return ( string[i] for i  in  range(len(string) -1 , -1 , -1) )
        # create a range from [len(string)-1 , 0] 
        # For indexes in the range , access the characters
        # in string , from end till start
        # return the generator object 


>>> mPrint = Print()                                                                                                         
>>> print(''.join(iter(mPrint)))   
# get an iterator from mPrint , 
# join it using the empty string 
# and print the result 
# output

0 : 0
    0  
    |  

>>> print(''.join(reversed(mPrint))) 
# get a reverse iterator from mPrint , 
# join it using the empty string 
# and print the result 
# output

    |  
    0  
0 : 0