问题:如何实现单例模式?
- 通过new方法来实现单例模式。
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
变体:
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
- 通过装饰器来实现单例模式
from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
- 通过元类来创建单例模式,因为元类是用于创建类对象的类,类对象创建实例对象时一定会调用call方法,因此在调用call时候保证始终只创建一个实例即可。
class Singleton(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instance
class Foo(object):
__metaclass__ = Singleton
- 通过共享属性来实现单例模式(通过这种方式实现,只是两个对象有相同的属性,但是在实例化之后,one is two 将会返回False), 将所有实例的dict指向同一个字典,这样实例就共享相同的方法和属性。对任何实例的名字属性的设置,无论是在init中修改还是直接修改,所有的实例都会受到影响。不过实例的id是不同的。要保证类实例能共享属性,但不和子类共享。
class Singleton(object):
_state = {}
def __new__(cls, *args, **kwargs):
orig = super(Singleton, cls).__new__(cls, *args, **kwargs)
orig.__dict__ = cls._state
return orig
- 使用模块, Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:
# singleton.py
class Singleton(object):
def foo(self):
pass
my_singleton = Singleton()
变体:
# singleton.py
import sys
class Singleton(object):
pass
sys.modules[__name__] = Singleton()