python 实现类属性的懒加载装饰器

class lazy:
    # 告诉 Python 不要创建对象的 __dict__,而是只给一个固定集合的属性分配空间。
    __slots__ = ['func']

    def __init__(self, func):
        self.func = func

def __get__(self, instance, owner):
    name = self.func.__name__
    # 如果 func 不为 None 则赋值给 owner (这里是 `MyClass`) 的 `name` 属性,
    # 此后 owner 的 name() 不再是装饰器方法,而是实实在在的 func() 方法返回值!
    if (v := self.func(owner)) is not None:
        setattr(owner, name, v)
    return owner.__dict__.get(name) if v else None

class MyClass:
    @lazy
    def name(self) -> str:
        print("debug: name(self)")
        return "get name"

if __name__ == '__main__':
    name = MyClass.name  # output: 'debug: name(self)'
    print(f'[{name}]', type(name))  # => [get name] <class 'str'>
    print(f'[{MyClass.name}]')  # => [get name]

第一次调用 MyClass.name 时会进入到装饰器的 __get__ 方法中返回值,我们在 __get__ 方法的内部再重新把装饰器的 func 返回值赋值给 owner ( 这里是 MyClass ) 的 name 属性,从而达到 替换值 的概念。

本作品采用《CC 协议》,转载必须注明作者和本文链接
一代咩神
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!