I understand that while defining functions we have to use self as the first argument but in my particular coding example for insert_node method I got an error while calling insert_node(node,new_node) saying 3 arguments expected when I did not use self as the first argument in insert_node
class Node:
def __init__(self,value=None):
self.value = value
self.left = None
self.right = None
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
def insert_node(self,node,new_node):
if node.value == new_node.value:
return
if node.value > new_node.value:
if node.left is None:
node.left = new_node
return
else:
insert_node(self,node.left,new_node)
else:
if node.right is None:
node.right = new_node
return
else:
insert_node(self,node.right,new_node)
insert_node(self,curr,new_node)
1 Answer 1
insert_node() is not a method, it is a function nested inside insert(). You don't need to use self in this function, at all, because it makes no use of that argument, and even if it did, it could access the self reference from the parent insert() method as a closure.
Removing the self argument altogether works:
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
def insert_node(node, new_node):
if node.value == new_node.value:
return
if node.value > new_node.value:
if node.left is None:
node.left = new_node
return
else:
insert_node(node.left, new_node)
else:
if node.right is None:
node.right = new_node
return
else:
insert_node(node.right, new_node)
insert_node(curr, new_node)
You can move that function out of the insert() method too, it doesn't need to be nested there:
def insert_node(node, new_node):
if node.value == new_node.value:
return
if node.value > new_node.value:
if node.left is None:
node.left = new_node
return
else:
insert_node(node.left, new_node)
else:
if node.right is None:
node.right = new_node
return
else:
insert_node(node.right, new_node)
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
insert_node(curr, new_node)
However, this really should be a method on the Node class:
class Node:
def __init__(self, value=None):
self.value = value
self.left = None
self.right = None
def insert_node(self, new_node):
if self.value == new_node.value:
return
if self.value > new_node.value:
if self.left is None:
self.left = new_node
return
else:
self.left.insert_node(new_node)
else:
if self.right is None:
self.right = new_node
return
else:
self.right.insert_node(new_node)
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
curr.insert_node(new_node)
Because you access insert_node() on Node instances (via curr.insert_node(...), self.left.insert_node(...) and self.right.insert_node(...), it is bound to that instance for you by Python, and passed into the method as self.
5 Comments
_insert_node if you want to flag it as API private, but that's no more than a convention.
insert_nodeisn't an instance method, it's a nested function inside one.insert_node()is not a method, it is a function nested insideinsert().