美文网首页
Python中实现lazy_property懒加载属性

Python中实现lazy_property懒加载属性

作者: 我只要喝点果粒橙 | 来源:发表于2022-04-02 10:49 被阅读0次

看本文之前,可以先阅读Python中的lazy property,概念与用法在上述文章中有比较详细的介绍,本文是对其未讲解清晰地方的具体分析。

描述符+类装饰器实现


class LazyProperty(object):
    def __init__(self, func):
        # 初始化func为serverHost函数
        self.func = func

    def __get__(self, instance, owner):
        if instance is None:
            return self
        else:
            value = self.func(instance)
            # 会将结果值通过setattr方法存入到instance实例的__dict__中
            setattr(instance, self.func.__name__, value)
            return value


class ConfigHandler:
    def __init__(self):
        pass
    # 返回一个LazyProperty实例 
    @LazyProperty
    def serverHost(self):
        return os.environ.get("HOST", setting.HOST)

setting = namedtuple("setting", ["HOST"])
setting.HOST = "g"

# 测试一
a = ConfigHandler()
print(a.__dict__)
# 1. 注解先是创建了LazyProperty(serverHost)的实例
# 2. 再是语法糖进行了赋值serverHost = LazyProperty(serverHost)
# 3. 当第一次进行调用的时候, instance = configHandler**实例**, self.func(instance实例) == 调用serverHost(instance实例)从而获得了真正值value。而之后的 setattr处将self实例的__dict__中添加了serverHost-value,再次访问self.serverHost时, 已经不再是函数, 而是value值(serverHost不再从ConfigHandler.__dict__中取, 而是实例a.__dict__中取)
print(a.serverHost)
print("say")
print(a.__dict__)

# 测试二
# 如果先执行类的__dict__能看到类的serverHost是一个**描述器对象实例**=> 'serverHost': <__main__.LazyProperty object at 0x0000020A1AEB7FD0>
print(ConfigHandler.__dict__)
# 通过__dir__能见到serverHost为实例的一个方法
print(a.__dir__())
# 此时a.__dict__为空
print(a.serverHost)
# 等到调用过a.serverHost后可以发现a.__dict__中多了serverHost
print(a.__dict__)
# 由于实例__dict__会优先于类的__dict__使用,所以直接返回了value值

重点:

  1. 跟[print(t.des)](#3.object.__get__(self, instance, owner))会触发t.des指向的descriptor实例的__get__一样,通过类__dict__["serverHost"],其也是个描述器实例,因此也会触发LazyProperty object的__get__
  2. 实例__dict__会优先于类的__dict__使用,如果实例__dict__找不到,会往上类__dict__

修饰符(方法装饰器)

def lazy_property(func):
    # 创建protected属性
    attr_name = "_lazy_" + func.__name__
    @property
    def _lazy_property(self):
        # print("done")
        if not hasattr(self, attr_name):
            # print("set")
            setattr(self, attr_name, func(self))
        return getattr(self, attr_name)
    return _lazy_property


class Circle(object):
    def __init__(self, radius):
        self.radius = radius

    @lazy_property
    def area(self):
        return 3.14 * self.radius ** 2

# 当解析Circle类、定义area方法的时候,会将Circle.area = @property修饰的_lazy_property函数
c = Circle(4)
print('before calculate area')
print(c.__dict__)
# 当调用c.area时,会输出done, 此时会执行_lazy_property内的具体函数, 此次会进行setattr
print(c.area)
# 此次不会调用setattr
print(c.area)
print('after calculate area')
print(c.__dict__)
c.radius = 5

相关文章

  • Python中实现lazy_property懒加载属性

    看本文之前,可以先阅读Python中的lazy property[https://www.jianshu.com/...

  • Swift:)懒加载Lazy

    OC中,要实现懒加载是用到getter方法,例如 Swift懒加载差别就很大了,懒加载属性用lazy修饰,注意结尾...

  • Swift 如何实现懒加载

    通过懒加载来实现从相册或拍照添加图片1、声明懒加载属性imagePickerController 2、显示相册和拍...

  • iOS 重构之路 - 分类属性懒加载

    iOS 分类属性实现懒加载(用途:项目重构,继承->组合)

  • Swift: lazy 属性的写法

    序言:OC中有懒加载,Swift中用lazy关键字声明属性,也可以实现懒加载。lazy所修饰的属性只有第一次访问时...

  • Swift懒加载

    懒加载的2个好处:延迟加载属性(UI类型控件一般都会延迟加载)在后边的代码中,延迟加载的属性,不用再强制解包 懒加...

  • Angular4-lazyload懒加载

    在Angular4中实现懒加载html、js、css等资源。利用Angular CLI实现懒加载,通过loadCh...

  • kotlin—lazy及其原理

    1、lazy简介 lazy是属性委托的一种,是有kotlin标准库实现。它是属性懒加载的一种实现方式,在对属性使用...

  • swift学习09(懒加载)

    swift中是通过专门的关键字(lazy)来实现懒加载; 一、直接懒加载赋值 二、懒加载赋一个函数 三、懒加载赋一...

  • vue中组件懒加载

    vue中组件懒加载的方法 1.异步实现路由懒加载 2.import(推荐使用这种方式) 同理,路由懒加载和组件懒加...

网友评论

      本文标题:Python中实现lazy_property懒加载属性

      本文链接:https://www.haomeiwen.com/subject/kgltsrtx.html