Python 实现单例模式的几种方式以及存在的问题

这篇具有很好参考价值的文章主要介绍了Python 实现单例模式的几种方式以及存在的问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、模块单例

Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。

#foo1.py
class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()


#foo.py
from foo1 import singleton

直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象

二、静态变量方法

先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式。

class Singleton(object):
    def __new__(cls,a):
        if not hasattr(cls, '_instance'):
            cls._instance = object.__new__(cls)
        return cls._instance
    def __init__(self,a):
        self.a = a
    def aa(self):
        print(self.a)

a = Singleton("a")

变种:利用类的静态方法或者类方法,实现对函数初始化的控制。该方法需要手动调用静态方法实现实例。本质上是手动版的__new__方法。

class Singleton:
    @staticmethod
    def instance1(*args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            Singleton._instance = Singleton(*args, **kwargs)
        return Singleton._instance

  
    @classmethod
    def instance2(cls,*args, **kwargs):
        if not hasattr(cls, "_instance"):
            Singleton._instance = Singleton(*args, **kwargs)
        return Singleton._instance


a = Singleton.instance1() 
b = Singleton.instance2() 
print(a == b)```

## 三、元类方法
此方法是在__new__方法的更上层对实例化过程进行控制。

原理:执行元类的 元类的__new__方法和__init__方法用来实例化类对象,__call__ 方法用来对实例化的对象的实例即类的对象进行控制。__call__方法会调用实例类的 __new__方法,用于创建对象。返回对象给__call__方法,然后调用类对象的 __init__方法,用于对对象初始化。

```python
class Singleton1(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super(Singleton1,self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(Singleton1,self).__call__(*args, **kwargs)
        return self.__instance

class Singleton2(type):
    _inst = {}
    def __call__(cls, *args, **kwargs):
        print(cls)
        if cls not in cls._inst:
            cls._inst[cls] = super(Singleton2, cls).__call__(*args)
        return cls._inst[cls]

class C(metaclass=Singleton1):
    pass

四、装饰器

原理:装饰器用来控制类调用__call__方法。

def singleton(cls, *args, **kw):
    instance = {}
    def _singleton(args):
        if cls not in instance:
            instance[cls] = cls(*args, **kw)
        return instance[cls]
    return _singleton

@singleton
class A:
    pass

五、注意

除了模块单例外,其他几种模式的本质都是通过设置中间变量,来判断类是否已经被实例。区别就是中间变量的位置不同,或设置在元类中,或封装在函数中,或设置在类中作为静态变量。

注意1:中间变量的访问和更改存在线程安全的问题:在开启多线程模式的时候需要加锁处理。

注意2:new__方法无法避免触发__init(),初始的成员变量会进行覆盖。其他方法不会。文章来源地址https://www.toymoban.com/news/detail-814154.html

到了这里,关于Python 实现单例模式的几种方式以及存在的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Qt专栏】实现单例程序,禁止程序多开的几种方式

    目录 一,简要介绍 二,实现示例(Windows) 1.使用系统级别的互斥机制 2.通过共享内存(进程间通信-IPC) 3.使用命名互斥锁(不推荐) 4.使用文件锁 5.通过网络端口检测 前言 禁止程序多开,也称为“单实例应用程序”或“单例应用程序”,是指通过各种手段防止同一个应用

    2024年02月10日
    浏览(56)
  • Jenkins的几种安装方式以及邮件配置

    目录 Jenkins介绍 Jenkins下载、安装 一、通过war包安装 二、通过docker安装 jenkins 容器中添加 git, maven 等组件 jenkins 容器中的公钥私钥 在 jenkins 容器中调用 docker 简单的方式启动 Docker server REST API 一个 jenkins 示例 三、通过Homebrew安装 访问Jenkins、Jenkins配置 Jenkins配置邮件发送 Jen

    2024年02月16日
    浏览(38)
  • uniapp页面跳转的几种方式 以及举例(2)

    又来混时长 嫖流量卷了 保留当前页面,跳转到应用内的某个页面,使用 uni.navigateBack 可以返回到原页面。   关闭当前页面,跳转到应用内的某个页面。   关闭所有页面,打开到应用内的某个页面。 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。 关闭当前页面,返回上一

    2024年01月19日
    浏览(46)
  • mysql备份以及还原表与库的几种常见方式

    (1)备份包括系统数据库在内的所有数据库(所有库表结构及数据) 备注:例子是备份本地库到本地目录,如需备份其他机器上的mysql数据库到本地需要加上端口参数以及主机地址(以下类似):   (2)备份单个库(单个库表结构及数据) (3)备份单个库里的单个表(单个表

    2024年02月01日
    浏览(50)
  • 单例模式有几种写法?【如何实现单例模式?】

    专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录) 文章字体风格: 红色文字表示:重难点★✔ 蓝色文字表示:思路以及想法★✔ 如果大家觉得有帮助的话,感谢大家帮

    2024年02月07日
    浏览(45)
  • python的几种输出方式

    1.输出百分比方法 2. print(f “{}”) 的用法 3. .format格式   4. 加号拼接(针对字符串) 扩展知识 -格式化输出 字符 含有 %s 字符串 %d 有符号十进制整数,%06d表示输出的整数显示位数字,不足的地方使用0补全 %f 浮点数,%.02f表示小数点后只显示两位 %% 输出%  %s:代表字符串的占

    2024年04月15日
    浏览(51)
  • 实战讲解及分析Spring新建Bean的几种方式以及创建过程(图+文+源码)

    作为一个应用开发人员而言,会使用某一个工具分为两个层次(个人观点): 第一个层次,知道工具,会使用这个工具解决问题; 第二个层次,理解工具的实现原理。 关于Spring的学习,还在第一个层次转悠,缺少原理的研究, 随着学习的深入,开始研究些Spring源码,配合

    2023年04月08日
    浏览(38)
  • springBoot使用webSocket的几种方式以及在高并发出现的问题及解决

    1、该类可以作为一个基础的安全抽象层,后续项目中如果需要做认证的操作,都可以继承该抽象类 ClientUserInfoService 大家可以看作一个 UserService 就是一张用户表的service类 这里认证采用的是 jwt的方式,大家可以换成自己的 2、 大家这里注意,我们使用的是 javax.websocket.Sessio

    2024年02月09日
    浏览(51)
  • Python保存图像的几种方式

    记录读取和保存图像的几种方式 1.1、使用 cv2 读取图片,注意:opencv打开路径中不能有中文!!! 1.2、使用 rasterio 读取遥感影像 1.3、使用 Image 读取图像 2.1、使用 cv2 保存图片 2.2、使用numpy保存 2.3、使用plt保存 参考: https://blog.csdn.net/xzm961226xzm/article/details/120951317 https://bl

    2024年02月11日
    浏览(51)
  • python数组循环的几种方式

     Python中循环数组有几种方式: for-in循环,可以遍历数组中的每一个元素。 while循环,使用索引进行循环。 列表推导式,可以快速创建新的列表。 递归,可以遍历多维数组。 enumerate() 函数,在循环中同时获取索引和元素

    2024年02月16日
    浏览(83)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包