Python中的单例模式

(梳理下python中的设计模式。这里面的设计模式不仅仅是传统意义中的设计模式,还有python中的一些惯用法。)

单例模式 Singleton


单例模式的用途与全局变量一样,提供全局共享的唯一数据。单例模式封装数据和操作方法,需要保证方法返回的值一致(不变),并且单利模式类的初始化函数一般不能有参数。使用场景长见于处理和保存配置文件、只会实例化一次的实例等等。

1. 一般的单例模式,利用锁保证一致性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import threading
class Singleton(object):
_singleton_lock = threading.Lock()
@classmethod
def instance(cls):
if not hasattr(cls, '_instance'):
with cls._singleton_lock:
if not hasattr(cls, '_instance'):
cls._instance = cls()
return cls._instance
def test(self):
print('ok')
assert Singleton.instance() is Singleton.instance() #True

2. python的单利模式,利用__new__返回唯一的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import threading
class PySingleton(object):
_singleton_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
with cls._singleton_lock:
if not hasattr(cls, '_instance'):
cls._instance = super(PySingleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self, *args, **kwargs):
print 'init runs once'
ps1 = PySingleton() #init runs once
ps2 = PySingleton() #init runs once
assert ps1 is ps2 #True

Python的__new__特殊方法会多次调用初始化函数__init__,导致这个唯一的实例反复初始化。

3. 模块单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#singleton.py # 文件
class _Singleton(object):
@classmethod
def instance(cls):
if not hasattr(cls, '_instance'):
cls._instance = cls()
return cls._instance
Singleton = _Singleton()
del _Singleton
#other.py
from singleton import Singleton
Singleton.instance().start() # 或者直接使用Singleton实例

import有锁机制,不需要再使用锁进行并行保护;classmethod类方法可以通过方法和实例调用。