Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is it a good idea to have functions whose sole purpose it is to call another function?

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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())
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading