Метод класса не находит данный аргумент

1

Я только что научился создавать двоичные деревья поиска в С#. Я решил попробовать закодировать то же самое в Python 3.x. Однако, когда я добрался до моего метода печати, эта ошибка появилась:

Traceback (most recent call last):
  File "C:\Users\danie\Desktop\Python\BinarySearchTree\BinarySearchTree\BinarySearchTree.py", line 62, in <module>
    b.BSTprint()
  File "C:\Users\danie\Desktop\Python\BinarySearchTree\BinarySearchTree\BinarySearchTree.py", line 46, in BSTprint
    BST.Print(current)
TypeError: Print() missing 1 required positional argument: 'cur'

Проблема, я поставил требуемый позиционный аргумент. Я попытался исправить это сам и обнаружил, что если я удалю параметр self, он будет работать. Тем не менее, я всегда думал, что вам нужно иметь этот параметр self во всех методах класса. Я понятия не имею, что не так. Вот код

import random
class BST:
    #Node class 
    class Node:
        data = None
        left = None
        right = None
        def __init__(self, d):
            self.data = d
    first = None
    #Add method
    def Add(self, d):
        #Checks if the Binary Search Tree is empty
       if(BST.first == None):
           BST.first = BST.Node(d)
           #Debugging purposes
           #print("Added: {}".format(d))
           return;
       else:
           newNode = BST.Node(d)
           cur = BST.first
           while(cur != None):
               if(cur.data < newNode.data):
                   if(cur.left == None):
                       cur.left = newNode
                       #print("Added: {}".format(newNode.data))
                       return
                   else:
                       cur = cur.left
               elif(cur.data > newNode.data):
                   if(cur.right == None):
                       cur.right = newNode
                       #print("Added: {}".format(newNode.data))
                       return
                   else:
                       cur = cur.right
               else:
                    print("Value already in BST")
                    return


    def BSTprint(self):
        current = BST.first
        if(current == None):
            return
        BST.Print(current)
    def Print(self, cur):

        if(cur.left != None):
            BST.Print(cur.left)
        print(cur.data)
        if(cur.right != None):
            BST.Print(cur.right)



b = BST()
#Adds values into BST
for i in range(10):
    x = random.randint(1,100)
    b.Add(x)
b.BSTprint()
Теги:

3 ответа

0
Лучший ответ

Как отмечали другие, в методе Print вам нужно вызвать BSTprint как метод экземпляра, например self.BSTprint(node) чтобы экземпляр был правильно передан методу. Но есть и другие проблемы с вашим кодом.

Выполнение first = None создает first как атрибут класса, что означает, что он будет использоваться всеми экземплярами BST. Это не очень хорошая идея: каждый экземпляр должен иметь свой собственный корневой узел! Конечно, если программа создает только один экземпляр BST вы не заметите эту ошибку, но если вы решите, что хотите создать несколько деревьев, тогда произойдет Bad Things. ;)

Вместо этого вы должны создать first как атрибут экземпляра, обычный способ сделать это в методе __init__.

Ваш код определяет класс Node внутри класса BST. Это нормально, но это немного необычно для Python. Проще просто сделать его отдельным классом. Еще раз, вы определяете атрибуты Node как атрибуты класса. Это действительно нормально, поскольку вы никогда не изменяете эти атрибуты класса: ваш метод Add создает атрибуты экземпляра с теми же именами, которые "теневые" атрибуты класса. Тем не менее, это делает код немного проще анализировать, если вы избавитесь от этих атрибутов класса и просто используйте атрибуты экземпляра с самого начала.

Здесь изменена версия вашего кода. Я сделал несколько косметических изменений, чтобы код соответствовал руководству по стилю Python PEP-0008. Простые имена переменных, атрибутов и методов должны начинаться с строчных букв. Я также избавился от лишних круглых скобок. И рекомендуется использовать is при тестировании для None singleton, это немного более эффективно (и лучше читать), чем при использовании тестирования == или !=.

Я изменил first на root, в соответствии с замечанием Берка Эзбалци. И я дал Node метод __repr__ чтобы упростить печать данных узла.

Я также добавил вызов random.seed с жестко закодированным начальным значением, чтобы программа генерировала одинаковые номера при каждом запуске. Это упрощает тестирование и отладку. Трудно понять, что происходит, когда данные продолжают меняться.

import random

random.seed(42)

class Node:
    """ A binary tree node """
    def __init__(self, d):
        self.data = d
        self.left = self.right = None

    def __repr__(self):
        return repr(self.data)

class BST:
    """ Binary search tree """
    def __init__(self):
        self.root = None

    def add(self, d):
       # Check if the Binary Search Tree is empty
       if self.root is None:
           self.root = Node(d)
           #Debugging purposes
           print("Added: {} root".format(self.root))
           return
       else:
           newNode = Node(d)
           cur = self.root
           while cur is not None:
               if cur.data < newNode.data:
                   if cur.left is None:
                       cur.left = newNode
                       print("Added: {} left".format(newNode))
                       return
                   else:
                       cur = cur.left
               elif cur.data > newNode.data:
                   if cur.right is None:
                       cur.right = newNode
                       print("Added: {} right".format(newNode))
                       return
                   else:
                       cur = cur.right
               else:
                    print("Value already in BST:", d)
                    return

    def bst_print(self):
        current = self.root
        if current is None:
            return
        self.show(current)

    def show(self, cur=None):
        if cur.left is not None:
            self.show(cur.left)
        print(cur)
        if cur.right is not None:
            self.show(cur.right)


b = BST()

# Add values into BST
for i in range(10):
    x = random.randint(1, 100)
    print(x)
    b.add(x)

print('\nSorted')
b.bst_print()

выход

82
Added: 82 root
15
Added: 15 right
4
Added: 4 right
95
Added: 95 left
36
Added: 36 left
32
Added: 32 right
29
Added: 29 right
18
Added: 18 right
95
Value already in BST: 95
14
Added: 14 left

Sorted
95
82
36
32
29
18
15
14
4
1

Что я хотел бы выделить:

BST - класс

Print - метод объекта (привязанный к объекту, а не классу), и для этого требуется передать ссылку на объект (self), которая отличается от других языков Java/C++.

Вы вызываете BST.Print который похож на вызов статических методов в Java/C++, но его неправильно, потому что метод Print принимает параметр объекта

Поскольку вы вызываете метод, связанный с объектом (поскольку он принимает параметр self), вам нужно вызвать его с помощью объектов.

Дело в том:

Если вы используете методы с параметром self, то они должны быть вызваны с объектами. Если вы хотите вызвать их из класса, вы можете использовать @staticmethod и удалить параметр self и передать объект, который хотите обработать

Обратите внимание: разница между методами класса и экземпляра

Надеюсь это поможет

1

Вы перепутали переменные класса и переменные экземпляра.

В Python первый аргумент методов зарезервирован для вызывающего объекта (за исключением, в некоторых случаях, их нет, например, в методах класса или staticmethods). Измените метод Add следующим образом:

class BST:
...
    def Add(self, d):
        if self.first is None:
            self.first = BST.Node(d)
            return
    ...

Обратите внимание, что BST.Node(d) все тот же, потому что я имею в виду то, что принадлежит классу: другой класс.

Измените BST.Print(current) на self.Print(current).

Необычно ссылаться на корневой узел BST как на first, вместо этого вместо этого использовать root !

Ещё вопросы

Сообщество Overcoder
Наверх
Меню