Reputation: 199
I am writing a class that takes input list of integers at initialization. The class has bunch of sorting methods. i wanted to add a decorator which would shuffle the input list before every method call. When trying to implement a recursive bubble sort, the decorator causes RecursionError: maximum recursion depth exceeded in comparison
I tried to pass the self argument so the decorator can access the class variable. However i need help on how to let the recursive function work with decorator
import functools
from searching import timer
import random
def shuffle(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
random.shuffle(self.ip_list)
value = func(self, *args, **kwargs)
return value
return wrapper
class sorting:
def __init__(self, ip_list):
self.ip_list = ip_list
self.n = len(self.ip_list)
self.timer_dict = {}
@shuffle
@timer
def recursive_bubble_sort(self):
print(self.ip_list)
for j in range(self.n):
try:
if self.ip_list[j] > self.ip_list[j+1]:
self.ip_list[j], self.ip_list[j + 1] = self.ip_list[j + 1], self.ip_list[j]
self.recursive_bubble_sort()
except IndexError:
pass
print(self.ip_list)
x = [i for i in range(0,30)]
s = sorting(x)
s.recursive_bubble_sort()
Upvotes: 0
Views: 660
Reputation: 104792
It's a very bad idea to decorate a recursive method like the one in your example. For some methods and decorators it could work, but not a sorting algorithm. The issue is that every recursive call is going to end up calling through the decorator's wrapper. With your shuffle
decorator, that means you're going to reshuffle the list on every recursive call, which is why your list is never getting sorted. Even if the sort didn't get reshuffled on every call, your timer
decorator would probably have a similar issue, as it would be trying to time every recursive call, not just the top level call to the function.
One option might be to keep the recursive method and the decorated method separate. This is often a good way to design an API for a function that's going to be implemented with recursion anyway, as you will often need to pass extra arguments into the recursive calls, but the top level call doesn't need them.
@shuffle
@timer
def bubble_sort_recursive(self): # despite the name, this function is not recursive itself
self.bubble_sort_recursive_helper()
def bubble_sort_recursive_helper(self): # all the recursion happens in this helper method
... # recursive code goes here, recursive calls should be to the helper!
Upvotes: 5