2012-02-14 8 views
5

オブジェクト属性の遅延読み込みを実装する方法、つまり属性にアクセスしてもまだ存在しない場合、これらを読み込むオブジェクトメソッドが呼び出されますか?属性の遅延ロード

私の最初の試みは、私が唯一の特定の属性名にlazyloadが特定のようになります

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 

です。 私はまだ多くのメタクラスを行っていないので、それが正しいアプローチであるかどうかはわかりません。 あなたは何をお勧めしますか?シンプルなpropertyが良いトリックを行うだろうよう

+1

*「メタクラスは、あなたがそれらを必要とするかどうかを疑問に思う場合は、あなたがしていないユーザーの99%が今まで心配しなければならないより深い魔法です。 " - TP *。私はダニエルによって提案された財産が良いと思う。 –

+0

私はこのレシピを使用しています。http://code.activestate.com/recipes/576563-cached-property/ – reclosedev

+0

@Rik:私はメタクラスが必要かどうかは考えていませんが、むしろlazyload問題を解決する方法を考えています。ダニエルズの例ではまだ読んでいないので、それはまだ解決していません。それは調整できますか? – Gerenuk

答えて

6

は思え:。

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

音がきれいですが、今問題はそれが便利にできるかどうかです?私も書き込み可能なプロパティが必要です。さらに重要なのは、同じ4行のコードを何度も書き直すことなく、これを素敵な表記にすることができますか? – Gerenuk

+0

'my_attribute = lazyload(load_method)'をクラス定義などに書くことができますか? – Gerenuk