专栏首页未闻Code一日一技:Python 下面最简单的单例模式写法

一日一技:Python 下面最简单的单例模式写法

摄影:产品经理

买单:kingname

二十几种设计模式中,单例模式是最简单最常用的一种。在其他语言里面实现单例模式要写不少代码,但是在 Python 里面,有一种非常简单的单例模式写法。

为了演示这种简单的写法,我们首先创建一个文件,DBUtil.py文件,用来模拟数据库操作类。这个文件里面的代码如下:

class DBUtil:
    def __init__(self):
        self.conn = self.connect()
    
    def connect(self):
        print('创建数据库连接')
        return 'connect'
  
    def write(self, data):
        print(f'写入数据:{data}')
   
    def read(self):
        print('从数据库中读取数据')
        return 123

现在我们创建两个文件:a.pyb.py,用来模拟在一个工程里面的两个不同地方同时调用数据库操作类并初始化的过程。

a.py内容如下:

from DBUtil import DBUtil
from b import run

data = run()
db_util = DBUtil()
db_util.write(data)

b.py的内容如下:

from DBUtil import DBUtil

def run():
    db_util = DBUtil()
    data = db_util.read()
    return data

运行效果如下图所示:

可以看到,创建数据库连接被打印了两次,说明DBUtil类被实例化了两次。对应到真实的项目中,就是创建了多个到数据库的链接。这样是很浪费资源的。

当然,你可以在 a.py中初始化DBUtil,然后把这个对象作为参数传入run函数里面,再run函数里面调用这个对象的read()方法。

但是在实际项目中,往往会出现很多层的调用,如果要把一个对象一层一层传下去,不仅让参数列表显得杂乱,还容易漏掉或者搞错顺序。

所以,使用单例模式就能避免通过参数传递对象,但又不会创建多个数据库连接。

网上关于单例模式的代码有很多。本文将会介绍最简单的一种,利用 Python 的import机制。在 Python 里面,一个模块只会被导入1次,如果多次使用import xxx导入同一个模块,后面的导入语句会被自动忽略。利用这个机制,我们就能很容易实现单例模式。

修改DBUtil.py,在它的最下面加上一行代码:

class DBUtil:
    def __init__(self):
        self.conn = self.connect()
    
    def connect(self):
        print('创建数据库连接')
        return 'connect'
  
    def write(self, data):
        print(f'写入数据:{data}')
   
    def read(self):
        print('从数据库中读取数据')
        return 123

db_util = DBUtil()

修改a.py:

from DBUtil import db_util
from b import run

data = run()
db_util.write(data)

修改b.py:

from DBUtil import db_util

def run():
    data = db_util.read()
    return data

运行以后的效果如下图所示:

可以看到,创建数据库连接只打印了1次,说明单例模式成功。

这种单例模式非常简单,但是有一个弊端,就是无法实现懒加载。程序刚刚开始运行,DBUtil类就会被实例化,无法做到等到需要的时候才实例化。

本文分享自微信公众号 - 未闻Code(itskingname),作者:kingname

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一日一技:Python多线程的事件监控

    你创建了10个子线程,每个子线程分别爬一个网站,一开始所有子线程都是阻塞等待。一旦某个事件发生:例如有人在网页上点了一个按钮,或者某人在命令行输入了一个命令,1...

    青南
  • 一日一技:在Python中,如何获得一个函数的名字?

    青南
  • Bytes型数据decode时是如何知道要把几位数据组合在一起的?

    我们知道,在 Unicode 编码中,中文占3个字节,所以一个中文字符编码为 Bytes 型数据以后,会占用3个 Bytes 字符,例如:

    青南
  • opencl:一个关于向量赋值的异常

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • “E安全”手机App 2.0越级版即将上线

    由中国信息安全测评中心和杭州安恒信息技术有限公司联合开发的信息安全类手机App——E安全2.0越级版即将上线。 这是一款基于信息安全移动课程教学、信息安全资料分...

    安恒信息
  • Google 开源 Docker 镜像差异分析工具 container-diff

    Google 发布了一个名为 container-diff 的开源项目,这是一个分析和比较容器镜像的工具,可用来分析 Docker 镜像之间的差异。

    Debian社区
  • 通过 http 方式获取 RabbitM

      在使用 pika 连接 RabbitMQ 的过程中,发现只能获取 ready 状态的消息数量,只好用 http 请求来实现目的。

    py3study
  • Java--JDBC总结

    SuperHeroes
  • SQL SERVER修改函数名引起的问题

    1. 问题 今天遇到一个奇怪的问题:使用sp_helptext XXX查询出来的函数定义名竟然跟函数名不同,而sp_helptext实际是查询sys.all_s...

    逸鹏
  • 只需看一眼,伯克利最新机器人就可以copy你的动作!

    通过观察另一个人的做法来学习一项新技能,即模仿的能力,是人类和动物智力的关键部分。我们能让机器人做同样的事情吗?

    大数据文摘

扫码关注云+社区

领取腾讯云代金券