在 Python 中,我们可以用多种方法来实现单例模式:

  • 使用模块
  • 使用 __new__
  • 使用装饰器(decorator)
  • 使用元类(metaclass)
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton() ##############调用
from mysingleton import my_singleton my_singleton.foo()

使用 __new__

为了使类只能出现一个实例,我们可以使用 __new__ 来控制实例的创建过程

class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance class MyClass(Singleton):
c = 1 a=MyClass()
b=MyClass()
print(a==b)
print(a is b)
print(id(a),id(b))
"""
True
True
1947813794256 1947813794256
"""

edition 2

class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance class MyClass(Singleton):
a = 1 a=MyClass()
b=MyClass()
print(a==b)
print(a is b)
print(id(a),id(b))

共享属性

创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法.

class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
# ob = super(Borg, cls).__new__(cls, *args, **kw)
cls._state[cls]= super(Borg, cls).__new__(cls, *args, **kw)
cls._state[cls].__dict__ = cls._state
print(cls._state)
print(cls) class MyClass(Borg):
a = 1 a=MyClass()
b=MyClass()
print(a==b)
print(a is b)
print(id(a),id(b))
print(MyClass.__dict__)
"""
{<class '__main__.MyClass'>: <__main__.MyClass object at 0x000001E31655D940>}
<class '__main__.MyClass'>
{<class '__main__.MyClass'>: <__main__.MyClass object at 0x000001E31656F940>}
<class '__main__.MyClass'>
True
True
1438393552 1438393552
{'__module__': '__main__', 'a': 1, '__doc__': None}
"""

装饰器(decorator)可以动态地修改一个类或函数的功能。

这里,我们也可以使用装饰器来装饰某个类,使其只能生成一个实例,代码如下:

from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance @singleton
class MyClass(object):
a = 1 a=MyClass()
b=MyClass()
print(a==b)
print(a is b)
print(id(a),id(b))

在上面,我们定义了一个装饰器 singleton,它返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]

也可以是:

def singleton(cls, *args, **kw):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance @singleton
class MyClass:
a=1

使用 metaclass

元类(metaclass)可以控制类的创建过程,它主要做三件事:

  • 拦截类的创建
  • 修改类的定义
  • 返回修改后的类

使用元类实现单例模式的代码如下:

class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls] # Python2
# class MyClass(object):
# __metaclass__ = Singleton # Python3
class MyClass(metaclass=Singleton):
pass a=MyClass()
b=MyClass()
print(a==b)
print(a is b)
print(id(a),id(b))

Python 的模块是天然的单例模式,这在大部分情况下应该是够用的,当然,我们也可以使用装饰器、元类等方法

最新文章

  1. JQuery实现方法,简单示例
  2. java 堆栈分析
  3. 多表利用DIH批量导入数据并建立索引注意事项
  4. HBase 使用场景和成功案例
  5. SQL中如何使用UPDATE语句进行联表更新(转)
  6. arm汇编:ldr,str,ldm,stm,伪指令ldr
  7. POI读入excel文件到Java中
  8. springmvc(三) 参数绑定、
  9. java web学习笔记 servlet
  10. 欢迎来到Hadoop
  11. Windows 支持 OpenSSH 了!
  12. docker修改默认存储位置
  13. ini (ini-parser)配置文件解析 for donet
  14. LeetCode 961 N-Repeated Element in Size 2N Array 解题报告
  15. js图的数据结构处理----普里姆算法
  16. Modern Data Lake with Minio : Part 1
  17. JUC回顾之-ArrayBlockingQueue底层实现和原理
  18. 微信小程序一些总结
  19. 【POJ】1026.Cipher
  20. Connect C# to MySQL

热门文章

  1. ViewPager使用记录2——展示动态数据
  2. C#中的协变(Covariance)和逆变(Contravariance)
  3. cordova封装h5为app,cookie不可用解决方法
  4. Spark SQL数据源
  5. iOS之 Category 属性 的理解
  6. babel从入门到入门
  7. 2015ACM/ICPC亚洲区沈阳站 B-Bazinga
  8. 数据库无法连接JDBC
  9. c++学习笔记---01---C++语言与OO思想介绍
  10. AngularJS学习篇(十八)