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