如何实现Python中的单例
1.重写Class的new方法
#__new__函数就是class在创建对象时会调用的方法
#通过重写__new__函数可以控制只创建一个对象
#子类可以通过重写__new__函数
class Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
2.指定metaclass
#通过metaclass控制class的__new__函数
#子类除非指定别的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)
else:
#这段代码的作用是每次都调用class的init函数
cls._instances[cls].__init__(*args, **kwargs)
return cls._instances[cls]
#Python2
class MyClass(BaseClass):
__metaclass__ = Singleton
#Python3
class MyClass(BaseClass, metaclass=Singleton):
pass
PS:上面的写法都没有加线程锁,如果考虑在多线程的环境下使用需要加线程锁
import functools
import threading
lock = threading.Lock()
def synchronized(lock):
""" Synchronization decorator """
def wrapper(f):
@functools.wraps(f)
def inner_wrapper(*args, **kw):
with lock:
return f(*args, **kw)
return inner_wrapper
return wrapper
class Singleton(type):
_instances = {}
@synchronized(lock)
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class SingletonClass(metaclass=Singleton):
pass
PS: 在Python中,import默认只会导入一次,除非使用reload函数刷新,否则每个module只会导入一次,这样的话,如果导入一个变量,则这个变量就相当于单例