一日一技:使用装饰器实现类属性的懒加载

简介: 一日一技:使用装饰器实现类属性的懒加载

假设我们有一个工具类MongoUtil,它的作用是封装一些数据库操作。例如:


import pymongo
class MongoUtil:
    def __init__(self):
        connect = pymongo.MongoClient()
        db = connect.tieba
        self.post = db.post
        self.user = db.user
    def write_post(self, post):
        # 处理post信息
        self.post.insert_one(post)
    def read_user_info(self):
        rows = self.user.find()
        # 读取user信息并处理
        # ...


我们发现这样写有一个问题——类在初始化的时候,就会创建数据库的链接。但我们并

不是在类刚刚初始化时就读写数据库。


为了让数据库在第一次使用时再创建连接,我们就要实现懒加载机制:


import pymongo
class MongoUtil:
    def __init__(self):
        connect = pymongo.MongoClient()
        self.db = connect.tieba
        self.post = None
        self.user = None
    def write_post(self, post):
        # 处理post信息
        if not self.post:
            self.post = self.db.post
        self.post.insert_one(post)
    def read_user_info(self):
        if not self.user:
            self.user = self.db.user
        rows = self.user.find()
        # 读取user信息并处理
        # ...


这样写确实实现了懒加载,但每一个操作都需要判断当前是否联系到了对应的集合中。

这样就会出现大量的重复代码。


为了解决这个问题,我们可以使用装饰器实现一个懒加载机制:


import pymongo
class lazy:
    def __init__(self, func):
        self.func = func
    def __get__(self, instance, cls):
        if instance is None:
            return self
        else:
            value = self.func(instance)
            setattr(instance, self.func.__name__, value)
            return value
class MongoUtil:
    def __init__(self):
        connect = pymongo.MongoClient()
        self.db = connect.tieba
    @lazy
    def post(self):
        return self.db.post
    @lazy
    def user(self):
        return self.db.user
    def write_post(self, post):
        # 处理post信息
        self.post.insert_one(post)
    def read_user_info(self):
        rows = self.user.find()
        # 读取user信息并处理
        # ...


我们实现了一个装饰器类lazy来装饰两个类属性postuser。当self.post第一次被调用时,它会正常连接结合,当第二次或以上访问self.post时,就会直接使用第一次返回的对象,不会再次连接MongoDB的集合。self.user同理。


我们来测试一下,如下图所示。


640.png



可以看到,第二次调用self.post时,并没有打印出第一次访问self.post,因为第二次会直接使用之前的缓存。


最后,特别说明:本文使用MongoDB举例只是为了说明基于装饰器的类属性懒加载的代码写法。而实际上,pymongo已经自动实现了懒加载机制,当我们直接

db.tieba.post时,它并不会真的去连接MongoDB,只有当我们要增删改查集合里面的数据时,pymongo才会创建连接。


请关注微信公众号【未闻Code】获取更多精彩文章。

目录
相关文章
|
算法 计算机视觉
图像处理常用算法—6个算子 !!
图像处理常用算法—6个算子 !!
594 2
|
数据可视化 Go 数据库
性能分析神器:pprof命令详解与实战
性能分析神器:pprof命令详解与实战
1544 0
性能分析神器:pprof命令详解与实战
|
前端开发 JavaScript 容器
bootstrap-treeview树
bootstrap-treeview树
233 0
|
安全 编译器 程序员
全面解析C++11新特性:现代编程的新起点(上)
全面解析C++11新特性:现代编程的新起点
全面解析C++11新特性:现代编程的新起点(上)
|
机器学习/深度学习 数据可视化 PyTorch
OneFlow深度学习框架介绍:新手快速上手指南
【4月更文挑战第12天】OneFlow是一款高性能的深度学习框架,由一流科技公司研发,以其数据流编程模型、动态图执行和高效分布式训练等功能脱颖而出。其易用性、卓越性能和强大的分布式训练能力使其在AI领域备受关注。新手可以通过简单的安装和基础程序快速上手,利用OneFlow的Module构建模型,结合损失函数和优化器进行训练。此外,OneFlow支持ONNX模型导入导出、TensorBoard可视化及与其他Python库集成,助力无缝对接现有生态。深入了解和实践OneFlow,可提升深度学习开发效率。
440 2
|
前端开发 Oracle Java
Java 22 新增利器: 使用 Java Stream Gather 优雅地处理流中的状态
本文我们分析了 什么 是 “流”,对比了 Java 上几种常见的 “流”库,引入和详细介绍了 Java 22 中的 Stream Gather API 。同时也简单分享了利用 虚拟线程 如何简化 StreammapConcurrent操作符的实现。
|
Java Python Windows
Python pip 源设置成国内源,阿里云源,清华大学源,最方便的方式,都在这里了
Python pip 源设置成国内源,阿里云源,清华大学源,最方便的方式,都在这里了
74290 0
|
Ubuntu 应用服务中间件 数据库
Nginx配置:阻止非国内IP地址访问的设置方法
此外,出于用户隐私和法律合规性的考虑,应慎重考虑阻止特定国家或地区IP地址的决策。在某些情况下,这可能被视为歧视性或违反当地法律。
710 3
|
应用服务中间件
Spring-boot启动失败 Unregistering JMX-exposed beans on shutdown 异常处理
Spring-boot启动失败 Unregistering JMX-exposed beans on shutdown 异常处理
594 0
|
弹性计算 缓存 前端开发
阿里云服务器配置选择指南2核4G、4核8G和8核16G性能全解析!
阿里云2核4G、4核8G与8核16G服务器配置解析及选择指南。根据不同业务需求,推荐ECS经济型e、通用算力型u1、计算型c7/c8i实例。企业用户专享2核4G ECS u1实例仅199元/年,自带5M带宽;4核8G u1实例起价955.58元/年;8核16G c7实例起价6544元/年。各实例CPU性能各异,如c7采用第三代Intel Xeon处理器,适配高性能计算场景。
737 10