title: Wrapping a constructor in decorator in python
body: <p>I want to have a handy decorator that checks if the value of attribute passed to the method is not None. I then want to use it as a general purpose decorator in class methods. For this, I wrote:</p>
  
  <pre><code>def check_empty(name):
    def wrap_outer(function):
      def wrapped(*args, **kwargs):
        if kwargs.get(name, None) is None:
          raise Exception('{item} cannot be empty'.format(item=name))
        return function(args, kwargs)
      return wrapped
    return wrap_outer
  </code></pre>
  
  <p>And, the class is defined as:</p>
  
  <pre><code>class Player(object):
    @check_empty('name')
    def __init__(self, name):
      self.name = name
  
  def __str__(self):
    return self.name
  </code></pre>
  
  <p>However, this does not work. The template for the constructor and the decorator do not match. How can we create a function decorator for a constructor? Or is class based decorator a better option?</p>
  
  <hr>
  
  <p>Thanks to @ajax1234, I figured out the problem. It was in the way I was passing down my <code>args</code> and <code>kwargs</code>. It should have been:</p>
  
  <pre><code>def check_empty(attr):
    def wrap_outer(function):
      def wrapped(*args, **kwargs):
        if (len(args) &gt; 1 and args[1] is None) or (len(args)==1 and len(kwargs)==0):
          raise Exception('{item} cannot be empty'.format(item=attr))
        elif attr in kwargs and kwargs.get(attr, None) is None:
          raise Exception('{item} cannot be empty'.format(item=attr))
      return function(*args, **kwargs)
    return wrapped
  return wrap_outer
  </code></pre>
  
  <p>This takes care of checking on the parameter if it is passed as a keyword argument or just a positional argument.</p>
  
  <p><strong>NOTE:</strong> It does have a restriction that positional argument logic won't scale well while maintaining the generic nature. (We'd need to look into the positional argument's position using <code>inspect.getargspec</code> and then build up from there.)</p>