简体   繁体   English

在python类中实现合并排序功能,错误

[英]Implementing merge sort function in python class, errors

So I have a function defined that works great at doing merge sort on a linear array if it is implemented by its lonesome, but if I put it into a class it bugs out. 因此,我定义了一个函数,如果该函数是由它的寂寞实现的,则非常适合对线性数组执行合并排序,但是如果将其放入类中,则会出错。 I think it's a great example of what I don't quite understand about how classes work; 我认为这是一个很好的例子,说明了我对类的工作方式不太了解。 possibly in regards to namespace management(?). 可能与名称空间管理(?)有关。

See below: 见下文:

def sort(array):
    print('Splitting', array)
    if len(array) > 1:
        m = len(array)//2
        left = array[:m]
        right = array[m:]

        sort(left)
        sort(right)

        i = 0
        j = 0
        k = 0

        while i < len(left) and j < len(right):
            if left[i] < right[j]:
                array[k] = left[i]
                i += 1
            else:
                array[k] = right[j]
                j += 1
            k += 1

        while i < len(left):
            array[k] = left[i]
            i += 1
            k += 1

        while j < len(right):
            array[k] = right[j]
            j += 1
            k += 1
    print('Merging', array)

arr = [1,6,5,2,10,8,7,4,3,9]
sort(arr)

Produces the expected correct output: 产生预期的正确输出:

Splitting  [1, 6, 5, 2, 10, 8, 7, 4, 3, 9]
Splitting  [1, 6, 5, 2, 10]
Splitting  [1, 6]
Splitting  [1]
Merging  [1]
Splitting  [6]
Merging  [6]
Merging  [1, 6]
Splitting  [5, 2, 10]
Splitting  [5]
Merging  [5]
Splitting  [2, 10]
Splitting  [2]
Merging  [2]
Splitting  [10]
Merging  [10]
Merging  [2, 10]
Merging  [2, 5, 10]
Merging  [1, 2, 5, 6, 10]
Splitting  [8, 7, 4, 3, 9]
Splitting  [8, 7]
Splitting  [8]
Merging  [8]
Splitting  [7]
Merging  [7]
Merging  [7, 8]
Splitting  [4, 3, 9]
Splitting  [4]
Merging  [4]
Splitting  [3, 9]
Splitting  [3]
Merging  [3]
Splitting  [9]
Merging  [9]
Merging  [3, 9]
Merging  [3, 4, 9]
Merging  [3, 4, 7, 8, 9]
Merging  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

However, I get an error when I attempt to use this function in a class; 但是,当我试图在一个类中使用此函数时,我得到一个错误。 something to do with namespace managment, I think. 我认为这与名称空间管理有关。 See below: 见下文:

class MergeSort(object):

    def __init__(self, array):
        self.array = array

    def sort(self):
        print('Splitting', self.array)
        if len(self.array) > 1:
            m = len(self.array)//2
            left = self.array[:m]
            right = self.array[m:]

            sort(left)
            sort(right)

            i = 0
            j = 0
            k = 0

            while i < len(left) and j < len(right):
                if left[i] < right[j]:
                    self.array[k] = left[i]
                    i += 1
                else:
                    self.array[k] = right[j]
                    j += 1
                k += 1

            while i < len(left):
                self.array[k] = left[i]
                i += 1
                k += 1

            while j < len(right):
                self.array[k] = right[j]
                j += 1
                k += 1
        print('Merging', self.array)

x = MergeSort([1,6,5,2,10,8,7,4,3,9])
x.sort()

Produces the error output: 产生错误输出:

Splitting [1, 6, 5, 2, 10, 8, 7, 4, 3, 9]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-15-89509f86277e> in <module>()
      1 x = MergeSort([1,6,5,2,10,8,7,4,3,9])
----> 2 x.sort()

<ipython-input-14-2bba116f00ce> in sort(self)
     11             right = self.array[m:]
     12 
---> 13             sort(left)
     14             sort(right)
     15 

