2

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?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 2
    There is nothing wrong with having a function that just calls another function, if it makes sense in your code. – khelwood Mar 30 '22 at 10:05
  • 1
    There is absolutely nothing wrong with what you've done. The point is that you are exposing a particular interface to your class the implementation of which might change. For example, you might want to carry out some kind of validation before calling the other function. But you can do that without changing the interface – DarkKnight Mar 30 '22 at 10:18
  • 1
    I think your friend is right in general, but for this instance your code is fine, as the methods such as `inorder_traversal` are not solely calling other methods; they are calling other methods _with a specific parameter_. This looks like a good way of defining an interface to me. – Jack Taylor Mar 30 '22 at 10:18

1 Answers1

3

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())
trincot
  • 317,000
  • 35
  • 244
  • 286
  • 1
    Thank you, and the improvement you made to the existing code is great. I just learned something new. – Ritik Tyagi Mar 30 '22 at 10:42
  • 1
    Now that I have fully digested the improvements you made, I can't tell you how grateful I am, as you solved so many of my queries at once. – Ritik Tyagi Mar 30 '22 at 11:14