code: def log(fn):
      
  
      def func(*args, **kwargs):
          arg_string = ""
          for i in range(0, len(args)):
              var_name = fn.__code__.co_varnames[i]
              if var_name != "self":
                  arg_string += var_name + ":" + str(args[i]) + ","
          arg_string = arg_string[0:len(arg_string) - 1]
          string = (RED + BOLD + '>> ' + END + 'Calling {0}({1})'.format(fn.__code__.co_name, arg_string))
          if len(kwargs):
              string = (RED + BOLD + '>> ' + END + 'Calling {0} with args {1} and kwargs {2}'.format(fn.__code__.co_name,
                                                                                                     arg_string, kwargs))
          print(string)
          result = fn(*args, **kwargs)
          string = BLUE + BOLD + '<< ' + END + 'Return {0} with result :{1}'.format(fn.__code__.co_name, result)
          print(string)
          return result
  
      return func
docs: logs parameters and result - takes no arguments