title: Descriptor for lazy loading
body: <p>I wanted to implement lazy loading of variables, but I seem to misunderstand descriptors a bit. I'd like to have object variables, which on first access will call the obj.load() function which will initialize the variables with their real value. I wrote</p>
  
  <pre><code>class ToLoad(object):
      def __init__(self, loader_name="load")
          self.loader_name=loader_name
  
      def __get__(self, obj, type):
          if not (hasattr(obj, "_loaded") and obj._loaded):
              obj._loaded=True
              getattr(obj, self.loader_name)()
          return None
  
  class Test(object):
      x=ToLoad()
      def __init__(self, y):
          self.y=y
  
      def load(self):
          print("Loading {}".format(self.y))
          self.x=self.y
  
  t1=Test(1)
  t2=Test(2)
  print("A", t1.x)
  print("B", t2.x)
  print("C", t1.x)
  </code></pre>
  
  <p>which fails to return the actual value on loading at least the first time. Could someone suggest another way to solve that problem? I'm not sure how to return the correct value in <strong>get</strong> since at that point I do not know that the attribute is called "x"? Any other way?</p>
  
  <p>DAMN, can't answer my own question... So here is the
  EDIT:
  Thanks for the input! However, my load() function does not return the variable itself, since it loads many different variables. And I want to minimize the notation for using lazy loading. So I came up with a decorator</p>
  
  <pre><code>class to_load:
      def __init__(self, *vars, loader="load"):
          self.vars=vars
          self.loader=loader
  
      def __call__(self, cls):
  
          def _getattr(obj, attr):
              if attr in self.vars:
                  getattr(obj, self.loader)()
                  return getattr(obj, attr)
              else:
                  raise AttributeError
  
          cls.__getattr__=_getattr
          return cls
  
  @to_load("a", "b")
  class Test:
      def load(self):
          print("Loading")
          self.a=1
          self.b=2
  
  t=Test()
  print("Starting")
  print(t.a)
  print(t.b)
  #print(t.c)
  </code></pre>
  
  <p>Is that OK? I'm not sure if I'm breaking things.</p>