title: python decorator to display passed AND default kwargs
body: <p>I am new to python and decorators and am stumped in writing a decorator which reports not only passed args and kwargs but ALSO the unchanged default kwargs.</p>
  
  <p>This is what I have so far.</p>
  
  <pre><code>def document_call(fn):
      def wrapper(*args, **kwargs):
          print 'function %s called with positional args %s and keyword args %s' % (fn.__name__, args, kwargs)
          return fn(*args, **kwargs)
      return wrapper
  
  @document_call
  def square(n, trial=True, output=False):
      # kwargs are a bit of nonsense to test function
      if not output:
          print 'no output'
      if trial:
          print n*n
  
  square(6) # with this call syntax, the default kwargs are not reported
  # function square called with positional args (6,) and keyword args {}
  # no output
  36
  
  square(7,output=True) # only if a kwarg is changed from default is it reported
  # function square called with positional args (7,) and keyword args {'output': True}
  49
  </code></pre>
  
  <p>The 'problem' is that this decorator reports the args that are passed in the call to square but does not report the default kwargs defined in the square definition. The only way kwargs are reported is if they're changed from their default i.e. passed to the square call.</p>
  
  <p>Any recommendations for how I get the kwargs in the square definition reported too? </p>
  
  <p>Edit after following up on the inspect suggestions, which helped me to the solution below. I changed the output of positional params to include their names because I thought it made the output easier to understand.</p>
  
  <pre><code>import inspect
  def document_call(fn):
      def wrapper(*args, **kwargs):            
              argspec = inspect.getargspec(fn)
              n_postnl_args = len(argspec.args) - len(argspec.defaults)
          # get kwargs passed positionally
          passed = {k:v for k,v in zip(argspec.args[n_postnl_args:], args[n_postnl_args:])}
          # update with kwargs
          passed.update({k:v for k,v in kwargs.iteritems()})            
          print 'function %s called with \n  positional args %s\n  passed kwargs %s\n  default kwargs %s' % (
                  fn.__name__, {k:v for k,v in zip(argspec.args, args[:n_postnl_args])},
                  passed,
                  {k:v for k,v in zip(argspec.args[n_postnl_args:], argspec.defaults) if k not in passed})        
          return fn(*args, **kwargs)
  return wrapper
  </code></pre>
  
  <p>That was a good learning experience. It's neat to see three different solutions to the same problem. Thanks to the Answerers!</p>