属性的懒加载

6 投票
2 回答
3683 浏览
提问于 2025-04-17 13:00

你会怎么实现对象属性的懒加载呢?也就是说,当访问某些属性但它们还不存在时,应该调用某个对象的方法来加载这些属性。

我第一次尝试是这样的:

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

我打算只对某些特定的属性名进行懒加载。因为我还没有做过很多元类的相关工作,所以不太确定这样做是否正确。你有什么建议吗?

2 个回答

1

看看 django/utils/functionals.py 里的 lazy

https://docs.djangoproject.com/en/2.1/_modules/django/utils/functional

7

看起来用一个简单的 property 就能更好地解决这个问题:

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

撰写回答