class Tree:
    LEAVES = 0
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right
        self.node_order = []
        self.increment_leaves()
        
    def clear_node_order(self):
        self.node_order.clear()
    
    def traverse_inorder(self, tree):        
        if tree:            
            self.traverse_inorder(tree.left)
            self.node_order.append(str(tree.value))
            self.traverse_inorder(tree.right)
            
        return ''.join(self.node_order)
            
    def traverse_preorder(self, tree):
        if tree:
            self.node_order.append(str(tree.value))
            self.traverse_preorder(tree.left)            
            self.traverse_preorder(tree.right)
            
        return ''.join(self.node_order)
            
    def traverse_postorder(self, tree):
        if tree:            
            self.traverse_postorder(tree.left)            
            self.traverse_postorder(tree.right)
            self.node_order.append(str(tree.value))
            
        return ''.join(self.node_order)
    
    def get_deepest_node(self, tree, level = 0, maxlevel=[-1], curr_deepest=[-1]):
        if tree:
            level += 1
            self.get_deepest_node(tree.left, level, maxlevel, curr_deepest)
            
            if level > maxlevel[0]:
                curr_deepest[0] = tree.value
                maxlevel[0] = level
                
            self.get_deepest_node(tree.right, level, maxlevel, curr_deepest)
        
        return curr_deepest[0]    
            
    def get_levels(self, tree):
        target = self.get_deepest_node(tree)
        queue = []
        level = 1
        queue.append(tree)
        queue.append(None)
        while len(queue):
            curr_node = queue[0]
            queue.pop(0)
            if not curr_node:
                if len(queue) == 0:
                    return 0
                if queue[0]:
                    queue.append(None)
                level += 1
            else:
                if curr_node.value == target:
                    return level
                
                if curr_node.left:
                    queue.append(curr_node.left)
                if curr_node.right:
                    queue.append(curr_node.right)
                    
        return 0
            
    @classmethod
    def increment_leaves(cls):
        cls.LEAVES += 1

    @staticmethod
    def help():
        return """
        This help method is a staticmethod
        """

def mirror(tree):
    if tree:  
        tree.right, tree.left = tree.left, tree.right
        try:
            mirror(tree.left)
            mirror(tree.right)
        except:
            pass
        
    return tree
        

tree = Tree(1)
tree.left = Tree(2)
tree.right = Tree(3)
tree.left.left = Tree(4)
tree.left.right = Tree(5)
tree.right.left = Tree(6)
tree.right.right = Tree(7)
tree.left.right.left = Tree(8)
tree.left.right.right = Tree(9)
tree.left.right.right.left = Tree('a')
tree.left.right.right.right = Tree('b')

print(f'Original Tree: Node ID: {hex(id(tree))}')
print(tree.traverse_inorder(tree))
tree.clear_node_order()

tree = mirror(tree)
print()
print(f'Mirrored Tree: Node ID: {hex(id(tree))}')
print(tree.traverse_inorder(tree))
tree.clear_node_order()

print()
print(f'Leaves: {tree.LEAVES}')
print(f'Help method bound to instance: {tree.help()}')
print(f'Help method bound to class: {tree.help()}')
print(f'Levels: {tree.get_levels(tree)}')

# Tests
test_tree = Tree(3)
assert test_tree.value == 3, 'Should be 3'

order_nodes = Tree(3)
order_nodes.left = Tree(4)
order_nodes.right = Tree(5)

assert order_nodes.traverse_inorder(order_nodes) == '435', 'should be 354'
order_nodes.clear_node_order()

assert order_nodes.traverse_preorder(order_nodes) == '345', 'should be 345'
order_nodes.clear_node_order()

assert order_nodes.traverse_postorder(order_nodes) == '453', 'should be 453'

Ouptputs:

Original Tree: Node ID: 0x7f09f0381f28
4285a9b1637

Mirrored Tree: Node ID: 0x7f09f0381f28
7361b9a5824

Leaves: 11
Help method bound to instance (tree): 
        This help method is a staticmethod
        
Help method bound to class (Tree): 
        This help method is a staticmethod
        
Levels: 5

Tree:


                1
               / \
              /   \
             /     \
            2       3
           / \     / \
          /   \   /   \
         4     5 6     7 
              / \
             8   9
                / \
               a   b