本文为大家分享了Python创建单例模式的5种常用方法,供大家参考,具体内容如下

所谓单例,是指一个类的实例从始至终只能被创建一次。

方法1:

如果想使得某个类从始至终最多只有一个实例,使用__new__方法会很简单。Python中类是通过__new__来创建实例的:

1

2

3

4

5

6

7

8

9

10

11

12

13

class Singleton(object):

def __new__(cls,*args,**kwargs):

if not hasattr(cls,'_inst'):

cls._inst=super(Singleton,cls).__new__(cls,*args,**kwargs)

return cls._inst

if __name__=='__main__':

class A(Singleton):

def __init__(self,s):

self.s=s

a=A('apple')

b=A('banana')

print id(a),a.s

print id(b),b.s

结果:

29922256 banana

29922256 banana

通过__new__方法,将类的实例在创建的时候绑定到类属性_inst上。如果cls._inst为None,说明类还未实例化,实例化并将实例绑定到cls._inst,以后每次实例化的时候都返回第一次实例化创建的实例。注意从Singleton派生子类的时候,不要重载__new__。

方法2:

有时候我们并不关心生成的实例是否具有同一id,而只关心其状态和行为方式。我们可以允许许多个实例被创建,但所有的实例都共享状态和行为方式:

1

2

3

4

5

6

class Borg(object):

_shared_state={}

def __new__(cls,*args,**kwargs):

obj=super(Borg,cls).__new__(cls,*args,**kwargs)

obj.__dict__=cls._shared_state

return obj

将所有实例的__dict__指向同一个字典,这样实例就共享相同的方法和属性。对任何实例的名字属性的设置,无论是在__init__中修改还是直接修改,所有的实例都会受到影响。不过实例的id是不同的。要保证类实例能共享属性,但不和子类共享,注意使用cls._shared_state,而不是Borg._shared_state。

因为实例是不同的id,所以每个实例都可以做字典的key:

1

2

3

4

5

6

7

8

9

10

11

12

13

if __name__=='__main__':

class Example(Borg):

pass

a=Example()

b=Example()

c=Example()

adict={}

j=0

for iin a,b,c:

adict[i]=j

j+=1

for iin a,b,c:

print adict[i]

结果:

0

1

2

如果这种行为不是你想要的,可以为Borg类添加__eq__和__hash__方法,使其更接近于单例模式的行为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

class Borg(object):

_shared_state={}

def __new__(cls,*args,**kwargs):

obj=super(Borg,cls).__new__(cls,*args,**kwargs)

obj.__dict__=cls._shared_state

return obj

def __hash__(self):

return 1

def __eq__(self,other):

try:

return self.__dict__is other.__dict__

except:

return False

if __name__=='__main__':

class Example(Borg):

pass

a=Example()

b=Example()

c=Example()

adict={}

j=0

for iin a,b,c:

adict[i]=j

j+=1

for iin a,b,c:

print adict[i]

结果:

2

2

2

所有的实例都能当一个key使用了。

方法3

当你编写一个类的时候,某种机制会使用类名字,基类元组,类字典来创建一个类对象。新型类中这种机制默认为type,而且这种机制是可编程的,称为元类__metaclass__ 。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

class Singleton(type):

def __init__(self,name,bases,class_dict):

super(Singleton,self).__init__(name,bases,class_dict)

self._instance=None

def __call__(self,*args,**kwargs):

if self._instanceis None:

self._instance=super(Singleton,self).__call__(*args,**kwargs)

return self._instance

if __name__=='__main__':

class A(object):

__metaclass__=Singleton

a=A()

b=A()

print id(a),id(b)

结果:

34248016 34248016

id是相同的。

例子中我们构造了一个Singleton元类,并使用__call__方法使其能够模拟函数的行为。构造类A时,将其元类设为Singleton,那么创建类对象A时,行为发生如下:

A=Singleton(name,bases,class_dict),A其实为Singleton类的一个实例。

创建A的实例时,A()=Singleton(name,bases,class_dict)()=Singleton(name,bases,class_dict).__call__(),这样就将A的所有实例都指向了A的属性_instance上,这种方法与方法1其实是相同的。

方法4

python中的模块module在程序中只被加载一次,本身就是单例的。可以直接写一个模块,将你需要的方法和属性,写在模块中当做函数和模块作用域的全局变量即可,根本不需要写类。

而且还有一些综合模块和类的优点的方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

class _singleton(object):

class ConstError(TypeError):

pass

def __setattr__(self,name,value):

if namein self.__dict__:

raise self.ConstError

self.__dict__[name]=value

def __delattr__(self,name):

if namein self.__dict__:

raise self.ConstError

raise NameError

import sys

sys.modules[__name__]=_singleton()

python并不会对sys.modules进行检查以确保他们是模块对象,我们利用这一点将模块绑定向一个类对象,而且以后都会绑定向同一个对象了。

将代码存放在single.py中:

1

2

3

>>>import single

>>> single.a=1

>>> single.a=2

ConstError

>>> del single.a

ConstError

方法5:

最简单的方法:

1

2

3

class singleton(object):

pass

singleton=singleton()

将名字singleton绑定到实例上,singleton就是它自己类的唯一对象了。

