Return the maximum height of a Binary Tree using Python

class Binary:
    def __init__(self, key):
        self.data = key
        self.left = None
        self.right = None

def height(A):
    if A == None:
        return 0
    else:
        ldepth = height(A.left)
        rdepth = height(A.right)

        if(ldepth > rdepth):
            return 1+ldepth
        return 1+rdepth

root = Binary(1)
root.left = Binary(2)
root.right = Binary(3)
root.left.left = Binary(4)
root.left.right = Binary(5)
root.left.left.left = Binary(7)
root.right.right = Binary(8)

print(height(root))


Program in Python to print first non-repeating character in Python

def first_non_repeating(string):
    dict = {}
    for items in range(len(string)):
        key = string[items]
        if key not in dict:
            dict[key] = 1
        else:
            dict[key]+=1
    counter = 0
    for i in range(len(string)):
        if dict[string[i]] == 1:
            return string[i], counter
        counter += 1
    # for key, value in dict.items():
    #     if value == 1:
    #         return(key)
    #         break   

s = 'ABCDEFGHABCDE'
print(first_non_repeating(s))

Passing arguments in decorators

from functools import wraps

def only_datatype_allow(datatype):
    def deco(function):
        @wraps(function)
        def wrapper(*args, **kwargs):
            if all([type(arg) == datatype for arg in args]):
                return function(*args, **kwargs)
            print("Invalid Argument. Should only be of type integer !!")
        return wrapper
    return deco

@only_datatype_allow(str)
def string_join(*args):
    string = ""
    for items in args:
        string += items
    return string

print(string_join('Sayan', 'Dey'))

Program Using Decorators

from functools import wraps

def allow_only_int(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if all([type(arg) == int for arg in args]):
            return func(*args, **kwargs)
        print("Invalid Argument. Should only be of type integer !!")
    return wrapper

@allow_only_int
def add_all(*args):
    total = 0
    for items in args:
        total+=items
    return total

print(add_all(1, 2, 3.2, 4.9, [1, 2, 3, 4]))

Using functools, decorators and time module in Python

from functools import wraps
import time
def calculate_time(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"You are running {func.__name__} function")
        t1 = time.time()
        returned = func(*args, **kwargs) 
        t2 = time.time()
        total = t2 - t1
        print(f"This function took {total} seconds to run")
        return returned
    return wrapper

@calculate_time
def squares(l):
    return[items**2 for items in range(1, l+1)]

print(squares(10000))

Print function name and docstrings using decorators in Python

from functools import wraps

def print_function_data(func):
    @wraps(func)
    def wrapper_function(*args, **kwargs):
        print(f"You are calling {func.__name__}")
        print(f"This function {func.__doc__}")
        return func(*args, **kwargs)
    return wrapper_function

@print_function_data
def add(a, b):
    '''takes two integers as input and returns their sum as output'''
    return a+b

print(add(5,6))

enumerate() in Python

What is enumerate ?

Enumerate() method adds a counter to an iterable and returns it in a form of enumerate object. This enumerate object can then be used directly in for loops or be converted into a list of tuples using list() method.

list1 = []
n = 10
for items in range(n):
    a = int(input("Enter your items : "))
    list1.append(a)
print(list1)
for e, items in enumerate(list1):
    print(f"The index is {e} and the value of index is {items}")