NameError: name 'sort' is not defined

My initial instinct, after google searching around was to change subroutines sort(left) and sort(right) by adding prefixive self., but that generates a positional argument error. 我最初的直觉是,在Google搜索之后,是通过添加前缀self。来更改子例程sort(left)和sort(right),但是这会产生位置参数错误。 Would love a comment or two on what it is that I'm not understanding here. 对于我在这里不了解的内容,我想发表一两个评论。 And cheers for good votes if my question is not stupid, and down votes if it is. 如果我的问题不是愚蠢的,那么他们将为获得良好的选票而欢呼,如果是我的问题,则为他们投反对票。

The reason sort(left) doesn't work is that, as you surmised, you can't call a method on self without specifying self . 如您所推测的那样, sort(left)不起作用的原因是,您必须在未指定self情况下才能对self调用方法。 Leaving that off means it looks for a local or global name sort , doesn't find one, and raises a NameError . 取消该设置意味着它会查找本地或全局名称sort ,找不到,然后引发NameError

The reason self.sort(left) doesn't work is that the API you defined doesn't work that way. self.sort(left)不起作用的原因是您定义的API不能那样工作。 Your class takes the list as a constructor argument, and then takes a sort with no arguments, that operates on the list passed in at construction time. 您的类将列表作为构造函数参数,然后进行不带参数的sort ,该sort对在构造时传入的列表进行操作。 So, you have no way to call your own sort with a different array. 因此,您无法用其他数组调用自己的sort If you try self.sort(left) , you're passing the wrong number of arguments, just like calling abs(1, 2) , and you get the same TypeError . 如果尝试self.sort(left) ,则会传递错误数量的参数,就像调用abs(1, 2) ,并且得到相同的TypeError

You have to use your API the way you designed it: Create a new MergeSort sorter object with the new list, then call sort on that new object: 您必须按照设计方式使用API​​:使用新列表创建一个新的MergeSort排序器对象,然后对该新对象调用sort

leftsorter = MergeSort(left)
leftsorter.sort()
rightsorter = MergeSort(right)
rightsorter.sort()

Replacing the sort(left) and sort(right) components of the sort() function within my class with 用我的类替换sort()函数的sort(left)sort(right)组件

leftsorter = MergeSort(left)
leftsorter.sort()
rightsorter = MergeSort(right)
rightsorter.sort()

(Thank you abarnert) (谢谢你)

While at the same time removing debugging print statements from the code (thank you Evgany P), and by avoiding reusing a built in function name sort() to avoid confusion, I have a working MergeSort class. 同时从代码中删除调试打印语句(感谢Evgany P),并通过避免重复使用内置函数名称sort()以避免混淆,我有一个有效的MergeSort类。

class MergeSort(object):

    def __init__(self, array):
        self.array = array

    def merge_sort(self):
        if len(self.array) > 1:
            m = len(self.array)//2
            left = self.array[:m]
            right = self.array[m:]

            leftsorter = MergeSort(left)
            leftsorter.merge_sort()
            rightsorter = MergeSort(right)
            rightsorter.merge_sort()

            i = 0
            j = 0
            k = 0

            while i < len(left) and j < len(right):
                if left[i] < right[j]:
                    self.array[k] = left[i]
                    i += 1
                else:
                    self.array[k] = right[j]
                    j += 1
                k += 1

            while i < len(left):
                self.array[k] = left[i]
                i += 1
                k += 1

            while j < len(right):
                self.array[k] = right[j]
                j += 1
                k += 1

x = MergeSort([3,5,6,2,1,4,10,9,8,7])
x.merge_sort()
x.array

Out[ ]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Out []:[1、2、3、4、5、6、7、8、9、10]

Well done everybody! 大家做得好!

You need to call self.sort() within the class. 您需要在该类中调用self.sort()

A larger problem is that none of your function or class method return anything, just prints, are you satisfied with that? 一个更大的问题是您的函数或类方法都不返回任何内容,仅返回打印内容,您对此感到满意吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM