code: def argspec(callable_obj):
      
      if (isinstance(callable_obj, type)
          and issubclass(callable_obj, param.ParameterizedFunction)):
          # Parameterized function.__call__ considered function in py3 but not py2
          spec = _getargspec(callable_obj.__call__)
          args = spec.args[1:]
      elif inspect.isfunction(callable_obj):    # functions and staticmethods
          spec = _getargspec(callable_obj)
          args = spec.args
      elif isinstance(callable_obj, partial): # partials
          arglen = len(callable_obj.args)
          spec =  _getargspec(callable_obj.func)
          args = [arg for arg in spec.args[arglen:] if arg not in callable_obj.keywords]
      elif inspect.ismethod(callable_obj):    # instance and class methods
          spec = _getargspec(callable_obj)
          args = spec.args[1:]
      else:                                   # callable objects
          return argspec(callable_obj.__call__)
  
      return inspect.ArgSpec(args=args,
                             varargs=spec.varargs,
                             keywords=get_keywords(spec),
                             defaults=spec.defaults)
docs: Returns an ArgSpec object for functions, staticmethods, instance
      methods, classmethods and partials.
  
      Note that the args list for instance and class methods are those as
      seen by the user. In other words, the first argument which is
      conventionally called 'self' or 'cls' is omitted in these cases.