Reputation: 61
I just learned how to create Binary Search Trees in C#. I decided to try to code the same thing in Python 3.x. However, when I got to my Print method, this error showed up:
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'
The problem, I did put in the required positional argument. I tried fixing it myself and found that if I remove the self parameter, it works. However, I always thought you needed to have that self parameter in all of the class methods. I have no idea what is wrong. Here is the code
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()
Upvotes: 1
Views: 137
Reputation: 55469
As others have noted, in the Print
method you need to call BSTprint
as an instance method, eg self.BSTprint(node)
so that the instance gets passed to the method correctly. But there are a few other issues with your code.
Doing first = None
creates first
as a class attribute, which means it would be shared by all BST
instances. That's not a good idea: each instance should have its own root node! Of course, if the program only creates a single BST
instance you wouldn't notice that bug, but if you decide that you want to create several trees then Bad Things would happen. ;)
Instead, you should creates first
as an instance attribute, the usual way to do that is in the __init__
method.
Your code defines the Node
class inside the BST class. It's fine to do that, but it's a little unusual in Python. It's simpler just to make it a separate class. Once again, you're defining the Node
attributes as class attributes. That's actually ok here, since you never modify those class attributes: your Add
method creates instance attributes with the same names that "shadow" the class attributes. However, it makes the code a little simpler to analyse if you get rid of those class attributes and simply use instance attributes from the outset.
Here's a modified version of your code. I made a few cosmetic changes so that the code conforms with the Python PEP-0008 style guide. Simple variable, attribute, and method names should begin with lower case letters. I also got rid of redundant parentheses. And it's recommended to use is
when testing for the None
singleton, it's a little more efficient (and nicer to read) than using ==
or !=
value testing.
I changed first
to root
, in line with Berk Özbalcı's remark. And I gave Node
a __repr__
method to make it easier to print the Node data.
I also added a call to random.seed
, with a hard-coded seed value so that the program generates the same numbers each time we run it. That makes testing and debugging much easier. It can be hard to figure out what's going wrong when the data keeps changing.
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()
output
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
Upvotes: 0
Reputation: 1954
Things I would like to highlight:
BST
is a class
Print
is a object method(bound to object and not class) and it requires the object reference to be passed(self
) which is different from other languages Java/C++.
You're calling BST.Print
which is similar to calling static methods in Java/C++, but its wrong because Print
method takes object parameter
Since you're calling a method that is object bound(since it takes self
parameter), you need to call it with objects.
The point is:
If you're using methods with self parameter then they should be called with objects. If you want to call them from class then you can use @staticmethod
and remove the self parameter and pass the object you want to process
Please refer: Difference between Class and Instance methods
Hope this helps
Upvotes: 1
Reputation: 3196
You've got class variables and instance variables mixed up.
In Python, the first argument of methods are reserved for the calling object (except in some cases they aren't, such as in classmethods or staticmethods). Modify the Add method like this:
class BST:
...
def Add(self, d):
if self.first is None:
self.first = BST.Node(d)
return
...
Note that BST.Node(d)
is still the same, because I'm referring to something that is belonging to the class: another class.
Modify BST.Print(current)
to self.Print(current)
.
It's uncommon to refer to the root node of a BST as first
, prefer root
instead!
Upvotes: 1