以上就是Python单例模式的实现方式详细介绍,希望对大家的学习有所帮助。

python最简单单例模式_5种Python单例模式的实现方式相关推荐

  1. python爬虫框架排行榜-哪种Python框架适合你?简单介绍几种主流Python框架

    众所周知,Python开发框架大大减少了开发者不必要的重复劳动,提高了项目开发效率的同时,还使得创建的程序更加稳定.目前比较主流的Python框架都有哪些呢?一般大家用的比较多的是Django.Fla ...

  2. python第三方库排行-140种Python标准库、第三方库和外部工具

    导读:Python数据工具箱涵盖从数据源到数据可视化的完整流程中涉及到的常用库.函数和外部工具.其中既有Python内置函数和标准库,又有第三方库和工具. 这些库可用于文件读写.网络抓取和解析.数据连 ...

  3. 玩转Python? 一文总结30种Python的窍门和技巧!

    Python作为2019年必备语言之一,展现了不可替代作用.对于所有的数据科学工作者,如何提高使用Python的效率,这里,总结了30种Python的最佳实践.技巧和窍门.希望这些可以帮助大家在202 ...

  4. python编程制作_一种Python编程创作平台的制作方法

    本发明涉及在线浏览器技术领域,特别涉及一种Python编程创作平台. 背景技术: 目前项目整体使用javascript+html+css实现,用户界面编写上使用react框架.具体实现上是将pytho ...

  5. 玩转Python? 一文总结30种Python的窍门和技巧,不可错过哈!

    Python作为2020年必备语言之一,展现了不可替代作用.对于所有的数据科学工作者,如何提高使用Python的效率,这里,总结了30种Python的最佳实践.技巧和窍门.希望这些可以帮助大家在202 ...

  6. 为什么一个程序中变量只能定义一次_#带你学Python# 从简单程序出发理解Python基本语法

    欢迎回来. 通过上一篇文章,我们第一次触摸了Python,学会了如何用各种不同的方式运行Python的解释器.也介绍了很多工具和开发环境,是不是跃跃欲试了? 到这里,别的python教程就会从数据类型 ...

  7. python基础代码技巧_5行Python代码实现批量打水印技巧,值得收藏|python基础教程|python入门|python教程...

    在线工具需要上传到对方服务器,信息不安全. 很多工具不具备批量处理功能. 很多工具自定义的功能太少,如水印透明度,字体等. 操作繁琐. 现在只要你会使用命令,我们就能教大家怎么使用 Python 超级 ...

  8. python最简单的爬虫代码,python小实例一简单爬虫

    python新手求助 关于爬虫的简单例子 #coding=utf-8from bs4 import BeautifulSoupwith open('', 'r') as file: fcontent ...

  9. python优化算法工具包_12种Python 机器学习 数据挖掘工具包,一定让你受益匪浅...

    作为一种解释型语言,Python的设计哲学强调代码的可读性和简洁的语法(尤其是使用空格缩进划分代码块,而非使用大括号或者关键词).相比于C++或Java,Python让开发者能够用更少的代码表达想法. ...

最新文章

  1. C#学习-EF在三层中使用
  2. 推荐15个高质量学习网站,仅看一眼,就收获满满,赶紧收藏!
  3. Python 字符串的所有方法详解
  4. 语法手册_是真的猛!SQL 语法速成手册
  5. servlet类中@WebServlet 报错,不变色
  6. python socket清空接受区_用Python制作只属于你和ta的聊天渠道吧
  7. 类的序列化[Serializable]
  8. 2021年考计算机考研三战,2021考研的小伙伴有3条忠告一定要记得,这些都是历年实战经验...
  9. 工业机器人专业展板图片_南充职业技术学院工业机器人专业线下课程开展情况...
  10. python程序员怎么建议_资深程序员对Python新手的八个建议,超级实用!
  11. Extjs6(六)——增删查改之查询
  12. CentOS服务器下nginx防盗链介绍与配置
  13. UITableViewCell delete button 上有其它覆盖层
  14. 【袋鼠云内推】杭州-高级java开发-3~5以及5年以上
  15. Silverlight 4 Tools中文版下载
  16. Onvif协议:门外汉理解ONVIF协议
  17. 一个迅雷480M,是搞笑的吗?
  18. SAP开发入门-ABAP
  19. c++ 头歌实训 第四关 日历打印
  20. Android蓝牙手柄摇杆 十字按键监听手机focus焦点

热门文章

  1. 苏宁易购出售苏宁消费金融39%股权
  2. 11月1日至11日 全国处理快件47.76亿件
  3. 首销价1999元起!OPPO K9 Pro开启预售:搭载天玑1200芯片
  4. 铁路部门调整车票预售期为15天 火车票今年不再“一票难求”
  5. 英特尔:把基带卖给苹果 完全是高通逼的
  6. 王者荣耀新英雄官宣:鲁班七号之父鲁班大师 即将上线
  7. HTC不认输!将再战智能手机市场,明年推出5G新机
  8. 上市在即!华为Mate 20 X 5G版证件照公布:国行首款5G手机
  9. 3个月内第4起!香港一辆特斯拉Model S再次起火自燃
  10. 最耐用的手机盘点 网友:我这个能用到品牌商“破产”!