title: Efficient pooling/caching of expensive objects
body: <p>How can I efficiently in a proper pythonic pool/cache objects holding an expensive answer from the database?</p>
  
  <p>My module contains following schematic code:</p>
  
  <pre><code>import sqlite3
  
  db = sqlite3.connect(config.DB) # application shared database
  db.row_factory = sqlite3.Row
  
  class Foo:
  
      def __init__(self, id):
          self.id = id
  
      @property
      def bar(self):
          if not hasattr(self, '_bar'):
              row = db.execute(
                  'SELECT bar FROM bars WHERE id=?', (self.id, )).fetchone()
              self._bar = row['bar'] if row else None
          return self._bar
  </code></pre>
  
  <p>Application is creating over its lifetime <code>Foo</code> objects to access some values <code>bar</code> in the database. The <code>Foo.bar</code> property represents an expensive operation, therefore the lazy processing. Instances of <code>Foo</code> class are not changing much at all, they are just a read-proxies for database stored data.</p>
  
  <p>Now I realized, that <code>Foo</code> instances with the same <code>id</code> are created and destroyed quite often. Every time the object dies, the knowledge of <code>Foo.bar</code> is lost and has to be fetched from the database later again.</p>
  
  <p>I figured two ways how I could deal with it, either pooling objects themselves:</p>
  
  <pre><code>class DBObject:
  
      _pool = {}
  
      def __new__(cls, *params, **key_params):        
          key = cls.__name__ + str(params) + str(key_params)
          if not key in DBObject._pool:
              self = object.__new__(cls, *params, **key_params)
              DBObject._pool[key] = self
          self = DBObject._pool[key]
          return self
  
  class Foo(DBObject):
      ...
  </code></pre>
  
  <p>or their states:</p>
  
  <pre><code>class DBObject:
  
      _states = {}
  
      def __new__(cls, *params, **key_params):        
          self = object.__new__(cls, *params, **key_params)        
          key = cls.__name__ + str(params) + str(key_params)
          if not key in DBObject._states:
              DBObject._states[key] = {}            
          self.__dict__ = DBObject._states[key]
          return self
  
  class Foo(DBObject):
      ...
  </code></pre>
  
  <p>Is there some better and more pythonic solution? Did I oversee something?</p>
  
  <p>PS: I am Python beginner with Java/C++ background.</p>