title: Multiple Python decorators when using "replacing" functions
body: <p>Perhaps what I'm trying to do just doesn't work. I also assume that there are other (better?) ways to accomplish the same thing, but what I'm trying to do is:</p>
  
  <p>I have a class that will have several (at least 4, possibly more) lists of dictionaries. I want to set up a single "load" function and a single search function that can be used for all of them. If any of the "load" or search functions is called, and the list is empty, the list should be loaded.</p>
  
  <p>The methods for loading them are each different and have different args. The search function needs to allow for searching on different members of the dictionaries that make up the list, and for returning either the entire matching dictionary or specific members.</p>
  
  <p>I have been using a decorator to specify the search function ala:</p>
  
  <pre><code>@search_list
  def get_name(self,id):
      pass
  </code></pre>
  
  <p>So that I effectively replace the function with the search, and can use the <code>func.__name__</code> in the search function to determine which list from the class to use and what member, if any (<code>_xx</code> on the end of the function name), to return.</p>
  
  <p>The problem I'm having is that I can use the load function, <code>get_list()</code>, by itself when doing something like:</p>
  
  <pre><code>@get_list
  def get_names(self):
      return self.names
  </code></pre>
  
  <p>But I have not been able to get it to load the list if the first thing I call is one of the search functions. If I call one of the <code>@get_list</code> functions, then the search function works fine after that, but I don't want to call a load function unless someone using the module wants that particular list. All of the lists are loaded via REST calls and some take a while.</p>
  
  <p>Like I said, there may be other (better) ways to accomplish this, but this has been driving me crazy...it's a short trip :-)</p>
  
  <p>Any suggestions would be appreciated. </p>
  
  <p>Here's the sample code I've been using:</p>
  
  <pre><code>#!/usr/bin/env python
  
  import re
  from functools import wraps
  
  NAMES = [
           {'name':'Fred Flintstone','id':1},
           {'name':'Barney Rubble','id':2},
           {'name':'Henry Ford','id':3},
           ]
  
  def get_list(func):
      @wraps(func)
      def wrapper(self,*args):
          res = re.match('get_(?P&lt;list&gt;[^_]+)(_(?P&lt;return&gt;.*))*',func.__name__)
          if res:
              list_name = res.group('list').endswith('s') and res.group('list') or (res.group('list') + 's')
              if not eval("self.%s" % list_name):
                  exec "self._Fred__get_%s()" % list_name in globals(),locals()
          return func(self,*args)
      return wrapper
  
  def search_list(func):
      @wraps(func)
      def wrapper(self,*args):
          res = re.match('get_(?P&lt;list&gt;[^_]+)(_(?P&lt;return&gt;.*))*',func.__name__)
          if res:          
              for x in eval('self.%ss' % res.group('list')):
                  if isinstance(args[0],(int,long)):
                      if x['id'] == args[0]: 
                          return res.group('return') and x[res.group('return')] or x
                  else:
                      if x['name'] == args[0]:
                          return res.group('return') and x[res.group('return')] or x
      return wrapper
  
  class Fred(object):
      def __init__(self):
          self.names = []
  
      def __get_names(self):
          self.names = NAMES
  
      @get_list
      def get_names(self):
          return self.names
  
      @get_list
      def get_name_names(self):
          return [x['name'] for x in self.names]
  
      @search_list
      @get_list
      def get_name(self,id):
          pass
  
      @search_list
      def get_name_name(self,id):
          pass
  
      @search_list
      def get_name_id(self,name):
          pass
  </code></pre>