2012-02-14 30 views
5

¿Cómo implementaría la carga diferida de los atributos del objeto, es decir, si se accede a los atributos pero aún no existen, se llama a algún método de objeto que supuestamente los carga?Carga diferida de los atributos

Mi primer intento es

def lazyload(cls): 
    def _getattr(obj, attr): 
     if "_loaded" not in obj.__dict__: 
      obj._loaded=True 
      try: 
       obj.load() 
      except Exception as e: 
       raise Exception("Load method failed when trying to access attribute '{}' of object\n{}".format(attr, e)) 
      if attr not in obj.__dict__: 
       AttributeError("No attribute '{}' in '{}' (after loading)".format(attr, type(obj))) # TODO: infinite recursion if obj fails 
      return getattr(obj, attr) 
     else: 
      raise AttributeError("No attribute '{}' in '{}' (already loaded)".format(attr, type(obj))) 

    cls.__getattr__=_getattr 
    return cls 

@lazyload 
class Test: 
    def load(self): 
     self.x=1 

t=Test()  # not loaded yet 
print(t.x) # will load as x isnt known yet 

haré lazyload específica a ciertos nombres de los atributos únicos. Como todavía no he hecho mucho metaclasificación, no estoy seguro de si ese es el enfoque correcto. ¿Qué sugerirías?

+1

* "metaclases son más profundas mágica del 99% de los usuarios debe preocuparse Si usted se pregunta si los necesita, no lo hace.. " - TP *. Creo que una propiedad según lo sugerido por Daniel sería mejor. –

+0

Estoy usando esta receta http://code.activestate.com/recipes/576563-cached-property/ – reclosedev

+0

@Rik: No estoy pensando si necesito metaclases sino cómo resolver el problema de lazyload. El ejemplo de Daniels aún no lo resuelve del todo, ya que es de solo lectura y no quiero líneas de código duplicadas para cada ocurrencia. ¿Se puede ajustar? – Gerenuk

Respuesta

6

parece como un simple property que hacer el truco mejor:

@property 
def my_attribute(): 
    if not hasattr(self, '_my_attribute'): 
     do_expensive_operation_to_get_attribute() 
    return self._my_attribute 
+1

Suena bien, pero ahora la pregunta es si puede ser conveniente. También necesito propiedades de escritura. Y, lo que es más importante, ¿puedo incluir esto en una buena notación sin reescribir las mismas 4 líneas de código muchas veces? – Gerenuk

+0

¿Puedo escribir 'my_attribute = lazyload (load_method)' en la definición de clase o algo similar? – Gerenuk

Cuestiones relacionadas