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