title: Decorator classes in Python
body: <p>I want to construct classes for use as decorators with the following principles intact:</p>
  
  <ol>
  <li>It should be possible to stack multiple such class decorators on top off 1 function.</li>
  <li>The resulting function name pointer should be indistinguishable from the same function without a decorator, save maybe for just which type/class it is.</li>
  <li>Ordering off the decorators should not be relevant unless actually mandated by the decorators. Ie. independent decorators could be applied in any order.</li>
  </ol>
  
  <p>This is for a Django project, and the specific case I am working on now the method needs 2 decorators, and to appear as a normal python function:</p>
  
  <pre><code>@AccessCheck
  @AutoTemplate
  def view(request, item_id) {}
  </code></pre>
  
  <p>@AutoTemplate changes the function so that instead of returning a HttpResponse, it just returns a dictionary for use in the context. A RequestContext is used, and the template name is inferred from the method name and module.</p>
  
  <p>@AccessCheck adds additional checks on the user based on the item_id.</p>
  
  <p>I am guessing it's just to get the constructor right and copy the appropriate attributes, but which attributes are these?</p>
  
  <p>The following decorator won't work as I describe:</p>
  
  <pre><code>class NullDecl (object):
      def __init__ (self, func):
          self.func = func
      def __call__ (self, * args):
          return self.func (*args)
  </code></pre>
  
  <p>As demonstrated by the following code:</p>
  
  <pre><code>@NullDecl
  @NullDecl
  def decorated():
      pass
  
  def pure():
      pass
  
  # results in set(['func_closure', 'func_dict', '__get__', 'func_name',
  # 'func_defaults', '__name__', 'func_code', 'func_doc', 'func_globals'])
  print set(dir(pure)) - set(dir(decorated));
  </code></pre>
  
  <p>Additionally, try and add "print func.<strong>name</strong>" in the NullDecl constructor, and it will work for the first decorator, but not the second - as name will be missing.</p>
  
  <p>Refined <strong>eduffy</strong>'s answer a bit, and it seems to work pretty well:</p>
  
  <pre><code>class NullDecl (object):
      def __init__ (self, func):
          self.func = func
          for n in set(dir(func)) - set(dir(self)):
              setattr(self, n, getattr(func, n))
  
      def __call__ (self, * args):
          return self.func (*args)
      def __repr__(self):
          return self.func
  </code></pre>