本篇主要介绍一下关于Python的单例模式,即让一个类对象有且只有一个实例化对象。

一、使用__new__方法(基类)

  要实现单例模式,即为了让一个类只能实例化一个实例,那么我们可以去想:既然限制创建实例,那么我们可以修改其创建实例的根源即可,那就是父类__new__方法。

  注意:不能使用自身的__new__()方法,应为自身这个类去进行实例化,是调用父类的__new__方法,若调用自身的__new__方法,那不就死循环了么,可以参考我的另外一篇博客:python类的__new__()

class SingleTon(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(cls, *args, **kwargs)
# return super().__new__(cls, *args, **kwargs)
return cls._instance class Foo(SingleTon):
pass if __name__ == '__main__':
f1 = Foo()
f2 = Foo()
print('f1的id:',id(f1))
print('f2的id:',id(f2)) # f1的id: 2151027475064
# f2的id: 2151027475064

  注释:通过修改父类的__new__方法,去干涉子类的实例化创建实例,实现只能一个类只能有一个实例的效果。

二、使用闭包的形式

  无论怎么实现,均为了让一个类只有一个实例对象,那么我们可以当类创建一个实例,我们就把使用一个变量把该实例记录下来,若该变量已经有实例了,便可把该变量返回即可,不让其进行创建新的实例。

def singleton(cls, *args, **kwargs):
instances = None
def get_instance(*args, **kwargs):
nonlocal instances
if instances is None:
instances = cls(*args, **kwargs)
return instances
return get_instance @singleton
class Bar(object):
def __init__(self,name):
self.name = name if __name__ == '__main__':
b1 = Bar('alex')
b2 = Bar('hello')
print(b1.name)
print(b2.name)

  注:为了实现单例模式,可以在类创建实例的时候对其进行限制,即通过判断该类是否已经创建了实例,若没有进行过实例化,则我们让其进行实例化,反之,返回原有对象即可。

三、使用元类的方式

 首先我们需要明确的是,当我们使用元类时:

  1、类由type创建,创建类时,type的__init__方法自动执行,类()  --》执行type的 __call__方法(类的__new__方法,类的__init__方法)。

  2、对象由类创建,创建对象时,类的__init__方法自动执行,对象() -- 》执行类的 __call__ 方法。

 那么我们可以思考:

  当我们调用 类() 时不就是一个实例化的过程吗,就自动回执行 type中的call方法,所以我们需要去实现单例模式,只需要在call方法中对其进行限制是不是就可以达到我们想要的效果呢?试一试

class SingleTonType(type):

    def __init__(self,*args, **kwargs):
super().__init__(*args, **kwargs) def __call__(cls, *args, **kwargs):
_instance = None # 设置一个变量,用来存储是否创建实例
print('cls:',cls)
if _instance is None:
obj = cls.__new__(cls,*args, **kwargs) # 会一直找到能创建实例的父类,创建实例
cls.__init__(obj, *args, **kwargs) # 构造方法去丰富该实例
cls._instance = obj # 并将变量修改的创建的实例
return _instance class Foo(metaclass=SingleTonType):
def __init__(self,name):
self.name = name if __name__ == '__main__':
obj1 = Foo('hello') # 会调用type类(SingleTonType)中的call方法
obj2 = Foo('world')

  执行结果:

cls: <class '__main__.Foo'>
cls: <class '__main__.Foo'>
1841145040 1841145040

  是不是达到我们实现 -- 一个类只拥有一个实例对象的效果了呢?

  总结:其实实现单例模式,只需要在类进行实例化的时候,对其进行限制即可。比如在类进行实例化时,会调用父类的__new__方法,若使用元类,会调用call()方法,那么我们只需要在这两个方法中对其加以限制即可。

  使用修饰器闭包的利用的也是同样的原理。

浅谈Python设计模式 - 单例模式的更多相关文章

  1. 浅谈Python设计模式 - 享元模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 享元模式: 享元模式是一种用于解决资源和性能压力时会使用到的设计模式,它的核心思 ...

  2. 浅谈Python设计模式 -- 责任链模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 之前在最开始就聊了Python设计模式有三种,其中关于创建型和结构型设计模式基本 ...

  3. 浅谈Python设计模式 - 代理模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 一.在某些应用中,我们想要在访问某个对象之前执行一个或者多个重要的操作,例如,访 ...

  4. 浅谈Python设计模式 - 外观模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 外观模式 外观模式的核心在于将复杂的内部实现包装起来,只向外界提供简单的调用接口 ...

  5. 浅谈Python设计模式 - 适配器模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 从本篇便开始介绍结构型设计模式,而适配器设计模式便是该类设计模式的一种,那么什么 ...

  6. 浅谈Python设计模式 - 建造者模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 建造者模式 当我们想要创建一个由多个部分构成的对象,而且他们的构建需要一步接一步 ...

  7. 浅谈Python设计模式 - 抽象工厂模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 在上一篇我们对工厂模式中的普通工厂模式有了一定的了解,其实抽象工作就是 表示针对 ...

  8. 浅谈Python设计模式 - 工厂模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 工厂模式: 顾名思义,工厂则是根据提供的不同的材料,生产出不同的产品.那么在编程 ...

  9. 浅谈Python设计模式 - 原型模式

    声明,本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 在<精通Python设计模式>中把设计模式分为三种类型: 创建型模式 ...

随机推荐

  1. 文件组 'PRIMARY' 已满 解决办法

    修改一个字段类型时,报的这个错. 此时需要增加次要数据文件 次要数据文件 次要数据文件包含除主要数据文件外的所有数据文件.有些数据库可能没有次要数据文件,而有些数据库则有多个次要数据文件.次要数据文件 ...

  2. Qt之如何自定义model

    Qt之如何自定义model https://blog.csdn.net/wei375653972/article/details/86592209

  3. JEECG实现模糊查询

    1.JEECG默认不带模糊查询的,但实际开发中会经常用到模糊查询,因此要适当修改(在相应的查询处). @RequestMapping(params = "datagrid") pu ...

  4. hive 集群搭建

    软件环境:centos7 + hadoop2.7.6 1.hive 下载 apache-hive-2.1.0-bin.tar.gz 2.copy  apache-hive-2.1.0-bin.tar. ...

  5. SpringBoot系列教程web篇之全局异常处理

    当我们的后端应用出现异常时,通常会将异常状况包装之后再返回给调用方或者前端,在实际的项目中,不可能对每一个地方都做好异常处理,再优雅的代码也可能抛出异常,那么在 Spring 项目中,可以怎样优雅的处 ...

  6. 使用echarts绘制条形图和扇形图

    使用echarts绘制条形图和扇形图 简单举例说明下echarts如何绘制条形图和扇形图 代码示例 <!doctype html> <html lang="en" ...

  7. PAt 1099

    1099 Build A Binary Search Tree (30 分)   A Binary Search Tree (BST) is recursively defined as a bina ...

  8. linux查看端口常用命令

    netstat命令参数: -t : 指明显示TCP端口 -u : 指明显示UDP端口 -l : 仅显示监听套接字(所谓套接字就是使应用程序能够读写与收发通讯协议(protocol)与资料的程序) -p ...

  9. [转帖]技术人眼中的Facebook Libra

    技术人眼中的Facebook Libra https://www.jianshu.com/p/ddc733077749 比特币 以太坊 EOS Libra 0.8352019.07.01 14:15: ...

  10. Flume和 Sqoop

    Sqoop简介 Sqoop是一种旨在有效地在Apache Hadoop和诸如关系数据库等结构化数据存储之间传输大量数据的工具 原理: 将导入或导出命令翻译成Mapreduce程序来实现. 在翻译出的M ...