Реализация функции сортировки слиянием в классе Python, ошибки

Итак, у меня есть определенная функция, которая отлично работает при выполнении сортировки слиянием на линейном массиве, если она реализована его одиноким массивом, но если я добавлю ее в класс, это вызовет ошибку. Я думаю, что это отличный пример того, что я не совсем понимаю о том, как работают классы; возможно, в отношении управления пространством имен (?).

Увидеть ниже:

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)

Производит ожидаемый правильный вывод:

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]

Тем не менее, я получаю ошибку, когда я пытаюсь использовать эту функцию в классе; я думаю, что это связано с управлением пространством имен. Увидеть ниже:

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

Выводит ошибку:

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

Мой первоначальный инстинкт, после поиска в Google, заключался в изменении подпрограмм сортировки (слева) и сортировки (справа) путем добавления префикса self., Но это вызывает ошибку позиционного аргумента. Хотелось бы комментарий или два о том, что я не понимаю здесь. И приветствует хорошие голоса, если мой вопрос не глупый, и отрицательные голоса, если это так.

3 ответа

Решение

Причина sort(left) не работает в том, что, как вы уже догадались, вы не можете вызвать метод на self без указания self, Отключение означает, что он ищет локальное или глобальное имя sortне находит и поднимает NameError,

Причина self.sort(left) не работает, потому что API, который вы определили, не работает таким образом. Ваш класс принимает список в качестве аргумента конструктора, а затем принимает sort без аргументов, который действует в списке, переданном во время создания. Таким образом, вы не можете позвонить своим sort с другим массивом. Если вы попытаетесь self.sort(left), вы передаете неправильное количество аргументов, так же, как вызов abs(1, 2)и вы получите то же самое TypeError,

Вы должны использовать свой API так, как вы его создали: создать новый MergeSort Сортировать объект с новым списком, затем вызвать sort на этом новом объекте:

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

Замена sort(left) а также sort(right) компоненты функции sort () в моем классе с

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

(Спасибо, Абарнерт)

В то же время, удаляя отладочные операторы печати из кода (спасибо 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]

Молодцы все!

Вам нужно позвонить self.sort() в классе.

Большая проблема в том, что ни одна из ваших функций или методов класса ничего не возвращает, только печатает, вас это устраивает?

Другие вопросы по тегам