【问题标题】:how to implement decorators for a recursive function in a class如何为类中的递归函数实现装饰器
【发布时间】:2019-09-14 04:43:59
【问题描述】:

我正在编写一个在初始化时接受整数输入列表的类。该类有一堆排序方法。我想添加一个装饰器,它会在每次方法调用之前对输入列表进行洗牌。尝试实现递归冒泡排序时,装饰器导致RecursionError: maximum recursion depth exceeded in comparison

我尝试传递 self 参数,以便装饰器可以访问类变量。但是我需要关于如何让递归函数与装饰器一起工作的帮助

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()

【问题讨论】:

  • 你为什么要为此使用装饰器,为什么要使用冒泡排序是我的第二个问题?
  • 只是学习它们并试图帮助提高自己
  • 我会研究学习归并排序。冒泡排序经常被教授,因为它很容易实现但效率极低(O(n ^ 2),我不确定他们为什么要教授它)。话虽如此,我会看看我是否可以调试它。
  • 如果不传递任何内容,您的排序将无法工作。递归函数通过将子集传递给递归调用来工作。您正在尝试全部到位,这会导致逻辑问题。
  • 是的,我正在创建一个包含所有排序方法的类,所以让合并排序可能是我在这个类中的下一个方法,我希望装饰器在方法之前对类变量 self.ip_list 进行洗牌被执行

标签: python recursion decorator


【解决方案1】:

装饰像您的示例中那样的递归方法是一个非常糟糕的主意。对于某些方法和装饰器,它可以工作,但不是排序算法。问题是每个递归调用最终都会通过装饰器的包装器调用。使用您的 shuffle 装饰器,这意味着您将在每次递归调用时重新排列列表,这就是您的列表永远不会排序的原因。即使每次调用都没有重新排序,您的 timer 装饰器也可能会遇到类似的问题,因为它会尝试对每次递归调用进行计时,而不仅仅是对函数的顶级调用。

一种选择可能是将递归方法和装饰方法分开。这通常是为将要通过递归实现的函数设计 API 的好方法,因为您经常需要将额外的参数传递给递归调用,但顶层调用不需要它们。

@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!

【讨论】:

  • 你是对的,这是每个递归调用的时间
猜你喜欢
  • 2020-05-20
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多