I wrote code for a Tree traversal. In the Binary_tree class, I wrote three methods: __Inorder
, __Postorder
, and __Preorder
, for tree traversal; and I wrote three other methods to call them and pass in self.root
as a parameter so that I don't have to pass it manually every time I want to traverse.
Code:
class Node():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class Binary_Tree():
def __init__(self):
self.root = None
def insert(self, data):
new_node = Node(data)
if self.root == None:
self.root = new_node
else:
current_node = self.root
while True:
if data > current_node.data:
if not current_node.right:
current_node.right = new_node
return
else:
current_node = current_node.right
else:
if not current_node.left:
current_node.left = new_node
return
else:
current_node = current_node.left
def inorder_traversal(self):
return self.__Inorder(self.root)
def postorder_traversal(self):
return self.__Postorder(self.root)
def preorder_traversal(self):
return self.__Preorder(self.root)
def __Inorder(self, current_node, visited_node = None):
if visited_node is None:
visited_node = []
if current_node:
self.__Inorder(current_node.left, visited_node)
visited_node.append(current_node.data)
self.__Inorder(current_node.right, visited_node)
return visited_node
def __Postorder(self, current_node, visited_node = None):
if visited_node is None:
visited_node = []
if current_node:
self.__Postorder(current_node.left, visited_node)
self.__Postorder(current_node.right, visited_node)
visited_node.append(current_node.data)
return visited_node
def __Preorder(self, current_node, visited_node = None):
if visited_node is None:
visited_node = []
if current_node:
visited_node.append(current_node.data)
self.__Preorder(current_node.left, visited_node)
self.__Preorder(current_node.right, visited_node)
return visited_node
I showed this code to a guy I know and he said "there is no point in writing a function whose sole instruction is to call another function" and it is bad code writing. So, is it true? If yes, then how should I do it?
Your friend is wrong.
Your function (like inorder_traversal
) is not just calling another function: it also disallows the caller to pass any arguments, which are none of their business (current_node
, visited_node
). And this makes it a good decision to have a clean public method, while the underscored "private" functions deal with implementation details that are reflected in their function parameters.
Not your question, but I do see some room for avoiding code repetition, as your base functions have very similar code. Also you could consider creating generators for them instead of populating lists. You could also consider moving those private methods to the Node
class.
For example:
class Node():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def traverse(self, order=0):
if order == -1:
yield self.data
if self.left:
yield from self.left.traverse(order)
if order == 0:
yield self.data
if self.right:
yield from self.right.traverse(order)
if order == 1:
yield self.data
class Binary_Tree():
def __init__(self):
self.root = None
def insert(self, data):
new_node = Node(data)
if self.root == None:
self.root = new_node
else:
current_node = self.root
while True:
if data > current_node.data:
if not current_node.right:
current_node.right = new_node
return
else:
current_node = current_node.right
else:
if not current_node.left:
current_node.left = new_node
return
else:
current_node = current_node.left
def preorder_traversal(self):
if self.root:
return self.root.traverse(-1)
def inorder_traversal(self):
if self.root:
return self.root.traverse(0)
def postorder_traversal(self):
if self.root:
return self.root.traverse(1)
# Demo run
tree = Binary_Tree()
for data in (4,2,3,1,6,5,7):
tree.insert(data)
print(*tree.inorder_traversal())